Skip to content

Commit

Permalink
all: implement eip-7002 EL triggered withdrawal requests
Browse files Browse the repository at this point in the history
  • Loading branch information
lightclient committed Aug 16, 2024
1 parent 94ea9c8 commit 96633cb
Show file tree
Hide file tree
Showing 12 changed files with 478 additions and 125 deletions.
78 changes: 42 additions & 36 deletions beacon/engine/gen_ed.go

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

68 changes: 42 additions & 26 deletions beacon/engine/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,24 +60,25 @@ type payloadAttributesMarshaling struct {

// ExecutableData is the data necessary to execute an EL payload.
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 []byte `json:"logsBloom" gencodec:"required"`
Random common.Hash `json:"prevRandao" gencodec:"required"`
Number uint64 `json:"blockNumber" gencodec:"required"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
Timestamp uint64 `json:"timestamp" gencodec:"required"`
ExtraData []byte `json:"extraData" gencodec:"required"`
BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"`
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
Transactions [][]byte `json:"transactions" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *uint64 `json:"blobGasUsed"`
ExcessBlobGas *uint64 `json:"excessBlobGas"`
Deposits types.Deposits `json:"depositRequests"`
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 []byte `json:"logsBloom" gencodec:"required"`
Random common.Hash `json:"prevRandao" gencodec:"required"`
Number uint64 `json:"blockNumber" gencodec:"required"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
Timestamp uint64 `json:"timestamp" gencodec:"required"`
ExtraData []byte `json:"extraData" gencodec:"required"`
BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"`
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
Transactions [][]byte `json:"transactions" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *uint64 `json:"blobGasUsed"`
ExcessBlobGas *uint64 `json:"excessBlobGas"`
Deposits types.Deposits `json:"depositRequests"`
WithdrawalRequests types.WithdrawalRequests `json:"withdrawalRequests"`
}

// JSON type overrides for executableData.
Expand Down Expand Up @@ -232,7 +233,9 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
h := types.DeriveSha(types.Withdrawals(data.Withdrawals), trie.NewStackTrie(nil))
withdrawalsRoot = &h
}
// Compute requestsHash if any requests are non-nil.
// Only set requestsHash if there exists requests in the ExecutableData. This
// allows CLs to continue using the data structure before requests are
// enabled.
var (
requestsHash *common.Hash
requests types.Requests
Expand All @@ -242,9 +245,17 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
for _, d := range data.Deposits {
requests = append(requests, types.NewRequest(d))
}
}
if data.WithdrawalRequests != nil {
for _, w := range data.WithdrawalRequests {
requests = append(requests, types.NewRequest(w))
}
}
if requests != nil {
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
requestsHash = &h
}

header := &types.Header{
ParentHash: data.ParentHash,
UncleHash: types.EmptyUncleHash,
Expand Down Expand Up @@ -319,22 +330,27 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
// assigns them to the associated fields in ExecutableData.
func requestsToExecutableData(requests types.Requests, data *ExecutableData) {
if requests != nil {
// If requests is non-nil, it means deposits are available in block and we
// should return an empty slice instead of nil if there are no deposits.
// If requests is non-nil, it means the requests are available in block and
// we should return an empty slice instead of nil.
data.Deposits = make(types.Deposits, 0)
data.WithdrawalRequests = make(types.WithdrawalRequests, 0)
}
for _, r := range requests {
if d, ok := r.Inner().(*types.Deposit); ok {
data.Deposits = append(data.Deposits, d)
switch v := r.Inner().(type) {
case *types.Deposit:
data.Deposits = append(data.Deposits, v)
case *types.WithdrawalRequest:
data.WithdrawalRequests = append(data.WithdrawalRequests, v)
}
}
}

// ExecutionPayloadBody is used in the response to GetPayloadBodiesByHash and GetPayloadBodiesByRange
type ExecutionPayloadBody struct {
TransactionData []hexutil.Bytes `json:"transactions"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
Deposits types.Deposits `json:"depositRequests"`
TransactionData []hexutil.Bytes `json:"transactions"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
Deposits types.Deposits `json:"depositRequests"`
WithdrawalRequests types.WithdrawalRequests `json:"withdrawalRequests"`
}

// Client identifiers to support ClientVersionV1.
Expand Down
109 changes: 63 additions & 46 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,22 @@ type Prestate struct {
// ExecutionResult contains the execution status after running a state test, any
// error that might have occurred and a dump of the final state if requested.
type ExecutionResult struct {
StateRoot common.Hash `json:"stateRoot"`
TxRoot common.Hash `json:"txRoot"`
ReceiptRoot common.Hash `json:"receiptsRoot"`
LogsHash common.Hash `json:"logsHash"`
Bloom types.Bloom `json:"logsBloom" gencodec:"required"`
Receipts types.Receipts `json:"receipts"`
Rejected []*rejectedTx `json:"rejected,omitempty"`
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
RequestsHash *common.Hash `json:"requestsRoot,omitempty"`
DepositRequests *types.Deposits `json:"depositRequests,omitempty"`
StateRoot common.Hash `json:"stateRoot"`
TxRoot common.Hash `json:"txRoot"`
ReceiptRoot common.Hash `json:"receiptsRoot"`
LogsHash common.Hash `json:"logsHash"`
Bloom types.Bloom `json:"logsBloom" gencodec:"required"`
Receipts types.Receipts `json:"receipts"`
Rejected []*rejectedTx `json:"rejected,omitempty"`
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
RequestsHash *common.Hash `json:"requestsRoot,omitempty"`
DepositRequests types.Deposits `json:"depositRequests,omitempty"`
WithdrawalRequests types.WithdrawalRequests `json:"withdrawalRequests,omitempty"`
}

type ommer struct {
Expand Down Expand Up @@ -347,33 +348,14 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
statedb.AddBalance(w.Address, uint256.MustFromBig(amount), tracing.BalanceIncreaseWithdrawal)
}
// Commit block
root, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber))
if err != nil {
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err))
}
execRs := &ExecutionResult{
StateRoot: root,
TxRoot: types.DeriveSha(includedTxs, trie.NewStackTrie(nil)),
ReceiptRoot: types.DeriveSha(receipts, trie.NewStackTrie(nil)),
Bloom: types.CreateBloom(receipts),
LogsHash: rlpHash(statedb.Logs()),
Receipts: receipts,
Rejected: rejectedTxs,
Difficulty: (*math.HexOrDecimal256)(vmContext.Difficulty),
GasUsed: (math.HexOrDecimal64)(gasUsed),
BaseFee: (*math.HexOrDecimal256)(vmContext.BaseFee),
}
if pre.Env.Withdrawals != nil {
h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil))
execRs.WithdrawalsRoot = &h
}
if vmContext.BlobBaseFee != nil {
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
}
// Retrieve deposit and withdrawal requests
var (
depositRequests types.Deposits
withdrawalRequests types.WithdrawalRequests
requestsHash *common.Hash
)
if chainConfig.IsPrague(vmContext.BlockNumber, vmContext.Time) {
// Parse the requests from the logs
// Parse deposit requests from the logs
var allLogs []*types.Log
for _, receipt := range receipts {
allLogs = append(allLogs, receipt.Logs...)
Expand All @@ -382,17 +364,52 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
if err != nil {
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
}
// Process the withdrawal requests contract execution
vmenv := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
wxs := core.ProcessDequeueWithdrawalRequests(vmenv, statedb)
requests = append(requests, wxs...)
// Calculate the requests root
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
execRs.RequestsHash = &h
requestsHash = &h
// Get the deposits from the requests
deposits := make(types.Deposits, 0)
depositRequests = make(types.Deposits, 0)
withdrawalRequests = make(types.WithdrawalRequests, 0)
for _, req := range requests {
if dep, ok := req.Inner().(*types.Deposit); ok {
deposits = append(deposits, dep)
switch v := req.Inner().(type) {
case *types.Deposit:
depositRequests = append(depositRequests, v)
case *types.WithdrawalRequest:
withdrawalRequests = append(withdrawalRequests, v)
}
}
execRs.DepositRequests = &deposits
}
// Commit block
root, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber))
if err != nil {
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err))
}
execRs := &ExecutionResult{
StateRoot: root,
TxRoot: types.DeriveSha(includedTxs, trie.NewStackTrie(nil)),
ReceiptRoot: types.DeriveSha(receipts, trie.NewStackTrie(nil)),
Bloom: types.CreateBloom(receipts),
LogsHash: rlpHash(statedb.Logs()),
Receipts: receipts,
Rejected: rejectedTxs,
Difficulty: (*math.HexOrDecimal256)(vmContext.Difficulty),
GasUsed: (math.HexOrDecimal64)(gasUsed),
BaseFee: (*math.HexOrDecimal256)(vmContext.BaseFee),
RequestsHash: requestsHash,
DepositRequests: depositRequests,
WithdrawalRequests: withdrawalRequests,
}
if pre.Env.Withdrawals != nil {
h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil))
execRs.WithdrawalsRoot = &h
}
if vmContext.BlobBaseFee != nil {
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
}
// Re-create statedb instance with new root upon the updated database
// for accessing latest states.
Expand Down
7 changes: 7 additions & 0 deletions core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,13 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
}
requests = append(requests, d...)
}

var (
blockContext = NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
vmenv = vm.NewEVM(blockContext, vm.TxContext{}, b.statedb, b.cm.config, vm.Config{})
)
wxs := ProcessDequeueWithdrawalRequests(vmenv, statedb)
requests = append(requests, wxs...)
}

body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals, Requests: requests}
Expand Down
Loading

0 comments on commit 96633cb

Please sign in to comment.