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