mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
core/types,catalyst,engine: add new engine api methods for prague and 6110 deposit type
This commit is contained in:
parent
de597af9c5
commit
a30e0dc4bd
8 changed files with 234 additions and 8 deletions
|
|
@ -36,6 +36,7 @@ var (
|
|||
PayloadV1 PayloadVersion = 0x1
|
||||
PayloadV2 PayloadVersion = 0x2
|
||||
PayloadV3 PayloadVersion = 0x3
|
||||
PayloadV4 PayloadVersion = 0x4
|
||||
)
|
||||
|
||||
//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
|
||||
|
|
@ -76,6 +77,7 @@ type ExecutableData struct {
|
|||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
||||
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
||||
Deposits []*types.Deposit `json:"depositReceipts"`
|
||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||
}
|
||||
|
||||
|
|
@ -231,6 +233,11 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
|
|||
h := types.DeriveSha(types.Withdrawals(data.Withdrawals), trie.NewStackTrie(nil))
|
||||
withdrawalsRoot = &h
|
||||
}
|
||||
var depositsRoot *common.Hash
|
||||
if data.Deposits != nil {
|
||||
h := types.DeriveSha(types.Deposits(data.Deposits), trie.NewStackTrie(nil))
|
||||
depositsRoot = &h
|
||||
}
|
||||
header := &types.Header{
|
||||
ParentHash: data.ParentHash,
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
|
|
@ -251,9 +258,10 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
|
|||
ExcessBlobGas: data.ExcessBlobGas,
|
||||
BlobGasUsed: data.BlobGasUsed,
|
||||
ParentBeaconRoot: beaconRoot,
|
||||
DepositsHash: depositsRoot,
|
||||
}
|
||||
block := types.NewBlockWithHeader(header)
|
||||
block = block.WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals})
|
||||
block = block.WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals, Deposits: data.Deposits})
|
||||
block = block.WithWitness(data.ExecutionWitness)
|
||||
if block.Hash() != data.BlockHash {
|
||||
return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", data.BlockHash, block.Hash())
|
||||
|
|
@ -282,6 +290,7 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
|
|||
Withdrawals: block.Withdrawals(),
|
||||
BlobGasUsed: block.BlobGasUsed(),
|
||||
ExcessBlobGas: block.ExcessBlobGas(),
|
||||
Deposits: block.Deposits(),
|
||||
ExecutionWitness: block.ExecutionWitness(),
|
||||
}
|
||||
bundle := BlobsBundleV1{
|
||||
|
|
|
|||
|
|
@ -102,6 +102,9 @@ type Header struct {
|
|||
|
||||
// ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers.
|
||||
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
|
||||
// DepositsHash was added by EIP-6110 and is ignored in legacy headers.
|
||||
DepositsHash *common.Hash `json:"depositsRoot" rlp:"optional"`
|
||||
}
|
||||
|
||||
// field type overrides for gencodec
|
||||
|
|
@ -180,6 +183,7 @@ type Body struct {
|
|||
Transactions []*Transaction
|
||||
Uncles []*Header
|
||||
Withdrawals []*Withdrawal `rlp:"optional"`
|
||||
Deposits []*Deposit `rlp:"optional"`
|
||||
}
|
||||
|
||||
// Block represents an Ethereum block.
|
||||
|
|
@ -204,6 +208,7 @@ type Block struct {
|
|||
uncles []*Header
|
||||
transactions Transactions
|
||||
withdrawals Withdrawals
|
||||
deposits Deposits
|
||||
|
||||
// witness is not an encoded part of the block body.
|
||||
// It is held in Block in order for easy relaying to the places
|
||||
|
|
@ -226,6 +231,7 @@ type extblock struct {
|
|||
Txs []*Transaction
|
||||
Uncles []*Header
|
||||
Withdrawals []*Withdrawal `rlp:"optional"`
|
||||
Deposits []*Deposit `rlp:"optional"`
|
||||
}
|
||||
|
||||
// NewBlock creates a new block. The input data is copied, changes to header and to the
|
||||
|
|
@ -315,6 +321,10 @@ func CopyHeader(h *Header) *Header {
|
|||
cpy.ParentBeaconRoot = new(common.Hash)
|
||||
*cpy.ParentBeaconRoot = *h.ParentBeaconRoot
|
||||
}
|
||||
if h.DepositsHash != nil {
|
||||
cpy.DepositsHash = new(common.Hash)
|
||||
*cpy.DepositsHash = *h.DepositsHash
|
||||
}
|
||||
return &cpy
|
||||
}
|
||||
|
||||
|
|
@ -343,7 +353,7 @@ func (b *Block) EncodeRLP(w io.Writer) error {
|
|||
// Body returns the non-header content of the block.
|
||||
// Note the returned data is not an independent copy.
|
||||
func (b *Block) Body() *Body {
|
||||
return &Body{b.transactions, b.uncles, b.withdrawals}
|
||||
return &Body{b.transactions, b.uncles, b.withdrawals, b.deposits}
|
||||
}
|
||||
|
||||
// Accessors for body data. These do not return a copy because the content
|
||||
|
|
@ -352,6 +362,7 @@ func (b *Block) Body() *Body {
|
|||
func (b *Block) Uncles() []*Header { return b.uncles }
|
||||
func (b *Block) Transactions() Transactions { return b.transactions }
|
||||
func (b *Block) Withdrawals() Withdrawals { return b.withdrawals }
|
||||
func (b *Block) Deposits() Deposits { return b.deposits }
|
||||
|
||||
func (b *Block) Transaction(hash common.Hash) *Transaction {
|
||||
for _, transaction := range b.transactions {
|
||||
|
|
|
|||
88
core/types/deposit.go
Normal file
88
core/types/deposit.go
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright 2024 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/fjl/gencodec -type Deposit -field-override depositMarshaling -out gen_deposit_json.go
|
||||
|
||||
// Deposit contians EIP-6110 deposit data.
|
||||
type Deposit struct {
|
||||
PublicKey BLSPublicKey `json:"pubkey"`
|
||||
WithdrawalCredentials common.Hash `json:"withdrawalCredentials"`
|
||||
Amount uint64 `json:"amount"` // in gwei
|
||||
Signature BLSSignature `json:"signature"`
|
||||
Index uint64 `json:"index"`
|
||||
}
|
||||
|
||||
type depositMarshaling struct {
|
||||
PublicKey hexutil.Bytes
|
||||
WithdrawalCredentials hexutil.Bytes
|
||||
Amount hexutil.Uint64
|
||||
Signature hexutil.Bytes
|
||||
Index hexutil.Uint64
|
||||
}
|
||||
|
||||
// Deposit implements DerivableList for withdrawals.
|
||||
type Deposits []*Deposit
|
||||
|
||||
// Len returns the length of s.
|
||||
func (s Deposits) Len() int { return len(s) }
|
||||
|
||||
// EncodeIndex encodes the i'th deposit to s.
|
||||
func (s Deposits) EncodeIndex(i int, w *bytes.Buffer) {
|
||||
rlp.Encode(w, s[i])
|
||||
}
|
||||
|
||||
// misc bls types
|
||||
////
|
||||
|
||||
var (
|
||||
pubkeyT = reflect.TypeOf(BLSPublicKey{})
|
||||
sigT = reflect.TypeOf(BLSSignature{})
|
||||
)
|
||||
|
||||
type BLSPublicKey [48]byte
|
||||
|
||||
// UnmarshalJSON parses a hash in hex syntax.
|
||||
func (h *BLSPublicKey) UnmarshalJSON(input []byte) error {
|
||||
return hexutil.UnmarshalFixedJSON(pubkeyT, input, h[:])
|
||||
}
|
||||
|
||||
// MarshalText returns the hex representation of h.
|
||||
func (h BLSPublicKey) MarshalText() ([]byte, error) {
|
||||
return hexutil.Bytes(h[:]).MarshalText()
|
||||
}
|
||||
|
||||
type BLSSignature [96]byte
|
||||
|
||||
// UnmarshalJSON parses a hash in hex syntax.
|
||||
func (h *BLSSignature) UnmarshalJSON(input []byte) error {
|
||||
return hexutil.UnmarshalFixedJSON(sigT, input, h[:])
|
||||
}
|
||||
|
||||
// MarshalText returns the hex representation of h.
|
||||
func (h BLSSignature) MarshalText() ([]byte, error) {
|
||||
return hexutil.Bytes(h[:]).MarshalText()
|
||||
}
|
||||
70
core/types/gen_deposit_json.go
Normal file
70
core/types/gen_deposit_json.go
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
)
|
||||
|
||||
var _ = (*depositMarshaling)(nil)
|
||||
|
||||
// MarshalJSON marshals as JSON.
|
||||
func (d Deposit) MarshalJSON() ([]byte, error) {
|
||||
type Deposit struct {
|
||||
PublicKey hexutil.Bytes `json:"pubkey"`
|
||||
WithdrawalCredentials hexutil.Bytes `json:"withdrawalCredentials"`
|
||||
Amount hexutil.Uint64 `json:"amount"`
|
||||
Signature hexutil.Bytes `json:"signature"`
|
||||
Index hexutil.Uint64 `json:"index"`
|
||||
}
|
||||
var enc Deposit
|
||||
enc.PublicKey = d.PublicKey[:]
|
||||
enc.WithdrawalCredentials = d.WithdrawalCredentials[:]
|
||||
enc.Amount = hexutil.Uint64(d.Amount)
|
||||
enc.Signature = d.Signature[:]
|
||||
enc.Index = hexutil.Uint64(d.Index)
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from JSON.
|
||||
func (d *Deposit) UnmarshalJSON(input []byte) error {
|
||||
type Deposit struct {
|
||||
PublicKey *hexutil.Bytes `json:"pubkey"`
|
||||
WithdrawalCredentials *hexutil.Bytes `json:"withdrawalCredentials"`
|
||||
Amount *hexutil.Uint64 `json:"amount"`
|
||||
Signature *hexutil.Bytes `json:"signature"`
|
||||
Index *hexutil.Uint64 `json:"index"`
|
||||
}
|
||||
var dec Deposit
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
if dec.PublicKey != nil {
|
||||
if len(*dec.PublicKey) != len(d.PublicKey) {
|
||||
return errors.New("field 'pubkey' has wrong length, need 48 items")
|
||||
}
|
||||
copy(d.PublicKey[:], *dec.PublicKey)
|
||||
}
|
||||
if dec.WithdrawalCredentials != nil {
|
||||
if len(*dec.WithdrawalCredentials) != len(d.WithdrawalCredentials) {
|
||||
return errors.New("field 'withdrawalCredentials' has wrong length, need 32 items")
|
||||
}
|
||||
copy(d.WithdrawalCredentials[:], *dec.WithdrawalCredentials)
|
||||
}
|
||||
if dec.Amount != nil {
|
||||
d.Amount = uint64(*dec.Amount)
|
||||
}
|
||||
if dec.Signature != nil {
|
||||
if len(*dec.Signature) != len(d.Signature) {
|
||||
return errors.New("field 'signature' has wrong length, need 96 items")
|
||||
}
|
||||
copy(d.Signature[:], *dec.Signature)
|
||||
}
|
||||
if dec.Index != nil {
|
||||
d.Index = uint64(*dec.Index)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -36,6 +36,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
|||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
|
||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
DepositsHash *common.Hash `json:"depositsRoot" rlp:"optional"`
|
||||
Hash common.Hash `json:"hash"`
|
||||
}
|
||||
var enc Header
|
||||
|
|
@ -59,6 +60,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
|||
enc.BlobGasUsed = (*hexutil.Uint64)(h.BlobGasUsed)
|
||||
enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas)
|
||||
enc.ParentBeaconRoot = h.ParentBeaconRoot
|
||||
enc.DepositsHash = h.DepositsHash
|
||||
enc.Hash = h.Hash()
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
|
@ -86,6 +88,7 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
|||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
|
||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
DepositsHash *common.Hash `json:"depositsRoot" rlp:"optional"`
|
||||
}
|
||||
var dec Header
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
|
@ -163,5 +166,8 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
|||
if dec.ParentBeaconRoot != nil {
|
||||
h.ParentBeaconRoot = dec.ParentBeaconRoot
|
||||
}
|
||||
if dec.DepositsHash != nil {
|
||||
h.DepositsHash = dec.DepositsHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,8 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
|
|||
_tmp3 := obj.BlobGasUsed != nil
|
||||
_tmp4 := obj.ExcessBlobGas != nil
|
||||
_tmp5 := obj.ParentBeaconRoot != nil
|
||||
if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 {
|
||||
_tmp6 := obj.DepositsHash != nil
|
||||
if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 {
|
||||
if obj.BaseFee == nil {
|
||||
w.Write(rlp.EmptyString)
|
||||
} else {
|
||||
|
|
@ -52,34 +53,41 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
|
|||
w.WriteBigInt(obj.BaseFee)
|
||||
}
|
||||
}
|
||||
if _tmp2 || _tmp3 || _tmp4 || _tmp5 {
|
||||
if _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 {
|
||||
if obj.WithdrawalsHash == nil {
|
||||
w.Write([]byte{0x80})
|
||||
} else {
|
||||
w.WriteBytes(obj.WithdrawalsHash[:])
|
||||
}
|
||||
}
|
||||
if _tmp3 || _tmp4 || _tmp5 {
|
||||
if _tmp3 || _tmp4 || _tmp5 || _tmp6 {
|
||||
if obj.BlobGasUsed == nil {
|
||||
w.Write([]byte{0x80})
|
||||
} else {
|
||||
w.WriteUint64((*obj.BlobGasUsed))
|
||||
}
|
||||
}
|
||||
if _tmp4 || _tmp5 {
|
||||
if _tmp4 || _tmp5 || _tmp6 {
|
||||
if obj.ExcessBlobGas == nil {
|
||||
w.Write([]byte{0x80})
|
||||
} else {
|
||||
w.WriteUint64((*obj.ExcessBlobGas))
|
||||
}
|
||||
}
|
||||
if _tmp5 {
|
||||
if _tmp5 || _tmp6 {
|
||||
if obj.ParentBeaconRoot == nil {
|
||||
w.Write([]byte{0x80})
|
||||
} else {
|
||||
w.WriteBytes(obj.ParentBeaconRoot[:])
|
||||
}
|
||||
}
|
||||
if _tmp6 {
|
||||
if obj.DepositsHash == nil {
|
||||
w.Write([]byte{0x80})
|
||||
} else {
|
||||
w.WriteBytes(obj.DepositsHash[:])
|
||||
}
|
||||
}
|
||||
w.ListEnd(_tmp0)
|
||||
return w.Flush()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@ var (
|
|||
// EmptyWithdrawalsHash is the known hash of the empty withdrawal set.
|
||||
EmptyWithdrawalsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
||||
|
||||
// EmptyDepositsHash is the known hash of the empty deposits set.
|
||||
EmptyDepositsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
||||
|
||||
// EmptyVerkleHash is the known hash of an empty verkle trie.
|
||||
EmptyVerkleHash = common.Hash{}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -86,9 +86,11 @@ var caps = []string{
|
|||
"engine_getPayloadV1",
|
||||
"engine_getPayloadV2",
|
||||
"engine_getPayloadV3",
|
||||
"engine_getPayloadV4",
|
||||
"engine_newPayloadV1",
|
||||
"engine_newPayloadV2",
|
||||
"engine_newPayloadV3",
|
||||
"engine_newPayloadV4",
|
||||
"engine_getPayloadBodiesByHashV1",
|
||||
"engine_getPayloadBodiesByRangeV1",
|
||||
"engine_getClientVersionV1",
|
||||
|
|
@ -220,7 +222,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa
|
|||
if params.BeaconRoot == nil {
|
||||
return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing beacon root"))
|
||||
}
|
||||
if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun {
|
||||
if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun && api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague {
|
||||
return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads"))
|
||||
}
|
||||
}
|
||||
|
|
@ -508,6 +510,34 @@ func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHas
|
|||
return api.newPayload(params, versionedHashes, beaconRoot)
|
||||
}
|
||||
|
||||
// NewPayloadV4 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
|
||||
func (api *ConsensusAPI) NewPayloadV4(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) {
|
||||
if params.Withdrawals == nil {
|
||||
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
|
||||
}
|
||||
if params.ExcessBlobGas == nil {
|
||||
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun"))
|
||||
}
|
||||
if params.BlobGasUsed == nil {
|
||||
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun"))
|
||||
}
|
||||
if params.Deposits == nil {
|
||||
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil deposits post-prague"))
|
||||
}
|
||||
|
||||
if versionedHashes == nil {
|
||||
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun"))
|
||||
}
|
||||
if beaconRoot == nil {
|
||||
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun"))
|
||||
}
|
||||
|
||||
if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun {
|
||||
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV3 must only be called for cancun payloads"))
|
||||
}
|
||||
return api.newPayload(params, versionedHashes, beaconRoot)
|
||||
}
|
||||
|
||||
func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) {
|
||||
// The locking here is, strictly, not required. Without these locks, this can happen:
|
||||
//
|
||||
|
|
@ -553,6 +583,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe
|
|||
"params.ExcessBlobGas", ebg,
|
||||
"len(params.Transactions)", len(params.Transactions),
|
||||
"len(params.Withdrawals)", len(params.Withdrawals),
|
||||
"len(params.Deposits)", len(params.Deposits),
|
||||
"beaconRoot", beaconRoot,
|
||||
"error", err)
|
||||
return api.invalid(err, nil), nil
|
||||
|
|
|
|||
Loading…
Reference in a new issue