github.com/amazechain/amc@v0.1.3/internal/tracers/tracers.go (about) 1 // Copyright 2023 The AmazeChain Authors 2 // This file is part of the AmazeChain library. 3 // 4 // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package tracers is a manager for transaction tracing engines. 18 19 package tracers 20 21 import ( 22 "encoding/json" 23 "math/big" 24 25 common "github.com/amazechain/amc/common/types" 26 "github.com/amazechain/amc/internal/vm" 27 ) 28 29 // Context contains some contextual infos for a transaction execution that is not 30 // available from within the EVM object. 31 type Context struct { 32 BlockHash common.Hash // Hash of the block the tx is contained within (zero if dangling tx or call) 33 BlockNumber *big.Int // Number of the block the tx is contained within (zero if dangling tx or call) 34 TxIndex int // Index of the transaction within a block (zero if dangling tx or call) 35 TxHash common.Hash // Hash of the transaction being traced (zero if dangling call) 36 } 37 38 // Tracer interface extends vm.EVMLogger and additionally 39 // allows collecting the tracing result. 40 type Tracer interface { 41 vm.EVMLogger 42 GetResult() (json.RawMessage, error) 43 // Stop terminates execution of the tracer at the first opportune moment. 44 Stop(err error) 45 } 46 47 type ctorFn func(*Context, json.RawMessage) (Tracer, error) 48 type jsCtorFn func(string, *Context, json.RawMessage) (Tracer, error) 49 50 type elem struct { 51 ctor ctorFn 52 isJS bool 53 } 54 55 // DefaultDirectory is the collection of tracers bundled by default. 56 var DefaultDirectory = directory{elems: make(map[string]elem)} 57 58 // directory provides functionality to lookup a tracer by name 59 // and a function to instantiate it. It falls back to a JS code evaluator 60 // if no tracer of the given name exists. 61 type directory struct { 62 elems map[string]elem 63 jsEval jsCtorFn 64 } 65 66 // Register registers a method as a lookup for tracers, meaning that 67 // users can invoke a named tracer through that lookup. 68 func (d *directory) Register(name string, f ctorFn, isJS bool) { 69 d.elems[name] = elem{ctor: f, isJS: isJS} 70 } 71 72 // RegisterJSEval registers a tracer that is able to parse 73 // dynamic user-provided JS code. 74 func (d *directory) RegisterJSEval(f jsCtorFn) { 75 d.jsEval = f 76 } 77 78 // New returns a new instance of a tracer, by iterating through the 79 // registered lookups. Name is either name of an existing tracer 80 // or an arbitrary JS code. 81 func (d *directory) New(name string, ctx *Context, cfg json.RawMessage) (Tracer, error) { 82 if elem, ok := d.elems[name]; ok { 83 return elem.ctor(ctx, cfg) 84 } 85 // Assume JS code 86 return d.jsEval(name, ctx, cfg) 87 } 88 89 // IsJS will return true if the given tracer will evaluate 90 // JS code. Because code evaluation has high overhead, this 91 // info will be used in determining fast and slow code paths. 92 func (d *directory) IsJS(name string) bool { 93 if elem, ok := d.elems[name]; ok { 94 return elem.isJS 95 } 96 // JS eval will execute JS code 97 return true 98 }