github.com/theQRL/go-zond@v0.2.1/beacon/engine/types.go (about) 1 // Copyright 2022 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 engine 18 19 import ( 20 "fmt" 21 "math/big" 22 23 "github.com/theQRL/go-zond/common" 24 "github.com/theQRL/go-zond/common/hexutil" 25 "github.com/theQRL/go-zond/core/types" 26 "github.com/theQRL/go-zond/trie" 27 ) 28 29 //go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go 30 31 // PayloadAttributes describes the environment context in which a block should 32 // be built. 33 type PayloadAttributes struct { 34 Timestamp uint64 `json:"timestamp" gencodec:"required"` 35 Random common.Hash `json:"prevRandao" gencodec:"required"` 36 SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"` 37 Withdrawals []*types.Withdrawal `json:"withdrawals"` 38 } 39 40 // JSON type overrides for PayloadAttributes. 41 type payloadAttributesMarshaling struct { 42 Timestamp hexutil.Uint64 43 } 44 45 //go:generate go run github.com/fjl/gencodec -type ExecutableData -field-override executableDataMarshaling -out gen_ed.go 46 47 // ExecutableData is the data necessary to execute an EL payload. 48 type ExecutableData struct { 49 ParentHash common.Hash `json:"parentHash" gencodec:"required"` 50 FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` 51 StateRoot common.Hash `json:"stateRoot" gencodec:"required"` 52 ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"` 53 LogsBloom []byte `json:"logsBloom" gencodec:"required"` 54 Random common.Hash `json:"prevRandao" gencodec:"required"` 55 Number uint64 `json:"blockNumber" gencodec:"required"` 56 GasLimit uint64 `json:"gasLimit" gencodec:"required"` 57 GasUsed uint64 `json:"gasUsed" gencodec:"required"` 58 Timestamp uint64 `json:"timestamp" gencodec:"required"` 59 ExtraData []byte `json:"extraData" gencodec:"required"` 60 BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"` 61 BlockHash common.Hash `json:"blockHash" gencodec:"required"` 62 Transactions [][]byte `json:"transactions" gencodec:"required"` 63 Withdrawals []*types.Withdrawal `json:"withdrawals"` 64 } 65 66 // JSON type overrides for executableData. 67 type executableDataMarshaling struct { 68 Number hexutil.Uint64 69 GasLimit hexutil.Uint64 70 GasUsed hexutil.Uint64 71 Timestamp hexutil.Uint64 72 BaseFeePerGas *hexutil.Big 73 ExtraData hexutil.Bytes 74 LogsBloom hexutil.Bytes 75 Transactions []hexutil.Bytes 76 } 77 78 //go:generate go run github.com/fjl/gencodec -type ExecutionPayloadEnvelope -field-override executionPayloadEnvelopeMarshaling -out gen_epe.go 79 80 type ExecutionPayloadEnvelope struct { 81 ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` 82 BlockValue *big.Int `json:"blockValue" gencodec:"required"` 83 Override bool `json:"shouldOverrideBuilder"` 84 } 85 86 // JSON type overrides for ExecutionPayloadEnvelope. 87 type executionPayloadEnvelopeMarshaling struct { 88 BlockValue *hexutil.Big 89 } 90 91 type PayloadStatusV1 struct { 92 Status string `json:"status"` 93 LatestValidHash *common.Hash `json:"latestValidHash"` 94 ValidationError *string `json:"validationError"` 95 } 96 97 // PayloadID is an identifier of the payload build process 98 type PayloadID [8]byte 99 100 func (b PayloadID) String() string { 101 return hexutil.Encode(b[:]) 102 } 103 104 func (b PayloadID) MarshalText() ([]byte, error) { 105 return hexutil.Bytes(b[:]).MarshalText() 106 } 107 108 func (b *PayloadID) UnmarshalText(input []byte) error { 109 err := hexutil.UnmarshalFixedText("PayloadID", input, b[:]) 110 if err != nil { 111 return fmt.Errorf("invalid payload id %q: %w", input, err) 112 } 113 return nil 114 } 115 116 type ForkChoiceResponse struct { 117 PayloadStatus PayloadStatusV1 `json:"payloadStatus"` 118 PayloadID *PayloadID `json:"payloadId"` 119 } 120 121 type ForkchoiceStateV1 struct { 122 HeadBlockHash common.Hash `json:"headBlockHash"` 123 SafeBlockHash common.Hash `json:"safeBlockHash"` 124 FinalizedBlockHash common.Hash `json:"finalizedBlockHash"` 125 } 126 127 func encodeTransactions(txs []*types.Transaction) [][]byte { 128 var enc = make([][]byte, len(txs)) 129 for i, tx := range txs { 130 enc[i], _ = tx.MarshalBinary() 131 } 132 return enc 133 } 134 135 func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) { 136 var txs = make([]*types.Transaction, len(enc)) 137 for i, encTx := range enc { 138 var tx types.Transaction 139 if err := tx.UnmarshalBinary(encTx); err != nil { 140 return nil, fmt.Errorf("invalid transaction %d: %v", i, err) 141 } 142 txs[i] = &tx 143 } 144 return txs, nil 145 } 146 147 // ExecutableDataToBlock constructs a block from executable data. 148 // It verifies that the following fields: 149 // 150 // len(extraData) <= 32 151 // 152 // and that the blockhash of the constructed block matches the parameters. Nil 153 // Withdrawals value will propagate through the returned block. Empty 154 // Withdrawals value must be passed via non-nil, length 0 value in params. 155 func ExecutableDataToBlock(params ExecutableData) (*types.Block, error) { 156 txs, err := decodeTransactions(params.Transactions) 157 if err != nil { 158 return nil, err 159 } 160 if len(params.ExtraData) > 32 { 161 return nil, fmt.Errorf("invalid extradata length: %v", len(params.ExtraData)) 162 } 163 if len(params.LogsBloom) != 256 { 164 return nil, fmt.Errorf("invalid logsBloom length: %v", len(params.LogsBloom)) 165 } 166 // Check that baseFeePerGas is not negative or too big 167 if params.BaseFeePerGas != nil && (params.BaseFeePerGas.Sign() == -1 || params.BaseFeePerGas.BitLen() > 256) { 168 return nil, fmt.Errorf("invalid baseFeePerGas: %v", params.BaseFeePerGas) 169 } 170 // Only set withdrawalsRoot if it is non-nil. This allows CLs to use 171 // ExecutableData before withdrawals are enabled by marshaling 172 // Withdrawals as the json null value. 173 var withdrawalsRoot *common.Hash 174 if params.Withdrawals != nil { 175 h := types.DeriveSha(types.Withdrawals(params.Withdrawals), trie.NewStackTrie(nil)) 176 withdrawalsRoot = &h 177 } 178 header := &types.Header{ 179 ParentHash: params.ParentHash, 180 Coinbase: params.FeeRecipient, 181 Root: params.StateRoot, 182 TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)), 183 ReceiptHash: params.ReceiptsRoot, 184 Bloom: types.BytesToBloom(params.LogsBloom), 185 Number: new(big.Int).SetUint64(params.Number), 186 GasLimit: params.GasLimit, 187 GasUsed: params.GasUsed, 188 Time: params.Timestamp, 189 BaseFee: params.BaseFeePerGas, 190 Extra: params.ExtraData, 191 Random: params.Random, 192 WithdrawalsHash: withdrawalsRoot, 193 } 194 block := types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs, Withdrawals: params.Withdrawals}) 195 if block.Hash() != params.BlockHash { 196 return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", params.BlockHash, block.Hash()) 197 } 198 return block, nil 199 } 200 201 // BlockToExecutableData constructs the ExecutableData structure by filling the 202 // fields from the given block. It assumes the given block is post-merge block. 203 func BlockToExecutableData(block *types.Block, fees *big.Int) *ExecutionPayloadEnvelope { 204 data := &ExecutableData{ 205 BlockHash: block.Hash(), 206 ParentHash: block.ParentHash(), 207 FeeRecipient: block.Coinbase(), 208 StateRoot: block.Root(), 209 Number: block.NumberU64(), 210 GasLimit: block.GasLimit(), 211 GasUsed: block.GasUsed(), 212 BaseFeePerGas: block.BaseFee(), 213 Timestamp: block.Time(), 214 ReceiptsRoot: block.ReceiptHash(), 215 LogsBloom: block.Bloom().Bytes(), 216 Transactions: encodeTransactions(block.Transactions()), 217 Random: block.Random(), 218 ExtraData: block.Extra(), 219 Withdrawals: block.Withdrawals(), 220 } 221 222 return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, Override: false} 223 } 224 225 // ExecutionPayloadBodyV1 is used in the response to GetPayloadBodiesByHashV1 and GetPayloadBodiesByRangeV1 226 type ExecutionPayloadBodyV1 struct { 227 TransactionData []hexutil.Bytes `json:"transactions"` 228 Withdrawals []*types.Withdrawal `json:"withdrawals"` 229 }