From c3f23ddce829ddb9bac444f019d2e47d5ba85ac7 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Thu, 11 Jun 2020 02:47:28 +0200 Subject: [PATCH] Refactor ExecutionResult to ExecutionTrace Signed-off-by: Jakub Sztandera --- api/api_full.go | 10 ++--- api/docgen/docgen.go | 2 +- chain/stmgr/call.go | 10 ++--- chain/stmgr/stmgr.go | 8 ++-- chain/types/execresult.go | 4 +- chain/vm/runtime.go | 37 +++++------------ chain/vm/vm.go | 86 +++++++++++++++++++++++---------------- cli/state.go | 14 +++---- go.mod | 1 + go.sum | 3 ++ node/impl/full/state.go | 10 ++--- 11 files changed, 95 insertions(+), 90 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 63d9a5e5d..e9370a0b8 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -350,11 +350,11 @@ type RetrievalOrder struct { } type InvocResult struct { - Msg *types.Message - MsgRct *types.MessageReceipt - InternalExecutions []*types.ExecutionResult - Error string - Duration time.Duration + Msg *types.Message + MsgRct *types.MessageReceipt + ExecutionTrace types.ExecutionTrace + Error string + Duration time.Duration } type MethodCall struct { diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index eb4ab5fd9..d0b5d8558 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -93,7 +93,7 @@ func init() { addExample(build.APIVersion) addExample(api.PCHInbound) addExample(time.Minute) - addExample(&types.ExecutionResult{ + addExample(&types.ExecutionTrace{ Msg: exampleValue(reflect.TypeOf(&types.Message{})).(*types.Message), MsgRct: exampleValue(reflect.TypeOf(&types.MessageReceipt{})).(*types.MessageReceipt), }) diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index b9635696f..32e502e95 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -62,11 +62,11 @@ func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate } return &api.InvocResult{ - Msg: msg, - MsgRct: &ret.MessageReceipt, - InternalExecutions: ret.InternalExecutions, - Error: errs, - Duration: ret.Duration, + Msg: msg, + MsgRct: &ret.MessageReceipt, + ExecutionTrace: ret.ExecutionTrace, + Error: errs, + Duration: ret.Duration, }, nil } diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index d6aaebab4..d4c12dffe 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -121,10 +121,10 @@ func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (c var trace []*api.InvocResult st, _, err := sm.computeTipSetState(ctx, ts.Blocks(), func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error { ir := &api.InvocResult{ - Msg: msg, - MsgRct: &ret.MessageReceipt, - InternalExecutions: ret.InternalExecutions, - Duration: ret.Duration, + Msg: msg, + MsgRct: &ret.MessageReceipt, + ExecutionTrace: ret.ExecutionTrace, + Duration: ret.Duration, } if ret.ActorErr != nil { ir.Error = ret.ActorErr.Error() diff --git a/chain/types/execresult.go b/chain/types/execresult.go index 56f2ef143..dd5c8fa3e 100644 --- a/chain/types/execresult.go +++ b/chain/types/execresult.go @@ -2,11 +2,11 @@ package types import "time" -type ExecutionResult struct { +type ExecutionTrace struct { Msg *Message MsgRct *MessageReceipt Error string Duration time.Duration - Subcalls []*ExecutionResult + Subcalls []ExecutionTrace } diff --git a/chain/vm/runtime.go b/chain/vm/runtime.go index d9268afe4..0067055d1 100644 --- a/chain/vm/runtime.go +++ b/chain/vm/runtime.go @@ -5,7 +5,6 @@ import ( "context" "encoding/binary" "fmt" - "time" "github.com/filecoin-project/go-address" "github.com/filecoin-project/specs-actors/actors/abi" @@ -51,10 +50,10 @@ type Runtime struct { origin address.Address originNonce uint64 - internalExecutions []*types.ExecutionResult - numActorsCreated uint64 - allowInternal bool - callerValidated bool + executionTrace types.ExecutionTrace + numActorsCreated uint64 + allowInternal bool + callerValidated bool } func (rt *Runtime) TotalFilCircSupply() abi.TokenAmount { @@ -368,7 +367,6 @@ func (rt *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMars } func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum, value types.BigInt, params []byte) ([]byte, aerrors.ActorError) { - start := time.Now() ctx, span := trace.StartSpan(rt.ctx, "vmc.Send") defer span.End() if span.IsRecordingEvents() { @@ -401,27 +399,10 @@ func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum, } } - mr := types.MessageReceipt{ - ExitCode: aerrors.RetCode(errSend), - Return: ret, - GasUsed: 0, - } - - er := types.ExecutionResult{ - Msg: msg, - MsgRct: &mr, - Duration: time.Since(start), - } - - if errSend != nil { - er.Error = errSend.Error() - } - if subrt != nil { - er.Subcalls = subrt.internalExecutions rt.numActorsCreated = subrt.numActorsCreated } - rt.internalExecutions = append(rt.internalExecutions, &er) + rt.executionTrace.Subcalls = append(rt.executionTrace.Subcalls, subrt.executionTrace) //&er) return ret, errSend } @@ -504,13 +485,13 @@ func (rt *Runtime) stateCommit(oldh, newh cid.Cid) aerrors.ActorError { } func (rt *Runtime) ChargeGas(toUse int64) { - err := rt.chargeGasSafe(toUse) + err := rt.chargeGasInternal(toUse) if err != nil { panic(err) } } -func (rt *Runtime) chargeGasSafe(toUse int64) aerrors.ActorError { +func (rt *Runtime) chargeGasInternal(toUse int64) aerrors.ActorError { if rt.gasUsed+toUse > rt.gasAvailable { rt.gasUsed = rt.gasAvailable return aerrors.Newf(exitcode.SysErrOutOfGas, "not enough gas: used=%d, available=%d", rt.gasUsed, rt.gasAvailable) @@ -519,6 +500,10 @@ func (rt *Runtime) chargeGasSafe(toUse int64) aerrors.ActorError { return nil } +func (rt *Runtime) chargeGasSafe(toUse int64) aerrors.ActorError { + return rt.chargeGasInternal(toUse) +} + func (rt *Runtime) Pricelist() Pricelist { return rt.pricelist } diff --git a/chain/vm/vm.go b/chain/vm/vm.go index da38fcbf3..42d6d373e 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -102,6 +102,7 @@ func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin addres pricelist: PricelistByEpoch(vm.blockHeight), allowInternal: true, callerValidated: false, + executionTrace: types.ExecutionTrace{Msg: msg}, } rt.cst = &cbor.BasicIpldStore{ @@ -163,14 +164,16 @@ type Rand interface { type ApplyRet struct { types.MessageReceipt - ActorErr aerrors.ActorError - Penalty types.BigInt - InternalExecutions []*types.ExecutionResult - Duration time.Duration + ActorErr aerrors.ActorError + Penalty types.BigInt + ExecutionTrace types.ExecutionTrace + Duration time.Duration } func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime, gasCharge int64) ([]byte, aerrors.ActorError, *Runtime) { + start := time.Now() + st := vm.cstate gasUsed := gasCharge @@ -191,35 +194,50 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime, }() } - if aerr := rt.chargeGasSafe(rt.Pricelist().OnMethodInvocation(msg.Value, msg.Method)); aerr != nil { - return nil, aerrors.Wrap(aerr, "not enough gas for method invocation"), rt - } + ret, err := func() ([]byte, aerrors.ActorError) { + if aerr := rt.chargeGasSafe(rt.Pricelist().OnMethodInvocation(msg.Value, msg.Method)); aerr != nil { + return nil, aerrors.Wrap(aerr, "not enough gas for method invocation") + } - toActor, err := st.GetActor(msg.To) - if err != nil { - if xerrors.Is(err, init_.ErrAddressNotFound) { - a, err := TryCreateAccountActor(rt, msg.To) - if err != nil { - return nil, aerrors.Wrapf(err, "could not create account"), rt + toActor, err := st.GetActor(msg.To) + if err != nil { + if xerrors.Is(err, init_.ErrAddressNotFound) { + a, err := TryCreateAccountActor(rt, msg.To) + if err != nil { + return nil, aerrors.Wrapf(err, "could not create account") + } + toActor = a + } else { + return nil, aerrors.Escalate(err, "getting actor") } - toActor = a - } else { - return nil, aerrors.Escalate(err, "getting actor"), rt } - } - if types.BigCmp(msg.Value, types.NewInt(0)) != 0 { - if err := vm.transfer(msg.From, msg.To, msg.Value); err != nil { - return nil, aerrors.Wrap(err, "failed to transfer funds"), nil + if types.BigCmp(msg.Value, types.NewInt(0)) != 0 { + if err := vm.transfer(msg.From, msg.To, msg.Value); err != nil { + return nil, aerrors.Wrap(err, "failed to transfer funds") + } } + + if msg.Method != 0 { + var ret []byte + ret, err := vm.Invoke(toActor, rt, msg.Method, msg.Params) + return ret, err + } + return nil, nil + }() + + mr := types.MessageReceipt{ + ExitCode: aerrors.RetCode(err), + Return: ret, + GasUsed: rt.gasUsed, + } + rt.executionTrace.MsgRct = &mr + rt.executionTrace.Duration = time.Since(start) + if err != nil { + rt.executionTrace.Error = err.Error() } - if msg.Method != 0 { - ret, err := vm.Invoke(toActor, rt, msg.Method, msg.Params) - return ret, err, rt - } - - return nil, nil, rt + return ret, err, rt } func checkMessage(msg *types.Message) error { @@ -250,10 +268,10 @@ func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*Ap Return: ret, GasUsed: 0, }, - ActorErr: actorErr, - InternalExecutions: rt.internalExecutions, - Penalty: types.NewInt(0), - Duration: time.Since(start), + ActorErr: actorErr, + ExecutionTrace: rt.executionTrace, + Penalty: types.NewInt(0), + Duration: time.Since(start), }, actorErr } @@ -419,10 +437,10 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, Return: ret, GasUsed: gasUsed, }, - ActorErr: actorErr, - InternalExecutions: rt.internalExecutions, - Penalty: types.NewInt(0), - Duration: time.Since(start), + ActorErr: actorErr, + ExecutionTrace: rt.executionTrace, + Penalty: types.NewInt(0), + Duration: time.Since(start), }, nil } diff --git a/cli/state.go b/cli/state.go index 6720ceacd..5b13c43b9 100644 --- a/cli/state.go +++ b/cli/state.go @@ -931,14 +931,14 @@ var stateComputeStateCmd = &cli.Command{ if cctx.Bool("show-trace") { for _, ir := range stout.Trace { fmt.Printf("%s\t%s\t%s\t%d\t%x\t%d\t%x\n", ir.Msg.From, ir.Msg.To, ir.Msg.Value, ir.Msg.Method, ir.Msg.Params, ir.MsgRct.ExitCode, ir.MsgRct.Return) - printInternalExecutions("\t", ir.InternalExecutions) + printInternalExecutions("\t", ir.ExecutionTrace.Subcalls) } } return nil }, } -func printInternalExecutions(prefix string, trace []*types.ExecutionResult) { +func printInternalExecutions(prefix string, trace []types.ExecutionTrace) { for _, im := range trace { fmt.Printf("%s%s\t%s\t%s\t%d\t%x\t%d\t%x\n", prefix, im.Msg.From, im.Msg.To, im.Msg.Value, im.Msg.Method, im.Msg.Params, im.MsgRct.ExitCode, im.MsgRct.Return) printInternalExecutions(prefix+"\t", im.Subcalls) @@ -1028,11 +1028,9 @@ func computeStateHtml(ts *types.TipSet, o *api.ComputeStateOutput, getCode func( fmt.Printf(`
Error:
%s
`, ir.Error) } - if len(ir.InternalExecutions) > 0 { - fmt.Println("
Internal executions:
") - if err := printInternalExecutionsHtml(cid.String(), ir.InternalExecutions, getCode); err != nil { - return err - } + fmt.Println("
Execution trace:
") + if err := printInternalExecutionsHtml(cid.String(), ir.ExecutionTrace.Subcalls, getCode); err != nil { + return err } fmt.Println("") } @@ -1042,7 +1040,7 @@ func computeStateHtml(ts *types.TipSet, o *api.ComputeStateOutput, getCode func( return nil } -func printInternalExecutionsHtml(hashName string, trace []*types.ExecutionResult, getCode func(addr address.Address) (cid.Cid, error)) error { +func printInternalExecutionsHtml(hashName string, trace []types.ExecutionTrace, getCode func(addr address.Address) (cid.Cid, error)) error { for i, im := range trace { hashName := fmt.Sprintf("%s-r%d", hashName, i) diff --git a/go.mod b/go.mod index 21fea095f..5a3cf4a07 100644 --- a/go.mod +++ b/go.mod @@ -104,6 +104,7 @@ require ( github.com/multiformats/go-multibase v0.0.2 github.com/multiformats/go-multihash v0.0.13 github.com/opentracing/opentracing-go v1.1.0 + github.com/prometheus/common v0.9.1 github.com/stretchr/objx v0.2.0 // indirect github.com/stretchr/testify v1.5.1 github.com/syndtr/goleveldb v1.0.0 diff --git a/go.sum b/go.sum index 35395be66..e10972bb6 100644 --- a/go.sum +++ b/go.sum @@ -42,9 +42,11 @@ github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75/go.mod h1:uAXEEpARkRhCZfEvy/y0Jcc888f9tHCc1W7/UeEtreE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= @@ -1575,6 +1577,7 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/node/impl/full/state.go b/node/impl/full/state.go index fae2a7b67..1d68a1858 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -242,11 +242,11 @@ func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid. } return &api.InvocResult{ - Msg: m, - MsgRct: &r.MessageReceipt, - InternalExecutions: r.InternalExecutions, - Error: errstr, - Duration: r.Duration, + Msg: m, + MsgRct: &r.MessageReceipt, + ExecutionTrace: r.ExecutionTrace, + Error: errstr, + Duration: r.Duration, }, nil }