github.com/ethereum/go-ethereum@v1.16.1/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, requests [][]byte) (*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  	if requests != nil {
    66  		reqHash := types.CalcRequestsHash(requests)
    67  		header.RequestsHash = &reqHash
    68  	}
    69  	block := types.NewBlockWithHeader(&header).WithBody(types.Body{Transactions: transactions, Withdrawals: withdrawals})
    70  	if hash := block.Hash(); hash != expectedHash {
    71  		return nil, fmt.Errorf("sanity check failed, payload hash does not match (expected %x, got %x)", expectedHash, hash)
    72  	}
    73  	return block, nil
    74  }
    75  
    76  func convertCapellaHeader(payload *capella.ExecutionPayload, h *types.Header) {
    77  	// note: h.TxHash is set in convertTransactions
    78  	h.ParentHash = common.Hash(payload.ParentHash)
    79  	h.UncleHash = types.EmptyUncleHash
    80  	h.Coinbase = common.Address(payload.FeeRecipient)
    81  	h.Root = common.Hash(payload.StateRoot)
    82  	h.ReceiptHash = common.Hash(payload.ReceiptsRoot)
    83  	h.Bloom = types.Bloom(payload.LogsBloom)
    84  	h.Difficulty = common.Big0
    85  	h.Number = new(big.Int).SetUint64(uint64(payload.BlockNumber))
    86  	h.GasLimit = uint64(payload.GasLimit)
    87  	h.GasUsed = uint64(payload.GasUsed)
    88  	h.Time = uint64(payload.Timestamp)
    89  	h.Extra = []byte(payload.ExtraData)
    90  	h.MixDigest = common.Hash(payload.PrevRandao)
    91  	h.Nonce = types.BlockNonce{}
    92  	h.BaseFee = (*uint256.Int)(&payload.BaseFeePerGas).ToBig()
    93  }
    94  
    95  func convertDenebHeader(payload *deneb.ExecutionPayload, parentRoot common.Hash, h *types.Header) {
    96  	// note: h.TxHash is set in convertTransactions
    97  	h.ParentHash = common.Hash(payload.ParentHash)
    98  	h.UncleHash = types.EmptyUncleHash
    99  	h.Coinbase = common.Address(payload.FeeRecipient)
   100  	h.Root = common.Hash(payload.StateRoot)
   101  	h.ReceiptHash = common.Hash(payload.ReceiptsRoot)
   102  	h.Bloom = types.Bloom(payload.LogsBloom)
   103  	h.Difficulty = common.Big0
   104  	h.Number = new(big.Int).SetUint64(uint64(payload.BlockNumber))
   105  	h.GasLimit = uint64(payload.GasLimit)
   106  	h.GasUsed = uint64(payload.GasUsed)
   107  	h.Time = uint64(payload.Timestamp)
   108  	h.Extra = []byte(payload.ExtraData)
   109  	h.MixDigest = common.Hash(payload.PrevRandao)
   110  	h.Nonce = types.BlockNonce{}
   111  	h.BaseFee = (*uint256.Int)(&payload.BaseFeePerGas).ToBig()
   112  	// new in deneb
   113  	h.BlobGasUsed = (*uint64)(&payload.BlobGasUsed)
   114  	h.ExcessBlobGas = (*uint64)(&payload.ExcessBlobGas)
   115  	h.ParentBeaconRoot = &parentRoot
   116  }
   117  
   118  func convertTransactions(list zrntcommon.PayloadTransactions, execHeader *types.Header) ([]*types.Transaction, error) {
   119  	txs := make([]*types.Transaction, len(list))
   120  	for i, opaqueTx := range list {
   121  		var tx types.Transaction
   122  		if err := tx.UnmarshalBinary(opaqueTx); err != nil {
   123  			return nil, fmt.Errorf("failed to parse tx %d: %v", i, err)
   124  		}
   125  		txs[i] = &tx
   126  	}
   127  	execHeader.TxHash = types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil))
   128  	return txs, nil
   129  }
   130  
   131  func convertWithdrawals(list zrntcommon.Withdrawals, execHeader *types.Header) []*types.Withdrawal {
   132  	withdrawals := make([]*types.Withdrawal, len(list))
   133  	for i, w := range list {
   134  		withdrawals[i] = &types.Withdrawal{
   135  			Index:     uint64(w.Index),
   136  			Validator: uint64(w.ValidatorIndex),
   137  			Address:   common.Address(w.Address),
   138  			Amount:    uint64(w.Amount),
   139  		}
   140  	}
   141  	wroot := types.DeriveSha(types.Withdrawals(withdrawals), trie.NewStackTrie(nil))
   142  	execHeader.WithdrawalsHash = &wroot
   143  	return withdrawals
   144  }