eth/tracers: package restructuring (#23857)

* eth/tracers: restructure tracer package

* core/vm/runtime: load js tracers

* eth/tracers: mv bigint js code to own file

* eth/tracers: add method docs for native tracers

* eth/tracers: minor doc fix

* core,eth: cancel evm on nativecalltracer stop

* core/vm: fix failing test

Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
This commit is contained in:
Martin Holst Swende
2021-11-09 12:09:35 +01:00
committed by GitHub
parent 9489853321
commit 6b9c77f060
54 changed files with 1393 additions and 1389 deletions

View File

@ -14,18 +14,25 @@
// 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 is a collection of JavaScript transaction tracers.
// Package tracers is a manager for transaction tracing engines.
package tracers
import (
"encoding/json"
"strings"
"unicode"
"errors"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/internal/tracers"
)
// Context contains some contextual infos for a transaction execution that is not
// available from within the EVM object.
type Context struct {
BlockHash common.Hash // Hash of the block the tx is contained within (zero if dangling tx or call)
TxIndex int // Index of the transaction within a block (zero if dangling tx or call)
TxHash common.Hash // Hash of the transaction being traced (zero if dangling call)
}
// Tracer interface extends vm.EVMLogger and additionally
// allows collecting the tracing result.
type Tracer interface {
@ -35,50 +42,31 @@ type Tracer interface {
Stop(err error)
}
type lookupFunc func(string, *Context) (Tracer, error)
var (
nativeTracers map[string]func() Tracer = make(map[string]func() Tracer)
jsTracers = make(map[string]string)
lookups []lookupFunc
)
// RegisterNativeTracer makes native tracers which adhere
// to the `Tracer` interface available to the rest of the codebase.
// It is typically invoked in the `init()` function, e.g. see the `native/call.go`.
func RegisterNativeTracer(name string, ctor func() Tracer) {
nativeTracers[name] = ctor
// RegisterLookup registers a method as a lookup for tracers, meaning that
// users can invoke a named tracer through that lookup. If 'wildcard' is true,
// then the lookup will be placed last. This is typically meant for interpreted
// engines (js) which can evaluate dynamic user-supplied code.
func RegisterLookup(wildcard bool, lookup lookupFunc) {
if wildcard {
lookups = append(lookups, lookup)
} else {
lookups = append([]lookupFunc{lookup}, lookups...)
}
}
// New returns a new instance of a tracer,
// 1. If 'code' is the name of a registered native tracer, then that tracer
// is instantiated and returned
// 2. If 'code' is the name of a registered js-tracer, then that tracer is
// instantiated and returned
// 3. Otherwise, the code is interpreted as the js code of a js-tracer, and
// is evaluated and returned.
// New returns a new instance of a tracer, by iterating through the
// registered lookups.
func New(code string, ctx *Context) (Tracer, error) {
// Resolve native tracer
if fn, ok := nativeTracers[code]; ok {
return fn(), nil
}
// Resolve js-tracers by name and assemble the tracer object
if tracer, ok := jsTracers[code]; ok {
code = tracer
}
return newJsTracer(code, ctx)
}
// camel converts a snake cased input string into a camel cased output.
func camel(str string) string {
pieces := strings.Split(str, "_")
for i := 1; i < len(pieces); i++ {
pieces[i] = string(unicode.ToUpper(rune(pieces[i][0]))) + pieces[i][1:]
}
return strings.Join(pieces, "")
}
// init retrieves the JavaScript transaction tracers included in go-ethereum.
func init() {
for _, file := range tracers.AssetNames() {
name := camel(strings.TrimSuffix(file, ".js"))
jsTracers[name] = string(tracers.MustAsset(file))
for _, lookup := range lookups {
if tracer, err := lookup(code, ctx); err == nil {
return tracer, nil
}
}
return nil, errors.New("tracer not found")
}