Skip to content

Commit 6aa88cc

Browse files
authored
beacon/engine, eth/catalyst, miner: EIP-4788 CL/EL protocol updates (#27872)
This PR makes EIP-4788 work in the engine API and miner. It also fixes some bugs related to EIP-4844 block processing and mining. Changes in detail: - Header.BeaconRoot has been renamed to ParentBeaconRoot. - The engine API now implements forkchoiceUpdatedV3 - newPayloadV3 method has been updated with the parentBeaconBlockRoot parameter - beacon root is now applied to new blocks in miner - For EIP-4844, block creation now updates the blobGasUsed field of the header
1 parent cde462c commit 6aa88cc

17 files changed

+299
-124
lines changed

beacon/engine/errors.go

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ var (
8080
InvalidPayloadAttributes = &EngineAPIError{code: -38003, msg: "Invalid payload attributes"}
8181
TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"}
8282
InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"}
83+
UnsupportedFork = &EngineAPIError{code: -38005, msg: "Unsupported fork"}
8384

8485
STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil}
8586
STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil}

beacon/engine/gen_blockparams.go

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

beacon/engine/types.go

+21-21
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ type PayloadAttributes struct {
3535
Random common.Hash `json:"prevRandao" gencodec:"required"`
3636
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
3737
Withdrawals []*types.Withdrawal `json:"withdrawals"`
38+
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
3839
}
3940

4041
// JSON type overrides for PayloadAttributes.
@@ -171,7 +172,7 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
171172
// and that the blockhash of the constructed block matches the parameters. Nil
172173
// Withdrawals value will propagate through the returned block. Empty
173174
// Withdrawals value must be passed via non-nil, length 0 value in params.
174-
func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash) (*types.Block, error) {
175+
func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
175176
txs, err := decodeTransactions(params.Transactions)
176177
if err != nil {
177178
return nil, err
@@ -207,25 +208,25 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash)
207208
withdrawalsRoot = &h
208209
}
209210
header := &types.Header{
210-
ParentHash: params.ParentHash,
211-
UncleHash: types.EmptyUncleHash,
212-
Coinbase: params.FeeRecipient,
213-
Root: params.StateRoot,
214-
TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
215-
ReceiptHash: params.ReceiptsRoot,
216-
Bloom: types.BytesToBloom(params.LogsBloom),
217-
Difficulty: common.Big0,
218-
Number: new(big.Int).SetUint64(params.Number),
219-
GasLimit: params.GasLimit,
220-
GasUsed: params.GasUsed,
221-
Time: params.Timestamp,
222-
BaseFee: params.BaseFeePerGas,
223-
Extra: params.ExtraData,
224-
MixDigest: params.Random,
225-
WithdrawalsHash: withdrawalsRoot,
226-
ExcessBlobGas: params.ExcessBlobGas,
227-
BlobGasUsed: params.BlobGasUsed,
228-
// TODO BeaconRoot
211+
ParentHash: params.ParentHash,
212+
UncleHash: types.EmptyUncleHash,
213+
Coinbase: params.FeeRecipient,
214+
Root: params.StateRoot,
215+
TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
216+
ReceiptHash: params.ReceiptsRoot,
217+
Bloom: types.BytesToBloom(params.LogsBloom),
218+
Difficulty: common.Big0,
219+
Number: new(big.Int).SetUint64(params.Number),
220+
GasLimit: params.GasLimit,
221+
GasUsed: params.GasUsed,
222+
Time: params.Timestamp,
223+
BaseFee: params.BaseFeePerGas,
224+
Extra: params.ExtraData,
225+
MixDigest: params.Random,
226+
WithdrawalsHash: withdrawalsRoot,
227+
ExcessBlobGas: params.ExcessBlobGas,
228+
BlobGasUsed: params.BlobGasUsed,
229+
ParentBeaconRoot: beaconRoot,
229230
}
230231
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals)
231232
if block.Hash() != params.BlockHash {
@@ -255,7 +256,6 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
255256
Withdrawals: block.Withdrawals(),
256257
BlobGasUsed: block.BlobGasUsed(),
257258
ExcessBlobGas: block.ExcessBlobGas(),
258-
// TODO BeaconRoot
259259
}
260260
bundle := BlobsBundleV1{
261261
Commitments: make([]hexutil.Bytes, 0),

consensus/beacon/consensus.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,11 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
277277
return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
278278
case header.BlobGasUsed != nil:
279279
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
280-
case header.BeaconRoot != nil:
281-
return fmt.Errorf("invalid beaconRoot, have %#x, expected nil", header.BeaconRoot)
280+
case header.ParentBeaconRoot != nil:
281+
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot)
282282
}
283283
} else {
284-
if header.BeaconRoot == nil {
284+
if header.ParentBeaconRoot == nil {
285285
return errors.New("header is missing beaconRoot")
286286
}
287287
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {

core/chain_makers.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
411411
excessBlobGas := eip4844.CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed)
412412
header.ExcessBlobGas = &excessBlobGas
413413
header.BlobGasUsed = new(uint64)
414-
header.BeaconRoot = new(common.Hash)
414+
header.ParentBeaconRoot = new(common.Hash)
415415
}
416416
return header
417417
}

core/genesis.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,11 @@ func (g *Genesis) ToBlock() *types.Block {
483483
withdrawals = make([]*types.Withdrawal, 0)
484484
}
485485
if conf.IsCancun(num, g.Timestamp) {
486+
// EIP-4788: The parentBeaconBlockRoot of the genesis block is always
487+
// the zero hash. This is because the genesis block does not have a parent
488+
// by definition.
489+
head.ParentBeaconRoot = new(common.Hash)
490+
// EIP-4844 fields
486491
head.ExcessBlobGas = g.ExcessBlobGas
487492
head.BlobGasUsed = g.BlobGasUsed
488493
if head.ExcessBlobGas == nil {
@@ -491,9 +496,6 @@ func (g *Genesis) ToBlock() *types.Block {
491496
if head.BlobGasUsed == nil {
492497
head.BlobGasUsed = new(uint64)
493498
}
494-
if head.BeaconRoot == nil {
495-
head.BeaconRoot = new(common.Hash)
496-
}
497499
}
498500
}
499501
return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals)

core/state_processor.go

+3
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta
135135
receipt.TxHash = tx.Hash()
136136
receipt.GasUsed = result.UsedGas
137137

138+
receipt.BlobGasUsed = uint64(len(tx.BlobHashes()) * params.BlobTxBlobGasPerBlob)
139+
receipt.BlobGasPrice = tx.BlobGasFeeCap()
140+
138141
// If the transaction created a contract, store the creation address in the receipt.
139142
if msg.To == nil {
140143
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())

core/state_processor_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
412412
header.BlobGasUsed = &used
413413

414414
beaconRoot := common.HexToHash("0xbeac00")
415-
header.BeaconRoot = &beaconRoot
415+
header.ParentBeaconRoot = &beaconRoot
416416
}
417417
// Assemble and return the final block for sealing
418418
if config.IsShanghai(header.Number, header.Time) {

core/types/block.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ type Header struct {
9191
// ExcessBlobGas was added by EIP-4844 and is ignored in legacy headers.
9292
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
9393

94-
// BeaconRoot was added by EIP-4788 and is ignored in legacy headers.
95-
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
94+
// ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers.
95+
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
9696
}
9797

9898
// field type overrides for gencodec
@@ -300,9 +300,9 @@ func CopyHeader(h *Header) *Header {
300300
cpy.BlobGasUsed = new(uint64)
301301
*cpy.BlobGasUsed = *h.BlobGasUsed
302302
}
303-
if h.BeaconRoot != nil {
304-
cpy.BeaconRoot = new(common.Hash)
305-
*cpy.BeaconRoot = *h.BeaconRoot
303+
if h.ParentBeaconRoot != nil {
304+
cpy.ParentBeaconRoot = new(common.Hash)
305+
*cpy.ParentBeaconRoot = *h.ParentBeaconRoot
306306
}
307307
return &cpy
308308
}
@@ -383,7 +383,7 @@ func (b *Block) BaseFee() *big.Int {
383383
return new(big.Int).Set(b.header.BaseFee)
384384
}
385385

386-
func (b *Block) BeaconRoot() *common.Hash { return b.header.BeaconRoot }
386+
func (b *Block) BeaconRoot() *common.Hash { return b.header.ParentBeaconRoot }
387387

388388
func (b *Block) ExcessBlobGas() *uint64 {
389389
var excessBlobGas *uint64

core/types/gen_header_json.go

+44-44
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/types/gen_header_rlp.go

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)