From 8dda3614e63aca6a6c266bdca3c8c50a1e9f5da8 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Mon, 23 Jan 2023 14:26:57 +0100 Subject: [PATCH] Added beacon state capella support (#6673) --- cl/cltypes/beacon_block.go | 3 -- cl/cltypes/historical_summary.go | 4 +++ cmd/erigon-cl/core/state/getters.go | 12 +++++++ cmd/erigon-cl/core/state/params.go | 6 ++-- cmd/erigon-cl/core/state/root.go | 27 +++++++++++++++ cmd/erigon-cl/core/state/setters.go | 12 +++++++ cmd/erigon-cl/core/state/ssz.go | 52 +++++++++++++++++++++++---- cmd/erigon-cl/core/state/state.go | 54 ++++++++++++++++------------- 8 files changed, 133 insertions(+), 37 deletions(-) diff --git a/cl/cltypes/beacon_block.go b/cl/cltypes/beacon_block.go index 00a80b15270..e778860be87 100644 --- a/cl/cltypes/beacon_block.go +++ b/cl/cltypes/beacon_block.go @@ -357,15 +357,12 @@ func (b *BeaconBody) DecodeSSZ(buf []byte, version clparams.StateVersion) error if offsetExecution > uint32(endOffset) || len(buf) < endOffset { return ssz_utils.ErrBadOffset } - fmt.Println(len(buf[offsetExecution:endOffset])) if err := b.ExecutionPayload.DecodeSSZ(buf[offsetExecution:endOffset], b.Version); err != nil { return err } } if b.Version >= clparams.CapellaVersion { - fmt.Println(blsChangesOffset) - fmt.Println(uint32(len(buf))) if b.ExecutionChanges, err = ssz_utils.DecodeStaticList[*SignedBLSToExecutionChange](buf, blsChangesOffset, uint32(len(buf)), 172, MaxExecutionChanges); err != nil { return err } diff --git a/cl/cltypes/historical_summary.go b/cl/cltypes/historical_summary.go index 32827601032..47f5e5fee93 100644 --- a/cl/cltypes/historical_summary.go +++ b/cl/cltypes/historical_summary.go @@ -25,6 +25,10 @@ func (h *HistoricalSummary) DecodeSSZ(buf []byte) error { return nil } +func (h *HistoricalSummary) DecodeSSZWithVersion(buf []byte, _ int) error { + return h.DecodeSSZ(buf) +} + func (h *HistoricalSummary) HashSSZ() ([32]byte, error) { return merkle_tree.ArraysRoot([][32]byte{h.BlockSummaryRoot, h.StateSummaryRoot}, 2) } diff --git a/cmd/erigon-cl/core/state/getters.go b/cmd/erigon-cl/core/state/getters.go index e2391fc4509..aa113531880 100644 --- a/cmd/erigon-cl/core/state/getters.go +++ b/cmd/erigon-cl/core/state/getters.go @@ -112,3 +112,15 @@ func (b *BeaconState) NextSyncCommittee() *cltypes.SyncCommittee { func (b *BeaconState) LatestExecutionPayloadHeader() *types.Header { return b.latestExecutionPayloadHeader } + +func (b *BeaconState) NextWithdrawalIndex() uint64 { + return b.nextWithdrawalIndex +} + +func (b *BeaconState) NextWithdrawalValidatorIndex() uint64 { + return b.nextWithdrawalValidatorIndex +} + +func (b *BeaconState) HistoricalSummaries() []*cltypes.HistoricalSummary { + return b.historicalSummaries +} diff --git a/cmd/erigon-cl/core/state/params.go b/cmd/erigon-cl/core/state/params.go index 5ca17d0402f..05dae884ba0 100644 --- a/cmd/erigon-cl/core/state/params.go +++ b/cmd/erigon-cl/core/state/params.go @@ -29,7 +29,7 @@ const ( CurrentSyncCommitteeLeafIndex StateLeafIndex = 22 NextSyncCommitteeLeafIndex StateLeafIndex = 23 LatestExecutionPayloadHeaderLeafIndex StateLeafIndex = 24 - - // Leaves sizes - BellatrixLeavesSize = 25 + NextWithdrawalIndexLeafIndex StateLeafIndex = 25 + NextWithdrawalValidatorIndexLeafIndex StateLeafIndex = 26 + HistoricalSummariesLeafIndex StateLeafIndex = 27 ) diff --git a/cmd/erigon-cl/core/state/root.go b/cmd/erigon-cl/core/state/root.go index 35f04558a5d..a2e2cc783b8 100644 --- a/cmd/erigon-cl/core/state/root.go +++ b/cmd/erigon-cl/core/state/root.go @@ -3,6 +3,7 @@ package state import ( libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/cl/merkle_tree" "github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state/state_encoding" ) @@ -216,6 +217,9 @@ func (b *BeaconState) computeDirtyLeaves() error { b.updateLeaf(NextSyncCommitteeLeafIndex, committeeRoot) } + if b.version < clparams.BellatrixVersion { + return nil + } // Field(24): LatestExecutionPayloadHeader if b.isLeafDirty(LatestExecutionPayloadHeaderLeafIndex) { headerRoot, err := b.latestExecutionPayloadHeader.HashSSZ() @@ -224,6 +228,29 @@ func (b *BeaconState) computeDirtyLeaves() error { } b.updateLeaf(LatestExecutionPayloadHeaderLeafIndex, headerRoot) } + + if b.version < clparams.CapellaVersion { + return nil + } + + // Field(25): NextWithdrawalIndex + if b.isLeafDirty(NextWithdrawalIndexLeafIndex) { + b.updateLeaf(NextWithdrawalIndexLeafIndex, merkle_tree.Uint64Root(b.nextWithdrawalIndex)) + } + + // Field(26): NextWithdrawalValidatorIndex + if b.isLeafDirty(NextWithdrawalValidatorIndexLeafIndex) { + b.updateLeaf(NextWithdrawalValidatorIndexLeafIndex, merkle_tree.Uint64Root(b.nextWithdrawalValidatorIndex)) + } + + // Field(27): HistoricalSummaries + if b.isLeafDirty(HistoricalSummariesLeafIndex) { + root, err := merkle_tree.ListObjectSSZRoot(b.historicalSummaries, state_encoding.HistoricalRootsLength) + if err != nil { + return err + } + b.updateLeaf(HistoricalSummariesLeafIndex, root) + } return nil } diff --git a/cmd/erigon-cl/core/state/setters.go b/cmd/erigon-cl/core/state/setters.go index c74caf8383e..49f630010a8 100644 --- a/cmd/erigon-cl/core/state/setters.go +++ b/cmd/erigon-cl/core/state/setters.go @@ -144,3 +144,15 @@ func (b *BeaconState) SetLatestExecutionPayloadHeader(header *types.Header) { b.touchedLeaves[LatestExecutionPayloadHeaderLeafIndex] = true b.latestExecutionPayloadHeader = header } + +func (b *BeaconState) SetNextWithdrawalIndex(index uint64) { + b.nextWithdrawalIndex = index +} + +func (b *BeaconState) SetNextWithdrawalValidatorIndex(index uint64) { + b.nextWithdrawalValidatorIndex = index +} + +func (b *BeaconState) AddHistoricalSummary(summary *cltypes.HistoricalSummary) { + b.historicalSummaries = append(b.historicalSummaries, summary) +} diff --git a/cmd/erigon-cl/core/state/ssz.go b/cmd/erigon-cl/core/state/ssz.go index 771638c8553..28aa26b4548 100644 --- a/cmd/erigon-cl/core/state/ssz.go +++ b/cmd/erigon-cl/core/state/ssz.go @@ -21,7 +21,7 @@ func (b *BeaconState) baseOffsetSSZ() uint32 { case clparams.BellatrixVersion: return 2736633 case clparams.CapellaVersion: - panic("not implemented") + return 2736653 default: // ????? panic("tf is that") @@ -38,6 +38,10 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) { return nil, fmt.Errorf("too many historical roots") } + if len(b.historicalSummaries) > state_encoding.HistoricalRootsLength { + return nil, fmt.Errorf("too many summaries") + } + if len(b.eth1DataVotes) > state_encoding.Eth1DataVotesRootsLimit { return nil, fmt.Errorf("too many votes") } @@ -144,10 +148,15 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) { // Offset (24) 'LatestExecutionPayloadHeader' dst = append(dst, ssz_utils.OffsetSSZ(offset)...) - /*if b.version >= clparams.BellatrixVersion { + if b.version >= clparams.BellatrixVersion { offset += uint32(b.latestExecutionPayloadHeader.EncodingSizeSSZ(b.version)) - } Will uncomment for Capella. - */ + } + + if b.version >= clparams.CapellaVersion { + dst = append(dst, ssz_utils.Uint64SSZ(b.nextWithdrawalIndex)...) + dst = append(dst, ssz_utils.Uint64SSZ(b.nextWithdrawalValidatorIndex)...) + dst = append(dst, ssz_utils.OffsetSSZ(offset)...) + } // Write historical roots (offset 1) for _, root := range b.historicalRoots { dst = append(dst, root[:]...) @@ -184,6 +193,14 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) { } } + if b.version >= clparams.CapellaVersion { + for _, summary := range b.historicalSummaries { + if dst, err = summary.EncodeSSZ(dst); err != nil { + return nil, err + } + } + } + return dst, nil } @@ -296,7 +313,16 @@ func (b *BeaconState) DecodeSSZWithVersion(buf []byte, version int) error { // Execution Payload header offset if b.version >= clparams.BellatrixVersion { executionPayloadOffset = ssz_utils.DecodeOffset(buf[pos:]) - // pos += 4 TODO: will uncomment in case + pos += 4 + } + var historicalSummariesOffset uint32 + if b.version >= clparams.CapellaVersion { + b.nextWithdrawalIndex = ssz_utils.UnmarshalUint64SSZ(buf[pos:]) + pos += 8 + b.nextWithdrawalValidatorIndex = ssz_utils.UnmarshalUint64SSZ(buf[pos:]) + pos += 8 + historicalSummariesOffset = ssz_utils.DecodeOffset(buf[pos:]) + // pos += 4 } // Now decode all the lists. var err error @@ -325,16 +351,27 @@ func (b *BeaconState) DecodeSSZWithVersion(buf []byte, version int) error { if b.inactivityScores, err = ssz_utils.DecodeNumbersList(buf, inactivityScoresOffset, endOffset, state_encoding.ValidatorRegistryLimit); err != nil { return err } - if b.version == clparams.AltairVersion { + if b.version <= clparams.AltairVersion { return nil } if len(buf) <= int(executionPayloadOffset) { return ssz_utils.ErrLowBufferSize } + endOffset = uint32(len(buf)) + if historicalSummariesOffset != 0 { + endOffset = historicalSummariesOffset + } b.latestExecutionPayloadHeader = new(types.Header) - if err := b.latestExecutionPayloadHeader.DecodeSSZ(buf[executionPayloadOffset:], b.version); err != nil { + if err := b.latestExecutionPayloadHeader.DecodeSSZ(buf[executionPayloadOffset:endOffset], b.version); err != nil { + return err + } + if b.version == clparams.BellatrixVersion { + return nil + } + if b.historicalSummaries, err = ssz_utils.DecodeStaticList[*cltypes.HistoricalSummary](buf, historicalSummariesOffset, uint32(len(buf)), 64, state_encoding.HistoricalRootsLength); err != nil { return err } + // Capella return nil } @@ -347,6 +384,7 @@ func (b *BeaconState) EncodingSizeSSZ() (size int) { size += len(b.previousEpochParticipation) size += len(b.currentEpochParticipation) size += len(b.inactivityScores) * 8 + size += len(b.historicalSummaries) * 64 return } diff --git a/cmd/erigon-cl/core/state/state.go b/cmd/erigon-cl/core/state/state.go index 0db8fe5a6d2..6c69ece67d2 100644 --- a/cmd/erigon-cl/core/state/state.go +++ b/cmd/erigon-cl/core/state/state.go @@ -19,31 +19,37 @@ const ( type BeaconState struct { // State fields - genesisTime uint64 - genesisValidatorsRoot libcommon.Hash - slot uint64 - fork *cltypes.Fork - latestBlockHeader *cltypes.BeaconBlockHeader - blockRoots [blockRootsLength]libcommon.Hash - stateRoots [stateRootsLength]libcommon.Hash - historicalRoots []libcommon.Hash - eth1Data *cltypes.Eth1Data - eth1DataVotes []*cltypes.Eth1Data - eth1DepositIndex uint64 - validators []*cltypes.Validator - balances []uint64 - randaoMixes [randoMixesLength]libcommon.Hash - slashings [slashingsLength]uint64 - previousEpochParticipation []byte - currentEpochParticipation []byte - justificationBits byte - previousJustifiedCheckpoint *cltypes.Checkpoint - currentJustifiedCheckpoint *cltypes.Checkpoint - finalizedCheckpoint *cltypes.Checkpoint - inactivityScores []uint64 - currentSyncCommittee *cltypes.SyncCommittee - nextSyncCommittee *cltypes.SyncCommittee + genesisTime uint64 + genesisValidatorsRoot libcommon.Hash + slot uint64 + fork *cltypes.Fork + latestBlockHeader *cltypes.BeaconBlockHeader + blockRoots [blockRootsLength]libcommon.Hash + stateRoots [stateRootsLength]libcommon.Hash + historicalRoots []libcommon.Hash + eth1Data *cltypes.Eth1Data + eth1DataVotes []*cltypes.Eth1Data + eth1DepositIndex uint64 + validators []*cltypes.Validator + balances []uint64 + randaoMixes [randoMixesLength]libcommon.Hash + slashings [slashingsLength]uint64 + previousEpochParticipation []byte + currentEpochParticipation []byte + justificationBits byte + // Altair + previousJustifiedCheckpoint *cltypes.Checkpoint + currentJustifiedCheckpoint *cltypes.Checkpoint + finalizedCheckpoint *cltypes.Checkpoint + inactivityScores []uint64 + currentSyncCommittee *cltypes.SyncCommittee + nextSyncCommittee *cltypes.SyncCommittee + // Bellatrix latestExecutionPayloadHeader *types.Header + // Capella + nextWithdrawalIndex uint64 + nextWithdrawalValidatorIndex uint64 + historicalSummaries []*cltypes.HistoricalSummary // Internals version clparams.StateVersion // State version leaves [32][32]byte // Pre-computed leaves.