Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

State: refactor common root functions #8630

Merged
merged 4 commits into from
Mar 18, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion beacon-chain/state/stateV0/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -7,7 +7,6 @@ go_library(
"cloners.go",
"doc.go",
"field_root_attestation.go",
"field_root_block_header.go",
"field_root_eth1.go",
"field_root_validator.go",
"field_root_vector.go",
160 changes: 10 additions & 150 deletions beacon-chain/state/stateV0/field_root_attestation.go
Original file line number Diff line number Diff line change
@@ -5,9 +5,8 @@ import (
"encoding/binary"

"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"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/htrutils"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -45,55 +44,20 @@ func (h *stateRootHasher) epochAttestationsRoot(atts []*pb.PendingAttestation) (
}

func (h *stateRootHasher) pendingAttestationRoot(hasher htrutils.HashFn, att *pb.PendingAttestation) ([32]byte, error) {
if att == nil {
return [32]byte{}, errors.New("nil pending attestation")
}
// Marshal attestation to determine if it exists in the cache.
enc := make([]byte, 2192)
fieldRoots := make([][]byte, 4)

if att != nil {
copy(enc[0:2048], att.AggregationBits)

inclusionBuf := make([]byte, 8)
binary.LittleEndian.PutUint64(inclusionBuf, uint64(att.InclusionDelay))
copy(enc[2048:2056], inclusionBuf)

attDataBuf := marshalAttestationData(att.Data)
copy(enc[2056:2184], attDataBuf)

proposerBuf := make([]byte, 8)
binary.LittleEndian.PutUint64(proposerBuf, uint64(att.ProposerIndex))
copy(enc[2184:2192], proposerBuf)

// Check if it exists in cache:
if h.rootsCache != nil {
if found, ok := h.rootsCache.Get(string(enc)); found != nil && ok {
return found.([32]byte), nil
}
}

// Bitfield.
aggregationRoot, err := htrutils.BitlistRoot(hasher, att.AggregationBits, 2048)
if err != nil {
return [32]byte{}, err
}
fieldRoots[0] = aggregationRoot[:]
enc := stateutil.PendingAttEncKey(att)

// Attestation data.
attDataRoot, err := attestationDataRoot(hasher, att.Data)
if err != nil {
return [32]byte{}, err
// Check if it exists in cache:
if h.rootsCache != nil {
if found, ok := h.rootsCache.Get(string(enc)); found != nil && ok {
return found.([32]byte), nil
}
fieldRoots[1] = attDataRoot[:]

// Inclusion delay.
inclusionRoot := bytesutil.ToBytes32(inclusionBuf)
fieldRoots[2] = inclusionRoot[:]

// Proposer index.
proposerRoot := bytesutil.ToBytes32(proposerBuf)
fieldRoots[3] = proposerRoot[:]
}

res, err := htrutils.BitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots)))
res, err := stateutil.PendingAttRootWithHasher(hasher, att)
if err != nil {
return [32]byte{}, err
}
@@ -102,107 +66,3 @@ func (h *stateRootHasher) pendingAttestationRoot(hasher htrutils.HashFn, att *pb
}
return res, nil
}

func marshalAttestationData(data *ethpb.AttestationData) []byte {
enc := make([]byte, 128)

if data != nil {
// Slot.
slotBuf := make([]byte, 8)
binary.LittleEndian.PutUint64(slotBuf, uint64(data.Slot))
copy(enc[0:8], slotBuf)

// Committee index.
indexBuf := make([]byte, 8)
binary.LittleEndian.PutUint64(indexBuf, uint64(data.CommitteeIndex))
copy(enc[8:16], indexBuf)

copy(enc[16:48], data.BeaconBlockRoot)

// Source epoch and root.
if data.Source != nil {
sourceEpochBuf := make([]byte, 8)
binary.LittleEndian.PutUint64(sourceEpochBuf, uint64(data.Source.Epoch))
copy(enc[48:56], sourceEpochBuf)
copy(enc[56:88], data.Source.Root)
}

// Target.
if data.Target != nil {
targetEpochBuf := make([]byte, 8)
binary.LittleEndian.PutUint64(targetEpochBuf, uint64(data.Target.Epoch))
copy(enc[88:96], targetEpochBuf)
copy(enc[96:128], data.Target.Root)
}
}

return enc
}

func attestationDataRoot(hasher htrutils.HashFn, data *ethpb.AttestationData) ([32]byte, error) {
fieldRoots := make([][]byte, 5)

if data != nil {
// Slot.
slotBuf := make([]byte, 8)
binary.LittleEndian.PutUint64(slotBuf, uint64(data.Slot))
slotRoot := bytesutil.ToBytes32(slotBuf)
fieldRoots[0] = slotRoot[:]

// CommitteeIndex.
indexBuf := make([]byte, 8)
binary.LittleEndian.PutUint64(indexBuf, uint64(data.CommitteeIndex))
interRoot := bytesutil.ToBytes32(indexBuf)
fieldRoots[1] = interRoot[:]

// Beacon block root.
blockRoot := bytesutil.ToBytes32(data.BeaconBlockRoot)
fieldRoots[2] = blockRoot[:]

// Source
sourceRoot, err := htrutils.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 := htrutils.CheckpointRoot(hasher, data.Target)
if err != nil {
return [32]byte{}, errors.Wrap(err, "could not compute target checkpoint merkleization")
}
fieldRoots[4] = targetRoot[:]
}

return htrutils.BitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots)))
}

// pendingAttestationRoot describes a method from which the hash tree root
// of a pending attestation is returned.
func pendingAttestationRoot(hasher htrutils.HashFn, att *pb.PendingAttestation) ([32]byte, error) {
var fieldRoots [][32]byte
if att != nil {
// Bitfield.
aggregationRoot, err := htrutils.BitlistRoot(hasher, att.AggregationBits, params.BeaconConfig().MaxValidatorsPerCommittee)
if err != nil {
return [32]byte{}, err
}
// Attestation data.
attDataRoot, err := attestationDataRoot(hasher, att.Data)
if err != nil {
return [32]byte{}, err
}
inclusionBuf := make([]byte, 8)
binary.LittleEndian.PutUint64(inclusionBuf, uint64(att.InclusionDelay))
// Inclusion delay.
inclusionRoot := bytesutil.ToBytes32(inclusionBuf)

proposerBuf := make([]byte, 8)
binary.LittleEndian.PutUint64(proposerBuf, uint64(att.ProposerIndex))
// Proposer index.
proposerRoot := bytesutil.ToBytes32(proposerBuf)

fieldRoots = [][32]byte{aggregationRoot, attDataRoot, inclusionRoot, proposerRoot}
}
return htrutils.BitwiseMerkleizeArrays(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots)))
}
78 changes: 17 additions & 61 deletions beacon-chain/state/stateV0/field_root_eth1.go
Original file line number Diff line number Diff line change
@@ -1,53 +1,33 @@
package stateV0

import (
"bytes"
"encoding/binary"

"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/htrutils"
"github.com/prysmaticlabs/prysm/shared/params"
)

// eth1Root computes the HashTreeRoot Merkleization of
// a BeaconBlockHeader struct according to the eth2
// Simple Serialize specification.
func eth1Root(hasher htrutils.HashFn, eth1Data *ethpb.Eth1Data) ([32]byte, error) {
enc := make([]byte, 0, 96)
fieldRoots := make([][]byte, 3)
for i := 0; i < len(fieldRoots); i++ {
fieldRoots[i] = make([]byte, 32)
if eth1Data == nil {
return [32]byte{}, errors.New("nil eth1 data")
}
if eth1Data != nil {
if len(eth1Data.DepositRoot) > 0 {
depRoot := bytesutil.ToBytes32(eth1Data.DepositRoot)
fieldRoots[0] = depRoot[:]
enc = append(enc, depRoot[:]...)
}
eth1DataCountBuf := make([]byte, 8)
binary.LittleEndian.PutUint64(eth1DataCountBuf, eth1Data.DepositCount)
eth1CountRoot := bytesutil.ToBytes32(eth1DataCountBuf)
fieldRoots[1] = eth1CountRoot[:]
enc = append(enc, eth1CountRoot[:]...)
if len(eth1Data.BlockHash) > 0 {
blockHash := bytesutil.ToBytes32(eth1Data.BlockHash)
fieldRoots[2] = blockHash[:]
enc = append(enc, blockHash[:]...)
}
if featureconfig.Get().EnableSSZCache {
if found, ok := cachedHasher.rootsCache.Get(string(enc)); ok && found != nil {
return found.([32]byte), nil
}

enc := stateutil.Eth1DataEncKey(eth1Data)
if featureconfig.Get().EnableSSZCache {
if found, ok := cachedHasher.rootsCache.Get(string(enc)); ok && found != nil {
return found.([32]byte), nil
}
}
root, err := htrutils.BitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots)))

root, err := stateutil.Eth1DataRootWithHasher(hasher, eth1Data)
if err != nil {
return [32]byte{}, err
}

if featureconfig.Get().EnableSSZCache {
cachedHasher.rootsCache.Set(string(enc), root, 32)
}
@@ -58,44 +38,20 @@ func eth1Root(hasher htrutils.HashFn, eth1Data *ethpb.Eth1Data) ([32]byte, error
// a list of Eth1Data structs according to the eth2
// Simple Serialize specification.
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(hasher, eth1DataVotes[i])
if err != nil {
return [32]byte{}, errors.Wrap(err, "could not compute eth1data merkleization")
}
copy(enc[(i*32):(i+1)*32], eth1[:])
eth1VotesRoots = append(eth1VotesRoots, eth1[:])
hashKey, err := stateutil.Eth1DatasEncKey(eth1DataVotes)
if err != nil {
return [32]byte{}, err
}
hashKey := hashutil.FastSum256(enc)

if featureconfig.Get().EnableSSZCache {
if found, ok := cachedHasher.rootsCache.Get(string(hashKey[:])); ok && found != nil {
return found.([32]byte), nil
}
}
eth1Chunks, err := htrutils.Pack(eth1VotesRoots)
root, err := stateutil.Eth1DatasRoot(eth1DataVotes)
if err != nil {
return [32]byte{}, errors.Wrap(err, "could not chunk eth1 votes roots")
}
eth1VotesRootsRoot, err := htrutils.BitwiseMerkleize(
hasher,
eth1Chunks,
uint64(len(eth1Chunks)),
uint64(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod))),
)
if err != nil {
return [32]byte{}, errors.Wrap(err, "could not compute eth1data votes merkleization")
}
eth1VotesRootBuf := new(bytes.Buffer)
if err := binary.Write(eth1VotesRootBuf, binary.LittleEndian, uint64(len(eth1DataVotes))); err != nil {
return [32]byte{}, errors.Wrap(err, "could not marshal eth1data votes length")
return [32]byte{}, err
}
// We need to mix in the length of the slice.
eth1VotesRootBufRoot := make([]byte, 32)
copy(eth1VotesRootBufRoot, eth1VotesRootBuf.Bytes())
root := htrutils.MixInLength(eth1VotesRootsRoot, eth1VotesRootBufRoot)
if featureconfig.Get().EnableSSZCache {
cachedHasher.rootsCache.Set(string(hashKey[:]), root, 32)
}
Loading