github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/eth/tracers/tracers_test.go (about) 1 // Copyright 2017 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 modif// it under the terms of the GNU Lesser General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // (at your option) any later version. 7 // 8 // The go-ethereum library is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Lesser General Public License for more details. 12 // 13 // You should have received a copy of the GNU Lesser General Public License 14 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 15 16 package tracers 17 18 import ( 19 "crypto/ecdsa" 20 "crypto/rand" 21 "encoding/json" 22 "math/big" 23 "testing" 24 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/common/hexutil" 27 "github.com/ethereum/go-ethereum/common/math" 28 "github.com/ethereum/go-ethereum/core" 29 "github.com/ethereum/go-ethereum/core/types" 30 "github.com/ethereum/go-ethereum/core/vm" 31 "github.com/ethereum/go-ethereum/crypto" 32 "github.com/ethereum/go-ethereum/ethdb" 33 "github.com/ethereum/go-ethereum/params" 34 "github.com/ethereum/go-ethereum/tests" 35 ) 36 37 // To generate a new callTracer test, copy paste the makeTest method below into 38 // a Geth console and call it with a transaction hash you which to export. 39 40 /* 41 // makeTest generates a callTracer test by running a prestate reassembled and a 42 // call trace run, assembling all the gathered information into a test case. 43 var makeTest = function(tx, rewind) { 44 // Generate the genesis block from the block, transaction and prestate data 45 var block = eth.getBlock(eth.getTransaction(tx).blockHash); 46 var genesis = eth.getBlock(block.parentHash); 47 48 delete genesis.gasUsed; 49 delete genesis.logsBloom; 50 delete genesis.parentHash; 51 delete genesis.receiptsRoot; 52 delete genesis.sha3Uncles; 53 delete genesis.size; 54 delete genesis.transactions; 55 delete genesis.transactionsRoot; 56 delete genesis.uncles; 57 58 genesis.gasLimit = genesis.gasLimit.toString(); 59 genesis.number = genesis.number.toString(); 60 genesis.timestamp = genesis.timestamp.toString(); 61 62 genesis.alloc = debug.traceTransaction(tx, {tracer: "prestateTracer", rewind: rewind}); 63 for (var key in genesis.alloc) { 64 genesis.alloc[key].nonce = genesis.alloc[key].nonce.toString(); 65 } 66 genesis.config = admin.nodeInfo.protocols.eth.config; 67 68 // Generate the call trace and produce the test input 69 var result = debug.traceTransaction(tx, {tracer: "callTracer", rewind: rewind}); 70 delete result.time; 71 72 console.log(JSON.stringify({ 73 genesis: genesis, 74 context: { 75 number: block.number.toString(), 76 difficulty: block.difficulty, 77 timestamp: block.timestamp.toString(), 78 gasLimit: block.gasLimit.toString(), 79 miner: block.miner, 80 }, 81 input: eth.getRawTransaction(tx), 82 result: result, 83 }, null, 2)); 84 } 85 */ 86 87 // callTrace is the result of a callTracer run. 88 type callTrace struct { 89 Type string `json:"type"` 90 From common.Address `json:"from"` 91 To common.Address `json:"to"` 92 Input hexutil.Bytes `json:"input"` 93 Output hexutil.Bytes `json:"output"` 94 Gas *hexutil.Uint64 `json:"gas,omitempty"` 95 GasUsed *hexutil.Uint64 `json:"gasUsed,omitempty"` 96 Value *hexutil.Big `json:"value,omitempty"` 97 Error string `json:"error,omitempty"` 98 Calls []callTrace `json:"calls,omitempty"` 99 } 100 101 type callContext struct { 102 Number math.HexOrDecimal64 `json:"number"` 103 Difficulty *math.HexOrDecimal256 `json:"difficulty"` 104 Time math.HexOrDecimal64 `json:"timestamp"` 105 GasLimit math.HexOrDecimal64 `json:"gasLimit"` 106 Miner common.Address `json:"miner"` 107 } 108 109 // callTracerTest defines a single test to check the call tracer against. 110 type callTracerTest struct { 111 Genesis *core.Genesis `json:"genesis"` 112 Context *callContext `json:"context"` 113 Input string `json:"input"` 114 Result *callTrace `json:"result"` 115 } 116 117 func TestPrestateTracerCreate2(t *testing.T) { 118 unsigned_tx := types.NewTransaction(1, common.HexToAddress("0x00000000000000000000000000000000deadbeef"), 119 new(big.Int), 5000000, big.NewInt(1), nil, nil, nil, []byte{}) 120 121 privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader) 122 if err != nil { 123 t.Fatalf("err %v", err) 124 } 125 signer := types.NewEIP155Signer(big.NewInt(1)) 126 tx, err := types.SignTx(unsigned_tx, signer, privateKeyECDSA) 127 if err != nil { 128 t.Fatalf("err %v", err) 129 } 130 /** 131 This comes from one of the test-vectors on the Skinny Create2 - EIP 132 133 address 0x00000000000000000000000000000000deadbeef 134 salt 0x00000000000000000000000000000000000000000000000000000000cafebabe 135 init_code 0xdeadbeef 136 gas (assuming no mem expansion): 32006 137 result: 0x60f3f640a8508fC6a86d45DF051962668E1e8AC7 138 */ 139 origin, _ := signer.Sender(tx) 140 context := vm.Context{ 141 CanTransfer: vm.CanTransfer, 142 Transfer: vm.Transfer, 143 Origin: origin, 144 Coinbase: common.Address{}, 145 BlockNumber: new(big.Int).SetUint64(8000000), 146 Time: new(big.Int).SetUint64(5), 147 Difficulty: big.NewInt(0x30000), 148 GasLimit: uint64(6000000), 149 GasPrice: big.NewInt(1), 150 } 151 alloc := core.GenesisAlloc{} 152 // The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns 153 // the address 154 alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = core.GenesisAccount{ 155 Nonce: 1, 156 Code: hexutil.MustDecode("0x63deadbeef60005263cafebabe6004601c6000F560005260206000F3"), 157 Balance: big.NewInt(1), 158 } 159 alloc[origin] = core.GenesisAccount{ 160 Nonce: 1, 161 Code: []byte{}, 162 Balance: big.NewInt(500000000000000), 163 } 164 statedb := tests.MakePreState(ethdb.NewMemDatabase(), alloc) 165 // Create the tracer, the EVM environment and run it 166 tracer, err := New("prestateTracer") 167 if err != nil { 168 t.Fatalf("failed to create call tracer: %v", err) 169 } 170 evm := vm.NewEVM(context, statedb, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer}) 171 172 msg, err := tx.AsMessage(signer) 173 if err != nil { 174 t.Fatalf("failed to prepare transaction for tracing: %v", err) 175 } 176 st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) 177 if _, _, _, err = st.TransitionDb(); err != nil { 178 t.Fatalf("failed to execute transaction: %v", err) 179 } 180 // Retrieve the trace result and compare against the etalon 181 res, err := tracer.GetResult() 182 if err != nil { 183 t.Fatalf("failed to retrieve trace result: %v", err) 184 } 185 ret := make(map[string]interface{}) 186 if err := json.Unmarshal(res, &ret); err != nil { 187 t.Fatalf("failed to unmarshal trace result: %v", err) 188 } 189 if _, has := ret["0x60f3f640a8508fc6a86d45df051962668e1e8ac7"]; !has { 190 t.Fatalf("Expected 0x60f3f640a8508fc6a86d45df051962668e1e8ac7 in result") 191 } 192 } 193 194 // TODO(kevjue/asaj): Figure out how to get the tracer tests to work with the new txn structure 195 // Iterates over all the input-output datasets in the tracer test harness and 196 // runs the JavaScript tracers against them. 197 198 /* 199 func TestCallTracer(t *testing.T) { 200 files, err := ioutil.ReadDir("testdata") 201 if err != nil { 202 t.Fatalf("failed to retrieve tracer test suite: %v", err) 203 } 204 for _, file := range files { 205 if !strings.HasPrefix(file.Name(), "call_tracer_") { 206 continue 207 } 208 209 file := file // capture range variable 210 t.Run(camel(strings.TrimSuffix(strings.TrimPrefix(file.Name(), "call_tracer_"), ".json")), func(t *testing.T) { 211 t.Parallel() 212 213 // Call tracer test found, read if from disk 214 blob, err := ioutil.ReadFile(filepath.Join("testdata", file.Name())) 215 if err != nil { 216 t.Fatalf("failed to read testcase: %v", err) 217 } 218 test := new(callTracerTest) 219 if err := json.Unmarshal(blob, test); err != nil { 220 t.Fatalf("failed to parse testcase: %v", err) 221 } 222 // Configure a blockchain with the given prestate 223 tx := new(types.Transaction) 224 if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil { 225 t.Fatalf("failed to parse testcase input: %v", err) 226 } 227 signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number))) 228 origin, _ := signer.Sender(tx) 229 230 context := vm.Context{ 231 CanTransfer: core.CanTransfer, 232 Transfer: vm.Transfer, 233 Origin: origin, 234 Coinbase: test.Context.Miner, 235 BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), 236 Time: new(big.Int).SetUint64(uint64(test.Context.Time)), 237 Difficulty: (*big.Int)(test.Context.Difficulty), 238 GasLimit: uint64(test.Context.GasLimit), 239 GasPrice: tx.GasPrice(), 240 } 241 statedb := tests.MakePreState(ethdb.NewMemDatabase(), test.Genesis.Alloc) 242 243 // Create the tracer, the EVM environment and run it 244 tracer, err := New("callTracer") 245 if err != nil { 246 t.Fatalf("failed to create call tracer: %v", err) 247 } 248 evm := vm.NewEVM(context, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer}) 249 250 msg, err := tx.AsMessage(signer) 251 if err != nil { 252 t.Fatalf("failed to prepare transaction for tracing: %v", err) 253 } 254 st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()), nil) 255 if _, _, _, err = st.TransitionDb(); err != nil { 256 t.Fatalf("failed to execute transaction: %v", err) 257 } 258 // Retrieve the trace result and compare against the etalon 259 res, err := tracer.GetResult() 260 if err != nil { 261 t.Fatalf("failed to retrieve trace result: %v", err) 262 } 263 ret := new(callTrace) 264 if err := json.Unmarshal(res, ret); err != nil { 265 t.Fatalf("failed to unmarshal trace result: %v", err) 266 } 267 268 if !reflect.DeepEqual(ret, test.Result) { 269 t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, test.Result) 270 } 271 }) 272 } 273 } 274 */