github.com/ethereum/go-ethereum@v1.14.3/beacon/types/exec_payload.go (about)

     1  // Copyright 2024 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package types
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/core/types"
    25  	"github.com/ethereum/go-ethereum/trie"
    26  	"github.com/holiman/uint256"
    27  	"github.com/protolambda/zrnt/eth2/beacon/capella"
    28  	zrntcommon "github.com/protolambda/zrnt/eth2/beacon/common"
    29  	"github.com/protolambda/zrnt/eth2/beacon/deneb"
    30  )
    31  
    32  type payloadType interface {
    33  	*capella.ExecutionPayload | *deneb.ExecutionPayload
    34  }
    35  
    36  // convertPayload converts a beacon chain execution payload to types.Block.
    37  func convertPayload[T payloadType](payload T, parentRoot *zrntcommon.Root) (*types.Block, error) {
    38  	var (
    39  		header       types.Header
    40  		transactions []*types.Transaction
    41  		withdrawals  []*types.Withdrawal
    42  		expectedHash [32]byte
    43  		err          error
    44  	)
    45  	switch p := any(payload).(type) {
    46  	case *capella.ExecutionPayload:
    47  		convertCapellaHeader(p, &header)
    48  		transactions, err = convertTransactions(p.Transactions, &header)
    49  		if err != nil {
    50  			return nil, err
    51  		}
    52  		withdrawals = convertWithdrawals(p.Withdrawals, &header)
    53  		expectedHash = p.BlockHash
    54  	case *deneb.ExecutionPayload:
    55  		convertDenebHeader(p, common.Hash(*parentRoot), &header)
    56  		transactions, err = convertTransactions(p.Transactions, &header)
    57  		if err != nil {
    58  			return nil, err
    59  		}
    60  		withdrawals = convertWithdrawals(p.Withdrawals, &header)
    61  		expectedHash = p.BlockHash
    62  	default:
    63  		panic("unsupported block type")
    64  	}
    65  
    66  	block := types.NewBlockWithHeader(&header).WithBody(types.Body{Transactions: transactions, Withdrawals: withdrawals})
    67  	if hash := block.Hash(); hash != expectedHash {
    68  		return nil, fmt.Errorf("Sanity check failed, payload hash does not match (expected %x, got %x)", expectedHash, hash)
    69  	}
    70  	return block, nil
    71  }
    72  
    73  func convertCapellaHeader(payload *capella.ExecutionPayload, h *types.Header) {
    74  	// note: h.TxHash is set in convertTransactions
    75  	h.ParentHash = common.Hash(payload.ParentHash)
    76  	h.UncleHash = types.EmptyUncleHash
    77  	h.Coinbase = common.Address(payload.FeeRecipient)
    78  	h.Root = common.Hash(payload.StateRoot)
    79  	h.ReceiptHash = common.Hash(payload.ReceiptsRoot)
    80  	h.Bloom = types.Bloom(payload.LogsBloom)
    81  	h.Difficulty = common.Big0
    82  	h.Number = new(big.Int).SetUint64(uint64(payload.BlockNumber))
    83  	h.GasLimit = uint64(payload.GasLimit)
    84  	h.GasUsed = uint64(payload.GasUsed)
    85  	h.Time = uint64(payload.Timestamp)
    86  	h.Extra = []byte(payload.ExtraData)
    87  	h.MixDigest = common.Hash(payload.PrevRandao)
    88  	h.Nonce = types.BlockNonce{}
    89  	h.BaseFee = (*uint256.Int)(&payload.BaseFeePerGas).ToBig()
    90  }
    91  
    92  func convertDenebHeader(payload *deneb.ExecutionPayload, parentRoot common.Hash, h *types.Header) {
    93  	// note: h.TxHash is set in convertTransactions
    94  	h.ParentHash = common.Hash(payload.ParentHash)
    95  	h.UncleHash = types.EmptyUncleHash
    96  	h.Coinbase = common.Address(payload.FeeRecipient)
    97  	h.Root = common.Hash(payload.StateRoot)
    98  	h.ReceiptHash = common.Hash(payload.ReceiptsRoot)
    99  	h.Bloom = types.Bloom(payload.LogsBloom)
   100  	h.Difficulty = common.Big0
   101  	h.Number = new(big.Int).SetUint64(uint64(payload.BlockNumber))
   102  	h.GasLimit = uint64(payload.GasLimit)
   103  	h.GasUsed = uint64(payload.GasUsed)
   104  	h.Time = uint64(payload.Timestamp)
   105  	h.Extra = []byte(payload.ExtraData)
   106  	h.MixDigest = common.Hash(payload.PrevRandao)
   107  	h.Nonce = types.BlockNonce{}
   108  	h.BaseFee = (*uint256.Int)(&payload.BaseFeePerGas).ToBig()
   109  	// new in deneb
   110  	h.BlobGasUsed = (*uint64)(&payload.BlobGasUsed)
   111  	h.ExcessBlobGas = (*uint64)(&payload.ExcessBlobGas)
   112  	h.ParentBeaconRoot = &parentRoot
   113  }
   114  
   115  func convertTransactions(list zrntcommon.PayloadTransactions, execHeader *types.Header) ([]*types.Transaction, error) {
   116  	txs := make([]*types.Transaction, len(list))
   117  	for i, opaqueTx := range list {
   118  		var tx types.Transaction
   119  		if err := tx.UnmarshalBinary(opaqueTx); err != nil {
   120  			return nil, fmt.Errorf("failed to parse tx %d: %v", i, err)
   121  		}
   122  		txs[i] = &tx
   123  	}
   124  	execHeader.TxHash = types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil))
   125  	return txs, nil
   126  }
   127  
   128  func convertWithdrawals(list zrntcommon.Withdrawals, execHeader *types.Header) []*types.Withdrawal {
   129  	withdrawals := make([]*types.Withdrawal, len(list))
   130  	for i, w := range list {
   131  		withdrawals[i] = &types.Withdrawal{
   132  			Index:     uint64(w.Index),
   133  			Validator: uint64(w.ValidatorIndex),
   134  			Address:   common.Address(w.Address),
   135  			Amount:    uint64(w.Amount),
   136  		}
   137  	}
   138  	wroot := types.DeriveSha(types.Withdrawals(withdrawals), trie.NewStackTrie(nil))
   139  	execHeader.WithdrawalsHash = &wroot
   140  	return withdrawals
   141  }