Skip to content

Commit

Permalink
add header & block fields for Withdrawals (#45)
Browse files Browse the repository at this point in the history
* add header & block fields for Withdrawals

* Update cmd/evm/internal/t8ntool/block.go

Co-authored-by: Inphi <mlaw2501@gmail.com>

Co-authored-by: Inphi <mlaw2501@gmail.com>
  • Loading branch information
roberto-bayardo and Inphi committed Nov 8, 2022
1 parent 6c556bd commit 4cefcee
Show file tree
Hide file tree
Showing 9 changed files with 356 additions and 121 deletions.
77 changes: 40 additions & 37 deletions cmd/evm/internal/t8ntool/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,24 @@ import (

//go:generate go run github.com/fjl/gencodec -type header -field-override headerMarshaling -out gen_header.go
type header struct {
ParentHash common.Hash `json:"parentHash"`
OmmerHash *common.Hash `json:"sha3Uncles"`
Coinbase *common.Address `json:"miner"`
Root common.Hash `json:"stateRoot" gencodec:"required"`
TxHash *common.Hash `json:"transactionsRoot"`
ReceiptHash *common.Hash `json:"receiptsRoot"`
Bloom types.Bloom `json:"logsBloom"`
Difficulty *big.Int `json:"difficulty"`
Number *big.Int `json:"number" gencodec:"required"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
GasUsed uint64 `json:"gasUsed"`
Time uint64 `json:"timestamp" gencodec:"required"`
Extra []byte `json:"extraData"`
MixDigest common.Hash `json:"mixHash"`
Nonce *types.BlockNonce `json:"nonce"`
BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
ExcessDataGas *big.Int `json:"excessDataGas" rlp:"optional"`
ParentHash common.Hash `json:"parentHash"`
OmmerHash *common.Hash `json:"sha3Uncles"`
Coinbase *common.Address `json:"miner"`
Root common.Hash `json:"stateRoot" gencodec:"required"`
TxHash *common.Hash `json:"transactionsRoot"`
ReceiptHash *common.Hash `json:"receiptsRoot"`
Bloom types.Bloom `json:"logsBloom"`
Difficulty *big.Int `json:"difficulty"`
Number *big.Int `json:"number" gencodec:"required"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
GasUsed uint64 `json:"gasUsed"`
Time uint64 `json:"timestamp" gencodec:"required"`
Extra []byte `json:"extraData"`
MixDigest common.Hash `json:"mixHash"`
Nonce *types.BlockNonce `json:"nonce"`
BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
ExcessDataGas *big.Int `json:"excessDataGas" rlp:"optional"`
}

type headerMarshaling struct {
Expand All @@ -68,10 +69,11 @@ type headerMarshaling struct {
}

type bbInput struct {
Header *header `json:"header,omitempty"`
OmmersRlp []string `json:"ommers,omitempty"`
TxRlp string `json:"txs,omitempty"`
Clique *cliqueInput `json:"clique,omitempty"`
Header *header `json:"header,omitempty"`
OmmersRlp []string `json:"ommers,omitempty"`
TxRlp string `json:"txs,omitempty"`
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
Clique *cliqueInput `json:"clique,omitempty"`

Ethash bool `json:"-"`
EthashDir string `json:"-"`
Expand Down Expand Up @@ -115,22 +117,23 @@ func (c *cliqueInput) UnmarshalJSON(input []byte) error {
// ToBlock converts i into a *types.Block
func (i *bbInput) ToBlock() *types.Block {
header := &types.Header{
ParentHash: i.Header.ParentHash,
UncleHash: types.EmptyUncleHash,
Coinbase: common.Address{},
Root: i.Header.Root,
TxHash: types.EmptyRootHash,
ReceiptHash: types.EmptyRootHash,
Bloom: i.Header.Bloom,
Difficulty: common.Big0,
Number: i.Header.Number,
GasLimit: i.Header.GasLimit,
GasUsed: i.Header.GasUsed,
Time: i.Header.Time,
Extra: i.Header.Extra,
MixDigest: i.Header.MixDigest,
BaseFee: i.Header.BaseFee,
ExcessDataGas: i.Header.ExcessDataGas,
ParentHash: i.Header.ParentHash,
UncleHash: types.EmptyUncleHash,
Coinbase: common.Address{},
Root: i.Header.Root,
TxHash: types.EmptyRootHash,
ReceiptHash: types.EmptyRootHash,
Bloom: i.Header.Bloom,
Difficulty: common.Big0,
Number: i.Header.Number,
GasLimit: i.Header.GasLimit,
GasUsed: i.Header.GasUsed,
Time: i.Header.Time,
Extra: i.Header.Extra,
MixDigest: i.Header.MixDigest,
BaseFee: i.Header.BaseFee,
WithdrawalsHash: i.Header.WithdrawalsHash,
ExcessDataGas: i.Header.ExcessDataGas,
}

// Fill optional values.
Expand Down
74 changes: 40 additions & 34 deletions cmd/evm/internal/t8ntool/gen_header.go

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

86 changes: 79 additions & 7 deletions core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package types
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"math/big"
Expand Down Expand Up @@ -88,6 +89,9 @@ type Header struct {
// BaseFee was added by EIP-1559 and is ignored in legacy headers.
BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`

// WithdrawalsHash was added by EIP-4895 and is ignored in legacy headers.
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`

// ExcessDataGas was added by EIP-4844 and is ignored in legacy headers.
ExcessDataGas *big.Int `json:"excessDataGas" rlp:"optional"`

Expand Down Expand Up @@ -117,6 +121,10 @@ func (h *Header) SetExcessDataGas(v *big.Int) {
if v != nil {
h.ExcessDataGas.Set(v)
}
if h.WithdrawalsHash == nil {
// leaving this nil would result in a buggy encoding
h.WithdrawalsHash = &EmptyRootHash
}
}

// Hash returns the block hash of the header, which is simply the keccak256 hash of its
Expand Down Expand Up @@ -184,6 +192,7 @@ type Block struct {
header *Header
uncles []*Header
transactions Transactions
withdrawals []*Withdrawal

// caches
hash atomic.Value
Expand Down Expand Up @@ -271,9 +280,10 @@ func (txs *extBlockTxs) EncodeRLP(w io.Writer) error {

// "external" block encoding. used for eth protocol, etc.
type extblock struct {
Header *Header
Txs *extBlockTxs
Uncles []*Header
Header *Header
Txs *extBlockTxs
Uncles []*Header
Withdrawals []*Withdrawal `rlp:"optional"`
}

// NewBlock creates a new block. The input data is copied,
Expand Down Expand Up @@ -315,6 +325,31 @@ func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*
return b
}

// NewBlock2 creates a new block with withdrawals. The input data
// is copied, changes to header and to the field values will not
// affect the block.
//
// The values of TxHash, UncleHash, ReceiptHash and Bloom in header
// are ignored and set to values derived from the given txs, uncles
// and receipts.
func NewBlock2(header *Header, txs []*Transaction, uncles []*Header, receipts []*Receipt, withdrawals []*Withdrawal, hasher TrieHasher) *Block {
b := NewBlock(header, txs, uncles, receipts, hasher)
if withdrawals == nil {
return b
}

b.withdrawals = make([]*Withdrawal, len(withdrawals))
copy(b.withdrawals, withdrawals)

if len(withdrawals) == 0 {
b.header.WithdrawalsHash = &EmptyRootHash
} else {
h := DeriveSha(Withdrawals(withdrawals), hasher)
b.header.WithdrawalsHash = &h
}
return b
}

// NewBlockWithHeader creates a block with the given header data. The
// header data is copied, changes to header and to the field values
// will not affect the block.
Expand Down Expand Up @@ -342,6 +377,10 @@ func CopyHeader(h *Header) *Header {
cpy.Extra = make([]byte, len(h.Extra))
copy(cpy.Extra, h.Extra)
}
if h.WithdrawalsHash != nil {
cpy.WithdrawalsHash = new(common.Hash)
cpy.WithdrawalsHash.SetBytes(h.WithdrawalsHash.Bytes())
}
return &cpy
}

Expand All @@ -357,17 +396,24 @@ func (b *Block) DecodeRLP(s *rlp.Stream) error {
return fmt.Errorf("transactions in blocks must not contain wrap-data, tx %d is bad", i)
}
}
b.header, b.uncles, b.transactions = eb.Header, eb.Uncles, []*Transaction(*eb.Txs)
b.header, b.uncles, b.transactions, b.withdrawals = eb.Header, eb.Uncles, []*Transaction(*eb.Txs), eb.Withdrawals
b.size.Store(rlp.ListSize(size))
return nil
}

// EncodeRLP serializes b into the Ethereum RLP block format.
func (b *Block) EncodeRLP(w io.Writer) error {
if b.header.ExcessDataGas != nil && b.header.WithdrawalsHash == nil {
// This situation should not arise, but if it does (due to a bug) you'd silently produce an
// encoding that would fail to decode. ref:
// https://github.com/ethereum/go-ethereum/pull/26077
return errors.New("nil WithdrawalsHash in header with non-nil ExcessDataGas")
}
return rlp.Encode(w, extblock{
Header: b.header,
Txs: (*extBlockTxs)(&b.transactions),
Uncles: b.uncles,
Header: b.header,
Txs: (*extBlockTxs)(&b.transactions),
Uncles: b.uncles,
Withdrawals: b.withdrawals,
})
}

Expand Down Expand Up @@ -410,6 +456,19 @@ func (b *Block) BaseFee() *big.Int {
return new(big.Int).Set(b.header.BaseFee)
}

func (b *Block) WithdrawalsHash() *common.Hash {
if b.header.WithdrawalsHash == nil {
return nil
}
var h common.Hash
h.SetBytes(b.header.WithdrawalsHash.Bytes())
return &h
}

func (b *Block) Withdrawals() Withdrawals {
return b.withdrawals
}

func (b *Block) ExcessDataGas() *big.Int {
if b.header.ExcessDataGas == nil {
return nil
Expand Down Expand Up @@ -463,6 +522,7 @@ func (b *Block) WithSeal(header *Header) *Block {
header: &cpy,
transactions: b.transactions,
uncles: b.uncles,
withdrawals: b.withdrawals,
}
}

Expand All @@ -480,6 +540,18 @@ func (b *Block) WithBody(transactions []*Transaction, uncles []*Header) *Block {
return block
}

// WithBody2 returns a new block with the given transaction, uncle, and
// withdrawal contents.
func (b *Block) WithBody2(transactions []*Transaction, uncles []*Header, withdrawals []*Withdrawal) *Block {
block := b.WithBody(transactions, uncles)
if withdrawals == nil {
return block
}
block.withdrawals = make([]*Withdrawal, len(withdrawals))
copy(block.withdrawals, withdrawals)
return block
}

// Hash returns the keccak256 hash of b's header.
// The hash is computed on the first call and cached thereafter.
func (b *Block) Hash() common.Hash {
Expand Down
Loading

0 comments on commit 4cefcee

Please sign in to comment.