Commit 1fb696ea authored by Danyal Prout's avatar Danyal Prout

Add withdrawals attribute / port geth v2 checks

parent a5a856b1
......@@ -6,6 +6,7 @@ import (
"encoding/binary"
"errors"
"fmt"
"math/big"
"time"
"github.com/ethereum-optimism/optimism/op-service/eth"
......@@ -185,19 +186,70 @@ func (ea *L2EngineAPI) GetPayloadV2(ctx context.Context, payloadId eth.PayloadID
return &eth.ExecutionPayloadEnvelope{ExecutionPayload: payload}, err
}
func (ea *L2EngineAPI) config() *params.ChainConfig {
return ea.backend.Config()
}
func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.ForkchoiceState, attr *eth.PayloadAttributes) (*eth.ForkchoiceUpdatedResult, error) {
if attr != nil {
if attr.Withdrawals != nil {
return STATUS_INVALID, engine.InvalidParams.With(errors.New("withdrawals not supported in V1"))
}
if ea.config().IsShanghai(ea.config().LondonBlock, uint64(attr.Timestamp)) {
return STATUS_INVALID, engine.InvalidParams.With(errors.New("forkChoiceUpdateV1 called post-shanghai"))
}
}
return ea.forkchoiceUpdated(ctx, state, attr)
}
func (ea *L2EngineAPI) ForkchoiceUpdatedV2(ctx context.Context, state *eth.ForkchoiceState, attr *eth.PayloadAttributes) (*eth.ForkchoiceUpdatedResult, error) {
if attr != nil {
if err := ea.verifyPayloadAttributes(attr); err != nil {
return STATUS_INVALID, engine.InvalidParams.With(err)
}
}
return ea.forkchoiceUpdated(ctx, state, attr)
}
func (ea *L2EngineAPI) verifyPayloadAttributes(attr *eth.PayloadAttributes) error {
c := ea.config()
// Verify withdrawals attribute for Shanghai.
if err := checkAttribute(c.IsShanghai, attr.Withdrawals != nil, c.LondonBlock, uint64(attr.Timestamp)); err != nil {
return fmt.Errorf("invalid withdrawals: %w", err)
}
return nil
}
func checkAttribute(active func(*big.Int, uint64) bool, exists bool, block *big.Int, time uint64) error {
if active(block, time) && !exists {
return errors.New("fork active, missing expected attribute")
}
if !active(block, time) && exists {
return errors.New("fork inactive, unexpected attribute set")
}
return nil
}
func (ea *L2EngineAPI) NewPayloadV1(ctx context.Context, payload *eth.ExecutionPayload) (*eth.PayloadStatusV1, error) {
if payload.Withdrawals != nil {
return &eth.PayloadStatusV1{Status: eth.ExecutionInvalid}, engine.InvalidParams.With(errors.New("withdrawals not supported in V1"))
}
return ea.newPayload(ctx, payload)
}
func (ea *L2EngineAPI) NewPayloadV2(ctx context.Context, payload *eth.ExecutionPayload) (*eth.PayloadStatusV1, error) {
if ea.config().IsShanghai(new(big.Int).SetUint64(uint64(payload.BlockNumber)), uint64(payload.Timestamp)) {
if payload.Withdrawals == nil {
return &eth.PayloadStatusV1{Status: eth.ExecutionInvalid}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
}
} else if payload.Withdrawals != nil {
return &eth.PayloadStatusV1{Status: eth.ExecutionInvalid}, engine.InvalidParams.With(errors.New("non-nil withdrawals pre-shanghai"))
}
return ea.newPayload(ctx, payload)
}
......
......@@ -143,6 +143,7 @@ type ExecutionPayload struct {
ExtraData BytesMax32 `json:"extraData"`
BaseFeePerGas Uint256Quantity `json:"baseFeePerGas"`
BlockHash common.Hash `json:"blockHash"`
Withdrawals *[]Withdrawal `json:"withdrawals,omitempty"`
// Array of transaction objects, each object is a byte list (DATA) representing
// TransactionType || TransactionPayload or LegacyTransaction as defined in EIP-2718
Transactions []Data `json:"transactions"`
......@@ -232,6 +233,8 @@ type PayloadAttributes struct {
PrevRandao Bytes32 `json:"prevRandao"`
// suggested value for the coinbase field of the new payload
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient"`
// Withdrawals to include into the block -- should be nil or empty depending on Shanghai enablement
Withdrawals *[]Withdrawal `json:"withdrawals,omitempty"`
// Transactions to force into the block (always at the start of the transactions list).
Transactions []Data `json:"transactions,omitempty"`
// NoTxPool to disable adding any transactions from the transaction-pool.
......@@ -297,3 +300,11 @@ type SystemConfig struct {
GasLimit uint64 `json:"gasLimit"`
// More fields can be added for future SystemConfig versions.
}
// Withdrawal represents a validator withdrawal from the consensus layer.
type Withdrawal struct {
Index uint64 `json:"index"` // monotonically increasing identifier issued by consensus layer
Validator uint64 `json:"validatorIndex"` // index of validator associated with withdrawal
Address common.Address `json:"address"` // target address for withdrawn ether
Amount uint64 `json:"amount"` // value of withdrawal in Gwei
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment