mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 11:41:19 +00:00
231e468e19
git-subtree-dir: erigon-lib git-subtree-mainline:3c8cbda809
git-subtree-split:93d9c9d9fe
215 lines
6.1 KiB
Go
215 lines
6.1 KiB
Go
//go:build !nofuzz
|
|
|
|
package commitment
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"math/rand"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"golang.org/x/crypto/sha3"
|
|
|
|
"github.com/ledgerwatch/erigon-lib/common/length"
|
|
)
|
|
|
|
// go test -trimpath -v -fuzz=Fuzz_ProcessUpdate$ -fuzztime=300s ./commitment
|
|
|
|
func Fuzz_ProcessUpdate(f *testing.F) {
|
|
ha, _ := hex.DecodeString("13ccfe8074645cab4cb42b423625e055f0293c87")
|
|
hb, _ := hex.DecodeString("73f822e709a0016bfaed8b5e81b5f86de31d6895")
|
|
|
|
f.Add(uint64(2), ha, uint64(1235105), hb)
|
|
|
|
f.Fuzz(func(t *testing.T, balanceA uint64, accountA []byte, balanceB uint64, accountB []byte) {
|
|
if len(accountA) == 0 || len(accountA) > 20 || len(accountB) == 0 || len(accountB) > 20 {
|
|
t.Skip()
|
|
}
|
|
|
|
builder := NewUpdateBuilder().
|
|
Balance(hex.EncodeToString(accountA), balanceA).
|
|
Balance(hex.EncodeToString(accountB), balanceB)
|
|
|
|
ms := NewMockState(t)
|
|
ms2 := NewMockState(t)
|
|
hph := NewHexPatriciaHashed(20, ms.branchFn, ms.accountFn, ms.storageFn)
|
|
hphAnother := NewHexPatriciaHashed(20, ms2.branchFn, ms2.accountFn, ms2.storageFn)
|
|
|
|
hph.SetTrace(false)
|
|
hphAnother.SetTrace(false)
|
|
|
|
plainKeys, hashedKeys, updates := builder.Build()
|
|
if err := ms.applyPlainUpdates(plainKeys, updates); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := ms2.applyPlainUpdates(plainKeys, updates); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
rootHash, branchNodeUpdates, err := hph.ReviewKeys(plainKeys, hashedKeys)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
ms.applyBranchNodeUpdates(branchNodeUpdates)
|
|
if len(rootHash) != 32 {
|
|
t.Fatalf("invalid root hash length: expected 32 bytes, got %v", len(rootHash))
|
|
}
|
|
|
|
rootHashAnother, branchNodeUpdates, err := hphAnother.ReviewKeys(plainKeys, hashedKeys)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ms2.applyBranchNodeUpdates(branchNodeUpdates)
|
|
|
|
if len(rootHashAnother) > 32 {
|
|
t.Fatalf("invalid root hash length: expected 32 bytes, got %v", len(rootHash))
|
|
}
|
|
if !bytes.Equal(rootHash, rootHashAnother) {
|
|
t.Fatalf("invalid second root hash with same updates: [%v] != [%v]", hex.EncodeToString(rootHash), hex.EncodeToString(rootHashAnother))
|
|
}
|
|
})
|
|
}
|
|
|
|
// go test -trimpath -v -fuzz=Fuzz_ProcessUpdates_ArbitraryUpdateCount -fuzztime=300s ./commitment
|
|
|
|
func Fuzz_ProcessUpdates_ArbitraryUpdateCount(f *testing.F) {
|
|
ha, _ := hex.DecodeString("0008852883b2850c7a48f4b0eea3ccc4c04e6cb6025e9e8f7db2589c7dae81517c514790cfd6f668903161349e")
|
|
|
|
f.Add(ha)
|
|
|
|
f.Fuzz(func(t *testing.T, build []byte) {
|
|
if len(build) < 12 {
|
|
t.Skip()
|
|
}
|
|
i := 0
|
|
keysCount := binary.BigEndian.Uint32(build[i : i+4])
|
|
i += 4
|
|
ks := binary.BigEndian.Uint32(build[i : i+4])
|
|
keysSeed := rand.New(rand.NewSource(int64(ks)))
|
|
i += 4
|
|
us := binary.BigEndian.Uint32(build[i : i+4])
|
|
updateSeed := rand.New(rand.NewSource(int64(us)))
|
|
|
|
t.Logf("fuzzing %d keys keysSeed=%d updateSeed=%d", keysCount, ks, us)
|
|
|
|
builder := NewUpdateBuilder()
|
|
for k := uint32(0); k < keysCount; k++ {
|
|
var key [length.Addr]byte
|
|
n, err := keysSeed.Read(key[:])
|
|
pkey := hex.EncodeToString(key[:])
|
|
require.NoError(t, err)
|
|
require.EqualValues(t, length.Addr, n)
|
|
|
|
aux := make([]byte, 32)
|
|
|
|
flg := UpdateFlags(updateSeed.Intn(int(CodeUpdate | DeleteUpdate | StorageUpdate | NonceUpdate | BalanceUpdate)))
|
|
switch {
|
|
case flg&BalanceUpdate != 0:
|
|
builder.Balance(pkey, updateSeed.Uint64()).Nonce(pkey, updateSeed.Uint64())
|
|
continue
|
|
case flg&CodeUpdate != 0:
|
|
keccak := sha3.NewLegacyKeccak256().(keccakState)
|
|
var s [8]byte
|
|
n, err := updateSeed.Read(s[:])
|
|
require.NoError(t, err)
|
|
require.EqualValues(t, len(s), n)
|
|
keccak.Write(s[:])
|
|
keccak.Read(aux)
|
|
|
|
builder.CodeHash(pkey, hex.EncodeToString(aux))
|
|
continue
|
|
case flg&StorageUpdate != 0:
|
|
sz := updateSeed.Intn(length.Hash)
|
|
n, err = updateSeed.Read(aux[:sz])
|
|
require.NoError(t, err)
|
|
require.EqualValues(t, sz, n)
|
|
|
|
loc := make([]byte, updateSeed.Intn(length.Hash-1)+1)
|
|
keysSeed.Read(loc)
|
|
builder.Storage(pkey, hex.EncodeToString(loc), hex.EncodeToString(aux[:sz]))
|
|
continue
|
|
case flg&DeleteUpdate != 0:
|
|
continue
|
|
default:
|
|
continue
|
|
}
|
|
}
|
|
|
|
ms := NewMockState(t)
|
|
ms2 := NewMockState(t)
|
|
hph := NewHexPatriciaHashed(20, ms.branchFn, ms.accountFn, ms.storageFn)
|
|
hphAnother := NewHexPatriciaHashed(20, ms2.branchFn, ms2.accountFn, ms2.storageFn)
|
|
|
|
plainKeys, hashedKeys, updates := builder.Build()
|
|
|
|
hph.SetTrace(false)
|
|
hphAnother.SetTrace(false)
|
|
|
|
err := ms.applyPlainUpdates(plainKeys, updates)
|
|
require.NoError(t, err)
|
|
|
|
rootHashReview, branchNodeUpdates, err := hph.ReviewKeys(plainKeys, hashedKeys)
|
|
require.NoError(t, err)
|
|
|
|
ms.applyBranchNodeUpdates(branchNodeUpdates)
|
|
require.Len(t, rootHashReview, length.Hash, "invalid root hash length")
|
|
|
|
err = ms2.applyPlainUpdates(plainKeys, updates)
|
|
require.NoError(t, err)
|
|
|
|
rootHashAnother, branchUpdatesAnother, err := hphAnother.ReviewKeys(plainKeys, hashedKeys)
|
|
require.NoError(t, err)
|
|
ms2.applyBranchNodeUpdates(branchUpdatesAnother)
|
|
|
|
require.Len(t, rootHashAnother, length.Hash, "invalid root hash length")
|
|
require.EqualValues(t, rootHashReview, rootHashAnother, "storage-based and update-based rootHash mismatch")
|
|
})
|
|
}
|
|
|
|
func Fuzz_HexPatriciaHashed_ReviewKeys(f *testing.F) {
|
|
var (
|
|
keysCount uint64 = 100
|
|
seed int64 = 1234123415
|
|
)
|
|
|
|
f.Add(keysCount, seed)
|
|
|
|
f.Fuzz(func(t *testing.T, keysCount uint64, seed int64) {
|
|
if keysCount > 10e9 {
|
|
return
|
|
}
|
|
|
|
rnd := rand.New(rand.NewSource(seed))
|
|
builder := NewUpdateBuilder()
|
|
|
|
// generate updates
|
|
for i := 0; i < int(keysCount); i++ {
|
|
key := make([]byte, length.Addr)
|
|
|
|
for j := 0; j < len(key); j++ {
|
|
key[j] = byte(rnd.Intn(256))
|
|
}
|
|
builder.Balance(hex.EncodeToString(key), rnd.Uint64())
|
|
}
|
|
|
|
ms := NewMockState(t)
|
|
hph := NewHexPatriciaHashed(length.Addr, ms.branchFn, ms.accountFn, ms.storageFn)
|
|
|
|
hph.SetTrace(false)
|
|
|
|
plainKeys, hashedKeys, updates := builder.Build()
|
|
if err := ms.applyPlainUpdates(plainKeys, updates); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
rootHash, branchNodeUpdates, err := hph.ReviewKeys(plainKeys, hashedKeys)
|
|
require.NoError(t, err)
|
|
|
|
ms.applyBranchNodeUpdates(branchNodeUpdates)
|
|
require.Lenf(t, rootHash, length.Hash, "invalid root hash length")
|
|
})
|
|
}
|