mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 07:58:22 -05:00
Update state root cache to fuzz in parallel (#5364)
* Update state root cache to fuzz in parallel * confirmed arrays passing Co-authored-by: rauljordan <raul@prysmaticlabs.com>
This commit is contained in:
@@ -933,8 +933,8 @@ go_repository(
|
||||
go_repository(
|
||||
name = "com_github_google_gofuzz",
|
||||
importpath = "github.com/google/gofuzz",
|
||||
sum = "h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=",
|
||||
version = "v1.0.0",
|
||||
sum = "h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=",
|
||||
version = "v1.1.0",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
|
||||
@@ -49,6 +49,7 @@ go_test(
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/hashutil:go_default_library",
|
||||
"//shared/interop:go_default_library",
|
||||
"//shared/mputil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"@com_github_google_gofuzz//:go_default_library",
|
||||
|
||||
@@ -25,13 +25,13 @@ func RootsArrayHashTreeRoot(vals [][]byte, length uint64, fieldName string) ([32
|
||||
}
|
||||
|
||||
func (h *stateRootHasher) arraysRoot(input [][]byte, length uint64, fieldName string) ([32]byte, error) {
|
||||
hashFunc := hashutil.CustomSHA256Hasher()
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
hashFunc := hashutil.CustomSHA256Hasher()
|
||||
if _, ok := layersCache[fieldName]; !ok && h.rootsCache != nil {
|
||||
depth := GetDepth(length)
|
||||
layersCache[fieldName] = make([][][32]byte, depth+1)
|
||||
}
|
||||
lock.Unlock()
|
||||
|
||||
leaves := make([][32]byte, length)
|
||||
for i, chunk := range input {
|
||||
@@ -39,9 +39,7 @@ func (h *stateRootHasher) arraysRoot(input [][]byte, length uint64, fieldName st
|
||||
}
|
||||
bytesProcessed := 0
|
||||
changedIndices := make([]int, 0)
|
||||
lock.RLock()
|
||||
prevLeaves, ok := leavesCache[fieldName]
|
||||
lock.RUnlock()
|
||||
if len(prevLeaves) == 0 || h.rootsCache == nil {
|
||||
prevLeaves = leaves
|
||||
}
|
||||
@@ -74,26 +72,20 @@ func (h *stateRootHasher) arraysRoot(input [][]byte, length uint64, fieldName st
|
||||
return [32]byte{}, err
|
||||
}
|
||||
}
|
||||
lock.Lock()
|
||||
leavesCache[fieldName] = chunks
|
||||
lock.Unlock()
|
||||
return rt, nil
|
||||
}
|
||||
|
||||
var res [32]byte
|
||||
res = h.merkleizeWithCache(leaves, length, fieldName, hashFunc)
|
||||
if h.rootsCache != nil {
|
||||
lock.Lock()
|
||||
leavesCache[fieldName] = leaves
|
||||
lock.Unlock()
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *stateRootHasher) merkleizeWithCache(leaves [][32]byte, length uint64,
|
||||
fieldName string, hasher func([]byte) [32]byte) [32]byte {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
if len(leaves) == 1 {
|
||||
var root [32]byte
|
||||
root = leaves[0]
|
||||
@@ -144,8 +136,6 @@ func merkleizeTrieLeaves(layers [][][32]byte, hashLayer [][32]byte,
|
||||
|
||||
func recomputeRoot(idx int, chunks [][32]byte, length uint64,
|
||||
fieldName string, hasher func([]byte) [32]byte) ([32]byte, error) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
items, ok := layersCache[fieldName]
|
||||
if !ok {
|
||||
return [32]byte{}, errors.New("could not recompute root as there was no cache found")
|
||||
|
||||
@@ -2,10 +2,12 @@ package stateutil
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
ethereum_beacon_p2p_v1 "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/mputil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
@@ -27,49 +29,62 @@ func TestStateRootCacheFuzz_1000(t *testing.T) {
|
||||
|
||||
func fuzzStateRootCache(t *testing.T, seed int64, iterations uint64) {
|
||||
fuzzer := fuzz.NewWithSeed(seed)
|
||||
state := ðereum_beacon_p2p_v1.BeaconState{}
|
||||
|
||||
hasher := &stateRootHasher{}
|
||||
hasherWithCache := cachedHasher
|
||||
|
||||
mismatch := 0
|
||||
mismatchedIndices := make([]uint64, 0)
|
||||
for i := uint64(0); i < iterations; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
var a, b [32]byte
|
||||
func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Errorf("Non-cached HTR panicked on iteration %d", i)
|
||||
panic(r)
|
||||
|
||||
// Use scatter to run tests in parallel.
|
||||
if _, err := mputil.Scatter(int(iterations), func(start int, length int, _ *sync.RWMutex) (i interface{}, err error) {
|
||||
state := ðereum_beacon_p2p_v1.BeaconState{}
|
||||
for i := start; i < start+length; i++ {
|
||||
func() {
|
||||
defer func() {
|
||||
recover() // Ignore fuzzing panics for out of range values
|
||||
}()
|
||||
fuzzer.Fuzz(state)
|
||||
}()
|
||||
var a, b [32]byte
|
||||
func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Errorf("Non-cached HTR panicked on iteration %d", i)
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
var err error
|
||||
a, err = hasher.hashTreeRootState(state)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
var err error
|
||||
a, err = hasher.hashTreeRootState(state)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Errorf("Cached HTR panicked on iteration %d", i)
|
||||
panic(r)
|
||||
func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Errorf("Cached HTR panicked on iteration %d", i)
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
var err error
|
||||
b, err = hasherWithCache.hashTreeRootState(state)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
var err error
|
||||
b, err = hasherWithCache.hashTreeRootState(state)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
if a != b {
|
||||
mismatch++
|
||||
mismatchedIndices = append(mismatchedIndices, i)
|
||||
if a != b {
|
||||
mismatch++
|
||||
mismatchedIndices = append(mismatchedIndices, uint64(i))
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if mismatch > 0 {
|
||||
t.Errorf("Mismatched indices: %v", mismatchedIndices)
|
||||
t.Fatalf("%d of %d random states had different roots", mismatch, iterations)
|
||||
|
||||
Reference in New Issue
Block a user