Skip to content

Commit

Permalink
feat(genesis): implement marshaler for executionPayloadHeader wrapper…
Browse files Browse the repository at this point in the history
… type (#1512)

Co-authored-by: Devon Bear <itsdevbear@berachain.com>
  • Loading branch information
archbear and itsdevbear authored Jun 18, 2024
1 parent 5c6111f commit eb477fe
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 111 deletions.
6 changes: 2 additions & 4 deletions mod/beacon/blockchain/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,13 @@ func (s *Service[
]) ProcessGenesisData(
ctx context.Context,
genesisData *genesis.Genesis[
DepositT, *types.ExecutionPayloadHeaderDeneb,
DepositT, *types.ExecutionPayloadHeader,
],
) ([]*transition.ValidatorUpdate, error) {
return s.sp.InitializePreminedBeaconStateFromEth1(
s.sb.StateFromContext(ctx),
genesisData.Deposits,
&types.ExecutionPayloadHeader{
InnerExecutionPayloadHeader: genesisData.ExecutionPayloadHeader,
},
genesisData.ExecutionPayloadHeader,
genesisData.ForkVersion,
)
}
Expand Down
2 changes: 1 addition & 1 deletion mod/cli/pkg/commands/genesis/collect.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func CollectGenesisDepositsCmd() *cobra.Command {

genesisInfo := &genesis.Genesis[
*types.Deposit,
*types.ExecutionPayloadHeaderDeneb,
*types.ExecutionPayloadHeader,
]{}

if err = json.Unmarshal(
Expand Down
162 changes: 90 additions & 72 deletions mod/cli/pkg/commands/genesis/payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/berachain/beacon-kit/mod/primitives"
"github.com/berachain/beacon-kit/mod/primitives/pkg/constants"
"github.com/berachain/beacon-kit/mod/primitives/pkg/math"
"github.com/berachain/beacon-kit/mod/primitives/pkg/version"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
Expand Down Expand Up @@ -87,24 +88,27 @@ func AddExecutionPayloadCmd() *cobra.Command {
}

genesisInfo := &genesis.Genesis[
*types.Deposit,
*types.ExecutionPayloadHeaderDeneb,
*types.Deposit, *types.ExecutionPayloadHeader,
]{}

if err = json.Unmarshal(
appGenesisState["beacon"], genesisInfo,
); err != nil {
return errors.Wrap(err, "failed to unmarshal beacon state")
}

// Inject the execution payload.
genesisInfo.ExecutionPayloadHeader, err =
executableDataToExecutionPayloadHeader(payload)
header, err := executableDataToExecutionPayloadHeader(
version.ToUint32(genesisInfo.ForkVersion),
payload,
)
if err != nil {
return errors.Wrap(
err,
"failed to convert executable data to execution payload header",
)
}
genesisInfo.ExecutionPayloadHeader = header

appGenesisState["beacon"], err = json.Marshal(genesisInfo)
if err != nil {
Expand All @@ -127,77 +131,91 @@ func AddExecutionPayloadCmd() *cobra.Command {
// Converts the eth executable data type to the beacon execution payload header
// interface.
func executableDataToExecutionPayloadHeader(
forkVersion uint32,
data *ethengineprimitives.ExecutableData,
) (*types.ExecutionPayloadHeaderDeneb, error) {
withdrawals := make([]*engineprimitives.Withdrawal, 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),
) (*types.ExecutionPayloadHeader, error) {
var executionPayloadHeader *types.ExecutionPayloadHeader
switch forkVersion {
case version.Deneb:
withdrawals := make(
[]*engineprimitives.Withdrawal,
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),
)
}

if len(data.ExtraData) > constants.ExtraDataLength {
data.ExtraData = data.ExtraData[:constants.ExtraDataLength]
}

var blobGasUsed uint64
if data.BlobGasUsed != nil {
blobGasUsed = *data.BlobGasUsed
}

var excessBlobGas uint64
if data.ExcessBlobGas != nil {
excessBlobGas = *data.ExcessBlobGas
}

// Get the merkle roots of transactions and withdrawals in parallel.
var (
g, _ = errgroup.WithContext(context.Background())
txsRoot primitives.Root
withdrawalsRoot primitives.Root
)
}

if len(data.ExtraData) > constants.ExtraDataLength {
data.ExtraData = data.ExtraData[:constants.ExtraDataLength]
}

var blobGasUsed uint64
if data.BlobGasUsed != nil {
blobGasUsed = *data.BlobGasUsed
}

var excessBlobGas uint64
if data.ExcessBlobGas != nil {
excessBlobGas = *data.ExcessBlobGas
}

// Get the merkle roots of transactions and withdrawals in parallel.
var (
g, _ = errgroup.WithContext(context.Background())
txsRoot primitives.Root
withdrawalsRoot primitives.Root
)

g.Go(func() error {
var txsRootErr error
txsRoot, txsRootErr = engineprimitives.Transactions(
data.Transactions,
).HashTreeRoot()
return txsRootErr
})

g.Go(func() error {
var withdrawalsRootErr error
withdrawalsRoot, withdrawalsRootErr = engineprimitives.Withdrawals(
withdrawals,
).HashTreeRoot()
return withdrawalsRootErr
})

// If deriving either of the roots fails, return the error.
if err := g.Wait(); err != nil {
return nil, err
}

executionPayloadHeader := &types.ExecutionPayloadHeaderDeneb{
ParentHash: data.ParentHash,
FeeRecipient: data.FeeRecipient,
StateRoot: primitives.Bytes32(data.StateRoot),
ReceiptsRoot: primitives.Bytes32(data.ReceiptsRoot),
LogsBloom: data.LogsBloom,
Random: primitives.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,
BaseFeePerGas: math.MustNewU256LFromBigInt(data.BaseFeePerGas),
BlockHash: data.BlockHash,
TransactionsRoot: txsRoot,
WithdrawalsRoot: withdrawalsRoot,
BlobGasUsed: math.U64(blobGasUsed),
ExcessBlobGas: math.U64(excessBlobGas),
g.Go(func() error {
var txsRootErr error
txsRoot, txsRootErr = engineprimitives.Transactions(
data.Transactions,
).HashTreeRoot()
return txsRootErr
})

g.Go(func() error {
var withdrawalsRootErr error
withdrawalsRoot, withdrawalsRootErr = engineprimitives.Withdrawals(
withdrawals,
).HashTreeRoot()
return withdrawalsRootErr
})

// If deriving either of the roots fails, return the error.
if err := g.Wait(); err != nil {
return nil, err
}

executionPayloadHeader = &types.ExecutionPayloadHeader{
InnerExecutionPayloadHeader: &types.ExecutionPayloadHeaderDeneb{
ParentHash: data.ParentHash,
FeeRecipient: data.FeeRecipient,
StateRoot: primitives.Bytes32(data.StateRoot),
ReceiptsRoot: primitives.Bytes32(data.ReceiptsRoot),
LogsBloom: data.LogsBloom,
Random: primitives.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,
BaseFeePerGas: math.MustNewU256LFromBigInt(
data.BaseFeePerGas,
),
BlockHash: data.BlockHash,
TransactionsRoot: txsRoot,
WithdrawalsRoot: withdrawalsRoot,
BlobGasUsed: math.U64(blobGasUsed),
ExcessBlobGas: math.U64(excessBlobGas),
}}
default:
return nil, errors.Newf("unsupported fork version %d", forkVersion)
}

return executionPayloadHeader, nil
Expand Down
51 changes: 45 additions & 6 deletions mod/consensus-types/pkg/genesis/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package genesis

import (
"context"
"encoding/json"
"math/big"

"github.com/berachain/beacon-kit/mod/consensus-types/pkg/types"
Expand All @@ -36,9 +37,13 @@ import (

// Genesis is a struct that contains the genesis information
// need to start the beacon chain.
//
//nolint:lll
type Genesis[
DepositT any,
ExecutonPayloadHeaderT any,
ExecutionPayloadHeaderT interface {
NewFromJSON([]byte, uint32) (ExecutionPayloadHeaderT, error)
},
] struct {
// ForkVersion is the fork version of the genesis slot.
ForkVersion primitives.Version `json:"fork_version"`
Expand All @@ -49,12 +54,44 @@ type Genesis[

// ExecutionPayloadHeader is the header of the execution payload
// in the genesis.
ExecutionPayloadHeader ExecutonPayloadHeaderT `json:"execution_payload_header"`
ExecutionPayloadHeader ExecutionPayloadHeaderT `json:"execution_payload_header"`
}

// UnmarshalJSON for Genesis.
func (g *Genesis[DepositT, ExecutionPayloadHeaderT]) UnmarshalJSON(
data []byte,
) error {
type genesisMarshalable[Deposit any] struct {
ForkVersion primitives.Version `json:"fork_version"`
Deposits []DepositT `json:"deposits"`
ExecutionPayloadHeader json.RawMessage `json:"execution_payload_header"`
}
var g2 genesisMarshalable[DepositT]
if err := json.Unmarshal(data, &g2); err != nil {
return err
}

var (
payloadHeader ExecutionPayloadHeaderT
err error
)
payloadHeader, err = payloadHeader.NewFromJSON(
g2.ExecutionPayloadHeader,
version.ToUint32(g2.ForkVersion),
)
if err != nil {
return err
}

g.Deposits = g2.Deposits
g.ForkVersion = g2.ForkVersion
g.ExecutionPayloadHeader = payloadHeader
return nil
}

// DefaultGenesis returns a the default genesis.
func DefaultGenesisDeneb() *Genesis[
*types.Deposit, *types.ExecutionPayloadHeaderDeneb,
*types.Deposit, *types.ExecutionPayloadHeader,
] {
defaultHeader, err :=
DefaultGenesisExecutionPayloadHeaderDeneb()
Expand All @@ -63,12 +100,14 @@ func DefaultGenesisDeneb() *Genesis[
}

// TODO: Uncouple from deneb.
return &Genesis[*types.Deposit, *types.ExecutionPayloadHeaderDeneb]{
return &Genesis[*types.Deposit, *types.ExecutionPayloadHeader]{
ForkVersion: version.FromUint32[primitives.Version](
version.Deneb,
),
Deposits: make([]*types.Deposit, 0),
ExecutionPayloadHeader: defaultHeader,
Deposits: make([]*types.Deposit, 0),
ExecutionPayloadHeader: &types.ExecutionPayloadHeader{
InnerExecutionPayloadHeader: defaultHeader,
},
}
}

Expand Down
10 changes: 5 additions & 5 deletions mod/consensus-types/pkg/genesis/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ func TestDefaultGenesisDeneb(t *testing.T) {
t.Errorf("Expected ExecutionPayloadHeader to be non-nil")
}

require.Equal(t, common.ZeroHash, payloadHeader.ParentHash,
require.Equal(t, common.ZeroHash, payloadHeader.GetParentHash(),
"Unexpected ParentHash")
require.Equal(t, common.ZeroAddress, payloadHeader.FeeRecipient,
require.Equal(t, common.ZeroAddress, payloadHeader.GetFeeRecipient(),
"Unexpected FeeRecipient")
require.Equal(t, math.U64(30000000), payloadHeader.GasLimit,
require.Equal(t, math.U64(30000000), payloadHeader.GetGasLimit(),
"Unexpected GasLimit")
require.Equal(t, math.U64(0), payloadHeader.GasUsed,
require.Equal(t, math.U64(0), payloadHeader.GetGasUsed(),
"Unexpected GasUsed")
require.Equal(t, math.U64(0), payloadHeader.Timestamp,
require.Equal(t, math.U64(0), payloadHeader.GetTimestamp(),
"Unexpected Timestamp")
}

Expand Down
14 changes: 9 additions & 5 deletions mod/consensus-types/pkg/types/payload_header.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,15 @@ func (e *ExecutionPayloadHeader) NewFromSSZ(
return e, nil
}

// UnmarshalJSON unmarshals the JSON bytes into the ExecutionPayloadHeader.
func (e *ExecutionPayloadHeader) UnmarshalJSON(bz []byte) error {
// TODO: Generalize somehow.
e = e.Empty(version.Deneb)
return e.InnerExecutionPayloadHeader.UnmarshalJSON(bz)
// NewFromJSON returns a new ExecutionPayloadHeader from the given JSON bytes.
func (e *ExecutionPayloadHeader) NewFromJSON(
bz []byte, forkVersion uint32,
) (*ExecutionPayloadHeader, error) {
e = e.Empty(forkVersion)
if err := e.UnmarshalJSON(bz); err != nil {
return nil, err
}
return e, nil
}

// ExecutionPayloadHeaderDeneb is the execution header payload of Deneb.
Expand Down
2 changes: 1 addition & 1 deletion mod/consensus-types/pkg/types/payload_header.ssz.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit eb477fe

Please sign in to comment.