diff --git a/beacon-chain/state/BUILD.bazel b/beacon-chain/state/BUILD.bazel index f71c86d5f09a..c7346deb3783 100644 --- a/beacon-chain/state/BUILD.bazel +++ b/beacon-chain/state/BUILD.bazel @@ -29,7 +29,6 @@ go_library( "//shared/sliceutil:go_default_library", "@com_github_gogo_protobuf//proto:go_default_library", "@com_github_pkg_errors//:go_default_library", - "@com_github_protolambda_zssz//merkle:go_default_library", "@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@io_opencensus_go//trace:go_default_library", diff --git a/beacon-chain/state/field_trie.go b/beacon-chain/state/field_trie.go index 959e62f0157c..2d649c0ccf89 100644 --- a/beacon-chain/state/field_trie.go +++ b/beacon-chain/state/field_trie.go @@ -9,6 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" "github.com/prysmaticlabs/prysm/shared/bytesutil" + "github.com/prysmaticlabs/prysm/shared/hashutil" "github.com/prysmaticlabs/prysm/shared/memorypool" ) @@ -209,8 +210,9 @@ func handleByteArrays(val [][]byte, indices []uint64, convertAll bool) ([][32]by func handleEth1DataSlice(val []*ethpb.Eth1Data, indices []uint64, convertAll bool) ([][32]byte, error) { roots := [][32]byte{} + hasher := hashutil.CustomSHA256Hasher() rootCreater := func(input *ethpb.Eth1Data) error { - newRoot, err := stateutil.Eth1Root(input) + newRoot, err := stateutil.Eth1Root(hasher, input) if err != nil { return err } @@ -237,8 +239,9 @@ func handleEth1DataSlice(val []*ethpb.Eth1Data, indices []uint64, convertAll boo func handleValidatorSlice(val []*ethpb.Validator, indices []uint64, convertAll bool) ([][32]byte, error) { roots := [][32]byte{} + hasher := hashutil.CustomSHA256Hasher() rootCreater := func(input *ethpb.Validator) error { - newRoot, err := stateutil.ValidatorRoot(input) + newRoot, err := stateutil.ValidatorRoot(hasher, input) if err != nil { return err } @@ -265,8 +268,9 @@ func handleValidatorSlice(val []*ethpb.Validator, indices []uint64, convertAll b func handlePendingAttestation(val []*pb.PendingAttestation, indices []uint64, convertAll bool) ([][32]byte, error) { roots := [][32]byte{} + hasher := hashutil.CustomSHA256Hasher() rootCreator := func(input *pb.PendingAttestation) error { - newRoot, err := stateutil.PendingAttestationRoot(input) + newRoot, err := stateutil.PendingAttestationRoot(hasher, input) if err != nil { return err } diff --git a/beacon-chain/state/state_trie.go b/beacon-chain/state/state_trie.go index a73587b7902e..aaa2c89b24b0 100644 --- a/beacon-chain/state/state_trie.go +++ b/beacon-chain/state/state_trie.go @@ -8,7 +8,6 @@ import ( "github.com/gogo/protobuf/proto" "github.com/pkg/errors" - "github.com/protolambda/zssz/merkle" coreutils "github.com/prysmaticlabs/prysm/beacon-chain/core/state/stateutils" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" @@ -213,7 +212,7 @@ func (b *BeaconState) HashTreeRoot(ctx context.Context) ([32]byte, error) { // pads the leaves to a power-of-two length. func merkleize(leaves [][]byte) [][][]byte { hashFunc := hashutil.CustomSHA256Hasher() - layers := make([][][]byte, merkle.GetDepth(uint64(len(leaves)))+1) + layers := make([][][]byte, stateutil.GetDepth(uint64(len(leaves)))+1) for len(leaves) != 32 { leaves = append(leaves, make([]byte, 32)) } @@ -240,6 +239,7 @@ func merkleize(leaves [][]byte) [][][]byte { } func (b *BeaconState) rootSelector(field fieldIndex) ([32]byte, error) { + hasher := hashutil.CustomSHA256Hasher() switch field { case genesisTime: return stateutil.Uint64Root(b.state.GenesisTime), nil @@ -282,7 +282,7 @@ func (b *BeaconState) rootSelector(field fieldIndex) ([32]byte, error) { case historicalRoots: return stateutil.HistoricalRootsRoot(b.state.HistoricalRoots) case eth1Data: - return stateutil.Eth1Root(b.state.Eth1Data) + return stateutil.Eth1Root(hasher, b.state.Eth1Data) case eth1DataVotes: if featureconfig.Get().EnableFieldTrie { if b.rebuildTrie[field] { @@ -360,11 +360,11 @@ func (b *BeaconState) rootSelector(field fieldIndex) ([32]byte, error) { case justificationBits: return bytesutil.ToBytes32(b.state.JustificationBits), nil case previousJustifiedCheckpoint: - return stateutil.CheckpointRoot(b.state.PreviousJustifiedCheckpoint) + return stateutil.CheckpointRoot(hasher, b.state.PreviousJustifiedCheckpoint) case currentJustifiedCheckpoint: - return stateutil.CheckpointRoot(b.state.CurrentJustifiedCheckpoint) + return stateutil.CheckpointRoot(hasher, b.state.CurrentJustifiedCheckpoint) case finalizedCheckpoint: - return stateutil.CheckpointRoot(b.state.FinalizedCheckpoint) + return stateutil.CheckpointRoot(hasher, b.state.FinalizedCheckpoint) } return [32]byte{}, errors.New("invalid field index provided") } diff --git a/beacon-chain/state/stateutil/BUILD.bazel b/beacon-chain/state/stateutil/BUILD.bazel index e5d245163891..eefa48a04e06 100644 --- a/beacon-chain/state/stateutil/BUILD.bazel +++ b/beacon-chain/state/stateutil/BUILD.bazel @@ -47,6 +47,7 @@ go_test( "//proto/beacon/p2p/v1:go_default_library", "//shared/bytesutil:go_default_library", "//shared/featureconfig:go_default_library", + "//shared/hashutil:go_default_library", "//shared/interop:go_default_library", "//shared/params:go_default_library", "//shared/testutil:go_default_library", diff --git a/beacon-chain/state/stateutil/attestations.go b/beacon-chain/state/stateutil/attestations.go index 016e2f314ccf..45aea9e847e9 100644 --- a/beacon-chain/state/stateutil/attestations.go +++ b/beacon-chain/state/stateutil/attestations.go @@ -9,6 +9,7 @@ import ( pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" "github.com/prysmaticlabs/prysm/shared/bytesutil" "github.com/prysmaticlabs/prysm/shared/featureconfig" + "github.com/prysmaticlabs/prysm/shared/hashutil" "github.com/prysmaticlabs/prysm/shared/params" ) @@ -24,16 +25,16 @@ func EpochAttestationsRoot(atts []*pb.PendingAttestation) ([32]byte, error) { // PendingAttestationRoot describes a method from which the hash tree root // of a pending attestation is returned. -func PendingAttestationRoot(att *pb.PendingAttestation) ([32]byte, error) { +func PendingAttestationRoot(hasher HashFn, att *pb.PendingAttestation) ([32]byte, error) { fieldRoots := [][32]byte{} if att != nil { // Bitfield. - aggregationRoot, err := bitlistRoot(att.AggregationBits, params.BeaconConfig().MaxValidatorsPerCommittee) + aggregationRoot, err := bitlistRoot(hasher, att.AggregationBits, params.BeaconConfig().MaxValidatorsPerCommittee) if err != nil { return [32]byte{}, err } // Attestation data. - attDataRoot, err := attestationDataRoot(att.Data) + attDataRoot, err := attestationDataRoot(hasher, att.Data) if err != nil { return [32]byte{}, err } @@ -49,7 +50,7 @@ func PendingAttestationRoot(att *pb.PendingAttestation) ([32]byte, error) { fieldRoots = [][32]byte{aggregationRoot, attDataRoot, inclusionRoot, proposerRoot} } - return bitwiseMerkleizeArrays(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + return bitwiseMerkleizeArrays(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) } func marshalAttestationData(data *ethpb.AttestationData) []byte { @@ -88,17 +89,17 @@ func marshalAttestationData(data *ethpb.AttestationData) []byte { return enc } -func attestationRoot(att *ethpb.Attestation) ([32]byte, error) { +func attestationRoot(hasher HashFn, att *ethpb.Attestation) ([32]byte, error) { fieldRoots := make([][32]byte, 3) // Bitfield. - aggregationRoot, err := bitlistRoot(att.AggregationBits, params.BeaconConfig().MaxValidatorsPerCommittee) + aggregationRoot, err := bitlistRoot(hasher, att.AggregationBits, params.BeaconConfig().MaxValidatorsPerCommittee) if err != nil { return [32]byte{}, err } fieldRoots[0] = aggregationRoot - dataRoot, err := attestationDataRoot(att.Data) + dataRoot, err := attestationDataRoot(hasher, att.Data) if err != nil { return [32]byte{}, err } @@ -109,18 +110,19 @@ func attestationRoot(att *ethpb.Attestation) ([32]byte, error) { if err != nil { return [32]byte{}, err } - sigRoot, err := bitwiseMerkleize(packedSig, uint64(len(packedSig)), uint64(len(packedSig))) + sigRoot, err := bitwiseMerkleize(hasher, packedSig, uint64(len(packedSig)), uint64(len(packedSig))) if err != nil { return [32]byte{}, err } fieldRoots[2] = sigRoot - return bitwiseMerkleizeArrays(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + return bitwiseMerkleizeArrays(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) } func blockAttestationRoot(atts []*ethpb.Attestation) ([32]byte, error) { + hasher := hashutil.CustomSHA256Hasher() roots := make([][]byte, len(atts)) for i := 0; i < len(atts); i++ { - pendingRoot, err := attestationRoot(atts[i]) + pendingRoot, err := attestationRoot(hasher, atts[i]) if err != nil { return [32]byte{}, errors.Wrap(err, "could not attestation merkleization") } @@ -128,6 +130,7 @@ func blockAttestationRoot(atts []*ethpb.Attestation) ([32]byte, error) { } attsRootsRoot, err := bitwiseMerkleize( + hasher, roots, uint64(len(roots)), params.BeaconConfig().MaxAttestations, @@ -146,7 +149,7 @@ func blockAttestationRoot(atts []*ethpb.Attestation) ([32]byte, error) { return res, nil } -func attestationDataRoot(data *ethpb.AttestationData) ([32]byte, error) { +func attestationDataRoot(hasher HashFn, data *ethpb.AttestationData) ([32]byte, error) { fieldRoots := make([][]byte, 5) if data != nil { @@ -167,24 +170,24 @@ func attestationDataRoot(data *ethpb.AttestationData) ([32]byte, error) { fieldRoots[2] = blockRoot[:] // Source - sourceRoot, err := CheckpointRoot(data.Source) + sourceRoot, err := CheckpointRoot(hasher, data.Source) if err != nil { return [32]byte{}, errors.Wrap(err, "could not compute source checkpoint merkleization") } fieldRoots[3] = sourceRoot[:] // Target - targetRoot, err := CheckpointRoot(data.Target) + targetRoot, err := CheckpointRoot(hasher, data.Target) if err != nil { return [32]byte{}, errors.Wrap(err, "could not compute target checkpoint merkleization") } fieldRoots[4] = targetRoot[:] } - return bitwiseMerkleize(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + return bitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) } -func (h *stateRootHasher) pendingAttestationRoot(att *pb.PendingAttestation) ([32]byte, error) { +func (h *stateRootHasher) pendingAttestationRoot(hasher HashFn, att *pb.PendingAttestation) ([32]byte, error) { // Marshal attestation to determine if it exists in the cache. enc := make([]byte, 2192) fieldRoots := make([][]byte, 4) @@ -211,14 +214,14 @@ func (h *stateRootHasher) pendingAttestationRoot(att *pb.PendingAttestation) ([3 } // Bitfield. - aggregationRoot, err := bitlistRoot(att.AggregationBits, 2048) + aggregationRoot, err := bitlistRoot(hasher, att.AggregationBits, 2048) if err != nil { return [32]byte{}, err } fieldRoots[0] = aggregationRoot[:] // Attestation data. - attDataRoot, err := attestationDataRoot(att.Data) + attDataRoot, err := attestationDataRoot(hasher, att.Data) if err != nil { return [32]byte{}, err } @@ -232,7 +235,7 @@ func (h *stateRootHasher) pendingAttestationRoot(att *pb.PendingAttestation) ([3 proposerRoot := bytesutil.ToBytes32(proposerBuf) fieldRoots[3] = proposerRoot[:] } - res, err := bitwiseMerkleize(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + res, err := bitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) if err != nil { return [32]byte{}, err } @@ -243,9 +246,10 @@ func (h *stateRootHasher) pendingAttestationRoot(att *pb.PendingAttestation) ([3 } func (h *stateRootHasher) epochAttestationsRoot(atts []*pb.PendingAttestation) ([32]byte, error) { + hasher := hashutil.CustomSHA256Hasher() roots := make([][]byte, len(atts)) for i := 0; i < len(atts); i++ { - pendingRoot, err := h.pendingAttestationRoot(atts[i]) + pendingRoot, err := h.pendingAttestationRoot(hasher, atts[i]) if err != nil { return [32]byte{}, errors.Wrap(err, "could not attestation merkleization") } @@ -253,6 +257,7 @@ func (h *stateRootHasher) epochAttestationsRoot(atts []*pb.PendingAttestation) ( } attsRootsRoot, err := bitwiseMerkleize( + hasher, roots, uint64(len(roots)), params.BeaconConfig().MaxAttestations*params.BeaconConfig().SlotsPerEpoch, diff --git a/beacon-chain/state/stateutil/blocks.go b/beacon-chain/state/stateutil/blocks.go index 4a1ec714530c..194f36008660 100644 --- a/beacon-chain/state/stateutil/blocks.go +++ b/beacon-chain/state/stateutil/blocks.go @@ -30,7 +30,7 @@ func BlockHeaderRoot(header *ethpb.BeaconBlockHeader) ([32]byte, error) { bodyRoot := bytesutil.ToBytes32(header.BodyRoot) fieldRoots[3] = bodyRoot[:] } - return bitwiseMerkleize(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + return bitwiseMerkleize(hashutil.CustomSHA256Hasher(), fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) } // BlockRoot returns the block hash tree root of the provided block. @@ -54,7 +54,7 @@ func BlockRoot(blk *ethpb.BeaconBlock) ([32]byte, error) { } fieldRoots[3] = bodyRoot } - return bitwiseMerkleizeArrays(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + return bitwiseMerkleizeArrays(hashutil.CustomSHA256Hasher(), fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) } // BlockBodyRoot returns the hash tree root of the block body. @@ -62,6 +62,7 @@ func BlockBodyRoot(body *ethpb.BeaconBlockBody) ([32]byte, error) { if !featureconfig.Get().EnableBlockHTR { return ssz.HashTreeRoot(body) } + hasher := hashutil.CustomSHA256Hasher() fieldRoots := make([][32]byte, 8) if body != nil { rawRandao := bytesutil.ToBytes96(body.RandaoReveal) @@ -69,13 +70,13 @@ func BlockBodyRoot(body *ethpb.BeaconBlockBody) ([32]byte, error) { if err != nil { return [32]byte{}, err } - randaoRoot, err := bitwiseMerkleize(packedRandao, uint64(len(packedRandao)), uint64(len(packedRandao))) + randaoRoot, err := bitwiseMerkleize(hasher, packedRandao, uint64(len(packedRandao)), uint64(len(packedRandao))) if err != nil { return [32]byte{}, err } fieldRoots[0] = randaoRoot - eth1Root, err := Eth1Root(body.Eth1Data) + eth1Root, err := Eth1Root(hasher, body.Eth1Data) if err != nil { return [32]byte{}, err } @@ -112,13 +113,13 @@ func BlockBodyRoot(body *ethpb.BeaconBlockBody) ([32]byte, error) { } fieldRoots[7] = exitRoot } - return bitwiseMerkleizeArrays(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + return bitwiseMerkleizeArrays(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) } // Eth1Root computes the HashTreeRoot Merkleization of // a BeaconBlockHeader struct according to the eth2 // Simple Serialize specification. -func Eth1Root(eth1Data *ethpb.Eth1Data) ([32]byte, error) { +func Eth1Root(hasher HashFn, eth1Data *ethpb.Eth1Data) ([32]byte, error) { enc := make([]byte, 0, 96) fieldRoots := make([][]byte, 3) for i := 0; i < len(fieldRoots); i++ { @@ -146,7 +147,7 @@ func Eth1Root(eth1Data *ethpb.Eth1Data) ([32]byte, error) { } } } - root, err := bitwiseMerkleize(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + root, err := bitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) if err != nil { return [32]byte{}, err } @@ -162,8 +163,9 @@ func Eth1Root(eth1Data *ethpb.Eth1Data) ([32]byte, error) { func Eth1DataVotesRoot(eth1DataVotes []*ethpb.Eth1Data) ([32]byte, error) { eth1VotesRoots := make([][]byte, 0) enc := make([]byte, len(eth1DataVotes)*32) + hasher := hashutil.CustomSHA256Hasher() for i := 0; i < len(eth1DataVotes); i++ { - eth1, err := Eth1Root(eth1DataVotes[i]) + eth1, err := Eth1Root(hasher, eth1DataVotes[i]) if err != nil { return [32]byte{}, errors.Wrap(err, "could not compute eth1data merkleization") } @@ -180,7 +182,7 @@ func Eth1DataVotesRoot(eth1DataVotes []*ethpb.Eth1Data) ([32]byte, error) { if err != nil { return [32]byte{}, errors.Wrap(err, "could not chunk eth1 votes roots") } - eth1VotesRootsRoot, err := bitwiseMerkleize(eth1Chunks, uint64(len(eth1Chunks)), params.BeaconConfig().SlotsPerEth1VotingPeriod) + eth1VotesRootsRoot, err := bitwiseMerkleize(hasher, eth1Chunks, uint64(len(eth1Chunks)), params.BeaconConfig().SlotsPerEth1VotingPeriod) if err != nil { return [32]byte{}, errors.Wrap(err, "could not compute eth1data votes merkleization") } diff --git a/beacon-chain/state/stateutil/helpers.go b/beacon-chain/state/stateutil/helpers.go index cc6403d28a54..55525d811d80 100644 --- a/beacon-chain/state/stateutil/helpers.go +++ b/beacon-chain/state/stateutil/helpers.go @@ -7,14 +7,13 @@ import ( "github.com/minio/sha256-simd" "github.com/pkg/errors" "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/shared/hashutil" ) -func bitlistRoot(bfield bitfield.Bitfield, maxCapacity uint64) ([32]byte, error) { +func bitlistRoot(hasher HashFn, bfield bitfield.Bitfield, maxCapacity uint64) ([32]byte, error) { limit := (maxCapacity + 255) / 256 if bfield == nil || bfield.Len() == 0 { length := make([]byte, 32) - root, err := bitwiseMerkleize([][]byte{}, 0, limit) + root, err := bitwiseMerkleize(hasher, [][]byte{}, 0, limit) if err != nil { return [32]byte{}, err } @@ -30,7 +29,7 @@ func bitlistRoot(bfield bitfield.Bitfield, maxCapacity uint64) ([32]byte, error) } output := make([]byte, 32) copy(output, buf.Bytes()) - root, err := bitwiseMerkleize(chunks, uint64(len(chunks)), limit) + root, err := bitwiseMerkleize(hasher, chunks, uint64(len(chunks)), limit) if err != nil { return [32]byte{}, err } @@ -41,11 +40,11 @@ func bitlistRoot(bfield bitfield.Bitfield, maxCapacity uint64) ([32]byte, error) // number of chunks is a power of two, Merkleize the chunks, and return the root. // Note that merkleize on a single chunk is simply that chunk, i.e. the identity // when the number of chunks is one. -func bitwiseMerkleize(chunks [][]byte, count uint64, limit uint64) ([32]byte, error) { +func bitwiseMerkleize(hasher HashFn, chunks [][]byte, count uint64, limit uint64) ([32]byte, error) { if count > limit { return [32]byte{}, errors.New("merkleizing list that is too large, over limit") } - hashFn := NewHasherFunc(hashutil.CustomSHA256Hasher()) + hashFn := NewHasherFunc(hasher) leafIndexer := func(i uint64) []byte { return chunks[i] } @@ -53,11 +52,11 @@ func bitwiseMerkleize(chunks [][]byte, count uint64, limit uint64) ([32]byte, er } // bitwiseMerkleizeArrays is used when a set of 32-byte root chunks are provided. -func bitwiseMerkleizeArrays(chunks [][32]byte, count uint64, limit uint64) ([32]byte, error) { +func bitwiseMerkleizeArrays(hasher HashFn, chunks [][32]byte, count uint64, limit uint64) ([32]byte, error) { if count > limit { return [32]byte{}, errors.New("merkleizing list that is too large, over limit") } - hashFn := NewHasherFunc(hashutil.CustomSHA256Hasher()) + hashFn := NewHasherFunc(hasher) leafIndexer := func(i uint64) []byte { return chunks[i][:] } diff --git a/beacon-chain/state/stateutil/state_root.go b/beacon-chain/state/stateutil/state_root.go index 124d8a717e64..244b9d4005f8 100644 --- a/beacon-chain/state/stateutil/state_root.go +++ b/beacon-chain/state/stateutil/state_root.go @@ -10,6 +10,7 @@ import ( pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" "github.com/prysmaticlabs/prysm/shared/bytesutil" "github.com/prysmaticlabs/prysm/shared/featureconfig" + "github.com/prysmaticlabs/prysm/shared/hashutil" "github.com/prysmaticlabs/prysm/shared/params" ) @@ -70,13 +71,14 @@ func (h *stateRootHasher) hashTreeRootState(state *pb.BeaconState) ([32]byte, er return [32]byte{}, err } } - return bitwiseMerkleize(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + return bitwiseMerkleize(hashutil.CustomSHA256Hasher(), fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) } func (h *stateRootHasher) computeFieldRoots(state *pb.BeaconState) ([][]byte, error) { if state == nil { return nil, errors.New("nil state") } + hasher := hashutil.CustomSHA256Hasher() // There are 20 fields in the beacon state. fieldRoots := make([][]byte, 20) @@ -124,7 +126,7 @@ func (h *stateRootHasher) computeFieldRoots(state *pb.BeaconState) ([][]byte, er fieldRoots[6] = historicalRootsRt[:] // Eth1Data data structure root. - eth1HashTreeRoot, err := Eth1Root(state.Eth1Data) + eth1HashTreeRoot, err := Eth1Root(hasher, state.Eth1Data) if err != nil { return nil, errors.Wrap(err, "could not compute eth1data merkleization") } @@ -190,21 +192,21 @@ func (h *stateRootHasher) computeFieldRoots(state *pb.BeaconState) ([][]byte, er fieldRoots[16] = justifiedBitsRoot[:] // PreviousJustifiedCheckpoint data structure root. - prevCheckRoot, err := CheckpointRoot(state.PreviousJustifiedCheckpoint) + prevCheckRoot, err := CheckpointRoot(hasher, state.PreviousJustifiedCheckpoint) if err != nil { return nil, errors.Wrap(err, "could not compute previous justified checkpoint merkleization") } fieldRoots[17] = prevCheckRoot[:] // CurrentJustifiedCheckpoint data structure root. - currJustRoot, err := CheckpointRoot(state.CurrentJustifiedCheckpoint) + currJustRoot, err := CheckpointRoot(hasher, state.CurrentJustifiedCheckpoint) if err != nil { return nil, errors.Wrap(err, "could not compute current justified checkpoint merkleization") } fieldRoots[18] = currJustRoot[:] // FinalizedCheckpoint data structure root. - finalRoot, err := CheckpointRoot(state.FinalizedCheckpoint) + finalRoot, err := CheckpointRoot(hasher, state.FinalizedCheckpoint) if err != nil { return nil, errors.Wrap(err, "could not compute finalized checkpoint merkleization") } @@ -237,13 +239,13 @@ func ForkRoot(fork *pb.Fork) ([32]byte, error) { epochRoot := bytesutil.ToBytes32(forkEpochBuf) fieldRoots[2] = epochRoot[:] } - return bitwiseMerkleize(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + return bitwiseMerkleize(hashutil.CustomSHA256Hasher(), fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) } // CheckpointRoot computes the HashTreeRoot Merkleization of // a Checkpoint struct value according to the eth2 // Simple Serialize specification. -func CheckpointRoot(checkpoint *ethpb.Checkpoint) ([32]byte, error) { +func CheckpointRoot(hasher HashFn, checkpoint *ethpb.Checkpoint) ([32]byte, error) { fieldRoots := make([][]byte, 2) if checkpoint != nil { epochBuf := make([]byte, 8) @@ -253,14 +255,14 @@ func CheckpointRoot(checkpoint *ethpb.Checkpoint) ([32]byte, error) { ckpRoot := bytesutil.ToBytes32(checkpoint.Root) fieldRoots[1] = ckpRoot[:] } - return bitwiseMerkleize(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + return bitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) } // HistoricalRootsRoot computes the HashTreeRoot Merkleization of // a list of [32]byte historical block roots according to the eth2 // Simple Serialize specification. func HistoricalRootsRoot(historicalRoots [][]byte) ([32]byte, error) { - result, err := bitwiseMerkleize(historicalRoots, uint64(len(historicalRoots)), params.BeaconConfig().HistoricalRootsLimit) + result, err := bitwiseMerkleize(hashutil.CustomSHA256Hasher(), historicalRoots, uint64(len(historicalRoots)), params.BeaconConfig().HistoricalRootsLimit) if err != nil { return [32]byte{}, errors.Wrap(err, "could not compute historical roots merkleization") } @@ -289,5 +291,5 @@ func SlashingsRoot(slashings []uint64) ([32]byte, error) { if err != nil { return [32]byte{}, errors.Wrap(err, "could not pack slashings into chunks") } - return bitwiseMerkleize(slashingChunks, uint64(len(slashingChunks)), uint64(len(slashingChunks))) + return bitwiseMerkleize(hashutil.CustomSHA256Hasher(), slashingChunks, uint64(len(slashingChunks)), uint64(len(slashingChunks))) } diff --git a/beacon-chain/state/stateutil/trie_helpers_test.go b/beacon-chain/state/stateutil/trie_helpers_test.go index 14d199b762c6..888f48c8ebb7 100644 --- a/beacon-chain/state/stateutil/trie_helpers_test.go +++ b/beacon-chain/state/stateutil/trie_helpers_test.go @@ -3,6 +3,8 @@ package stateutil_test import ( "testing" + "github.com/prysmaticlabs/prysm/shared/hashutil" + ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/shared/bytesutil" @@ -34,10 +36,11 @@ func TestReturnTrieLayerVariable_OK(t *testing.T) { if err != nil { t.Fatal(err) } + hasher := hashutil.CustomSHA256Hasher() validators := newState.Validators() roots := make([][32]byte, 0, len(validators)) for _, val := range validators { - rt, err := stateutil.ValidatorRoot(val) + rt, err := stateutil.ValidatorRoot(hasher, val) if err != nil { t.Fatal(err) } @@ -84,9 +87,10 @@ func TestRecomputeFromLayer_FixedSizedArray(t *testing.T) { func TestRecomputeFromLayer_VariableSizedArray(t *testing.T) { newState, _ := testutil.DeterministicGenesisState(t, 32) validators := newState.Validators() + hasher := hashutil.CustomSHA256Hasher() roots := make([][32]byte, 0, len(validators)) for _, val := range validators { - rt, err := stateutil.ValidatorRoot(val) + rt, err := stateutil.ValidatorRoot(hasher, val) if err != nil { t.Fatal(err) } @@ -119,7 +123,7 @@ func TestRecomputeFromLayer_VariableSizedArray(t *testing.T) { } roots = make([][32]byte, 0, len(changedVals)) for _, val := range changedVals { - rt, err := stateutil.ValidatorRoot(val) + rt, err := stateutil.ValidatorRoot(hasher, val) if err != nil { t.Fatal(err) } diff --git a/beacon-chain/state/stateutil/validators.go b/beacon-chain/state/stateutil/validators.go index fa9ecad15fd3..560b3ebbbc29 100644 --- a/beacon-chain/state/stateutil/validators.go +++ b/beacon-chain/state/stateutil/validators.go @@ -26,6 +26,7 @@ func ValidatorRegistryRoot(vals []*ethpb.Validator) ([32]byte, error) { // a list of validator uint64 balances according to the eth2 // Simple Serialize specification. func ValidatorBalancesRoot(balances []uint64) ([32]byte, error) { + hasher := hashutil.CustomSHA256Hasher() balancesMarshaling := make([][]byte, 0) for i := 0; i < len(balances); i++ { balanceBuf := make([]byte, 8) @@ -46,7 +47,7 @@ func ValidatorBalancesRoot(balances []uint64) ([32]byte, error) { balLimit = uint64(len(balances)) } } - balancesRootsRoot, err := bitwiseMerkleize(balancesChunks, uint64(len(balancesChunks)), balLimit) + balancesRootsRoot, err := bitwiseMerkleize(hasher, balancesChunks, uint64(len(balancesChunks)), balLimit) if err != nil { return [32]byte{}, errors.Wrap(err, "could not compute balances merkleization") } @@ -61,7 +62,7 @@ func ValidatorBalancesRoot(balances []uint64) ([32]byte, error) { // ValidatorRoot describes a method from which the hash tree root // of a validator is returned. -func ValidatorRoot(validator *ethpb.Validator) ([32]byte, error) { +func ValidatorRoot(hasher HashFn, validator *ethpb.Validator) ([32]byte, error) { fieldRoots := [][32]byte{} if validator != nil { pubkey := bytesutil.ToBytes48(validator.PublicKey) @@ -92,23 +93,24 @@ func ValidatorRoot(validator *ethpb.Validator) ([32]byte, error) { if err != nil { return [32]byte{}, err } - pubKeyRoot, err := bitwiseMerkleize(pubKeyChunks, uint64(len(pubKeyChunks)), uint64(len(pubKeyChunks))) + pubKeyRoot, err := bitwiseMerkleize(hasher, pubKeyChunks, uint64(len(pubKeyChunks)), uint64(len(pubKeyChunks))) if err != nil { return [32]byte{}, err } fieldRoots = [][32]byte{pubKeyRoot, withdrawCreds, effectiveBalanceBuf, slashBuf, activationEligibilityBuf, activationBuf, exitBuf, withdrawalBuf} } - return bitwiseMerkleizeArrays(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + return bitwiseMerkleizeArrays(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) } func (h *stateRootHasher) validatorRegistryRoot(validators []*ethpb.Validator) ([32]byte, error) { hashKeyElements := make([]byte, len(validators)*32) roots := make([][32]byte, len(validators)) emptyKey := hashutil.FastSum256(hashKeyElements) + hasher := hashutil.CustomSHA256Hasher() bytesProcessed := 0 for i := 0; i < len(validators); i++ { - val, err := h.validatorRoot(validators[i]) + val, err := h.validatorRoot(hasher, validators[i]) if err != nil { return [32]byte{}, errors.Wrap(err, "could not compute validators merkleization") } @@ -124,7 +126,7 @@ func (h *stateRootHasher) validatorRegistryRoot(validators []*ethpb.Validator) ( } } - validatorsRootsRoot, err := bitwiseMerkleizeArrays(roots, uint64(len(roots)), params.BeaconConfig().ValidatorRegistryLimit) + validatorsRootsRoot, err := bitwiseMerkleizeArrays(hasher, roots, uint64(len(roots)), params.BeaconConfig().ValidatorRegistryLimit) if err != nil { return [32]byte{}, errors.Wrap(err, "could not compute validator registry merkleization") } @@ -142,7 +144,7 @@ func (h *stateRootHasher) validatorRegistryRoot(validators []*ethpb.Validator) ( return res, nil } -func (h *stateRootHasher) validatorRoot(validator *ethpb.Validator) ([32]byte, error) { +func (h *stateRootHasher) validatorRoot(hasher HashFn, validator *ethpb.Validator) ([32]byte, error) { // Validator marshaling for caching. enc := make([]byte, 122) fieldRoots := make([][32]byte, 2, 8) @@ -188,7 +190,7 @@ func (h *stateRootHasher) validatorRoot(validator *ethpb.Validator) ([32]byte, e if err != nil { return [32]byte{}, err } - pubKeyRoot, err := bitwiseMerkleize(pubKeyChunks, uint64(len(pubKeyChunks)), uint64(len(pubKeyChunks))) + pubKeyRoot, err := bitwiseMerkleize(hasher, pubKeyChunks, uint64(len(pubKeyChunks)), uint64(len(pubKeyChunks))) if err != nil { return [32]byte{}, err } @@ -222,7 +224,7 @@ func (h *stateRootHasher) validatorRoot(validator *ethpb.Validator) ([32]byte, e fieldRoots = append(fieldRoots, withdrawalBuf) } - valRoot, err := bitwiseMerkleizeArrays(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) + valRoot, err := bitwiseMerkleizeArrays(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) if err != nil { return [32]byte{}, err }