github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/cmd/evm/internal/t8ntool/block.go (about) 1 // Copyright 2021 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU 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 // go-ethereum 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 General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package t8ntool 18 19 import ( 20 "crypto/ecdsa" 21 "encoding/json" 22 "errors" 23 "fmt" 24 "math/big" 25 "os" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/common/hexutil" 29 "github.com/ethereum/go-ethereum/common/math" 30 "github.com/ethereum/go-ethereum/consensus/clique" 31 "github.com/ethereum/go-ethereum/core/types" 32 "github.com/ethereum/go-ethereum/crypto" 33 "github.com/ethereum/go-ethereum/rlp" 34 "github.com/urfave/cli/v2" 35 ) 36 37 //go:generate go run github.com/fjl/gencodec -type header -field-override headerMarshaling -out gen_header.go 38 type header struct { 39 ParentHash common.Hash `json:"parentHash"` 40 OmmerHash *common.Hash `json:"sha3Uncles"` 41 Coinbase *common.Address `json:"miner"` 42 Root common.Hash `json:"stateRoot" gencodec:"required"` 43 TxHash *common.Hash `json:"transactionsRoot"` 44 ReceiptHash *common.Hash `json:"receiptsRoot"` 45 Bloom types.Bloom `json:"logsBloom"` 46 Difficulty *big.Int `json:"difficulty"` 47 Number *big.Int `json:"number" gencodec:"required"` 48 GasLimit uint64 `json:"gasLimit" gencodec:"required"` 49 GasUsed uint64 `json:"gasUsed"` 50 Time uint64 `json:"timestamp" gencodec:"required"` 51 Extra []byte `json:"extraData"` 52 MixDigest common.Hash `json:"mixHash"` 53 Nonce *types.BlockNonce `json:"nonce"` 54 BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"` 55 WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` 56 BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"` 57 ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"` 58 ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` 59 } 60 61 type headerMarshaling struct { 62 Difficulty *math.HexOrDecimal256 63 Number *math.HexOrDecimal256 64 GasLimit math.HexOrDecimal64 65 GasUsed math.HexOrDecimal64 66 Time math.HexOrDecimal64 67 Extra hexutil.Bytes 68 BaseFee *math.HexOrDecimal256 69 BlobGasUsed *math.HexOrDecimal64 70 ExcessBlobGas *math.HexOrDecimal64 71 } 72 73 type bbInput struct { 74 Header *header `json:"header,omitempty"` 75 OmmersRlp []string `json:"ommers,omitempty"` 76 TxRlp string `json:"txs,omitempty"` 77 Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` 78 Clique *cliqueInput `json:"clique,omitempty"` 79 80 Ethash bool `json:"-"` 81 Txs []*types.Transaction `json:"-"` 82 Ommers []*types.Header `json:"-"` 83 } 84 85 type cliqueInput struct { 86 Key *ecdsa.PrivateKey 87 Voted *common.Address 88 Authorize *bool 89 Vanity common.Hash 90 } 91 92 // UnmarshalJSON implements json.Unmarshaler interface. 93 func (c *cliqueInput) UnmarshalJSON(input []byte) error { 94 var x struct { 95 Key *common.Hash `json:"secretKey"` 96 Voted *common.Address `json:"voted"` 97 Authorize *bool `json:"authorize"` 98 Vanity common.Hash `json:"vanity"` 99 } 100 if err := json.Unmarshal(input, &x); err != nil { 101 return err 102 } 103 if x.Key == nil { 104 return errors.New("missing required field 'secretKey' for cliqueInput") 105 } 106 if ecdsaKey, err := crypto.ToECDSA(x.Key[:]); err != nil { 107 return err 108 } else { 109 c.Key = ecdsaKey 110 } 111 c.Voted = x.Voted 112 c.Authorize = x.Authorize 113 c.Vanity = x.Vanity 114 return nil 115 } 116 117 // ToBlock converts i into a *types.Block 118 func (i *bbInput) ToBlock() *types.Block { 119 header := &types.Header{ 120 ParentHash: i.Header.ParentHash, 121 UncleHash: types.EmptyUncleHash, 122 Coinbase: common.Address{}, 123 Root: i.Header.Root, 124 TxHash: types.EmptyTxsHash, 125 ReceiptHash: types.EmptyReceiptsHash, 126 Bloom: i.Header.Bloom, 127 Difficulty: common.Big0, 128 Number: i.Header.Number, 129 GasLimit: i.Header.GasLimit, 130 GasUsed: i.Header.GasUsed, 131 Time: i.Header.Time, 132 Extra: i.Header.Extra, 133 MixDigest: i.Header.MixDigest, 134 BaseFee: i.Header.BaseFee, 135 WithdrawalsHash: i.Header.WithdrawalsHash, 136 BlobGasUsed: i.Header.BlobGasUsed, 137 ExcessBlobGas: i.Header.ExcessBlobGas, 138 ParentBeaconRoot: i.Header.ParentBeaconBlockRoot, 139 } 140 141 // Fill optional values. 142 if i.Header.OmmerHash != nil { 143 header.UncleHash = *i.Header.OmmerHash 144 } else if len(i.Ommers) != 0 { 145 // Calculate the ommer hash if none is provided and there are ommers to hash 146 header.UncleHash = types.CalcUncleHash(i.Ommers) 147 } 148 if i.Header.Coinbase != nil { 149 header.Coinbase = *i.Header.Coinbase 150 } 151 if i.Header.TxHash != nil { 152 header.TxHash = *i.Header.TxHash 153 } 154 if i.Header.ReceiptHash != nil { 155 header.ReceiptHash = *i.Header.ReceiptHash 156 } 157 if i.Header.Nonce != nil { 158 header.Nonce = *i.Header.Nonce 159 } 160 if i.Header.Difficulty != nil { 161 header.Difficulty = i.Header.Difficulty 162 } 163 return types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: i.Txs, Uncles: i.Ommers, Withdrawals: i.Withdrawals}) 164 } 165 166 // SealBlock seals the given block using the configured engine. 167 func (i *bbInput) SealBlock(block *types.Block) (*types.Block, error) { 168 switch { 169 case i.Clique != nil: 170 return i.sealClique(block) 171 default: 172 return block, nil 173 } 174 } 175 176 // sealClique seals the given block using clique. 177 func (i *bbInput) sealClique(block *types.Block) (*types.Block, error) { 178 // If any clique value overwrites an explicit header value, fail 179 // to avoid silently building a block with unexpected values. 180 if i.Header.Extra != nil { 181 return nil, NewError(ErrorConfig, errors.New("sealing with clique will overwrite provided extra data")) 182 } 183 header := block.Header() 184 if i.Clique.Voted != nil { 185 if i.Header.Coinbase != nil { 186 return nil, NewError(ErrorConfig, errors.New("sealing with clique and voting will overwrite provided coinbase")) 187 } 188 header.Coinbase = *i.Clique.Voted 189 } 190 if i.Clique.Authorize != nil { 191 if i.Header.Nonce != nil { 192 return nil, NewError(ErrorConfig, errors.New("sealing with clique and voting will overwrite provided nonce")) 193 } 194 if *i.Clique.Authorize { 195 header.Nonce = [8]byte{} 196 } else { 197 header.Nonce = [8]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 198 } 199 } 200 // Extra is fixed 32 byte vanity and 65 byte signature 201 header.Extra = make([]byte, 32+65) 202 copy(header.Extra[0:32], i.Clique.Vanity.Bytes()[:]) 203 204 // Sign the seal hash and fill in the rest of the extra data 205 h := clique.SealHash(header) 206 sighash, err := crypto.Sign(h[:], i.Clique.Key) 207 if err != nil { 208 return nil, err 209 } 210 copy(header.Extra[32:], sighash) 211 block = block.WithSeal(header) 212 return block, nil 213 } 214 215 // BuildBlock constructs a block from the given inputs. 216 func BuildBlock(ctx *cli.Context) error { 217 baseDir, err := createBasedir(ctx) 218 if err != nil { 219 return NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err)) 220 } 221 inputData, err := readInput(ctx) 222 if err != nil { 223 return err 224 } 225 block := inputData.ToBlock() 226 block, err = inputData.SealBlock(block) 227 if err != nil { 228 return err 229 } 230 return dispatchBlock(ctx, baseDir, block) 231 } 232 233 func readInput(ctx *cli.Context) (*bbInput, error) { 234 var ( 235 headerStr = ctx.String(InputHeaderFlag.Name) 236 ommersStr = ctx.String(InputOmmersFlag.Name) 237 withdrawalsStr = ctx.String(InputWithdrawalsFlag.Name) 238 txsStr = ctx.String(InputTxsRlpFlag.Name) 239 cliqueStr = ctx.String(SealCliqueFlag.Name) 240 inputData = &bbInput{} 241 ) 242 if headerStr == stdinSelector || ommersStr == stdinSelector || txsStr == stdinSelector || cliqueStr == stdinSelector { 243 decoder := json.NewDecoder(os.Stdin) 244 if err := decoder.Decode(inputData); err != nil { 245 return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshalling stdin: %v", err)) 246 } 247 } 248 if cliqueStr != stdinSelector && cliqueStr != "" { 249 var clique cliqueInput 250 if err := readFile(cliqueStr, "clique", &clique); err != nil { 251 return nil, err 252 } 253 inputData.Clique = &clique 254 } 255 if headerStr != stdinSelector { 256 var env header 257 if err := readFile(headerStr, "header", &env); err != nil { 258 return nil, err 259 } 260 inputData.Header = &env 261 } 262 if ommersStr != stdinSelector && ommersStr != "" { 263 var ommers []string 264 if err := readFile(ommersStr, "ommers", &ommers); err != nil { 265 return nil, err 266 } 267 inputData.OmmersRlp = ommers 268 } 269 if withdrawalsStr != stdinSelector && withdrawalsStr != "" { 270 var withdrawals []*types.Withdrawal 271 if err := readFile(withdrawalsStr, "withdrawals", &withdrawals); err != nil { 272 return nil, err 273 } 274 inputData.Withdrawals = withdrawals 275 } 276 if txsStr != stdinSelector { 277 var txs string 278 if err := readFile(txsStr, "txs", &txs); err != nil { 279 return nil, err 280 } 281 inputData.TxRlp = txs 282 } 283 // Deserialize rlp txs and ommers 284 var ( 285 ommers = []*types.Header{} 286 txs = []*types.Transaction{} 287 ) 288 if inputData.TxRlp != "" { 289 if err := rlp.DecodeBytes(common.FromHex(inputData.TxRlp), &txs); err != nil { 290 return nil, NewError(ErrorRlp, fmt.Errorf("unable to decode transaction from rlp data: %v", err)) 291 } 292 inputData.Txs = txs 293 } 294 for _, str := range inputData.OmmersRlp { 295 type extblock struct { 296 Header *types.Header 297 Txs []*types.Transaction 298 Ommers []*types.Header 299 } 300 var ommer *extblock 301 if err := rlp.DecodeBytes(common.FromHex(str), &ommer); err != nil { 302 return nil, NewError(ErrorRlp, fmt.Errorf("unable to decode ommer from rlp data: %v", err)) 303 } 304 ommers = append(ommers, ommer.Header) 305 } 306 inputData.Ommers = ommers 307 308 return inputData, nil 309 } 310 311 // dispatchBlock writes the output data to either stderr or stdout, or to the specified 312 // files 313 func dispatchBlock(ctx *cli.Context, baseDir string, block *types.Block) error { 314 raw, _ := rlp.EncodeToBytes(block) 315 type blockInfo struct { 316 Rlp hexutil.Bytes `json:"rlp"` 317 Hash common.Hash `json:"hash"` 318 } 319 enc := blockInfo{ 320 Rlp: raw, 321 Hash: block.Hash(), 322 } 323 b, err := json.MarshalIndent(enc, "", " ") 324 if err != nil { 325 return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err)) 326 } 327 switch dest := ctx.String(OutputBlockFlag.Name); dest { 328 case "stdout": 329 os.Stdout.Write(b) 330 os.Stdout.WriteString("\n") 331 case "stderr": 332 os.Stderr.Write(b) 333 os.Stderr.WriteString("\n") 334 default: 335 if err := saveFile(baseDir, dest, enc); err != nil { 336 return err 337 } 338 } 339 return nil 340 }