diff --git a/beacon-chain/core/epoch/epoch_processing_test.go b/beacon-chain/core/epoch/epoch_processing_test.go index 84108a65ea..0aa5109a46 100644 --- a/beacon-chain/core/epoch/epoch_processing_test.go +++ b/beacon-chain/core/epoch/epoch_processing_test.go @@ -525,8 +525,9 @@ func TestProcessHistoricalDataUpdate(t *testing.T) { StateSummaryRoot: sr[:], } require.DeepEqual(t, b, summaries[0]) - _, err = st.HistoricalRoots() - require.ErrorContains(t, "HistoricalRoots is not supported for capella", err) + hrs, err := st.HistoricalRoots() + require.NoError(t, err) + require.DeepEqual(t, hrs, [][]byte{}) }, }, } diff --git a/beacon-chain/state/state-native/getters_misc.go b/beacon-chain/state/state-native/getters_misc.go index e1a0872711..310256b030 100644 --- a/beacon-chain/state/state-native/getters_misc.go +++ b/beacon-chain/state/state-native/getters_misc.go @@ -69,10 +69,6 @@ func (b *BeaconState) forkVal() *ethpb.Fork { // HistoricalRoots based on epochs stored in the beacon state. func (b *BeaconState) HistoricalRoots() ([][]byte, error) { - if b.version > version.Bellatrix { - return nil, errNotSupported("HistoricalRoots", b.version) - } - if b.historicalRoots == nil { return nil, nil } diff --git a/beacon-chain/state/state-native/hasher.go b/beacon-chain/state/state-native/hasher.go index c1879b7611..11efe56501 100644 --- a/beacon-chain/state/state-native/hasher.go +++ b/beacon-chain/state/state-native/hasher.go @@ -1,10 +1,8 @@ package state_native import ( - "bytes" "context" "encoding/binary" - "fmt" "github.com/pkg/errors" nativetypes "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native/types" @@ -14,7 +12,6 @@ import ( "github.com/prysmaticlabs/prysm/v3/crypto/hash" "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v3/encoding/ssz" - ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v3/runtime/version" "go.opencensus.io/trace" ) @@ -260,7 +257,7 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b fieldRoots[nativetypes.NextWithdrawalValidatorIndex.RealPosition()] = nextWithdrawalValidatorIndexRoot // Historical summary root. - historicalSummaryRoot, err := historicalSummaryRoot(state.historicalSummaries) + historicalSummaryRoot, err := stateutil.HistoricalSummariesRoot(state.historicalSummaries) if err != nil { return nil, errors.Wrap(err, "could not compute historical summary merkleization") } @@ -269,39 +266,3 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b return fieldRoots, nil } - -func historicalSummaryRoot(summaries []*ethpb.HistoricalSummary) ([32]byte, error) { - max := uint64(fieldparams.HistoricalRootsLength) - if uint64(len(summaries)) > max { - return [32]byte{}, fmt.Errorf("historical summary exceeds max length %d", max) - } - - hasher := hash.CustomSHA256Hasher() - roots := make([][32]byte, len(summaries)) - for i := 0; i < len(summaries); i++ { - r, err := summaries[i].HashTreeRoot() - if err != nil { - return [32]byte{}, errors.Wrap(err, "could not merkleize historical summary") - } - roots[i] = r - } - - summariesRoot, err := ssz.BitwiseMerkleize( - hasher, - roots, - uint64(len(roots)), - fieldparams.HistoricalRootsLength, - ) - if err != nil { - return [32]byte{}, errors.Wrap(err, "could not compute historical summaries merkleization") - } - summariesLenBuf := new(bytes.Buffer) - if err := binary.Write(summariesLenBuf, binary.LittleEndian, uint64(len(summaries))); err != nil { - return [32]byte{}, errors.Wrap(err, "could not marshal historical summary length") - } - // We need to mix in the length of the slice. - summariesLenRoot := make([]byte, 32) - copy(summariesLenRoot, summariesLenBuf.Bytes()) - res := ssz.MixInLength(summariesRoot, summariesLenRoot) - return res, nil -} diff --git a/beacon-chain/state/state-native/state_trie.go b/beacon-chain/state/state-native/state_trie.go index 175a1dbcea..d2b434c1a0 100644 --- a/beacon-chain/state/state-native/state_trie.go +++ b/beacon-chain/state/state-native/state_trie.go @@ -515,6 +515,7 @@ func (b *BeaconState) Copy() state.BeaconState { // Large arrays, increases over time. balances: b.balances, historicalRoots: b.historicalRoots, + historicalSummaries: b.historicalSummaries, validators: b.validators, previousEpochParticipation: b.previousEpochParticipation, currentEpochParticipation: b.currentEpochParticipation, @@ -533,7 +534,6 @@ func (b *BeaconState) Copy() state.BeaconState { nextSyncCommittee: b.nextSyncCommitteeVal(), latestExecutionPayloadHeader: b.latestExecutionPayloadHeaderVal(), latestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapellaVal(), - historicalSummaries: b.historicalSummariesVal(), dirtyFields: make(map[nativetypes.FieldIndex]bool, fieldCount), dirtyIndices: make(map[nativetypes.FieldIndex][]uint64, fieldCount), @@ -838,7 +838,7 @@ func (b *BeaconState) rootSelector(ctx context.Context, field nativetypes.FieldI case nativetypes.NextWithdrawalValidatorIndex: return ssz.Uint64Root(uint64(b.nextWithdrawalValidatorIndex)), nil case nativetypes.HistoricalSummaries: - return historicalSummaryRoot(b.historicalSummaries) + return stateutil.HistoricalSummariesRoot(b.historicalSummaries) } 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 b006d2f33a..317840a451 100644 --- a/beacon-chain/state/stateutil/BUILD.bazel +++ b/beacon-chain/state/stateutil/BUILD.bazel @@ -9,6 +9,7 @@ go_library( "field_root_eth1.go", "field_root_validator.go", "field_root_vector.go", + "historical_summaries_root.go", "participation_bit_root.go", "pending_attestation_root.go", "reference.go", diff --git a/beacon-chain/state/stateutil/historical_summaries_root.go b/beacon-chain/state/stateutil/historical_summaries_root.go new file mode 100644 index 0000000000..2934d030f5 --- /dev/null +++ b/beacon-chain/state/stateutil/historical_summaries_root.go @@ -0,0 +1,49 @@ +package stateutil + +import ( + "bytes" + "encoding/binary" + "fmt" + + "github.com/pkg/errors" + fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams" + "github.com/prysmaticlabs/prysm/v3/crypto/hash" + "github.com/prysmaticlabs/prysm/v3/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" +) + +func HistoricalSummariesRoot(summaries []*ethpb.HistoricalSummary) ([32]byte, error) { + max := uint64(fieldparams.HistoricalRootsLength) + if uint64(len(summaries)) > max { + return [32]byte{}, fmt.Errorf("historical summary exceeds max length %d", max) + } + + hasher := hash.CustomSHA256Hasher() + roots := make([][32]byte, len(summaries)) + for i := 0; i < len(summaries); i++ { + r, err := summaries[i].HashTreeRoot() + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not merkleize historical summary") + } + roots[i] = r + } + + summariesRoot, err := ssz.BitwiseMerkleize( + hasher, + roots, + uint64(len(roots)), + fieldparams.HistoricalRootsLength, + ) + if err != nil { + return [32]byte{}, errors.Wrap(err, "could not compute historical summaries merkleization") + } + summariesLenBuf := new(bytes.Buffer) + if err := binary.Write(summariesLenBuf, binary.LittleEndian, uint64(len(summaries))); err != nil { + return [32]byte{}, errors.Wrap(err, "could not marshal historical summary length") + } + // We need to mix in the length of the slice. + summariesLenRoot := make([]byte, 32) + copy(summariesLenRoot, summariesLenBuf.Bytes()) + res := ssz.MixInLength(summariesRoot, summariesLenRoot) + return res, nil +}