From c67e5a64280cee7c379e6ec642d4d70cf9eb63eb Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Mon, 13 May 2024 15:27:10 +0200 Subject: [PATCH 1/5] eth/catalyst: fix api --- eth/catalyst/api.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 0a674ba27b71..99552d8baa8c 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -230,7 +230,11 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa // hash, even if params are wrong. To do this we need to split up // forkchoiceUpdate into a function that only updates the head and then a // function that kicks off block construction. - return api.forkchoiceUpdated(update, params, engine.PayloadV3, false) + payloadVersion := engine.PayloadV3 + if api.eth.BlockChain().Config().LatestFork(params.Timestamp) == forks.Prague { + payloadVersion = engine.PayloadV4 + } + return api.forkchoiceUpdated(update, params, payloadVersion, false) } func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, payloadVersion engine.PayloadVersion, simulatorMode bool) (engine.ForkChoiceResponse, error) { From 3fe5eb35e1c2e91fd47f5a11395d6c5910ff848b Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Mon, 13 May 2024 15:45:08 +0200 Subject: [PATCH 2/5] eth/catalyst: fix api --- eth/catalyst/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 99552d8baa8c..b6d3bcb0186f 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -231,7 +231,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa // forkchoiceUpdate into a function that only updates the head and then a // function that kicks off block construction. payloadVersion := engine.PayloadV3 - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) == forks.Prague { + if params != nil && api.eth.BlockChain().Config().LatestFork(params.Timestamp) == forks.Prague { payloadVersion = engine.PayloadV4 } return api.forkchoiceUpdated(update, params, payloadVersion, false) From 73d0f304d441e6f40e1489b7ea59417140165150 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Mon, 13 May 2024 16:28:05 +0200 Subject: [PATCH 3/5] miner: process deposit requests --- miner/worker.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/miner/worker.go b/miner/worker.go index 91c4836e53dc..831f9a8aa0fd 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -105,7 +105,24 @@ func (miner *Miner) generateWork(params *generateParams) *newPayloadResult { log.Warn("Block building is interrupted", "allowance", common.PrettyDuration(miner.config.Recommit)) } } + body := types.Body{Transactions: work.txs, Withdrawals: params.withdrawals} + allLogs := make([]*types.Log, 0) + for _, r := range work.receipts { + allLogs = append(allLogs, r.Logs...) + } + // Read requests if Prague is enabled. + if miner.chainConfig.IsPrague(work.header.Number, work.header.Time) { + requests, err := core.ParseDepositLogs(allLogs) + if err != nil { + return &newPayloadResult{err: err} + } + context := core.NewEVMBlockContext(work.header, miner.chain, nil) + vmenv := vm.NewEVM(context, vm.TxContext{}, work.state, miner.chainConfig, vm.Config{}) + wxs := core.ProcessDequeueWithdrawalRequests(vmenv, work.state) + requests = append(requests, wxs...) + body.Requests = requests + } block, err := miner.engine.FinalizeAndAssemble(miner.chain, work.header, work.state, &body, work.receipts) if err != nil { return &newPayloadResult{err: err} From 0b7097db913c84f09595d41b65fbf46f0f6882ad Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Mon, 13 May 2024 16:59:46 +0200 Subject: [PATCH 4/5] nil reqs --- miner/worker.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/miner/worker.go b/miner/worker.go index 831f9a8aa0fd..316cf51b52f6 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -113,10 +113,12 @@ func (miner *Miner) generateWork(params *generateParams) *newPayloadResult { } // Read requests if Prague is enabled. if miner.chainConfig.IsPrague(work.header.Number, work.header.Time) { - requests, err := core.ParseDepositLogs(allLogs) + requests := make(types.Requests, 0) + reqs, err := core.ParseDepositLogs(allLogs) if err != nil { return &newPayloadResult{err: err} } + requests = append(requests, reqs...) context := core.NewEVMBlockContext(work.header, miner.chain, nil) vmenv := vm.NewEVM(context, vm.TxContext{}, work.state, miner.chainConfig, vm.Config{}) wxs := core.ProcessDequeueWithdrawalRequests(vmenv, work.state) From 704d0f2ae897a72d5e30df96de49ddd91ff76ffe Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Mon, 13 May 2024 17:38:44 +0200 Subject: [PATCH 5/5] eth/catalyst: fix api --- beacon/engine/gen_ed.go | 80 ++++++++++++++++++-------------- beacon/engine/types.go | 3 ++ eth/catalyst/simulated_beacon.go | 2 +- 3 files changed, 50 insertions(+), 35 deletions(-) diff --git a/beacon/engine/gen_ed.go b/beacon/engine/gen_ed.go index 6893d64a1626..64e4453d4bd7 100644 --- a/beacon/engine/gen_ed.go +++ b/beacon/engine/gen_ed.go @@ -17,23 +17,25 @@ var _ = (*executableDataMarshaling)(nil) // MarshalJSON marshals as JSON. func (e ExecutableData) MarshalJSON() ([]byte, error) { type ExecutableData struct { - ParentHash common.Hash `json:"parentHash" gencodec:"required"` - FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` - StateRoot common.Hash `json:"stateRoot" gencodec:"required"` - ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"` - LogsBloom hexutil.Bytes `json:"logsBloom" gencodec:"required"` - Random common.Hash `json:"prevRandao" gencodec:"required"` - Number hexutil.Uint64 `json:"blockNumber" gencodec:"required"` - GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` - ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"` - BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` - BlockHash common.Hash `json:"blockHash" gencodec:"required"` - Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` + ParentHash common.Hash `json:"parentHash" gencodec:"required"` + FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` + StateRoot common.Hash `json:"stateRoot" gencodec:"required"` + ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"` + LogsBloom hexutil.Bytes `json:"logsBloom" gencodec:"required"` + Random common.Hash `json:"prevRandao" gencodec:"required"` + Number hexutil.Uint64 `json:"blockNumber" gencodec:"required"` + GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` + ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"` + BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` + BlockHash common.Hash `json:"blockHash" gencodec:"required"` + Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` + Withdrawals []*types.Withdrawal `json:"withdrawals"` + BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` + ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` + Deposits types.Deposits `json:"depositRequests"` + WithdrawalRequests types.WithdrawalRequests `json:"withdrawalRequests"` } var enc ExecutableData enc.ParentHash = e.ParentHash @@ -58,29 +60,33 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) { enc.Withdrawals = e.Withdrawals enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed) enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas) + enc.Deposits = e.Deposits + enc.WithdrawalRequests = e.WithdrawalRequests return json.Marshal(&enc) } // UnmarshalJSON unmarshals from JSON. func (e *ExecutableData) UnmarshalJSON(input []byte) error { type ExecutableData struct { - ParentHash *common.Hash `json:"parentHash" gencodec:"required"` - FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"` - StateRoot *common.Hash `json:"stateRoot" gencodec:"required"` - ReceiptsRoot *common.Hash `json:"receiptsRoot" gencodec:"required"` - LogsBloom *hexutil.Bytes `json:"logsBloom" gencodec:"required"` - Random *common.Hash `json:"prevRandao" gencodec:"required"` - Number *hexutil.Uint64 `json:"blockNumber" gencodec:"required"` - GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` - ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"` - BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` - BlockHash *common.Hash `json:"blockHash" gencodec:"required"` - Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` + ParentHash *common.Hash `json:"parentHash" gencodec:"required"` + FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"` + StateRoot *common.Hash `json:"stateRoot" gencodec:"required"` + ReceiptsRoot *common.Hash `json:"receiptsRoot" gencodec:"required"` + LogsBloom *hexutil.Bytes `json:"logsBloom" gencodec:"required"` + Random *common.Hash `json:"prevRandao" gencodec:"required"` + Number *hexutil.Uint64 `json:"blockNumber" gencodec:"required"` + GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` + ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"` + BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` + BlockHash *common.Hash `json:"blockHash" gencodec:"required"` + Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` + Withdrawals []*types.Withdrawal `json:"withdrawals"` + BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` + ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` + Deposits *types.Deposits `json:"depositRequests"` + WithdrawalRequests *types.WithdrawalRequests `json:"withdrawalRequests"` } var dec ExecutableData if err := json.Unmarshal(input, &dec); err != nil { @@ -154,5 +160,11 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error { if dec.ExcessBlobGas != nil { e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) } + if dec.Deposits != nil { + e.Deposits = *dec.Deposits + } + if dec.WithdrawalRequests != nil { + e.WithdrawalRequests = *dec.WithdrawalRequests + } return nil } diff --git a/beacon/engine/types.go b/beacon/engine/types.go index 0ba338b3af91..33e847364a3f 100644 --- a/beacon/engine/types.go +++ b/beacon/engine/types.go @@ -241,9 +241,12 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash, requests types.Requests ) if params.Deposits != nil { + requests = make(types.Requests, 0) requests = append(requests, params.Deposits.Requests()...) } if params.WithdrawalRequests != nil { + // We assume that withdrawal reqs are non-nil only if deposits are non-nil + // (both can be empty) requests = append(requests, params.WithdrawalRequests.Requests()...) } if requests != nil { diff --git a/eth/catalyst/simulated_beacon.go b/eth/catalyst/simulated_beacon.go index 77aeba336af4..77fb51e727d8 100644 --- a/eth/catalyst/simulated_beacon.go +++ b/eth/catalyst/simulated_beacon.go @@ -164,7 +164,7 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u Withdrawals: withdrawals, Random: random, BeaconRoot: &common.Hash{}, - }, engine.PayloadV3, true) + }, engine.PayloadV4, true) if err != nil { return err }