diff --git a/beacon-chain/state/fieldtrie/BUILD.bazel b/beacon-chain/state/fieldtrie/BUILD.bazel index 6afdf72b5..5c463fef1 100644 --- a/beacon-chain/state/fieldtrie/BUILD.bazel +++ b/beacon-chain/state/fieldtrie/BUILD.bazel @@ -15,7 +15,6 @@ go_library( "//beacon-chain/state/types:go_default_library", "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", - "//encoding/ssz:go_default_library", "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", diff --git a/beacon-chain/state/fieldtrie/field_trie_helpers.go b/beacon-chain/state/fieldtrie/field_trie_helpers.go index 4b2aca667..52dc568de 100644 --- a/beacon-chain/state/fieldtrie/field_trie_helpers.go +++ b/beacon-chain/state/fieldtrie/field_trie_helpers.go @@ -12,7 +12,6 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/state/types" "github.com/prysmaticlabs/prysm/crypto/hash" "github.com/prysmaticlabs/prysm/encoding/bytesutil" - "github.com/prysmaticlabs/prysm/encoding/ssz" pmath "github.com/prysmaticlabs/prysm/math" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/runtime/version" @@ -353,17 +352,7 @@ func handlePendingAttestationSlice(val []*ethpb.PendingAttestation, indices []ui // handleBalanceSlice returns the root of a slice of validator balances. func handleBalanceSlice(val, indices []uint64, convertAll bool) ([][32]byte, error) { if convertAll { - balancesMarshaling := make([][]byte, len(val)) - for i, b := range val { - balanceBuf := make([]byte, 8) - binary.LittleEndian.PutUint64(balanceBuf, b) - balancesMarshaling[i] = balanceBuf - } - balancesChunks, err := ssz.PackByChunk(balancesMarshaling) - if err != nil { - return [][32]byte{}, errors.Wrap(err, "could not pack balances into chunks") - } - return balancesChunks, nil + return stateutil.PackUint64IntoChunks(val) } if len(val) > 0 { numOfElems, err := types.Balances.ElemsInChunk() diff --git a/beacon-chain/state/stateutil/validator_root.go b/beacon-chain/state/stateutil/validator_root.go index 21eb8edc0..d2ab417d1 100644 --- a/beacon-chain/state/stateutil/validator_root.go +++ b/beacon-chain/state/stateutil/validator_root.go @@ -64,13 +64,7 @@ func ValidatorFieldRoots(hasher ssz.HashFn, validator *ethpb.Validator) ([][32]b // a list of uint64 and mixed with registry limit. func Uint64ListRootWithRegistryLimit(balances []uint64) ([32]byte, error) { hasher := hash.CustomSHA256Hasher() - balancesMarshaling := make([][]byte, 0, len(balances)) - for i := 0; i < len(balances); i++ { - balanceBuf := make([]byte, 8) - binary.LittleEndian.PutUint64(balanceBuf, balances[i]) - balancesMarshaling = append(balancesMarshaling, balanceBuf) - } - balancesChunks, err := ssz.PackByChunk(balancesMarshaling) + balancesChunks, err := PackUint64IntoChunks(balances) if err != nil { return [32]byte{}, errors.Wrap(err, "could not pack balances into chunks") } @@ -87,3 +81,37 @@ func Uint64ListRootWithRegistryLimit(balances []uint64) ([32]byte, error) { binary.LittleEndian.PutUint64(balancesLengthRoot, uint64(len(balances))) return ssz.MixInLength(balancesRootsRoot, balancesLengthRoot), nil } + +// PackUint64IntoChunks packs a list of uint64 values into 32 byte roots. +func PackUint64IntoChunks(vals []uint64) ([][32]byte, error) { + // Initialize how many uint64 values we can pack + // into a single chunk(32 bytes). Each uint64 value + // would take up 8 bytes. + numOfElems := 4 + sizeOfElem := 32 / numOfElems + // Determine total number of chunks to be + // allocated to provided list of unsigned + // 64-bit integers. + numOfChunks := len(vals) / numOfElems + // Add an extra chunk if the list size + // is not a perfect multiple of the number + // of elements. + if len(vals)%numOfElems != 0 { + numOfChunks++ + } + chunkList := make([][32]byte, numOfChunks) + for idx, b := range vals { + // In order to determine how to pack in the uint64 value by index into + // our chunk list we need to determine a few things. + // 1) The chunk which the particular uint64 value corresponds to. + // 2) The position of the value in the chunk itself. + // + // Once we have determined these 2 values we can simply find the correct + // section of contiguous bytes to insert the value in the chunk. + chunkIdx := idx / numOfElems + idxInChunk := idx % numOfElems + chunkPos := idxInChunk * sizeOfElem + binary.LittleEndian.PutUint64(chunkList[chunkIdx][chunkPos:chunkPos+sizeOfElem], b) + } + return chunkList, nil +}