diff --git a/cli/commands/genesis/genesis.go b/cli/commands/genesis/genesis.go index 5bbfa517f5..673b807d5b 100644 --- a/cli/commands/genesis/genesis.go +++ b/cli/commands/genesis/genesis.go @@ -44,7 +44,7 @@ func Commands( cmd.AddCommand( AddGenesisDepositCmd(csc), CollectGenesisDepositsCmd(), - AddExecutionPayloadCmd(csc), + AddExecutionPayloadCmd(), GetGenesisValidatorRootCmd(csc), SetDepositStorageCmd(csc), ) diff --git a/cli/commands/genesis/payload.go b/cli/commands/genesis/payload.go index 3f09aee793..192d48653f 100644 --- a/cli/commands/genesis/payload.go +++ b/cli/commands/genesis/payload.go @@ -24,7 +24,6 @@ import ( "fmt" "unsafe" - servertypes "github.com/berachain/beacon-kit/cli/commands/server/types" "github.com/berachain/beacon-kit/cli/context" "github.com/berachain/beacon-kit/consensus-types/types" engineprimitives "github.com/berachain/beacon-kit/engine-primitives/engine-primitives" @@ -34,7 +33,6 @@ import ( "github.com/berachain/beacon-kit/primitives/constants" "github.com/berachain/beacon-kit/primitives/encoding/json" "github.com/berachain/beacon-kit/primitives/math" - "github.com/berachain/beacon-kit/primitives/version" cmtcfg "github.com/cometbft/cometbft/config" "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" @@ -42,41 +40,33 @@ import ( "github.com/spf13/cobra" ) -func AddExecutionPayloadCmd(chainSpecCreator servertypes.ChainSpecCreator) *cobra.Command { +func AddExecutionPayloadCmd() *cobra.Command { cmd := &cobra.Command{ Use: "execution-payload [eth/genesis/file.json]", Short: "adds the eth1 genesis execution payload to the genesis file", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - // Read the genesis file. - elGenesisPath := args[0] - config := context.GetConfigFromCmd(cmd) - v := context.GetViperFromCmd(cmd) - chainSpec, err := chainSpecCreator(v) - if err != nil { - return err - } - return AddExecutionPayload(chainSpec, elGenesisPath, config) + return AddExecutionPayload(args[0], context.GetConfigFromCmd(cmd)) }, } return cmd } -func AddExecutionPayload(chainSpec ChainSpec, elGenesisPath string, config *cmtcfg.Config) error { +func AddExecutionPayload(elGenesisPath string, config *cmtcfg.Config) error { genesisBz, err := afero.ReadFile(afero.NewOsFs(), elGenesisPath) if err != nil { return errors.Wrap(err, "failed to read eth1 genesis file") } - // Unmarshal the genesis file. + // Unmarshal the EL genesis file. ethGenesis := &gethprimitives.Genesis{} if err = ethGenesis.UnmarshalJSON(genesisBz); err != nil { return errors.Wrap(err, "failed to unmarshal eth1 genesis") } genesisBlock := ethGenesis.ToBlock() - // Create the execution payload. + // Create the executable data from the EL genesis file. payload := gethprimitives.BlockToExecutableData( genesisBlock, nil, @@ -84,122 +74,82 @@ func AddExecutionPayload(chainSpec ChainSpec, elGenesisPath string, config *cmtc nil, ).ExecutionPayload - appGenesis, err := genutiltypes.AppGenesisFromFile( - config.GenesisFile(), - ) + appGenesis, err := genutiltypes.AppGenesisFromFile(config.GenesisFile()) if err != nil { return errors.Wrap(err, "failed to read genesis doc from file") } - // create the app state - appGenesisState, err := genutiltypes.GenesisStateFromAppGenesis( - appGenesis, - ) + // Create the app state. + appGenesisState, err := genutiltypes.GenesisStateFromAppGenesis(appGenesis) if err != nil { return err } genesisInfo := &types.Genesis{} - - if err = json.Unmarshal( - appGenesisState["beacon"], genesisInfo, - ); err != nil { + if err = json.Unmarshal(appGenesisState["beacon"], genesisInfo); err != nil { return errors.Wrap(err, "failed to unmarshal beacon state") } - // Inject the execution payload. - eph, err := executableDataToExecutionPayloadHeader( - chainSpec.GenesisForkVersion(), - payload, - chainSpec.MaxWithdrawalsPerPayload(), - ) + + // Inject the execution payload headerfrom the executable data. + eph, err := executableDataToExecutionPayloadHeader(payload) if err != nil { return errors.Wrap(err, "failed to convert executable data to execution payload header") } - if eph == nil { - return errors.New("failed to get execution payload header") - } genesisInfo.ExecutionPayloadHeader = eph - appGenesisState["beacon"], err = json.Marshal(genesisInfo) - if err != nil { + if appGenesisState["beacon"], err = json.Marshal(genesisInfo); err != nil { return errors.Wrap(err, "failed to marshal beacon state") } - if appGenesis.AppState, err = json.MarshalIndent( - appGenesisState, "", " ", - ); err != nil { + if appGenesis.AppState, err = json.MarshalIndent(appGenesisState, "", " "); err != nil { return err } return genutil.ExportGenesisFile(appGenesis, config.GenesisFile()) } -// Converts the eth executable data type to the beacon execution payload header -// interface. +// Converts the eth executable data type to the beacon execution payload header. func executableDataToExecutionPayloadHeader( - forkVersion common.Version, data *gethprimitives.ExecutableData, - // todo: re-enable when codec supports. - _ uint64, ) (*types.ExecutionPayloadHeader, error) { - eph := &types.ExecutionPayloadHeader{} - - // We do not support fork versions before Deneb and after Electra. - if version.IsAfter(forkVersion, version.Electra()) || - version.IsBefore(forkVersion, version.Deneb()) { - return nil, types.ErrForkVersionNotSupported - } - - withdrawals := make( - engineprimitives.Withdrawals, - len(data.Withdrawals), - ) - for i, withdrawal := range data.Withdrawals { - // #nosec:G103 // primitives.Withdrawals is data.Withdrawals with - // hard - // types. - withdrawals[i] = (*engineprimitives.Withdrawal)( - unsafe.Pointer(withdrawal), - ) - } + eph := &types.ExecutionPayloadHeader{ + ParentHash: common.ExecutionHash(data.ParentHash), + FeeRecipient: common.ExecutionAddress(data.FeeRecipient), + StateRoot: common.Bytes32(data.StateRoot), + ReceiptsRoot: common.Bytes32(data.ReceiptsRoot), + LogsBloom: [256]byte(data.LogsBloom), + Random: common.Bytes32(data.Random), + Number: math.U64(data.Number), + GasLimit: math.U64(data.GasLimit), + GasUsed: math.U64(data.GasUsed), + Timestamp: math.U64(data.Timestamp), + ExtraData: data.ExtraData, + BlockHash: common.ExecutionHash(data.BlockHash), + TransactionsRoot: engineprimitives.Transactions(data.Transactions).HashTreeRoot(), + } + + // #nosec:G103 // engineprimitives.Withdrawals is data.Withdrawals with hard types. + withdrawals := *(*engineprimitives.Withdrawals)(unsafe.Pointer(&data.Withdrawals)) + eph.WithdrawalsRoot = withdrawals.HashTreeRoot() if len(data.ExtraData) > constants.ExtraDataLength { data.ExtraData = data.ExtraData[:constants.ExtraDataLength] } + eph.ExtraData = data.ExtraData - var blobGasUsed uint64 if data.BlobGasUsed != nil { - blobGasUsed = *data.BlobGasUsed + eph.BlobGasUsed = math.U64(*data.BlobGasUsed) } - var excessBlobGas uint64 if data.ExcessBlobGas != nil { - excessBlobGas = *data.ExcessBlobGas + eph.ExcessBlobGas = math.U64(*data.ExcessBlobGas) } baseFeePerGas, err := math.NewU256FromBigInt(data.BaseFeePerGas) if err != nil { return nil, fmt.Errorf("failed baseFeePerGas conversion: %w", err) } - - eph.Versionable = types.NewVersionable(forkVersion) - eph.ParentHash = common.ExecutionHash(data.ParentHash) - eph.FeeRecipient = common.ExecutionAddress(data.FeeRecipient) - eph.StateRoot = common.Bytes32(data.StateRoot) - eph.ReceiptsRoot = common.Bytes32(data.ReceiptsRoot) - eph.LogsBloom = [256]byte(data.LogsBloom) - eph.Random = common.Bytes32(data.Random) - eph.Number = math.U64(data.Number) - eph.GasLimit = math.U64(data.GasLimit) - eph.GasUsed = math.U64(data.GasUsed) - eph.Timestamp = math.U64(data.Timestamp) - eph.ExtraData = data.ExtraData eph.BaseFeePerGas = baseFeePerGas - eph.BlockHash = common.ExecutionHash(data.BlockHash) - eph.TransactionsRoot = engineprimitives.Transactions(data.Transactions).HashTreeRoot() - eph.WithdrawalsRoot = withdrawals.HashTreeRoot() - eph.BlobGasUsed = math.U64(blobGasUsed) - eph.ExcessBlobGas = math.U64(excessBlobGas) return eph, nil } diff --git a/cli/utils/genesis/root_test.go b/cli/utils/genesis/root_test.go index d5a2bb0259..4e2b607256 100644 --- a/cli/utils/genesis/root_test.go +++ b/cli/utils/genesis/root_test.go @@ -108,7 +108,7 @@ func TestCompareGenesisCmdWithStateProcessor(t *testing.T) { // genesis validators root from StateProcessor sp, st, _, _, _, _ := statetransition.SetupTestState(t, cs) - genPayloadHeader := types.NewEmptyExecutionPayloadHeaderWithVersion(cs.GenesisForkVersion()) + genPayloadHeader := types.NewEmptyExecutionPayloadHeader() _, err = sp.InitializeBeaconStateFromEth1( st, diff --git a/consensus-types/types/errors.go b/consensus-types/types/errors.go index 72b97e51b0..4c52330226 100644 --- a/consensus-types/types/errors.go +++ b/consensus-types/types/errors.go @@ -28,12 +28,9 @@ var ( ErrDepositMessage = errors.New("invalid deposit message") // ErrInvalidWithdrawalCredentials is an error for when the. - ErrInvalidWithdrawalCredentials = errors.New( - "invalid withdrawal credentials", - ) + ErrInvalidWithdrawalCredentials = errors.New("invalid withdrawal credentials") - // ErrForkVersionNotSupported is an error for when the fork - // version is not supported. + // ErrForkVersionNotSupported is an error for when the fork version is not supported. ErrForkVersionNotSupported = errors.New("fork version not supported") // ErrNilValue is an error for when a getter returns nil on a value diff --git a/consensus-types/types/genesis.go b/consensus-types/types/genesis.go index 364816cb1b..538916225e 100644 --- a/consensus-types/types/genesis.go +++ b/consensus-types/types/genesis.go @@ -82,7 +82,7 @@ func (g *Genesis) UnmarshalJSON( return err } - payloadHeader := NewEmptyExecutionPayloadHeaderWithVersion(g2.ForkVersion) + payloadHeader := NewEmptyExecutionPayloadHeader() if err := json.Unmarshal(g2.ExecutionPayloadHeader, payloadHeader); err != nil { return err } @@ -95,7 +95,7 @@ func (g *Genesis) UnmarshalJSON( // DefaultGenesis returns the default genesis. func DefaultGenesis(v common.Version) *Genesis { - defaultHeader, err := DefaultGenesisExecutionPayloadHeader(v) + defaultHeader, err := DefaultGenesisExecutionPayloadHeader() if err != nil { panic(err) } @@ -108,7 +108,7 @@ func DefaultGenesis(v common.Version) *Genesis { } // DefaultGenesisExecutionPayloadHeader returns a default ExecutionPayloadHeader. -func DefaultGenesisExecutionPayloadHeader(v common.Version) (*ExecutionPayloadHeader, error) { +func DefaultGenesisExecutionPayloadHeader() (*ExecutionPayloadHeader, error) { stateRoot, err := bytes.ToBytes32( hex.MustToBytes( "0x12965ab9cbe2d2203f61d23636eb7e998f167cb79d02e452f532535641e35bcc", @@ -135,7 +135,6 @@ func DefaultGenesisExecutionPayloadHeader(v common.Version) (*ExecutionPayloadHe } return &ExecutionPayloadHeader{ - Versionable: NewVersionable(v), ParentHash: common.ExecutionHash{}, FeeRecipient: common.ExecutionAddress{}, StateRoot: stateRoot, diff --git a/consensus-types/types/genesis_test.go b/consensus-types/types/genesis_test.go index 87339570e2..6a36181e80 100644 --- a/consensus-types/types/genesis_test.go +++ b/consensus-types/types/genesis_test.go @@ -70,11 +70,9 @@ func TestDefaultGenesis(t *testing.T) { func TestDefaultGenesisExecutionPayloadHeader(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - header, err := types.DefaultGenesisExecutionPayloadHeader(v) - require.NoError(t, err) - require.NotNil(t, header) - }) + header, err := types.DefaultGenesisExecutionPayloadHeader() + require.NoError(t, err) + require.NotNil(t, header) } func TestGenesisGetForkVersion(t *testing.T) { diff --git a/consensus-types/types/payload.go b/consensus-types/types/payload.go index dd6afb8669..12b850c945 100644 --- a/consensus-types/types/payload.go +++ b/consensus-types/types/payload.go @@ -577,7 +577,6 @@ func (p *ExecutionPayload) ToHeader() (*ExecutionPayloadHeader, error) { switch p.GetForkVersion() { case version.Deneb(), version.Deneb1(), version.Electra(): return &ExecutionPayloadHeader{ - Versionable: p.Versionable, ParentHash: p.GetParentHash(), FeeRecipient: p.GetFeeRecipient(), StateRoot: p.GetStateRoot(), @@ -597,6 +596,6 @@ func (p *ExecutionPayload) ToHeader() (*ExecutionPayloadHeader, error) { ExcessBlobGas: p.GetExcessBlobGas(), }, nil default: - return nil, errors.New("unknown fork version") + return nil, ErrForkVersionNotSupported } } diff --git a/consensus-types/types/payload_header.go b/consensus-types/types/payload_header.go index 1af7bb87d4..76d6bb5405 100644 --- a/consensus-types/types/payload_header.go +++ b/consensus-types/types/payload_header.go @@ -36,22 +36,12 @@ const ExecutionPayloadHeaderStaticSize uint32 = 584 // Compile-time assertions to ensure ExecutionPayloadHeader implements necessary interfaces. var ( - _ ssz.DynamicObject = (*ExecutionPayloadHeader)(nil) - _ constraints.SSZVersionedMarshallableRootable = (*ExecutionPayloadHeader)(nil) + _ ssz.DynamicObject = (*ExecutionPayloadHeader)(nil) + _ constraints.SSZMarshallableRootable = (*ExecutionPayloadHeader)(nil) ) // ExecutionPayloadHeader represents the payload header of an execution block. type ExecutionPayloadHeader struct { - // NOTE: This version is not required but left in for backwards compatibility. - // - // A recommended alternative to `GetForkVersion()` on this struct would be to use the chain - // spec's `ActiveForkVersionForTimestamp()` on the value of `GetTimestamp()`. - // - // This version should still be set to the correct value to avoid potential inconsistencies. - constraints.Versionable - - // Contents - // // ParentHash is the hash of the parent block. ParentHash common.ExecutionHash `json:"parentHash"` // FeeRecipient is the address of the fee recipient. @@ -88,9 +78,9 @@ type ExecutionPayloadHeader struct { ExcessBlobGas math.U64 `json:"excessBlobGas"` } -func NewEmptyExecutionPayloadHeaderWithVersion(version common.Version) *ExecutionPayloadHeader { +// NewEmptyExecutionPayloadHeader creates a new empty ExecutionPayloadHeader. +func NewEmptyExecutionPayloadHeader() *ExecutionPayloadHeader { return &ExecutionPayloadHeader{ - Versionable: NewVersionable(version), BaseFeePerGas: &math.U256{}, } } diff --git a/consensus-types/types/payload_header_test.go b/consensus-types/types/payload_header_test.go index f2f0c7d5bc..a16b92a6e3 100644 --- a/consensus-types/types/payload_header_test.go +++ b/consensus-types/types/payload_header_test.go @@ -31,16 +31,14 @@ import ( "github.com/berachain/beacon-kit/primitives/encoding/json" sszutil "github.com/berachain/beacon-kit/primitives/encoding/ssz" "github.com/berachain/beacon-kit/primitives/math" - "github.com/berachain/beacon-kit/primitives/version" fastssz "github.com/ferranbt/fastssz" "github.com/karalabe/ssz" "github.com/stretchr/testify/require" ) // generateExecutionPayloadHeader generates an ExecutionPayloadHeader. -func generateExecutionPayloadHeader(version common.Version) *types.ExecutionPayloadHeader { +func generateExecutionPayloadHeader() *types.ExecutionPayloadHeader { return &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(version), ParentHash: common.ExecutionHash{}, FeeRecipient: common.ExecutionAddress{}, StateRoot: bytes.B32{}, @@ -63,88 +61,71 @@ func generateExecutionPayloadHeader(version common.Version) *types.ExecutionPayl func TestExecutionPayloadHeader_Getters(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - header := generateExecutionPayloadHeader(v) - require.NotNil(t, header) - - require.Equal(t, common.ExecutionHash{}, header.GetParentHash()) - require.Equal( - t, - common.ExecutionAddress{}, - header.GetFeeRecipient(), - ) - require.Equal(t, bytes.B32{}, header.GetStateRoot()) - require.Equal(t, bytes.B32{}, header.GetReceiptsRoot()) - require.Equal(t, bytes.B256{}, header.GetLogsBloom()) - require.Equal(t, bytes.B32{}, header.GetPrevRandao()) - require.Equal(t, math.U64(0), header.GetNumber()) - require.Equal(t, math.U64(0), header.GetGasLimit()) - require.Equal(t, math.U64(0), header.GetGasUsed()) - require.Equal(t, math.U64(0), header.GetTimestamp()) - require.Equal(t, []byte(nil), header.GetExtraData()) - require.Equal(t, math.NewU256(0), header.GetBaseFeePerGas()) - require.Equal(t, common.ExecutionHash{}, header.GetBlockHash()) - require.Equal(t, common.Root{}, header.GetTransactionsRoot()) - require.Equal(t, common.Root{}, header.GetWithdrawalsRoot()) - require.Equal(t, math.U64(0), header.GetBlobGasUsed()) - require.Equal(t, math.U64(0), header.GetExcessBlobGas()) - }) + header := generateExecutionPayloadHeader() + require.NotNil(t, header) + + require.Equal(t, common.ExecutionHash{}, header.GetParentHash()) + require.Equal( + t, + common.ExecutionAddress{}, + header.GetFeeRecipient(), + ) + require.Equal(t, bytes.B32{}, header.GetStateRoot()) + require.Equal(t, bytes.B32{}, header.GetReceiptsRoot()) + require.Equal(t, bytes.B256{}, header.GetLogsBloom()) + require.Equal(t, bytes.B32{}, header.GetPrevRandao()) + require.Equal(t, math.U64(0), header.GetNumber()) + require.Equal(t, math.U64(0), header.GetGasLimit()) + require.Equal(t, math.U64(0), header.GetGasUsed()) + require.Equal(t, math.U64(0), header.GetTimestamp()) + require.Equal(t, []byte(nil), header.GetExtraData()) + require.Equal(t, math.NewU256(0), header.GetBaseFeePerGas()) + require.Equal(t, common.ExecutionHash{}, header.GetBlockHash()) + require.Equal(t, common.Root{}, header.GetTransactionsRoot()) + require.Equal(t, common.Root{}, header.GetWithdrawalsRoot()) + require.Equal(t, math.U64(0), header.GetBlobGasUsed()) + require.Equal(t, math.U64(0), header.GetExcessBlobGas()) } func TestExecutionPayloadHeader_IsNil(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - header := generateExecutionPayloadHeader(v) - require.NotNil(t, header) - }) -} - -func TestExecutionPayloadHeader_Version(t *testing.T) { - t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - header := generateExecutionPayloadHeader(v) - require.Equal(t, v, header.GetForkVersion()) - }) + header := generateExecutionPayloadHeader() + require.NotNil(t, header) } func TestExecutionPayloadHeader_MarshalUnmarshalJSON(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - originalHeader := generateExecutionPayloadHeader(v) - - data, err := originalHeader.MarshalJSON() - require.NoError(t, err) - require.NotNil(t, data) - - var header types.ExecutionPayloadHeader - err = header.UnmarshalJSON(data) - require.NoError(t, err) - header.Versionable = types.NewVersionable(originalHeader.GetForkVersion()) - require.Equal(t, originalHeader, &header) - }) + originalHeader := generateExecutionPayloadHeader() + + data, err := originalHeader.MarshalJSON() + require.NoError(t, err) + require.NotNil(t, data) + + var header types.ExecutionPayloadHeader + err = header.UnmarshalJSON(data) + require.NoError(t, err) + require.Equal(t, *originalHeader, header) } func TestExecutionPayloadHeader_Serialization(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - original := generateExecutionPayloadHeader(v) + original := generateExecutionPayloadHeader() - data, err := original.MarshalSSZ() - require.NoError(t, err) - require.NotNil(t, data) + data, err := original.MarshalSSZ() + require.NoError(t, err) + require.NotNil(t, data) - unmarshalled := types.NewEmptyExecutionPayloadHeaderWithVersion(original.GetForkVersion()) - err = sszutil.Unmarshal(data, unmarshalled) - require.NoError(t, err) - require.Equal(t, original, unmarshalled) - }) + unmarshalled := types.NewEmptyExecutionPayloadHeader() + err = sszutil.Unmarshal(data, unmarshalled) + require.NoError(t, err) + require.Equal(t, *original, *unmarshalled) } func TestExecutionPayloadHeader_MarshalSSZTo(t *testing.T) { t.Parallel() testcases := []struct { name string - malleate func(common.Version) *types.ExecutionPayloadHeader + malleate func() *types.ExecutionPayloadHeader expErr error }{ { @@ -154,8 +135,8 @@ func TestExecutionPayloadHeader_MarshalSSZTo(t *testing.T) { }, { name: "invalid extra data passes marshalling", - malleate: func(version common.Version) *types.ExecutionPayloadHeader { - header := generateExecutionPayloadHeader(version) + malleate: func() *types.ExecutionPayloadHeader { + header := generateExecutionPayloadHeader() header.ExtraData = make([]byte, 100) return header }, @@ -166,28 +147,25 @@ func TestExecutionPayloadHeader_MarshalSSZTo(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - header := tc.malleate(v) - buf := make([]byte, 64) - _, err := header.MarshalSSZTo(buf) - if tc.expErr != nil { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) + + header := tc.malleate() + buf := make([]byte, 64) + _, err := header.MarshalSSZTo(buf) + if tc.expErr != nil { + require.Error(t, err) + } else { + require.NoError(t, err) + } }) } } func TestExecutionPayloadHeader_NewFromSSZ_EmptyBuf(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - buf := make([]byte, 0) - header := types.NewEmptyExecutionPayloadHeaderWithVersion(v) - err := sszutil.Unmarshal(buf, header) - require.ErrorIs(t, err, io.ErrUnexpectedEOF) - }) + buf := make([]byte, 0) + header := types.NewEmptyExecutionPayloadHeader() + err := sszutil.Unmarshal(buf, header) + require.ErrorIs(t, err, io.ErrUnexpectedEOF) } func TestExecutionPayloadHeader_NewFromSSZ_Invalid(t *testing.T) { @@ -200,7 +178,7 @@ func TestExecutionPayloadHeader_NewFromSSZ_Invalid(t *testing.T) { { name: "offset exceeds length", malleate: func() []byte { - header := generateExecutionPayloadHeader(version.Deneb()) + header := generateExecutionPayloadHeader() buf, err := header.MarshalSSZ() require.NoError(t, err) @@ -215,7 +193,7 @@ func TestExecutionPayloadHeader_NewFromSSZ_Invalid(t *testing.T) { { name: "invalid extra data: extra data too large", malleate: func() []byte { - header := generateExecutionPayloadHeader(version.Deneb()) + header := generateExecutionPayloadHeader() buf, err := header.MarshalSSZ() // add dummy extra data to exceed the 32 limit @@ -230,7 +208,7 @@ func TestExecutionPayloadHeader_NewFromSSZ_Invalid(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { buf := tc.malleate() - dest := types.NewEmptyExecutionPayloadHeaderWithVersion(version.Deneb()) + dest := types.NewEmptyExecutionPayloadHeader() err := sszutil.Unmarshal(buf, dest) require.ErrorIs(t, err, tc.expErr) }) @@ -239,7 +217,7 @@ func TestExecutionPayloadHeader_NewFromSSZ_Invalid(t *testing.T) { func TestExecutionPayloadHeader_NewFromSSZ_Invalid_TooSmall(t *testing.T) { t.Parallel() - header := generateExecutionPayloadHeader(version.Deneb()) + header := generateExecutionPayloadHeader() buf, err := header.MarshalSSZ() require.NoError(t, err) @@ -248,7 +226,7 @@ func TestExecutionPayloadHeader_NewFromSSZ_Invalid_TooSmall(t *testing.T) { buf[438] = 0 buf[439] = 0 - dest := types.NewEmptyExecutionPayloadHeaderWithVersion(version.Deneb()) + dest := types.NewEmptyExecutionPayloadHeader() err = sszutil.Unmarshal(buf, dest) require.Error(t, err) @@ -270,135 +248,127 @@ func TestExecutionPayloadHeader_NewFromSSZ_Invalid_TooSmall(t *testing.T) { func TestExecutionPayloadHeader_SizeSSZ(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - header := generateExecutionPayloadHeader(v) - size := ssz.Size(header) - require.Equal(t, types.ExecutionPayloadHeaderStaticSize, size) - }) + header := generateExecutionPayloadHeader() + size := ssz.Size(header) + require.Equal(t, types.ExecutionPayloadHeaderStaticSize, size) } func TestExecutionPayloadHeader_HashTreeRoot(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - header := generateExecutionPayloadHeader(v) - require.NotPanics(t, func() { - header.HashTreeRoot() - }) + header := generateExecutionPayloadHeader() + require.NotPanics(t, func() { + header.HashTreeRoot() }) } func TestExecutionPayloadHeader_GetTree(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - header := generateExecutionPayloadHeader(v) - _, err := header.GetTree() - require.NoError(t, err) - }) + header := generateExecutionPayloadHeader() + _, err := header.GetTree() + require.NoError(t, err) } func TestExecutablePayloadHeader_UnmarshalJSON_Error(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - original := generateExecutionPayloadHeader(v) - validJSON, err := original.MarshalJSON() - require.NoError(t, err) - - testCases := []struct { - name string - removeField string - expectedError string - }{ - { - name: "missing required field 'parentHash'", - removeField: "parentHash", - expectedError: "missing required field 'parentHash' for ExecutionPayloadHeader", - }, - { - name: "missing required field 'feeRecipient'", - removeField: "feeRecipient", - expectedError: "missing required field 'feeRecipient' for ExecutionPayloadHeader", - }, - { - name: "missing required field 'stateRoot'", - removeField: "stateRoot", - expectedError: "missing required field 'stateRoot' for ExecutionPayloadHeader", - }, - { - name: "missing required field 'receiptsRoot'", - removeField: "receiptsRoot", - expectedError: "missing required field 'receiptsRoot' for ExecutionPayloadHeader", - }, - { - name: "missing required field 'logsBloom'", - removeField: "logsBloom", - expectedError: "missing required field 'logsBloom' for ExecutionPayloadHeader", - }, - { - name: "missing required field 'prevRandao'", - removeField: "prevRandao", - expectedError: "missing required field 'prevRandao' for ExecutionPayloadHeader", - }, - { - name: "missing required field 'blockNumber'", - removeField: "blockNumber", - expectedError: "missing required field 'blockNumber' for ExecutionPayloadHeader", - }, - { - name: "missing required field 'gasLimit'", - removeField: "gasLimit", - expectedError: "missing required field 'gasLimit' for ExecutionPayloadHeader", - }, - { - name: "missing required field 'gasUsed'", - removeField: "gasUsed", - expectedError: "missing required field 'gasUsed' for ExecutionPayloadHeader", - }, - { - name: "missing required field 'timestamp'", - removeField: "timestamp", - expectedError: "missing required field 'timestamp' for ExecutionPayloadHeader", - }, - { - name: "missing required field 'extraData'", - removeField: "extraData", - expectedError: "missing required field 'extraData' for ExecutionPayloadHeader", - }, - { - name: "missing required field 'baseFeePerGas'", - removeField: "baseFeePerGas", - expectedError: "missing required field 'baseFeePerGas' for ExecutionPayloadHeader", - }, - { - name: "missing required field 'blockHash'", - removeField: "blockHash", - expectedError: "missing required field 'blockHash' for ExecutionPayloadHeader", - }, - { - name: "missing required field 'transactionsRoot'", - removeField: "transactionsRoot", - expectedError: "missing required field 'transactionsRoot' for ExecutionPayloadHeader", - }, - } + original := generateExecutionPayloadHeader() + validJSON, err := original.MarshalJSON() + require.NoError(t, err) + + testCases := []struct { + name string + removeField string + expectedError string + }{ + { + name: "missing required field 'parentHash'", + removeField: "parentHash", + expectedError: "missing required field 'parentHash' for ExecutionPayloadHeader", + }, + { + name: "missing required field 'feeRecipient'", + removeField: "feeRecipient", + expectedError: "missing required field 'feeRecipient' for ExecutionPayloadHeader", + }, + { + name: "missing required field 'stateRoot'", + removeField: "stateRoot", + expectedError: "missing required field 'stateRoot' for ExecutionPayloadHeader", + }, + { + name: "missing required field 'receiptsRoot'", + removeField: "receiptsRoot", + expectedError: "missing required field 'receiptsRoot' for ExecutionPayloadHeader", + }, + { + name: "missing required field 'logsBloom'", + removeField: "logsBloom", + expectedError: "missing required field 'logsBloom' for ExecutionPayloadHeader", + }, + { + name: "missing required field 'prevRandao'", + removeField: "prevRandao", + expectedError: "missing required field 'prevRandao' for ExecutionPayloadHeader", + }, + { + name: "missing required field 'blockNumber'", + removeField: "blockNumber", + expectedError: "missing required field 'blockNumber' for ExecutionPayloadHeader", + }, + { + name: "missing required field 'gasLimit'", + removeField: "gasLimit", + expectedError: "missing required field 'gasLimit' for ExecutionPayloadHeader", + }, + { + name: "missing required field 'gasUsed'", + removeField: "gasUsed", + expectedError: "missing required field 'gasUsed' for ExecutionPayloadHeader", + }, + { + name: "missing required field 'timestamp'", + removeField: "timestamp", + expectedError: "missing required field 'timestamp' for ExecutionPayloadHeader", + }, + { + name: "missing required field 'extraData'", + removeField: "extraData", + expectedError: "missing required field 'extraData' for ExecutionPayloadHeader", + }, + { + name: "missing required field 'baseFeePerGas'", + removeField: "baseFeePerGas", + expectedError: "missing required field 'baseFeePerGas' for ExecutionPayloadHeader", + }, + { + name: "missing required field 'blockHash'", + removeField: "blockHash", + expectedError: "missing required field 'blockHash' for ExecutionPayloadHeader", + }, + { + name: "missing required field 'transactionsRoot'", + removeField: "transactionsRoot", + expectedError: "missing required field 'transactionsRoot' for ExecutionPayloadHeader", + }, + } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - var payload types.ExecutionPayloadHeader - var jsonMap map[string]interface{} + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + var payload types.ExecutionPayloadHeader + var jsonMap map[string]interface{} - errUnmarshal := json.Unmarshal(validJSON, &jsonMap) - require.NoError(t, errUnmarshal) + errUnmarshal := json.Unmarshal(validJSON, &jsonMap) + require.NoError(t, errUnmarshal) - delete(jsonMap, tc.removeField) + delete(jsonMap, tc.removeField) - malformedJSON, errMarshal := json.Marshal(jsonMap) - require.NoError(t, errMarshal) + malformedJSON, errMarshal := json.Marshal(jsonMap) + require.NoError(t, errMarshal) - err = payload.UnmarshalJSON(malformedJSON) - require.Error(t, err) - require.Contains(t, err.Error(), tc.expectedError) - }) - } - }) + err = payload.UnmarshalJSON(malformedJSON) + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectedError) + }) + } } func TestExecutablePayloadHeader_UnmarshalJSON_Empty(t *testing.T) { @@ -410,134 +380,128 @@ func TestExecutablePayloadHeader_UnmarshalJSON_Empty(t *testing.T) { func TestExecutablePayloadHeader_HashTreeRootWith(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - testcases := []struct { - name string - malleate func() *types.ExecutionPayloadHeader - expErr error - }{ - { - name: "invalid ExtraData length", - malleate: func() *types.ExecutionPayloadHeader { - var header = generateExecutionPayloadHeader(v) - header.ExtraData = make([]byte, 50) - return header - }, - expErr: fastssz.ErrIncorrectListSize, + testcases := []struct { + name string + malleate func() *types.ExecutionPayloadHeader + expErr error + }{ + { + name: "invalid ExtraData length", + malleate: func() *types.ExecutionPayloadHeader { + var header = generateExecutionPayloadHeader() + header.ExtraData = make([]byte, 50) + return header }, - } - - for _, tc := range testcases { - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - hh := fastssz.DefaultHasherPool.Get() - header := tc.malleate() - err := header.HashTreeRootWith(hh) - require.Equal(t, tc.expErr, err) - }) - } - }) + expErr: fastssz.ErrIncorrectListSize, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + hh := fastssz.DefaultHasherPool.Get() + header := tc.malleate() + err := header.HashTreeRootWith(hh) + require.Equal(t, tc.expErr, err) + }) + } } func TestExecutionPayloadHeader_NewFromSSZ(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - testCases := []struct { - name string - data []byte - expErr error - expectedHeader *types.ExecutionPayloadHeader - }{ - { - name: "Valid SSZ data", - data: func() []byte { - data, _ := generateExecutionPayloadHeader(v).MarshalSSZ() - return data - }(), - expErr: nil, - expectedHeader: generateExecutionPayloadHeader(v), - }, - { - name: "Invalid SSZ data", - data: []byte{0x01, 0x02}, - expErr: io.ErrUnexpectedEOF, - expectedHeader: nil, - }, - { - name: "Empty SSZ data", - data: []byte{}, - expErr: io.ErrUnexpectedEOF, - expectedHeader: nil, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - header := types.NewEmptyExecutionPayloadHeaderWithVersion(v) - if tc.name == "Different fork version" { - require.Panics(t, func() { - _ = sszutil.Unmarshal(tc.data, header) - }, "Expected panic for different fork version") + testCases := []struct { + name string + data []byte + expErr error + expectedHeader *types.ExecutionPayloadHeader + }{ + { + name: "Valid SSZ data", + data: func() []byte { + data, _ := generateExecutionPayloadHeader().MarshalSSZ() + return data + }(), + expErr: nil, + expectedHeader: generateExecutionPayloadHeader(), + }, + { + name: "Invalid SSZ data", + data: []byte{0x01, 0x02}, + expErr: io.ErrUnexpectedEOF, + expectedHeader: nil, + }, + { + name: "Empty SSZ data", + data: []byte{}, + expErr: io.ErrUnexpectedEOF, + expectedHeader: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + header := types.NewEmptyExecutionPayloadHeader() + if tc.name == "Different fork version" { + require.Panics(t, func() { + _ = sszutil.Unmarshal(tc.data, header) + }, "Expected panic for different fork version") + } else { + err := sszutil.Unmarshal(tc.data, header) + if tc.expErr != nil { + require.ErrorIs(t, err, tc.expErr) } else { - err := sszutil.Unmarshal(tc.data, header) - if tc.expErr != nil { - require.ErrorIs(t, err, tc.expErr) - } else { - require.NoError(t, err) - require.Equal(t, tc.expectedHeader, header) - } + require.NoError(t, err) + require.Equal(t, tc.expectedHeader, header) } - }) - } - }) + } + }) + } } func TestExecutionPayloadHeader_NewFromJSON(t *testing.T) { t.Parallel() - runForAllSupportedVersions(t, func(t *testing.T, v common.Version) { - type testCase struct { - name string - data []byte - header *types.ExecutionPayloadHeader - expectedError error - } - testCases := []testCase{ - func() testCase { - header := generateExecutionPayloadHeader(v) - return testCase{ - name: "Valid JSON", - header: header, - data: func() []byte { - data, err := json.Marshal(header) - require.NoError(t, err) - return data - }(), - } - }(), - { - name: "Invalid JSON", - data: []byte{}, - expectedError: errors.New("unexpected end of JSON input"), - }, - } + type testCase struct { + name string + data []byte + header *types.ExecutionPayloadHeader + expectedError error + } + testCases := []testCase{ + func() testCase { + header := generateExecutionPayloadHeader() + return testCase{ + name: "Valid JSON", + header: header, + data: func() []byte { + data, err := json.Marshal(header) + require.NoError(t, err) + return data + }(), + } + }(), + { + name: "Invalid JSON", + data: []byte{}, + expectedError: errors.New("unexpected end of JSON input"), + }, + } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - header := types.NewEmptyExecutionPayloadHeaderWithVersion(v) - err := json.Unmarshal(tc.data, header) + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + header := types.NewEmptyExecutionPayloadHeader() + err := json.Unmarshal(tc.data, header) - if tc.expectedError != nil { - require.Error(t, err) - require.Contains(t, err.Error(), tc.expectedError.Error()) - } else { - require.NoError(t, err) - } - if tc.header != nil { - require.Equal(t, tc.header, header) - } - }) - } - }) + if tc.expectedError != nil { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectedError.Error()) + } else { + require.NoError(t, err) + } + if tc.header != nil { + require.Equal(t, tc.header, header) + } + }) + } } diff --git a/consensus-types/types/payload_test.go b/consensus-types/types/payload_test.go index 102af86de0..3d306bec28 100644 --- a/consensus-types/types/payload_test.go +++ b/consensus-types/types/payload_test.go @@ -254,7 +254,6 @@ func TestExecutionPayload_ToHeader(t *testing.T) { require.Equal(t, payload.GetBlockHash(), header.GetBlockHash()) require.Equal(t, payload.GetBlobGasUsed(), header.GetBlobGasUsed()) require.Equal(t, payload.GetExcessBlobGas(), header.GetExcessBlobGas()) - require.Equal(t, payload.GetForkVersion(), header.GetForkVersion()) require.Equal(t, payload.HashTreeRoot(), header.HashTreeRoot()) } diff --git a/consensus-types/types/state.go b/consensus-types/types/state.go index c1063bb66b..3833b3273b 100644 --- a/consensus-types/types/state.go +++ b/consensus-types/types/state.go @@ -266,7 +266,7 @@ func (st *BeaconState) HashTreeRootWith( // Field (8) 'LatestExecutionPayloadHeader' if st.LatestExecutionPayloadHeader == nil { - st.LatestExecutionPayloadHeader = NewEmptyExecutionPayloadHeaderWithVersion(st.GetForkVersion()) + st.LatestExecutionPayloadHeader = NewEmptyExecutionPayloadHeader() } if err := st.LatestExecutionPayloadHeader.HashTreeRootWith(hh); err != nil { return err diff --git a/node-api/backend/validator_test.go b/node-api/backend/validator_test.go index 2a15c17fb7..bc9b718b36 100644 --- a/node-api/backend/validator_test.go +++ b/node-api/backend/validator_test.go @@ -407,9 +407,9 @@ func setupStateDummyParts(t *testing.T, cs chain.Spec, st *statedb.StateDB, dumm require.NoError(t, st.UpdateStateRootAtIndex(i, common.Root{})) } - payload, err := ctypes.DefaultGenesisExecutionPayloadHeader(version.Deneb()) + payload, err := ctypes.DefaultGenesisExecutionPayloadHeader() require.NoError(t, err) - require.NoError(t, st.SetLatestExecutionPayloadHeader(payload)) + require.NoError(t, st.SetLatestExecutionPayloadHeader(payload, version.Deneb())) eth1Data := &ctypes.Eth1Data{ DepositRoot: common.Root{}, diff --git a/node-api/handlers/proof/merkle/mock/beacon_state.go b/node-api/handlers/proof/merkle/mock/beacon_state.go index cc0768c8cf..67682ee3a3 100644 --- a/node-api/handlers/proof/merkle/mock/beacon_state.go +++ b/node-api/handlers/proof/merkle/mock/beacon_state.go @@ -42,7 +42,7 @@ func NewBeaconStateWith( } // Create an empty execution payload header with the given execution number and fee recipient. - execPayloadHeader := types.NewEmptyExecutionPayloadHeaderWithVersion(forkVersion) + execPayloadHeader := types.NewEmptyExecutionPayloadHeader() execPayloadHeader.Number = executionNumber execPayloadHeader.FeeRecipient = executionFeeRecipient diff --git a/state-transition/core/state_processor_genesis.go b/state-transition/core/state_processor_genesis.go index 95e81adeb4..699c16e70d 100644 --- a/state-transition/core/state_processor_genesis.go +++ b/state-transition/core/state_processor_genesis.go @@ -101,7 +101,7 @@ func (sp *StateProcessor) InitializeBeaconStateFromEth1( return nil, err } - if err = st.SetLatestExecutionPayloadHeader(execPayloadHeader); err != nil { + if err = st.SetLatestExecutionPayloadHeader(execPayloadHeader, genesisVersion); err != nil { return nil, err } diff --git a/state-transition/core/state_processor_genesis_test.go b/state-transition/core/state_processor_genesis_test.go index 3bb797c4b4..f386edd756 100644 --- a/state-transition/core/state_processor_genesis_test.go +++ b/state-transition/core/state_processor_genesis_test.go @@ -128,10 +128,8 @@ func TestInitialize(t *testing.T) { genDeposits[0], genDeposits[1], genDeposits[3], genDeposits[5], genDeposits[6], } - executionPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - fork = &types.Fork{ + executionPayloadHeader = &types.ExecutionPayloadHeader{} + fork = &types.Fork{ PreviousVersion: cs.GenesisForkVersion(), CurrentVersion: cs.GenesisForkVersion(), Epoch: constants.GenesisEpoch, diff --git a/state-transition/core/state_processor_payload.go b/state-transition/core/state_processor_payload.go index 8644aacdde..8686f6cd0c 100644 --- a/state-transition/core/state_processor_payload.go +++ b/state-transition/core/state_processor_payload.go @@ -97,7 +97,7 @@ func (sp *StateProcessor) processExecutionPayload( } // Set the latest execution payload header. - return st.SetLatestExecutionPayloadHeader(header) + return st.SetLatestExecutionPayloadHeader(header, payload.GetForkVersion()) } // validateExecutionPayload validates the execution payload against both local diff --git a/state-transition/core/state_processor_payload_test.go b/state-transition/core/state_processor_payload_test.go index 0b546b95eb..367c04fa5d 100644 --- a/state-transition/core/state_processor_payload_test.go +++ b/state-transition/core/state_processor_payload_test.go @@ -64,9 +64,7 @@ func TestPayloadTimestampVerification(t *testing.T) { Index: 0, }, } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(genesisFork), - } + genPayloadHeader = &types.ExecutionPayloadHeader{} ) genPayloadHeader.Timestamp = math.U64(genesisTime.Unix()) diff --git a/state-transition/core/state_processor_staking_test.go b/state-transition/core/state_processor_staking_test.go index c26211c7cc..2fc9568b55 100644 --- a/state-transition/core/state_processor_staking_test.go +++ b/state-transition/core/state_processor_staking_test.go @@ -53,36 +53,31 @@ func TestTransitionUpdateValidators(t *testing.T) { ) // STEP 0: Setup initial state via genesis - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x00}, - Credentials: emptyCredentials, - Amount: minBalance + increment, - Index: uint64(0), - }, - { - Pubkey: [48]byte{0x01}, - Credentials: emptyCredentials, - Amount: maxBalance - 6*increment, - Index: uint64(1), - }, - { - Pubkey: [48]byte{0x03}, - Credentials: emptyCredentials, - Amount: maxBalance - 3*increment, - Index: uint64(2), - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x00}, + Credentials: emptyCredentials, + Amount: minBalance + increment, + Index: uint64(0), + }, + { + Pubkey: [48]byte{0x01}, + Credentials: emptyCredentials, + Amount: maxBalance - 6*increment, + Index: uint64(1), + }, + { + Pubkey: [48]byte{0x03}, + Credentials: emptyCredentials, + Amount: maxBalance - 3*increment, + Index: uint64(2), + }, + } require.NoError(t, ds.EnqueueDeposits(ctx.ConsensusCtx(), genDeposits)) valDiff, err := sp.InitializeBeaconStateFromEth1( st, genDeposits, - genPayloadHeader, + &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) @@ -192,25 +187,20 @@ func TestTransitionCreateValidator(t *testing.T) { ) // STEP 0: Setup initial state via genesis - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x01}, - Credentials: emptyCredentials, - Amount: minBalance + increment, - Index: uint64(0), - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x01}, + Credentials: emptyCredentials, + Amount: minBalance + increment, + Index: uint64(0), + }, + } require.NoError(t, ds.EnqueueDeposits(ctx.ConsensusCtx(), genDeposits)) genVals, err := sp.InitializeBeaconStateFromEth1( st, genDeposits, - genPayloadHeader, + &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) @@ -370,12 +360,7 @@ func TestTransitionHittingValidatorsCap_ExtraSmall(t *testing.T) { // STEP 0: Setup genesis with GetValidatorSetCap validators // TODO: consider instead setting state artificially - var ( - genDeposits = make(types.Deposits, 0, cs.ValidatorSetCap()) - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := make(types.Deposits, 0, cs.ValidatorSetCap()) // let genesis define all available validators for idx := range cs.ValidatorSetCap() { @@ -401,7 +386,7 @@ func TestTransitionHittingValidatorsCap_ExtraSmall(t *testing.T) { _, err := sp.InitializeBeaconStateFromEth1( st, genDeposits, - genPayloadHeader, + &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) @@ -603,12 +588,7 @@ func TestTransitionHittingValidatorsCap_ExtraBig(t *testing.T) { // STEP 0: Setup genesis with GetValidatorSetCap validators // TODO: consider instead setting state artificially - var ( - genDeposits = make(types.Deposits, 0, cs.ValidatorSetCap()) - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := make(types.Deposits, 0, cs.ValidatorSetCap()) // let genesis define all available validators for idx := range cs.ValidatorSetCap() { @@ -636,7 +616,7 @@ func TestTransitionHittingValidatorsCap_ExtraBig(t *testing.T) { genVals, err := sp.InitializeBeaconStateFromEth1( st, genDeposits, - genPayloadHeader, + &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) diff --git a/state-transition/core/state_processor_test.go b/state-transition/core/state_processor_test.go index 6536af7ced..17812f3cd4 100644 --- a/state-transition/core/state_processor_test.go +++ b/state-transition/core/state_processor_test.go @@ -42,20 +42,17 @@ func TestStateProcessor_ProcessSlots(t *testing.T) { // Initialize state with genesis. genesisTime := time.Now().Truncate(time.Second) - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x00}, - Credentials: types.NewCredentialsFromExecutionAddress(common.ExecutionAddress{}), - Amount: cs.MaxEffectiveBalance(), - Index: 0, - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) - genPayloadHeader.Timestamp = math.U64(genesisTime.Unix()) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x00}, + Credentials: types.NewCredentialsFromExecutionAddress(common.ExecutionAddress{}), + Amount: cs.MaxEffectiveBalance(), + Index: 0, + }, + } + genPayloadHeader := &types.ExecutionPayloadHeader{ + Timestamp: math.U64(genesisTime.Unix()), + } _, err := sp.InitializeBeaconStateFromEth1( st, genDeposits, genPayloadHeader, cs.GenesisForkVersion(), ) diff --git a/state-transition/core/state_processor_withdrawals_test.go b/state-transition/core/state_processor_withdrawals_test.go index 0e29e05b62..c8045f59b0 100644 --- a/state-transition/core/state_processor_withdrawals_test.go +++ b/state-transition/core/state_processor_withdrawals_test.go @@ -59,21 +59,16 @@ func TestPartialWithdrawalRequestGenesisValidators(t *testing.T) { ) // Add a single validator to which we will target withdrawal requests - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x00}, - Credentials: creds, - Amount: maxBalance, - Index: 0, - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x00}, + Credentials: creds, + Amount: maxBalance, + Index: 0, + }, + } _, err := sp.InitializeBeaconStateFromEth1( - st, genDeposits, genPayloadHeader, cs.GenesisForkVersion(), + st, genDeposits, &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) require.NoError(t, ds.EnqueueDeposits(ctx.ConsensusCtx(), genDeposits)) @@ -266,27 +261,22 @@ func TestFullWithdrawalRequestGenesisValidators(t *testing.T) { ) // Add a couple of validators and fully withdraw one of them - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x00}, - Credentials: creds1, - Amount: maxBalance, - Index: 0, - }, - { - Pubkey: [48]byte{0x01}, - Credentials: creds2, - Amount: maxBalance, - Index: 1, - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x00}, + Credentials: creds1, + Amount: maxBalance, + Index: 0, + }, + { + Pubkey: [48]byte{0x01}, + Credentials: creds2, + Amount: maxBalance, + Index: 1, + }, + } _, err := sp.InitializeBeaconStateFromEth1( - st, genDeposits, genPayloadHeader, cs.GenesisForkVersion(), + st, genDeposits, &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) require.NoError(t, ds.EnqueueDeposits(ctx.ConsensusCtx(), genDeposits)) @@ -511,21 +501,16 @@ func TestWithdrawalRequestsNonGenesisValidators(t *testing.T) { valCreds = types.NewCredentialsFromExecutionAddress(valAddr) ) - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x00}, - Credentials: genCreds, - Amount: maxBalance, - Index: 0, - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x00}, + Credentials: genCreds, + Amount: maxBalance, + Index: 0, + }, + } _, err := sp.InitializeBeaconStateFromEth1( - st, genDeposits, genPayloadHeader, cs.GenesisForkVersion(), + st, genDeposits, &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) require.NoError(t, ds.EnqueueDeposits(ctx.ConsensusCtx(), genDeposits)) @@ -762,12 +747,7 @@ func TestConcurrentAutomaticAndVoluntaryWithdrawalRequests(t *testing.T) { rndSeed = 2024 // seed used to generate unique random value ) - var ( - genDeposits = make(types.Deposits, 0, cs.ValidatorSetCap()) - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := make(types.Deposits, 0, cs.ValidatorSetCap()) // Step1: let blockchain have as many validators as cap allows for idx := range cs.ValidatorSetCap() { @@ -793,7 +773,7 @@ func TestConcurrentAutomaticAndVoluntaryWithdrawalRequests(t *testing.T) { _, err := sp.InitializeBeaconStateFromEth1( st, genDeposits, - genPayloadHeader, + &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) @@ -922,27 +902,22 @@ func TestDoubleFullWithdrawalRequests(t *testing.T) { ) // Add a couple of validators and fully withdraw one of them - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x00}, - Credentials: creds1, - Amount: maxBalance, - Index: 0, - }, - { - Pubkey: [48]byte{0x01}, - Credentials: creds2, - Amount: maxBalance, - Index: 1, - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x00}, + Credentials: creds1, + Amount: maxBalance, + Index: 0, + }, + { + Pubkey: [48]byte{0x01}, + Credentials: creds2, + Amount: maxBalance, + Index: 1, + }, + } _, err := sp.InitializeBeaconStateFromEth1( - st, genDeposits, genPayloadHeader, cs.GenesisForkVersion(), + st, genDeposits, &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) require.NoError(t, ds.EnqueueDeposits(ctx.ConsensusCtx(), genDeposits)) @@ -1022,28 +997,23 @@ func TestPartialWithdrawalsOfBalanceAboveMaxEffectiveBalance(t *testing.T) { ) // Setup initial state so that validator 1 is partially withdrawable. - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x00}, - Credentials: credentials0, - Amount: maxBalance - 3*minBalance, - Index: 0, - }, - { - Pubkey: [48]byte{0x01}, - Credentials: credentials1, - Amount: maxBalance + minBalance, - Index: 1, - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x00}, + Credentials: credentials0, + Amount: maxBalance - 3*minBalance, + Index: 0, + }, + { + Pubkey: [48]byte{0x01}, + Credentials: credentials1, + Amount: maxBalance + minBalance, + Index: 1, + }, + } require.NoError(t, ds.EnqueueDeposits(ctx.ConsensusCtx(), genDeposits)) _, err := sp.InitializeBeaconStateFromEth1( - st, genDeposits, genPayloadHeader, cs.GenesisForkVersion(), + st, genDeposits, &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) @@ -1109,28 +1079,23 @@ func TestTransitionMaxWithdrawals(t *testing.T) { ) // Setup initial state so that both validators are partially withdrawable. - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x00}, - Credentials: credentials0, - Amount: maxBalance + minBalance, - Index: 0, - }, - { - Pubkey: [48]byte{0x01}, - Credentials: credentials1, - Amount: maxBalance + minBalance, - Index: 1, - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x00}, + Credentials: credentials0, + Amount: maxBalance + minBalance, + Index: 0, + }, + { + Pubkey: [48]byte{0x01}, + Credentials: credentials1, + Amount: maxBalance + minBalance, + Index: 1, + }, + } require.NoError(t, ds.EnqueueDeposits(ctx.ConsensusCtx(), genDeposits)) _, err = sp.InitializeBeaconStateFromEth1( - st, genDeposits, genPayloadHeader, cs.GenesisForkVersion(), + st, genDeposits, &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) @@ -1235,22 +1200,17 @@ func TestValidatorNotWithdrawable(t *testing.T) { ) // Setup initial state with one validator - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x00}, - Credentials: validCredentials, - Amount: maxBalance, - Index: 0, - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x00}, + Credentials: validCredentials, + Amount: maxBalance, + Index: 0, + }, + } require.NoError(t, ds.EnqueueDeposits(ctx.ConsensusCtx(), genDeposits)) _, err := sp.InitializeBeaconStateFromEth1( - st, genDeposits, genPayloadHeader, cs.GenesisForkVersion(), + st, genDeposits, &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) diff --git a/state-transition/core/validation_deposits_test.go b/state-transition/core/validation_deposits_test.go index a989c53a11..617d02a51f 100644 --- a/state-transition/core/validation_deposits_test.go +++ b/state-transition/core/validation_deposits_test.go @@ -46,22 +46,17 @@ func TestInvalidDeposits(t *testing.T) { ) // Setup initial state with one validator - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x00}, - Credentials: credentials0, - Amount: maxBalance, - Index: 0, - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x00}, + Credentials: credentials0, + Amount: maxBalance, + Index: 0, + }, + } require.NoError(t, ds.EnqueueDeposits(ctx.ConsensusCtx(), genDeposits)) _, err := sp.InitializeBeaconStateFromEth1( - st, genDeposits, genPayloadHeader, cs.GenesisForkVersion(), + st, genDeposits, &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) @@ -114,22 +109,17 @@ func TestInvalidDepositsCount(t *testing.T) { ) // Setup initial state with one validator - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x00}, - Credentials: credentials0, - Amount: maxBalance, - Index: 0, - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x00}, + Credentials: credentials0, + Amount: maxBalance, + Index: 0, + }, + } require.NoError(t, ds.EnqueueDeposits(ctx.ConsensusCtx(), genDeposits)) _, err := sp.InitializeBeaconStateFromEth1( - st, genDeposits, genPayloadHeader, cs.GenesisForkVersion(), + st, genDeposits, &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) @@ -185,22 +175,17 @@ func TestLocalDepositsExceedBlockDeposits(t *testing.T) { ) // Setup initial state with one validator - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x00}, - Credentials: credentials0, - Amount: maxBalance, - Index: 0, - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x00}, + Credentials: credentials0, + Amount: maxBalance, + Index: 0, + }, + } require.NoError(t, ds.EnqueueDeposits(ctx.ConsensusCtx(), genDeposits)) _, err = sp.InitializeBeaconStateFromEth1( - st, genDeposits, genPayloadHeader, cs.GenesisForkVersion(), + st, genDeposits, &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) @@ -256,22 +241,17 @@ func TestLocalDepositsExceedBlockDepositsBadRoot(t *testing.T) { ) // Setup initial state with one validator - var ( - genDeposits = types.Deposits{ - { - Pubkey: [48]byte{0x00}, - Credentials: credentials0, - Amount: maxBalance, - Index: 0, - }, - } - genPayloadHeader = &types.ExecutionPayloadHeader{ - Versionable: types.NewVersionable(cs.GenesisForkVersion()), - } - ) + genDeposits := types.Deposits{ + { + Pubkey: [48]byte{0x00}, + Credentials: credentials0, + Amount: maxBalance, + Index: 0, + }, + } require.NoError(t, ds.EnqueueDeposits(ctx.ConsensusCtx(), genDeposits)) _, err = sp.InitializeBeaconStateFromEth1( - st, genDeposits, genPayloadHeader, cs.GenesisForkVersion(), + st, genDeposits, &types.ExecutionPayloadHeader{}, cs.GenesisForkVersion(), ) require.NoError(t, err) diff --git a/storage/beacondb/eth1.go b/storage/beacondb/eth1.go index fb2db02486..fc6eec5a37 100644 --- a/storage/beacondb/eth1.go +++ b/storage/beacondb/eth1.go @@ -22,7 +22,8 @@ package beacondb import ( ctypes "github.com/berachain/beacon-kit/consensus-types/types" - "github.com/berachain/beacon-kit/primitives/bytes" + "github.com/berachain/beacon-kit/primitives/common" + "github.com/berachain/beacon-kit/primitives/version" ) // GetLatestExecutionPayloadHeader retrieves the latest execution payload @@ -30,30 +31,23 @@ import ( func (kv *KVStore) GetLatestExecutionPayloadHeader() ( *ctypes.ExecutionPayloadHeader, error, ) { - // NOTE: unmarshalling this struct is NOT affected by it's own fork version. The versioned - // codec is left in for backwards compatibility. - forkVersion, err := kv.latestExecutionPayloadVersion.Get(kv.ctx) - if err != nil { - return nil, err - } - kv.latestExecutionPayloadCodec.SetActiveForkVersion(bytes.FromUint32(forkVersion)) return kv.latestExecutionPayloadHeader.Get(kv.ctx) } // SetLatestExecutionPayloadHeader sets the latest execution payload header in // the BeaconStore. func (kv *KVStore) SetLatestExecutionPayloadHeader( - payloadHeader *ctypes.ExecutionPayloadHeader, + payloadHeader *ctypes.ExecutionPayloadHeader, forkVersion common.Version, ) error { - // NOTE: marshalling this struct is NOT affected by it's own fork version. The versioned - // codec is left in for backwards compatibility. - version := payloadHeader.GetForkVersion() - if err := kv.latestExecutionPayloadVersion.Set( - kv.ctx, version.ToUint32(), - ); err != nil { - return err + // NOTE: marshalling this struct is NOT affected by it's own fork version. + if version.IsBefore(forkVersion, version.Electra()) { + // The storage value of the fork version is left in for backwards compatibility for + // versions before Electra. + err := kv.latestExecutionPayloadVersion.Set(kv.ctx, forkVersion.ToUint32()) + if err != nil { + return err + } } - kv.latestExecutionPayloadCodec.SetActiveForkVersion(version) return kv.latestExecutionPayloadHeader.Set(kv.ctx, payloadHeader) } diff --git a/storage/beacondb/kvstore.go b/storage/beacondb/kvstore.go index 76ecb1669e..8a74fde903 100644 --- a/storage/beacondb/kvstore.go +++ b/storage/beacondb/kvstore.go @@ -57,11 +57,8 @@ type KVStore struct { // eth1DepositIndex is the index of the latest eth1 deposit. eth1DepositIndex sdkcollections.Item[uint64] // latestExecutionPayloadVersion stores the latest execution payload - // version. + // version. Kept for backwards compatibility for versions before Electra. latestExecutionPayloadVersion sdkcollections.Item[uint32] - // latestExecutionPayloadCodec is the codec for the latest execution - // payload, it allows us to update the codec with the latest version. - latestExecutionPayloadCodec *encoding.SSZVersionedValueCodec[*ctypes.ExecutionPayloadHeader] // latestExecutionPayloadHeader stores the latest execution payload header. latestExecutionPayloadHeader sdkcollections.Item[*ctypes.ExecutionPayloadHeader] // Registry @@ -105,9 +102,6 @@ type KVStore struct { func New(kss store.KVStoreService) *KVStore { var ( schemaBuilder = sdkcollections.NewSchemaBuilder(kss) - payloadCodec = &encoding.SSZVersionedValueCodec[*ctypes.ExecutionPayloadHeader]{ - NewEmptyF: ctypes.NewEmptyExecutionPayloadHeaderWithVersion, - } ) res := &KVStore{ @@ -168,14 +162,15 @@ func New(kss store.KVStoreService) *KVStore { keys.LatestExecutionPayloadVersionPrefixHumanReadable, sdkcollections.Uint32Value, ), - latestExecutionPayloadCodec: payloadCodec, latestExecutionPayloadHeader: sdkcollections.NewItem( schemaBuilder, sdkcollections.NewPrefix( []byte{keys.LatestExecutionPayloadHeaderPrefix}, ), keys.LatestExecutionPayloadHeaderPrefixHumanReadable, - payloadCodec, + encoding.SSZValueCodec[*ctypes.ExecutionPayloadHeader]{ + NewEmptyF: ctypes.NewEmptyExecutionPayloadHeader, + }, ), validatorIndex: sdkcollections.NewSequence( schemaBuilder, diff --git a/storage/encoding/ssz.go b/storage/encoding/ssz.go index 1f3751d5ea..2d56cbad9c 100644 --- a/storage/encoding/ssz.go +++ b/storage/encoding/ssz.go @@ -21,7 +21,6 @@ package encoding import ( - "github.com/berachain/beacon-kit/primitives/common" "github.com/berachain/beacon-kit/primitives/constraints" "github.com/berachain/beacon-kit/primitives/encoding/ssz" "github.com/davecgh/go-spew/spew" @@ -62,45 +61,3 @@ func (SSZValueCodec[T]) Stringify(value T) string { func (SSZValueCodec[T]) ValueType() string { return "SSZMarshallable" } - -// SSZVersionedValueCodec provides methods to encode and decode SSZ values for a specific version. -type SSZVersionedValueCodec[T constraints.SSZMarshallable] struct { - NewEmptyF func(common.Version) T // constructor - latestVersion common.Version -} - -// SetActiveForkVersion sets the fork version for the codec. -func (cdc *SSZVersionedValueCodec[T]) SetActiveForkVersion(version common.Version) { - cdc.latestVersion = version -} - -// Encode marshals the provided value into its SSZ encoding. -func (cdc *SSZVersionedValueCodec[T]) Encode(value T) ([]byte, error) { - return value.MarshalSSZ() -} - -// Decode unmarshals the provided bytes into a value of type T. -func (cdc *SSZVersionedValueCodec[T]) Decode(b []byte) (T, error) { - dest := cdc.NewEmptyF(cdc.latestVersion) - return dest, ssz.Unmarshal(b, dest) -} - -// EncodeJSON is not implemented and will panic if called. -func (cdc *SSZVersionedValueCodec[T]) EncodeJSON(_ T) ([]byte, error) { - panic("not implemented") -} - -// DecodeJSON is not implemented and will panic if called. -func (cdc *SSZVersionedValueCodec[T]) DecodeJSON(_ []byte) (T, error) { - panic("not implemented") -} - -// Stringify returns the string representation of the provided value. -func (cdc *SSZVersionedValueCodec[T]) Stringify(value T) string { - return spew.Sdump(value) -} - -// ValueType returns the name of the interface that this codec is intended for. -func (cdc *SSZVersionedValueCodec[T]) ValueType() string { - return "SSZVersionedMarshallable" -} diff --git a/testing/simulated/homedir.go b/testing/simulated/homedir.go index b5ba89ef69..a4469abd26 100644 --- a/testing/simulated/homedir.go +++ b/testing/simulated/homedir.go @@ -81,7 +81,7 @@ func InitializeHomeDir(t *testing.T, chainSpec chain.Spec, tempHomeDir string, e require.NoError(t, err, "failed to set deposit storage") // Add the execution payload to the genesis configuration. - err = genesis.AddExecutionPayload(chainSpec, path.Join(cometConfig.RootDir, filepath.Base(elGenesisPath)), cometConfig) + err = genesis.AddExecutionPayload(path.Join(cometConfig.RootDir, filepath.Base(elGenesisPath)), cometConfig) require.NoError(t, err, "failed to add execution payload") // Compute the validators root from the genesis file.