github.com/amazechain/amc@v0.1.3/internal/tracers/native/mux.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 native 18 19 import ( 20 "encoding/json" 21 "github.com/holiman/uint256" 22 23 common "github.com/amazechain/amc/common/types" 24 "github.com/amazechain/amc/internal/tracers" 25 "github.com/amazechain/amc/internal/vm" 26 ) 27 28 func init() { 29 tracers.DefaultDirectory.Register("muxTracer", newMuxTracer, false) 30 } 31 32 // muxTracer is a go implementation of the Tracer interface which 33 // runs multiple tracers in one go. 34 type muxTracer struct { 35 names []string 36 tracers []tracers.Tracer 37 } 38 39 // newMuxTracer returns a new mux tracer. 40 func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { 41 var config map[string]json.RawMessage 42 if cfg != nil { 43 if err := json.Unmarshal(cfg, &config); err != nil { 44 return nil, err 45 } 46 } 47 objects := make([]tracers.Tracer, 0, len(config)) 48 names := make([]string, 0, len(config)) 49 for k, v := range config { 50 t, err := tracers.DefaultDirectory.New(k, ctx, v) 51 if err != nil { 52 return nil, err 53 } 54 objects = append(objects, t) 55 names = append(names, k) 56 } 57 58 return &muxTracer{names: names, tracers: objects}, nil 59 } 60 61 // CaptureStart implements the EVMLogger interface to initialize the tracing operation. 62 func (t *muxTracer) CaptureStart(env vm.VMInterface, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *uint256.Int) { 63 for _, t := range t.tracers { 64 t.CaptureStart(env, from, to, create, input, gas, value) 65 } 66 } 67 68 // CaptureEnd is called after the call finishes to finalize the tracing. 69 func (t *muxTracer) CaptureEnd(output []byte, gasUsed uint64, err error) { 70 for _, t := range t.tracers { 71 t.CaptureEnd(output, gasUsed, err) 72 } 73 } 74 75 // CaptureState implements the EVMLogger interface to trace a single step of VM execution. 76 func (t *muxTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { 77 for _, t := range t.tracers { 78 t.CaptureState(pc, op, gas, cost, scope, rData, depth, err) 79 } 80 } 81 82 // CaptureFault implements the EVMLogger interface to trace an execution fault. 83 func (t *muxTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { 84 for _, t := range t.tracers { 85 t.CaptureFault(pc, op, gas, cost, scope, depth, err) 86 } 87 } 88 89 // CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). 90 func (t *muxTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *uint256.Int) { 91 for _, t := range t.tracers { 92 t.CaptureEnter(typ, from, to, input, gas, value) 93 } 94 } 95 96 // CaptureExit is called when EVM exits a scope, even if the scope didn't 97 // execute any code. 98 func (t *muxTracer) CaptureExit(output []byte, gasUsed uint64, err error) { 99 for _, t := range t.tracers { 100 t.CaptureExit(output, gasUsed, err) 101 } 102 } 103 104 func (t *muxTracer) CaptureTxStart(gasLimit uint64) { 105 for _, t := range t.tracers { 106 t.CaptureTxStart(gasLimit) 107 } 108 } 109 110 func (t *muxTracer) CaptureTxEnd(restGas uint64) { 111 for _, t := range t.tracers { 112 t.CaptureTxEnd(restGas) 113 } 114 } 115 116 // GetResult returns an empty json object. 117 func (t *muxTracer) GetResult() (json.RawMessage, error) { 118 resObject := make(map[string]json.RawMessage) 119 for i, tt := range t.tracers { 120 r, err := tt.GetResult() 121 if err != nil { 122 return nil, err 123 } 124 resObject[t.names[i]] = r 125 } 126 res, err := json.Marshal(resObject) 127 if err != nil { 128 return nil, err 129 } 130 return res, nil 131 } 132 133 // Stop terminates execution of the tracer at the first opportune moment. 134 func (t *muxTracer) Stop(err error) { 135 for _, t := range t.tracers { 136 t.Stop(err) 137 } 138 }