github.com/ethereum/go-ethereum@v1.10.9/cmd/evm/internal/t8ntool/transaction.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 "encoding/json" 21 "errors" 22 "fmt" 23 "math/big" 24 "os" 25 "strings" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/common/hexutil" 29 "github.com/ethereum/go-ethereum/core/types" 30 "github.com/ethereum/go-ethereum/log" 31 "github.com/ethereum/go-ethereum/params" 32 "github.com/ethereum/go-ethereum/rlp" 33 "github.com/ethereum/go-ethereum/tests" 34 "gopkg.in/urfave/cli.v1" 35 ) 36 37 type result struct { 38 Error error 39 Address common.Address 40 Hash common.Hash 41 } 42 43 // MarshalJSON marshals as JSON with a hash. 44 func (r *result) MarshalJSON() ([]byte, error) { 45 type xx struct { 46 Error string `json:"error,omitempty"` 47 Address *common.Address `json:"address,omitempty"` 48 Hash *common.Hash `json:"hash,omitempty"` 49 } 50 var out xx 51 if r.Error != nil { 52 out.Error = r.Error.Error() 53 } 54 if r.Address != (common.Address{}) { 55 out.Address = &r.Address 56 } 57 if r.Hash != (common.Hash{}) { 58 out.Hash = &r.Hash 59 } 60 return json.Marshal(out) 61 } 62 63 func Transaction(ctx *cli.Context) error { 64 // Configure the go-ethereum logger 65 glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) 66 glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name))) 67 log.Root().SetHandler(glogger) 68 69 var ( 70 err error 71 ) 72 // We need to load the transactions. May be either in stdin input or in files. 73 // Check if anything needs to be read from stdin 74 var ( 75 txStr = ctx.String(InputTxsFlag.Name) 76 inputData = &input{} 77 chainConfig *params.ChainConfig 78 ) 79 // Construct the chainconfig 80 if cConf, _, err := tests.GetChainConfig(ctx.String(ForknameFlag.Name)); err != nil { 81 return NewError(ErrorVMConfig, fmt.Errorf("failed constructing chain configuration: %v", err)) 82 } else { 83 chainConfig = cConf 84 } 85 // Set the chain id 86 chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name)) 87 var body hexutil.Bytes 88 if txStr == stdinSelector { 89 decoder := json.NewDecoder(os.Stdin) 90 if err := decoder.Decode(inputData); err != nil { 91 return NewError(ErrorJson, fmt.Errorf("failed unmarshaling stdin: %v", err)) 92 } 93 // Decode the body of already signed transactions 94 body = common.FromHex(inputData.TxRlp) 95 } else { 96 // Read input from file 97 inFile, err := os.Open(txStr) 98 if err != nil { 99 return NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err)) 100 } 101 defer inFile.Close() 102 decoder := json.NewDecoder(inFile) 103 if strings.HasSuffix(txStr, ".rlp") { 104 if err := decoder.Decode(&body); err != nil { 105 return err 106 } 107 } else { 108 return NewError(ErrorIO, errors.New("only rlp supported")) 109 } 110 } 111 signer := types.MakeSigner(chainConfig, new(big.Int)) 112 // We now have the transactions in 'body', which is supposed to be an 113 // rlp list of transactions 114 it, err := rlp.NewListIterator([]byte(body)) 115 if err != nil { 116 return err 117 } 118 var results []result 119 for it.Next() { 120 var tx types.Transaction 121 err := rlp.DecodeBytes(it.Value(), &tx) 122 if err != nil { 123 results = append(results, result{Error: err}) 124 continue 125 } 126 sender, err := types.Sender(signer, &tx) 127 if err != nil { 128 results = append(results, result{Error: err}) 129 continue 130 } 131 results = append(results, result{Address: sender, Hash: tx.Hash()}) 132 } 133 out, err := json.MarshalIndent(results, "", " ") 134 fmt.Println(string(out)) 135 return err 136 }