diff --git a/.travis.yml b/.travis.yml index 7be2400526..95817408dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ env: - TEST="bash ./scripts/travis_go_checker.sh" - TEST="bash ./scripts/travis_rpc_checker.sh" - TEST="bash ./scripts/travis_pyhmy_checker.sh" + - TEST="bash ./scripts/travis_rosetta_checker.sh" # We enable Travis on the main/dev branches. # pull_request type includes both main repo/fork PR workflow diff --git a/hmy/tracer.go b/hmy/tracer.go index aff9c3cbd0..6c92a8b58f 100644 --- a/hmy/tracer.go +++ b/hmy/tracer.go @@ -819,7 +819,39 @@ func (hmy *Harmony) traceTx(ctx context.Context, message core.Message, txctx *tr if config == nil { config = &tracers.TraceConfig{} } - // Default tracer is the struct logger + + //switch { + //case config.Tracer != nil: + // if *config.Tracer == "ParityBlockTracer" { + // tracer = &tracers.ParityBlockTracer{} + // break + // } else if *config.Tracer == "RosettaBlockTracer" { + // tracer = &tracers.RosettaBlockTracer{ParityBlockTracer: &tracers.ParityBlockTracer{}} + // break + // } + // // Define a meaningful timeout of a single transaction trace + // //timeout := defaultTraceTimeout + // //if config.Timeout != nil { + // // if timeout, err = time.ParseDuration(*config.Timeout); err != nil { + // // return nil, err + // // } + // //} + // //// Constuct the JavaScript tracer to execute with + // //if tracer, err = tracers.New(*config.Tracer); err != nil { + // // return nil, err + // //} + // //// Handle timeouts and RPC cancellations + // //deadlineCtx, cancel := context.WithTimeout(ctx, timeout) + // //go func() { + // // <-deadlineCtx.Done() + // // tracer.(*tracers.Tracer).Stop(errors.New("execution timeout")) + // //}() + // //defer cancel() + //default: + // // Default tracer is the struct logger + // tracer = logger.NewStructLogger(config.Config) + //} + tracer = logger.NewStructLogger(config.Config) if config.Tracer != nil { tracer, err = tracers.New(*config.Tracer, txctx, config.TracerConfig) diff --git a/hmy/tracers/block_tracer.go b/hmy/tracers/block_tracer.go index 02db9871d4..cb214c5e3b 100644 --- a/hmy/tracers/block_tracer.go +++ b/hmy/tracers/block_tracer.go @@ -216,6 +216,10 @@ type ParityBlockTracer struct { tracers []*ParityTxTracer } +func (jst *ParityBlockTracer) Stop(err error) { + +} + func (jst *ParityBlockTracer) CaptureTxStart(gasLimit uint64) { } @@ -255,7 +259,11 @@ func (ptt *ParityTxTracer) len() int { } // CaptureStart implements the ParityBlockTracer interface to initialize the tracing operation. -func (jst *ParityBlockTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { +func (jst *ParityBlockTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + jst.captureStart(env, from, to, create, input, gas, value) +} + +func (jst *ParityBlockTracer) captureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { jst.cur = &ParityTxTracer{} jst.cur.op = vm.CALL // vritual call if create { @@ -275,10 +283,14 @@ func (jst *ParityBlockTracer) CaptureStart(env *vm.EVM, from common.Address, to return nil } +func (jst *ParityBlockTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rdata []byte, depth int, err error) { + jst.captureState(env, pc, op, gas, cost, scope.Memory, scope.Stack, scope.Contract, depth, err) +} + // CaptureState implements the ParityBlockTracer interface to trace a single step of VM execution. -func (jst *ParityBlockTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) (vm.HookAfter, error) { +func (jst *ParityBlockTracer) captureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) (vm.HookAfter, error) { if err != nil { - return nil, jst.CaptureFault(env, pc, op, gas, cost, memory, stack, contract, depth, err) + return nil, jst.captureFault(env, pc, op, gas, cost, memory, stack, contract, depth, err) } var retErr error stackPeek := func(n int) *uint256.Int { @@ -393,9 +405,13 @@ func (jst *ParityBlockTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, return nil, retErr } +func (jst *ParityBlockTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { + jst.captureFault(nil, pc, op, gas, cost, scope.Memory, scope.Stack, scope.Contract, depth, err) +} + // CaptureFault implements the ParityBlockTracer interface to trace an execution fault // while running an opcode. -func (jst *ParityBlockTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error { +func (jst *ParityBlockTracer) captureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error { if jst.cur.last().err != nil { return nil } @@ -417,7 +433,12 @@ func (jst *ParityBlockTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, } // CaptureEnd is called after the call finishes to finalize the tracing. -func (jst *ParityBlockTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error { +func (jst *ParityBlockTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) { + jst.captureEnd(output, gasUsed, t, err) + return +} + +func (jst *ParityBlockTracer) captureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error { jst.cur.output = output jst.cur.gasUsed = gasUsed if err != nil { @@ -461,7 +482,7 @@ func (jst *ParityBlockTracer) GetStorage() *TraceBlockStorage { } // GetResult calls the Javascript 'result' function and returns its value, or any accumulated error -func (jst *ParityBlockTracer) GetResult() ([]json.RawMessage, error) { +func (jst *ParityBlockTracer) GetResult() (json.RawMessage, error) { var results []json.RawMessage var err error var headPiece string @@ -501,5 +522,6 @@ func (jst *ParityBlockTracer) GetResult() ([]json.RawMessage, error) { ) finalize(root, make([]int, 0)) } - return results, err + _ = err + return json.Marshal(results) } diff --git a/hmy/tracers/rosetta_block_tracer.go b/hmy/tracers/rosetta_block_tracer.go index d1b573d7a9..081f8e0288 100644 --- a/hmy/tracers/rosetta_block_tracer.go +++ b/hmy/tracers/rosetta_block_tracer.go @@ -17,11 +17,27 @@ package tracers import ( + "encoding/json" "math/big" "github.com/harmony-one/harmony/core/vm" + "github.com/pkg/errors" ) +// init registers itself this packages as a lookup for tracers. +func init() { + RegisterLookup(false, newPrestateTracer) +} + +func newPrestateTracer(code string, ctx *Context, _ json.RawMessage) (Tracer, error) { + if code != "RosettaBlockTracer" { + return nil, errors.New("invalid code") + } + tracer := &RosettaBlockTracer{ParityBlockTracer: &ParityBlockTracer{}} + return tracer, nil + //return &prestateTracer{prestate: prestate{}}, nil +} + type RosettaLogItem struct { IsSuccess bool Reverted bool @@ -67,11 +83,11 @@ func (rbt *RosettaBlockTracer) AddRosettaLog(op vm.OpCode, from, to *vm.RosettaL }) } -func (rbt *RosettaBlockTracer) GetResult() ([]*RosettaLogItem, error) { +func (rbt *RosettaBlockTracer) GetResult() (json.RawMessage, error) { root := &rbt.cur.action var results = make([]*RosettaLogItem, 0) - var err error + //var err error var finalize func(ac *action, parentErr error, traceAddress []int) finalize = func(ac *action, parentErr error, traceAddress []int) { results = append(results, rbt.formatAction(traceAddress, parentErr, ac)) @@ -90,5 +106,7 @@ func (rbt *RosettaBlockTracer) GetResult() ([]*RosettaLogItem, error) { finalize(subAc, root.err, append(traceAddress[:], i)) } - return append(results, rbt.logs...), err + // TODO + return json.RawMessage{}, nil + //return append(results, rbt.logs...), err }