Skip to content

Commit

Permalink
FVM: Support exectraces
Browse files Browse the repository at this point in the history
  • Loading branch information
arajasek committed Apr 19, 2022
1 parent 1922e76 commit 9f3de44
Show file tree
Hide file tree
Showing 10 changed files with 256 additions and 34 deletions.
169 changes: 169 additions & 0 deletions chain/vm/cbor_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 48 additions & 8 deletions chain/vm/fvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,37 @@ type FvmExtern struct {
base cid.Cid
}

// VerifyConsensusFault is similar to the one in syscalls.go used by the LegacyVM, except it never errors
// This may eventually become identical to ExecutionTrace, but we can make incremental progress towards that
type FvmExecutionTrace struct {
Msg *types.Message
MsgRct *types.MessageReceipt
Error string

Subcalls []FvmExecutionTrace
}

func (t *FvmExecutionTrace) ToExecutionTrace() types.ExecutionTrace {
if t == nil {
return types.ExecutionTrace{}
}

ret := types.ExecutionTrace{
Msg: t.Msg,
MsgRct: t.MsgRct,
Error: t.Error,
Duration: 0,
GasCharges: nil,
Subcalls: make([]types.ExecutionTrace, len(t.Subcalls)),
}

for i, v := range t.Subcalls {
ret.Subcalls[i] = v.ToExecutionTrace()
}

return ret
}

// VerifyConsensusFault is similar to the one in syscalls.go used by the Lotus VM, except it never errors
// Errors are logged and "no fault" is returned, which is functionally what go-actors does anyway
func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, a, b, extra []byte) (*ffi_cgo.ConsensusFault, int64) {
totalGas := int64(0)
Expand Down Expand Up @@ -249,6 +279,7 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) {
BaseCircSupply: circToReport,
NetworkVersion: opts.NetworkVersion,
StateBase: opts.StateBase,
Tracing: EnableDetailedTracing,
}

fvm, err := ffi.CreateFVM(&fvmOpts)
Expand All @@ -273,6 +304,13 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet
return nil, xerrors.Errorf("applying msg: %w", err)
}

var et FvmExecutionTrace
if len(ret.ExecTraceBytes) != 0 {
if err = et.UnmarshalCBOR(bytes.NewReader(ret.ExecTraceBytes)); err != nil {
return nil, xerrors.Errorf("failed to unmarshal exectrace: %w", err)
}
}

return &ApplyRet{
MessageReceipt: types.MessageReceipt{
Return: ret.Return,
Expand All @@ -289,10 +327,8 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet
GasRefund: 0,
GasBurned: 0,
},
// TODO: do these eventually, not consensus critical
// https://github.com/filecoin-project/ref-fvm/issues/318
ActorErr: nil,
ExecutionTrace: types.ExecutionTrace{},
ExecutionTrace: et.ToExecutionTrace(),
Duration: time.Since(start),
}, nil
}
Expand All @@ -308,17 +344,21 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (*
return nil, xerrors.Errorf("applying msg: %w", err)
}

var et FvmExecutionTrace
if len(ret.ExecTraceBytes) != 0 {
if err = et.UnmarshalCBOR(bytes.NewReader(ret.ExecTraceBytes)); err != nil {
return nil, xerrors.Errorf("failed to unmarshal exectrace: %w", err)
}
}

return &ApplyRet{
MessageReceipt: types.MessageReceipt{
Return: ret.Return,
ExitCode: exitcode.ExitCode(ret.ExitCode),
GasUsed: ret.GasUsed,
},
GasCosts: nil,
// TODO: do these eventually, not consensus critical
// https://github.com/filecoin-project/ref-fvm/issues/318
ActorErr: nil,
ExecutionTrace: types.ExecutionTrace{},
ExecutionTrace: et.ToExecutionTrace(),
Duration: time.Since(start),
}, nil
}
Expand Down
8 changes: 4 additions & 4 deletions chain/vm/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ func (m *Message) ValueReceived() abi.TokenAmount {
return m.msg.Value
}

// EnableGasTracing, if true, outputs gas tracing in execution traces.
var EnableGasTracing = os.Getenv("LOTUS_VM_ENABLE_GAS_TRACING_VERY_SLOW") == "1"
// EnableDetailedTracing, if true, outputs gas tracing in execution traces.
var EnableDetailedTracing = os.Getenv("LOTUS_VM_ENABLE_GAS_TRACING_VERY_SLOW") == "1"

type Runtime struct {
rt7.Message
Expand Down Expand Up @@ -516,7 +516,7 @@ func (rt *Runtime) stateCommit(oldh, newh cid.Cid) aerrors.ActorError {
}

func (rt *Runtime) finilizeGasTracing() {
if EnableGasTracing {
if EnableDetailedTracing {
if rt.lastGasCharge != nil {
rt.lastGasCharge.TimeTaken = time.Since(rt.lastGasChargeTime)
}
Expand Down Expand Up @@ -550,7 +550,7 @@ func (rt *Runtime) chargeGasFunc(skip int) func(GasCharge) {

func (rt *Runtime) chargeGasInternal(gas GasCharge, skip int) aerrors.ActorError {
toUse := gas.Total()
if EnableGasTracing {
if EnableDetailedTracing {
var callers [10]uintptr

cout := gruntime.Callers(2+skip, callers[:])
Expand Down
8 changes: 4 additions & 4 deletions chain/vm/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ func BenchmarkRuntime_CreateRuntimeChargeGas_TracingDisabled(b *testing.B) {

b.ResetTimer()

EnableGasTracing = false
noop := func() bool { return EnableGasTracing }
EnableDetailedTracing = false
noop := func() bool { return EnableDetailedTracing }
for n := 0; n < b.N; n++ {
// flip the value and access it to make sure
// the compiler doesn't optimize away
EnableGasTracing = true
EnableDetailedTracing = true
_ = noop()
EnableGasTracing = false
EnableDetailedTracing = false
_ = (&Runtime{cst: cst}).chargeGasInternal(gch, 0)
}
}
2 changes: 1 addition & 1 deletion chain/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ func (vm *LegacyVM) send(ctx context.Context, msg *types.Message, parent *Runtim
st := vm.cstate

rt := vm.makeRuntime(ctx, msg, parent)
if EnableGasTracing {
if EnableDetailedTracing {
rt.lastGasChargeTime = start
if parent != nil {
rt.lastGasChargeTime = parent.lastGasChargeTime
Expand Down
2 changes: 1 addition & 1 deletion documentation/misc/gas_balancing.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ may be subject to change.
Complete gas balancing is performed using `lotus-bench` the process is based on importing a chain export
and collecting gas traces which are later aggregated.

Before building `lotus-bench` make sure `EnableGasTracing` in `chain/vm/runtime.go` is set to `true`.
Before building `lotus-bench` make sure `EnableDetailedTracing` in `chain/vm/runtime.go` is set to `true`.

The process can be started using `./lotus-bench import` with `--car` flag set to the location of
CAR chain export. `--start-epoch` and `--end-epoch` can be used to to limit the range of epochs to run
Expand Down
10 changes: 10 additions & 0 deletions gen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"os"

"github.com/filecoin-project/lotus/chain/vm"

gen "github.com/whyrusleeping/cbor-gen"

"github.com/filecoin-project/lotus/api"
Expand Down Expand Up @@ -38,6 +40,14 @@ func main() {
os.Exit(1)
}

err = gen.WriteTupleEncodersToFile("./chain/vm/cbor_gen.go", "vm",
vm.FvmExecutionTrace{},
)
if err != nil {
fmt.Println(err)
os.Exit(1)
}

err = gen.WriteMapEncodersToFile("./paychmgr/cbor_gen.go", "paychmgr",
paychmgr.VoucherInfo{},
paychmgr.ChannelInfo{},
Expand Down
2 changes: 1 addition & 1 deletion testplans/lotus-soup/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ require (
github.com/ipfs/go-unixfs v0.3.1
github.com/ipld/go-car v0.3.3
github.com/kpacha/opencensus-influxdb v0.0.0-20181102202715-663e2683a27c
github.com/libp2p/go-libp2p v0.18.0
github.com/libp2p/go-libp2p v0.18.1
github.com/libp2p/go-libp2p-core v0.14.0
github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6
github.com/multiformats/go-multiaddr v0.5.0
Expand Down
Loading

0 comments on commit 9f3de44

Please sign in to comment.