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 }