| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | // Copyright 2017 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package tracers | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 	"crypto/ecdsa" | 
					
						
							|  |  |  | 	"crypto/rand" | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 	"reflect" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/common/hexutil" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/common/math" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/core" | 
					
						
							| 
									
										
										
										
											2018-09-24 15:57:49 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/rawdb" | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/types" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/core/vm" | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2021-10-13 13:32:37 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/eth/tracers/native" | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/rlp" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/tests" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // To generate a new callTracer test, copy paste the makeTest method below into | 
					
						
							|  |  |  | // a Geth console and call it with a transaction hash you which to export. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  | // makeTest generates a callTracer test by running a prestate reassembled and a | 
					
						
							|  |  |  | // call trace run, assembling all the gathered information into a test case. | 
					
						
							|  |  |  | var makeTest = function(tx, rewind) { | 
					
						
							|  |  |  |   // Generate the genesis block from the block, transaction and prestate data | 
					
						
							|  |  |  |   var block   = eth.getBlock(eth.getTransaction(tx).blockHash); | 
					
						
							|  |  |  |   var genesis = eth.getBlock(block.parentHash); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   delete genesis.gasUsed; | 
					
						
							|  |  |  |   delete genesis.logsBloom; | 
					
						
							|  |  |  |   delete genesis.parentHash; | 
					
						
							|  |  |  |   delete genesis.receiptsRoot; | 
					
						
							|  |  |  |   delete genesis.sha3Uncles; | 
					
						
							|  |  |  |   delete genesis.size; | 
					
						
							|  |  |  |   delete genesis.transactions; | 
					
						
							|  |  |  |   delete genesis.transactionsRoot; | 
					
						
							|  |  |  |   delete genesis.uncles; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   genesis.gasLimit  = genesis.gasLimit.toString(); | 
					
						
							|  |  |  |   genesis.number    = genesis.number.toString(); | 
					
						
							|  |  |  |   genesis.timestamp = genesis.timestamp.toString(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   genesis.alloc = debug.traceTransaction(tx, {tracer: "prestateTracer", rewind: rewind}); | 
					
						
							|  |  |  |   for (var key in genesis.alloc) { | 
					
						
							|  |  |  |     genesis.alloc[key].nonce = genesis.alloc[key].nonce.toString(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   genesis.config = admin.nodeInfo.protocols.eth.config; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Generate the call trace and produce the test input | 
					
						
							|  |  |  |   var result = debug.traceTransaction(tx, {tracer: "callTracer", rewind: rewind}); | 
					
						
							|  |  |  |   delete result.time; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   console.log(JSON.stringify({ | 
					
						
							|  |  |  |     genesis: genesis, | 
					
						
							|  |  |  |     context: { | 
					
						
							|  |  |  |       number:     block.number.toString(), | 
					
						
							|  |  |  |       difficulty: block.difficulty, | 
					
						
							|  |  |  |       timestamp:  block.timestamp.toString(), | 
					
						
							|  |  |  |       gasLimit:   block.gasLimit.toString(), | 
					
						
							|  |  |  |       miner:      block.miner, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     input:  eth.getRawTransaction(tx), | 
					
						
							|  |  |  |     result: result, | 
					
						
							|  |  |  |   }, null, 2)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // callTrace is the result of a callTracer run. | 
					
						
							|  |  |  | type callTrace struct { | 
					
						
							|  |  |  | 	Type    string          `json:"type"` | 
					
						
							|  |  |  | 	From    common.Address  `json:"from"` | 
					
						
							|  |  |  | 	To      common.Address  `json:"to"` | 
					
						
							|  |  |  | 	Input   hexutil.Bytes   `json:"input"` | 
					
						
							|  |  |  | 	Output  hexutil.Bytes   `json:"output"` | 
					
						
							|  |  |  | 	Gas     *hexutil.Uint64 `json:"gas,omitempty"` | 
					
						
							|  |  |  | 	GasUsed *hexutil.Uint64 `json:"gasUsed,omitempty"` | 
					
						
							|  |  |  | 	Value   *hexutil.Big    `json:"value,omitempty"` | 
					
						
							|  |  |  | 	Error   string          `json:"error,omitempty"` | 
					
						
							|  |  |  | 	Calls   []callTrace     `json:"calls,omitempty"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type callContext struct { | 
					
						
							|  |  |  | 	Number     math.HexOrDecimal64   `json:"number"` | 
					
						
							|  |  |  | 	Difficulty *math.HexOrDecimal256 `json:"difficulty"` | 
					
						
							|  |  |  | 	Time       math.HexOrDecimal64   `json:"timestamp"` | 
					
						
							|  |  |  | 	GasLimit   math.HexOrDecimal64   `json:"gasLimit"` | 
					
						
							|  |  |  | 	Miner      common.Address        `json:"miner"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // callTracerTest defines a single test to check the call tracer against. | 
					
						
							|  |  |  | type callTracerTest struct { | 
					
						
							|  |  |  | 	Genesis *core.Genesis `json:"genesis"` | 
					
						
							|  |  |  | 	Context *callContext  `json:"context"` | 
					
						
							|  |  |  | 	Input   string        `json:"input"` | 
					
						
							|  |  |  | 	Result  *callTrace    `json:"result"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | func TestPrestateTracerCreate2(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2019-02-14 06:38:55 -08:00
										 |  |  | 	unsignedTx := types.NewTransaction(1, common.HexToAddress("0x00000000000000000000000000000000deadbeef"), | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 		new(big.Int), 5000000, big.NewInt(1), []byte{}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("err %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	signer := types.NewEIP155Signer(big.NewInt(1)) | 
					
						
							| 
									
										
										
										
											2019-02-14 06:38:55 -08:00
										 |  |  | 	tx, err := types.SignTx(unsignedTx, signer, privateKeyECDSA) | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("err %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 		This comes from one of the test-vectors on the Skinny Create2 - EIP | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    address 0x00000000000000000000000000000000deadbeef | 
					
						
							|  |  |  | 	    salt 0x00000000000000000000000000000000000000000000000000000000cafebabe | 
					
						
							|  |  |  | 	    init_code 0xdeadbeef | 
					
						
							|  |  |  | 	    gas (assuming no mem expansion): 32006 | 
					
						
							|  |  |  | 	    result: 0x60f3f640a8508fC6a86d45DF051962668E1e8AC7 | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	origin, _ := signer.Sender(tx) | 
					
						
							| 
									
										
										
										
											2020-11-13 13:42:19 +01:00
										 |  |  | 	txContext := vm.TxContext{ | 
					
						
							|  |  |  | 		Origin:   origin, | 
					
						
							|  |  |  | 		GasPrice: big.NewInt(1), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	context := vm.BlockContext{ | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 		CanTransfer: core.CanTransfer, | 
					
						
							|  |  |  | 		Transfer:    core.Transfer, | 
					
						
							|  |  |  | 		Coinbase:    common.Address{}, | 
					
						
							|  |  |  | 		BlockNumber: new(big.Int).SetUint64(8000000), | 
					
						
							|  |  |  | 		Time:        new(big.Int).SetUint64(5), | 
					
						
							|  |  |  | 		Difficulty:  big.NewInt(0x30000), | 
					
						
							|  |  |  | 		GasLimit:    uint64(6000000), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	alloc := core.GenesisAlloc{} | 
					
						
							| 
									
										
										
										
											2018-09-24 15:57:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 	// The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns | 
					
						
							|  |  |  | 	// the address | 
					
						
							|  |  |  | 	alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = core.GenesisAccount{ | 
					
						
							|  |  |  | 		Nonce:   1, | 
					
						
							|  |  |  | 		Code:    hexutil.MustDecode("0x63deadbeef60005263cafebabe6004601c6000F560005260206000F3"), | 
					
						
							|  |  |  | 		Balance: big.NewInt(1), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	alloc[origin] = core.GenesisAccount{ | 
					
						
							|  |  |  | 		Nonce:   1, | 
					
						
							|  |  |  | 		Code:    []byte{}, | 
					
						
							|  |  |  | 		Balance: big.NewInt(500000000000000), | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-04 11:54:24 +03:00
										 |  |  | 	_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false) | 
					
						
							| 
									
										
										
										
											2018-09-24 15:57:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 	// Create the tracer, the EVM environment and run it | 
					
						
							| 
									
										
										
										
											2021-06-24 12:46:26 +03:00
										 |  |  | 	tracer, err := New("prestateTracer", new(Context)) | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to create call tracer: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-13 13:42:19 +01:00
										 |  |  | 	evm := vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer}) | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-17 15:13:22 +02:00
										 |  |  | 	msg, err := tx.AsMessage(signer, nil) | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to prepare transaction for tracing: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 	if _, err = st.TransitionDb(); err != nil { | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 		t.Fatalf("failed to execute transaction: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Retrieve the trace result and compare against the etalon | 
					
						
							|  |  |  | 	res, err := tracer.GetResult() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to retrieve trace result: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ret := make(map[string]interface{}) | 
					
						
							|  |  |  | 	if err := json.Unmarshal(res, &ret); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to unmarshal trace result: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if _, has := ret["0x60f3f640a8508fc6a86d45df051962668e1e8ac7"]; !has { | 
					
						
							|  |  |  | 		t.Fatalf("Expected 0x60f3f640a8508fc6a86d45df051962668e1e8ac7 in result") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | // Iterates over all the input-output datasets in the tracer test harness and | 
					
						
							|  |  |  | // runs the JavaScript tracers against them. | 
					
						
							| 
									
										
										
											
												core,eth: call frame tracing (#23087)
This change introduces 2 new optional methods; `enter()` and `exit()` for js tracers, and makes `step()` optiona. The two new methods are invoked when entering and exiting a call frame (but not invoked for the outermost scope, which has it's own methods). Currently these are the data fields passed to each of them:
    enter: type (opcode), from, to, input, gas, value
    exit: output, gasUsed, error
The PR also comes with a re-write of the callTracer. As a backup we keep the previous tracing script under the name `callTracerLegacy`. Behaviour of both tracers are equivalent for the most part, although there are some small differences (improvements), where the new tracer is more correct / has more information. 
											
										 
											2021-09-17 09:31:22 +02:00
										 |  |  | func TestCallTracerLegacy(t *testing.T) { | 
					
						
							|  |  |  | 	testCallTracer("callTracerLegacy", "call_tracer_legacy", t) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func testCallTracer(tracer string, dirPath string, t *testing.T) { | 
					
						
							|  |  |  | 	files, err := ioutil.ReadDir(filepath.Join("testdata", dirPath)) | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to retrieve tracer test suite: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, file := range files { | 
					
						
							| 
									
										
										
											
												core,eth: call frame tracing (#23087)
This change introduces 2 new optional methods; `enter()` and `exit()` for js tracers, and makes `step()` optiona. The two new methods are invoked when entering and exiting a call frame (but not invoked for the outermost scope, which has it's own methods). Currently these are the data fields passed to each of them:
    enter: type (opcode), from, to, input, gas, value
    exit: output, gasUsed, error
The PR also comes with a re-write of the callTracer. As a backup we keep the previous tracing script under the name `callTracerLegacy`. Behaviour of both tracers are equivalent for the most part, although there are some small differences (improvements), where the new tracer is more correct / has more information. 
											
										 
											2021-09-17 09:31:22 +02:00
										 |  |  | 		if !strings.HasSuffix(file.Name(), ".json") { | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		file := file // capture range variable | 
					
						
							| 
									
										
										
											
												core,eth: call frame tracing (#23087)
This change introduces 2 new optional methods; `enter()` and `exit()` for js tracers, and makes `step()` optiona. The two new methods are invoked when entering and exiting a call frame (but not invoked for the outermost scope, which has it's own methods). Currently these are the data fields passed to each of them:
    enter: type (opcode), from, to, input, gas, value
    exit: output, gasUsed, error
The PR also comes with a re-write of the callTracer. As a backup we keep the previous tracing script under the name `callTracerLegacy`. Behaviour of both tracers are equivalent for the most part, although there are some small differences (improvements), where the new tracer is more correct / has more information. 
											
										 
											2021-09-17 09:31:22 +02:00
										 |  |  | 		t.Run(camel(strings.TrimSuffix(file.Name(), ".json")), func(t *testing.T) { | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 			t.Parallel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Call tracer test found, read if from disk | 
					
						
							| 
									
										
										
											
												core,eth: call frame tracing (#23087)
This change introduces 2 new optional methods; `enter()` and `exit()` for js tracers, and makes `step()` optiona. The two new methods are invoked when entering and exiting a call frame (but not invoked for the outermost scope, which has it's own methods). Currently these are the data fields passed to each of them:
    enter: type (opcode), from, to, input, gas, value
    exit: output, gasUsed, error
The PR also comes with a re-write of the callTracer. As a backup we keep the previous tracing script under the name `callTracerLegacy`. Behaviour of both tracers are equivalent for the most part, although there are some small differences (improvements), where the new tracer is more correct / has more information. 
											
										 
											2021-09-17 09:31:22 +02:00
										 |  |  | 			blob, err := ioutil.ReadFile(filepath.Join("testdata", dirPath, file.Name())) | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatalf("failed to read testcase: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			test := new(callTracerTest) | 
					
						
							|  |  |  | 			if err := json.Unmarshal(blob, test); err != nil { | 
					
						
							|  |  |  | 				t.Fatalf("failed to parse testcase: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// Configure a blockchain with the given prestate | 
					
						
							|  |  |  | 			tx := new(types.Transaction) | 
					
						
							|  |  |  | 			if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil { | 
					
						
							|  |  |  | 				t.Fatalf("failed to parse testcase input: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number))) | 
					
						
							|  |  |  | 			origin, _ := signer.Sender(tx) | 
					
						
							| 
									
										
										
										
											2020-11-13 13:42:19 +01:00
										 |  |  | 			txContext := vm.TxContext{ | 
					
						
							|  |  |  | 				Origin:   origin, | 
					
						
							|  |  |  | 				GasPrice: tx.GasPrice(), | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			context := vm.BlockContext{ | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 				CanTransfer: core.CanTransfer, | 
					
						
							|  |  |  | 				Transfer:    core.Transfer, | 
					
						
							|  |  |  | 				Coinbase:    test.Context.Miner, | 
					
						
							|  |  |  | 				BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), | 
					
						
							|  |  |  | 				Time:        new(big.Int).SetUint64(uint64(test.Context.Time)), | 
					
						
							|  |  |  | 				Difficulty:  (*big.Int)(test.Context.Difficulty), | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 				GasLimit:    uint64(test.Context.GasLimit), | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-05-04 11:54:24 +03:00
										 |  |  | 			_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false) | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// Create the tracer, the EVM environment and run it | 
					
						
							| 
									
										
										
											
												core,eth: call frame tracing (#23087)
This change introduces 2 new optional methods; `enter()` and `exit()` for js tracers, and makes `step()` optiona. The two new methods are invoked when entering and exiting a call frame (but not invoked for the outermost scope, which has it's own methods). Currently these are the data fields passed to each of them:
    enter: type (opcode), from, to, input, gas, value
    exit: output, gasUsed, error
The PR also comes with a re-write of the callTracer. As a backup we keep the previous tracing script under the name `callTracerLegacy`. Behaviour of both tracers are equivalent for the most part, although there are some small differences (improvements), where the new tracer is more correct / has more information. 
											
										 
											2021-09-17 09:31:22 +02:00
										 |  |  | 			tracer, err := New(tracer, new(Context)) | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatalf("failed to create call tracer: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-11-13 13:42:19 +01:00
										 |  |  | 			evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer}) | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-17 15:13:22 +02:00
										 |  |  | 			msg, err := tx.AsMessage(signer, nil) | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatalf("failed to prepare transaction for tracing: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 			if _, err = st.TransitionDb(); err != nil { | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 				t.Fatalf("failed to execute transaction: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// Retrieve the trace result and compare against the etalon | 
					
						
							|  |  |  | 			res, err := tracer.GetResult() | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatalf("failed to retrieve trace result: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			ret := new(callTrace) | 
					
						
							|  |  |  | 			if err := json.Unmarshal(res, ret); err != nil { | 
					
						
							|  |  |  | 				t.Fatalf("failed to unmarshal trace result: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-27 17:33:45 +08:00
										 |  |  | 			if !jsonEqual(ret, test.Result) { | 
					
						
							|  |  |  | 				// uncomment this for easier debugging | 
					
						
							|  |  |  | 				//have, _ := json.MarshalIndent(ret, "", " ") | 
					
						
							|  |  |  | 				//want, _ := json.MarshalIndent(test.Result, "", " ") | 
					
						
							|  |  |  | 				//t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", string(have), string(want)) | 
					
						
							| 
									
										
										
										
											2019-01-06 04:26:50 +08:00
										 |  |  | 				t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, test.Result) | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-08-27 17:33:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												core,eth: call frame tracing (#23087)
This change introduces 2 new optional methods; `enter()` and `exit()` for js tracers, and makes `step()` optiona. The two new methods are invoked when entering and exiting a call frame (but not invoked for the outermost scope, which has it's own methods). Currently these are the data fields passed to each of them:
    enter: type (opcode), from, to, input, gas, value
    exit: output, gasUsed, error
The PR also comes with a re-write of the callTracer. As a backup we keep the previous tracing script under the name `callTracerLegacy`. Behaviour of both tracers are equivalent for the most part, although there are some small differences (improvements), where the new tracer is more correct / has more information. 
											
										 
											2021-09-17 09:31:22 +02:00
										 |  |  | func TestCallTracer(t *testing.T) { | 
					
						
							|  |  |  | 	testCallTracer("callTracer", "call_tracer", t) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-27 17:33:45 +08:00
										 |  |  | // jsonEqual is similar to reflect.DeepEqual, but does a 'bounce' via json prior to | 
					
						
							|  |  |  | // comparison | 
					
						
							|  |  |  | func jsonEqual(x, y interface{}) bool { | 
					
						
							|  |  |  | 	xTrace := new(callTrace) | 
					
						
							|  |  |  | 	yTrace := new(callTrace) | 
					
						
							|  |  |  | 	if xj, err := json.Marshal(x); err == nil { | 
					
						
							|  |  |  | 		json.Unmarshal(xj, xTrace) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if yj, err := json.Marshal(y); err == nil { | 
					
						
							|  |  |  | 		json.Unmarshal(yj, yTrace) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return reflect.DeepEqual(xTrace, yTrace) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-07-01 09:15:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | func BenchmarkTransactionTrace(b *testing.B) { | 
					
						
							|  |  |  | 	key, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") | 
					
						
							|  |  |  | 	from := crypto.PubkeyToAddress(key.PublicKey) | 
					
						
							|  |  |  | 	gas := uint64(1000000) // 1M gas | 
					
						
							|  |  |  | 	to := common.HexToAddress("0x00000000000000000000000000000000deadbeef") | 
					
						
							|  |  |  | 	signer := types.LatestSignerForChainID(big.NewInt(1337)) | 
					
						
							|  |  |  | 	tx, err := types.SignNewTx(key, signer, | 
					
						
							|  |  |  | 		&types.LegacyTx{ | 
					
						
							|  |  |  | 			Nonce:    1, | 
					
						
							|  |  |  | 			GasPrice: big.NewInt(500), | 
					
						
							|  |  |  | 			Gas:      gas, | 
					
						
							|  |  |  | 			To:       &to, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		b.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	txContext := vm.TxContext{ | 
					
						
							|  |  |  | 		Origin:   from, | 
					
						
							|  |  |  | 		GasPrice: tx.GasPrice(), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	context := vm.BlockContext{ | 
					
						
							|  |  |  | 		CanTransfer: core.CanTransfer, | 
					
						
							|  |  |  | 		Transfer:    core.Transfer, | 
					
						
							|  |  |  | 		Coinbase:    common.Address{}, | 
					
						
							|  |  |  | 		BlockNumber: new(big.Int).SetUint64(uint64(5)), | 
					
						
							|  |  |  | 		Time:        new(big.Int).SetUint64(uint64(5)), | 
					
						
							|  |  |  | 		Difficulty:  big.NewInt(0xffffffff), | 
					
						
							|  |  |  | 		GasLimit:    gas, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	alloc := core.GenesisAlloc{} | 
					
						
							|  |  |  | 	// The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns | 
					
						
							|  |  |  | 	// the address | 
					
						
							|  |  |  | 	loop := []byte{ | 
					
						
							|  |  |  | 		byte(vm.JUMPDEST), //  [ count ] | 
					
						
							|  |  |  | 		byte(vm.PUSH1), 0, // jumpdestination | 
					
						
							|  |  |  | 		byte(vm.JUMP), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = core.GenesisAccount{ | 
					
						
							|  |  |  | 		Nonce:   1, | 
					
						
							|  |  |  | 		Code:    loop, | 
					
						
							|  |  |  | 		Balance: big.NewInt(1), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	alloc[from] = core.GenesisAccount{ | 
					
						
							|  |  |  | 		Nonce:   1, | 
					
						
							|  |  |  | 		Code:    []byte{}, | 
					
						
							|  |  |  | 		Balance: big.NewInt(500000000000000), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false) | 
					
						
							|  |  |  | 	// Create the tracer, the EVM environment and run it | 
					
						
							|  |  |  | 	tracer := vm.NewStructLogger(&vm.LogConfig{ | 
					
						
							|  |  |  | 		Debug: false, | 
					
						
							|  |  |  | 		//DisableStorage: true, | 
					
						
							| 
									
										
										
										
											2021-09-13 18:59:52 +02:00
										 |  |  | 		//EnableMemory: false, | 
					
						
							|  |  |  | 		//EnableReturnData: false, | 
					
						
							| 
									
										
										
										
											2021-07-01 09:15:04 +02:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 	evm := vm.NewEVM(context, txContext, statedb, params.AllEthashProtocolChanges, vm.Config{Debug: true, Tracer: tracer}) | 
					
						
							|  |  |  | 	msg, err := tx.AsMessage(signer, nil) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		b.Fatalf("failed to prepare transaction for tracing: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	b.ResetTimer() | 
					
						
							|  |  |  | 	b.ReportAllocs() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < b.N; i++ { | 
					
						
							|  |  |  | 		snap := statedb.Snapshot() | 
					
						
							|  |  |  | 		st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) | 
					
						
							|  |  |  | 		_, err = st.TransitionDb() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			b.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		statedb.RevertToSnapshot(snap) | 
					
						
							|  |  |  | 		if have, want := len(tracer.StructLogs()), 244752; have != want { | 
					
						
							|  |  |  | 			b.Fatalf("trace wrong, want %d steps, have %d", want, have) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		tracer.Reset() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
											
												core,eth: call frame tracing (#23087)
This change introduces 2 new optional methods; `enter()` and `exit()` for js tracers, and makes `step()` optiona. The two new methods are invoked when entering and exiting a call frame (but not invoked for the outermost scope, which has it's own methods). Currently these are the data fields passed to each of them:
    enter: type (opcode), from, to, input, gas, value
    exit: output, gasUsed, error
The PR also comes with a re-write of the callTracer. As a backup we keep the previous tracing script under the name `callTracerLegacy`. Behaviour of both tracers are equivalent for the most part, although there are some small differences (improvements), where the new tracer is more correct / has more information. 
											
										 
											2021-09-17 09:31:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | func BenchmarkTracers(b *testing.B) { | 
					
						
							|  |  |  | 	files, err := ioutil.ReadDir(filepath.Join("testdata", "call_tracer")) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		b.Fatalf("failed to retrieve tracer test suite: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, file := range files { | 
					
						
							|  |  |  | 		if !strings.HasSuffix(file.Name(), ".json") { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		file := file // capture range variable | 
					
						
							|  |  |  | 		b.Run(camel(strings.TrimSuffix(file.Name(), ".json")), func(b *testing.B) { | 
					
						
							|  |  |  | 			blob, err := ioutil.ReadFile(filepath.Join("testdata", "call_tracer", file.Name())) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				b.Fatalf("failed to read testcase: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			test := new(callTracerTest) | 
					
						
							|  |  |  | 			if err := json.Unmarshal(blob, test); err != nil { | 
					
						
							|  |  |  | 				b.Fatalf("failed to parse testcase: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-10-13 13:32:37 +02:00
										 |  |  | 			newTracer := func() native.Tracer { | 
					
						
							|  |  |  | 				tracer, err := New("callTracer", new(Context)) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					b.Fatalf("failed to create call tracer: %v", err) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return tracer | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			benchTracer(newTracer, test, b) | 
					
						
							| 
									
										
										
											
												core,eth: call frame tracing (#23087)
This change introduces 2 new optional methods; `enter()` and `exit()` for js tracers, and makes `step()` optiona. The two new methods are invoked when entering and exiting a call frame (but not invoked for the outermost scope, which has it's own methods). Currently these are the data fields passed to each of them:
    enter: type (opcode), from, to, input, gas, value
    exit: output, gasUsed, error
The PR also comes with a re-write of the callTracer. As a backup we keep the previous tracing script under the name `callTracerLegacy`. Behaviour of both tracers are equivalent for the most part, although there are some small differences (improvements), where the new tracer is more correct / has more information. 
											
										 
											2021-09-17 09:31:22 +02:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 13:32:37 +02:00
										 |  |  | func benchTracer(newTracer func() native.Tracer, test *callTracerTest, b *testing.B) { | 
					
						
							| 
									
										
										
											
												core,eth: call frame tracing (#23087)
This change introduces 2 new optional methods; `enter()` and `exit()` for js tracers, and makes `step()` optiona. The two new methods are invoked when entering and exiting a call frame (but not invoked for the outermost scope, which has it's own methods). Currently these are the data fields passed to each of them:
    enter: type (opcode), from, to, input, gas, value
    exit: output, gasUsed, error
The PR also comes with a re-write of the callTracer. As a backup we keep the previous tracing script under the name `callTracerLegacy`. Behaviour of both tracers are equivalent for the most part, although there are some small differences (improvements), where the new tracer is more correct / has more information. 
											
										 
											2021-09-17 09:31:22 +02:00
										 |  |  | 	// Configure a blockchain with the given prestate | 
					
						
							|  |  |  | 	tx := new(types.Transaction) | 
					
						
							|  |  |  | 	if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil { | 
					
						
							|  |  |  | 		b.Fatalf("failed to parse testcase input: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number))) | 
					
						
							|  |  |  | 	msg, err := tx.AsMessage(signer, nil) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		b.Fatalf("failed to prepare transaction for tracing: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	origin, _ := signer.Sender(tx) | 
					
						
							|  |  |  | 	txContext := vm.TxContext{ | 
					
						
							|  |  |  | 		Origin:   origin, | 
					
						
							|  |  |  | 		GasPrice: tx.GasPrice(), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	context := vm.BlockContext{ | 
					
						
							|  |  |  | 		CanTransfer: core.CanTransfer, | 
					
						
							|  |  |  | 		Transfer:    core.Transfer, | 
					
						
							|  |  |  | 		Coinbase:    test.Context.Miner, | 
					
						
							|  |  |  | 		BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), | 
					
						
							|  |  |  | 		Time:        new(big.Int).SetUint64(uint64(test.Context.Time)), | 
					
						
							|  |  |  | 		Difficulty:  (*big.Int)(test.Context.Difficulty), | 
					
						
							|  |  |  | 		GasLimit:    uint64(test.Context.GasLimit), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	b.ReportAllocs() | 
					
						
							|  |  |  | 	b.ResetTimer() | 
					
						
							|  |  |  | 	for i := 0; i < b.N; i++ { | 
					
						
							| 
									
										
										
										
											2021-10-13 13:32:37 +02:00
										 |  |  | 		tracer := newTracer() | 
					
						
							|  |  |  | 		evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer}) | 
					
						
							| 
									
										
										
											
												core,eth: call frame tracing (#23087)
This change introduces 2 new optional methods; `enter()` and `exit()` for js tracers, and makes `step()` optiona. The two new methods are invoked when entering and exiting a call frame (but not invoked for the outermost scope, which has it's own methods). Currently these are the data fields passed to each of them:
    enter: type (opcode), from, to, input, gas, value
    exit: output, gasUsed, error
The PR also comes with a re-write of the callTracer. As a backup we keep the previous tracing script under the name `callTracerLegacy`. Behaviour of both tracers are equivalent for the most part, although there are some small differences (improvements), where the new tracer is more correct / has more information. 
											
										 
											2021-09-17 09:31:22 +02:00
										 |  |  | 		snap := statedb.Snapshot() | 
					
						
							|  |  |  | 		st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) | 
					
						
							|  |  |  | 		if _, err = st.TransitionDb(); err != nil { | 
					
						
							|  |  |  | 			b.Fatalf("failed to execute transaction: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-10-13 13:32:37 +02:00
										 |  |  | 		_, err := tracer.GetResult() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			b.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												core,eth: call frame tracing (#23087)
This change introduces 2 new optional methods; `enter()` and `exit()` for js tracers, and makes `step()` optiona. The two new methods are invoked when entering and exiting a call frame (but not invoked for the outermost scope, which has it's own methods). Currently these are the data fields passed to each of them:
    enter: type (opcode), from, to, input, gas, value
    exit: output, gasUsed, error
The PR also comes with a re-write of the callTracer. As a backup we keep the previous tracing script under the name `callTracerLegacy`. Behaviour of both tracers are equivalent for the most part, although there are some small differences (improvements), where the new tracer is more correct / has more information. 
											
										 
											2021-09-17 09:31:22 +02:00
										 |  |  | 		statedb.RevertToSnapshot(snap) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |