beacon/engine, eth/catalyst, miner: add beaconroot to miner and CL api surface

miner, beacon/engine: process systemtx, update json tag
This commit is contained in:
Martin Holst Swende 2023-08-07 13:14:07 +02:00 committed by Felix Lange
parent 6b98d18789
commit 14eb33e5f9
8 changed files with 49 additions and 2 deletions

View file

@ -20,12 +20,14 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
Random common.Hash `json:"prevRandao" gencodec:"required"`
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
}
var enc PayloadAttributes
enc.Timestamp = hexutil.Uint64(p.Timestamp)
enc.Random = p.Random
enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
enc.Withdrawals = p.Withdrawals
enc.BeaconRoot = p.BeaconRoot
return json.Marshal(&enc)
}
@ -36,6 +38,7 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
Random *common.Hash `json:"prevRandao" gencodec:"required"`
SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
}
var dec PayloadAttributes
if err := json.Unmarshal(input, &dec); err != nil {
@ -56,5 +59,8 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
if dec.Withdrawals != nil {
p.Withdrawals = dec.Withdrawals
}
if dec.BeaconRoot != nil {
p.BeaconRoot = dec.BeaconRoot
}
return nil
}

View file

@ -34,6 +34,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
BeaconRoot *common.Hash `json:"beaconRoot"`
}
var enc ExecutableData
enc.ParentHash = e.ParentHash
@ -58,6 +59,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
enc.Withdrawals = e.Withdrawals
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
enc.BeaconRoot = e.BeaconRoot
return json.Marshal(&enc)
}
@ -81,6 +83,7 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
BeaconRoot *common.Hash `json:"beaconRoot"`
}
var dec ExecutableData
if err := json.Unmarshal(input, &dec); err != nil {
@ -154,5 +157,8 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
if dec.ExcessBlobGas != nil {
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
}
if dec.BeaconRoot != nil {
e.BeaconRoot = dec.BeaconRoot
}
return nil
}

View file

@ -35,6 +35,7 @@ type PayloadAttributes struct {
Random common.Hash `json:"prevRandao" gencodec:"required"`
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
}
// JSON type overrides for PayloadAttributes.
@ -63,6 +64,7 @@ type ExecutableData struct {
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *uint64 `json:"blobGasUsed"`
ExcessBlobGas *uint64 `json:"excessBlobGas"`
BeaconRoot *common.Hash `json:"beaconRoot"`
}
// JSON type overrides for executableData.
@ -225,7 +227,7 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash)
WithdrawalsHash: withdrawalsRoot,
ExcessBlobGas: params.ExcessBlobGas,
BlobGasUsed: params.BlobGasUsed,
// TODO BeaconRoot
BeaconRoot: params.BeaconRoot,
}
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals)
if block.Hash() != params.BlockHash {
@ -255,7 +257,7 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
Withdrawals: block.Withdrawals(),
BlobGasUsed: block.BlobGasUsed(),
ExcessBlobGas: block.ExcessBlobGas(),
// TODO BeaconRoot
BeaconRoot: block.BeaconRoot(),
}
bundle := BlobsBundleV1{
Commitments: make([]hexutil.Bytes, 0),

View file

@ -350,6 +350,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
FeeRecipient: payloadAttributes.SuggestedFeeRecipient,
Random: payloadAttributes.Random,
Withdrawals: payloadAttributes.Withdrawals,
BeaconRoot: payloadAttributes.BeaconRoot,
}
id := args.Id()
// If we already are busy generating this work, then we do not need
@ -462,6 +463,9 @@ func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHas
if versionedHashes != nil {
hashes = *versionedHashes
}
if params.BeaconRoot == nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun"))
}
return api.newPayload(params, hashes)
}

View file

@ -204,6 +204,7 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
Timestamp: blockParams.Timestamp,
FeeRecipient: blockParams.SuggestedFeeRecipient,
Random: blockParams.Random,
BeaconRoot: blockParams.BeaconRoot,
}).Id()
execData, err := api.GetPayloadV1(payloadID)
if err != nil {
@ -667,6 +668,7 @@ func assembleBlock(api *ConsensusAPI, parentHash common.Hash, params *engine.Pay
FeeRecipient: params.SuggestedFeeRecipient,
Random: params.Random,
Withdrawals: params.Withdrawals,
BeaconRoot: params.BeaconRoot,
}
payload, err := api.eth.Miner().BuildPayload(args)
if err != nil {
@ -1068,6 +1070,7 @@ func TestWithdrawals(t *testing.T) {
FeeRecipient: blockParams.SuggestedFeeRecipient,
Random: blockParams.Random,
Withdrawals: blockParams.Withdrawals,
BeaconRoot: blockParams.BeaconRoot,
}).Id()
execData, err := api.GetPayloadV2(payloadID)
if err != nil {
@ -1115,6 +1118,7 @@ func TestWithdrawals(t *testing.T) {
FeeRecipient: blockParams.SuggestedFeeRecipient,
Random: blockParams.Random,
Withdrawals: blockParams.Withdrawals,
BeaconRoot: blockParams.BeaconRoot,
}).Id()
execData, err = api.GetPayloadV2(payloadID)
if err != nil {
@ -1245,6 +1249,7 @@ func TestNilWithdrawals(t *testing.T) {
Timestamp: test.blockParams.Timestamp,
FeeRecipient: test.blockParams.SuggestedFeeRecipient,
Random: test.blockParams.Random,
BeaconRoot: test.blockParams.BeaconRoot,
}).Id()
execData, err := api.GetPayloadV2(payloadID)
if err != nil {

View file

@ -40,6 +40,7 @@ type BuildPayloadArgs struct {
FeeRecipient common.Address // The provided recipient address for collecting transaction fee
Random common.Hash // The provided randomness value
Withdrawals types.Withdrawals // The provided withdrawals
BeaconRoot *common.Hash // The provided beaconRoot (Cancun)
}
// Id computes an 8-byte identifier by hashing the components of the payload arguments.
@ -51,6 +52,9 @@ func (args *BuildPayloadArgs) Id() engine.PayloadID {
hasher.Write(args.Random[:])
hasher.Write(args.FeeRecipient[:])
rlp.Encode(hasher, args.Withdrawals)
if args.BeaconRoot != nil {
hasher.Write(args.BeaconRoot[:])
}
var out engine.PayloadID
copy(out[:], hasher.Sum(nil)[:8])
return out
@ -182,6 +186,7 @@ func (w *worker) buildPayload(args *BuildPayloadArgs) (*Payload, error) {
coinbase: args.FeeRecipient,
random: args.Random,
withdrawals: args.Withdrawals,
beaconRoot: args.BeaconRoot,
noTxs: true,
}
empty := w.getSealingBlock(emptyParams)
@ -212,6 +217,7 @@ func (w *worker) buildPayload(args *BuildPayloadArgs) (*Payload, error) {
coinbase: args.FeeRecipient,
random: args.Random,
withdrawals: args.Withdrawals,
beaconRoot: args.BeaconRoot,
noTxs: false,
}

View file

@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
@ -860,6 +861,7 @@ type generateParams struct {
coinbase common.Address // The fee recipient address for including transaction
random common.Hash // The randomness generated by beacon chain, empty before the merge
withdrawals types.Withdrawals // List of withdrawals to include in block.
beaconRoot *common.Hash // The beacon root (cancun field).
noTxs bool // Flag whether an empty block without any transaction is expected
}
@ -912,6 +914,7 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
header.GasLimit = core.CalcGasLimit(parentGasLimit, w.config.GasCeil)
}
}
// Apply EIP-4844, EIP-4788.
if w.chainConfig.IsCancun(header.Number, header.Time) {
var excessBlobGas uint64
if w.chainConfig.IsCancun(parent.Number, parent.Time) {
@ -921,6 +924,7 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
excessBlobGas = eip4844.CalcExcessBlobGas(0, 0)
}
header.ExcessBlobGas = &excessBlobGas
header.BeaconRoot = genParams.beaconRoot
}
// Run the consensus preparation with the default or customized consensus engine.
if err := w.engine.Prepare(w.chain, header); err != nil {
@ -935,6 +939,18 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
log.Error("Failed to create sealing context", "err", err)
return nil, err
}
if w.chainConfig.IsCancun(header.Number, header.Time) {
if header.BeaconRoot == nil {
// Failure: we are unable to construct a block if we do not have
// the beacon root.
err = errors.New("missing parentBeaconRoot")
log.Error("Failed to construct block", "err", err)
return nil, err
}
context := core.NewEVMBlockContext(header, w.chain, nil)
vmenv := vm.NewEVM(context, vm.TxContext{}, env.state, w.chainConfig, vm.Config{})
core.ProcessBeaconBlockRoot(*header.BeaconRoot, vmenv, env.state)
}
return env, nil
}

View file

@ -458,6 +458,7 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co
coinbase: c.coinbase,
random: c.random,
withdrawals: nil,
beaconRoot: nil,
noTxs: false,
forceTime: true,
})
@ -482,6 +483,7 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co
coinbase: c.coinbase,
random: c.random,
withdrawals: nil,
beaconRoot: nil,
noTxs: false,
forceTime: true,
})