From 54076e9a6bdcbb000e7071565ca50946631667c9 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Tue, 28 Jan 2020 15:17:25 -0800 Subject: [PATCH] Invoker autoshim Signed-off-by: Jakub Sztandera --- chain/actors/actor_multisig.go | 20 ++++--- chain/vm/invoker.go | 96 ++++++++++++++++++++++++++++++- chain/{actors => vm}/spec_shim.go | 9 +-- 3 files changed, 110 insertions(+), 15 deletions(-) rename chain/{actors => vm}/spec_shim.go (95%) diff --git a/chain/actors/actor_multisig.go b/chain/actors/actor_multisig.go index 1201ed9ef..8579c6643 100644 --- a/chain/actors/actor_multisig.go +++ b/chain/actors/actor_multisig.go @@ -1,8 +1,6 @@ package actors import ( - "github.com/filecoin-project/lotus/chain/types" - samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig" ) @@ -25,6 +23,15 @@ type musigMethods struct { var MultiSigMethods = musigMethods{1, 2, 3, 4, 5, 6, 7, 8, 9} +type MultiSigConstructorParams = samsig.ConstructorParams +type MultiSigProposeParams = samsig.ProposeParams +type MultiSigTxID = samsig.TxnIDParams +type MultiSigAddSignerParam = samsig.AddSigner +type MultiSigRemoveSignerParam = samsig.RemoveSigner +type MultiSigSwapSignerParams = samsig.SwapSignerParams +type MultiSigChangeReqParams = samsig.ChangeNumApprovalsThresholdParams + +/* func (msa MultiSigActor) Exports() []interface{} { return []interface{}{ 1: msa.MultiSigConstructor, @@ -39,7 +46,7 @@ func (msa MultiSigActor) Exports() []interface{} { } } -type MultiSigConstructorParams = samsig.ConstructorParams + func (MultiSigActor) MultiSigConstructor(act *types.Actor, vmctx types.VMContext, params *MultiSigConstructorParams) ([]byte, ActorError) { @@ -50,7 +57,6 @@ func (MultiSigActor) MultiSigConstructor(act *types.Actor, vmctx types.VMContext }) } -type MultiSigProposeParams = samsig.ProposeParams func (msa MultiSigActor) Propose(act *types.Actor, vmctx types.VMContext, params *MultiSigProposeParams) ([]byte, ActorError) { @@ -61,7 +67,6 @@ func (msa MultiSigActor) Propose(act *types.Actor, vmctx types.VMContext, }) } -type MultiSigTxID = samsig.TxnIDParams func (msa MultiSigActor) Approve(act *types.Actor, vmctx types.VMContext, params *MultiSigTxID) ([]byte, ActorError) { @@ -81,7 +86,6 @@ func (msa MultiSigActor) Cancel(act *types.Actor, vmctx types.VMContext, }) } -type MultiSigAddSignerParam = samsig.AddSigner func (msa MultiSigActor) AddSigner(act *types.Actor, vmctx types.VMContext, params *MultiSigAddSignerParam) ([]byte, ActorError) { @@ -92,7 +96,6 @@ func (msa MultiSigActor) AddSigner(act *types.Actor, vmctx types.VMContext, }) } -type MultiSigRemoveSignerParam = samsig.RemoveSigner func (msa MultiSigActor) RemoveSigner(act *types.Actor, vmctx types.VMContext, params *MultiSigRemoveSignerParam) ([]byte, ActorError) { @@ -103,7 +106,6 @@ func (msa MultiSigActor) RemoveSigner(act *types.Actor, vmctx types.VMContext, }) } -type MultiSigSwapSignerParams = samsig.SwapSignerParams func (msa MultiSigActor) SwapSigner(act *types.Actor, vmctx types.VMContext, params *MultiSigSwapSignerParams) ([]byte, ActorError) { @@ -114,7 +116,6 @@ func (msa MultiSigActor) SwapSigner(act *types.Actor, vmctx types.VMContext, }) } -type MultiSigChangeReqParams = samsig.ChangeNumApprovalsThresholdParams func (msa MultiSigActor) ChangeRequirement(act *types.Actor, vmctx types.VMContext, params *MultiSigChangeReqParams) ([]byte, ActorError) { @@ -124,3 +125,4 @@ func (msa MultiSigActor) ChangeRequirement(act *types.Actor, vmctx types.VMConte return (&samsig.MultiSigActor{}).ChangeNumApprovalsThreshold(shim, params) }) } +*/ diff --git a/chain/vm/invoker.go b/chain/vm/invoker.go index 529329a13..3317a0754 100644 --- a/chain/vm/invoker.go +++ b/chain/vm/invoker.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "fmt" "reflect" + "strings" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" @@ -13,6 +14,8 @@ import ( "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/specs-actors/actors/builtin/multisig" + vmr "github.com/filecoin-project/specs-actors/actors/runtime" ) type invoker struct { @@ -36,7 +39,7 @@ func NewInvoker() *invoker { inv.Register(actors.StorageMarketCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{}) inv.Register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{}) inv.Register(actors.StorageMiner2CodeCid, actors.StorageMinerActor2{}, actors.StorageMinerActorState{}) - inv.Register(actors.MultisigCodeCid, actors.MultiSigActor{}, actors.MultiSigActorState{}) + inv.Register(actors.MultisigCodeCid, multisig.MultiSigActor{}, multisig.MultiSigActorState{}) inv.Register(actors.PaymentChannelCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{}) return inv @@ -76,7 +79,96 @@ type Invokee interface { var tVMContext = reflect.TypeOf((*types.VMContext)(nil)).Elem() var tAError = reflect.TypeOf((*aerrors.ActorError)(nil)).Elem() -func (*invoker) transform(instance Invokee) (nativeCode, error) { +func (i *invoker) transform(instance Invokee) (nativeCode, error) { + itype := reflect.TypeOf(instance) + if strings.Contains(itype.PkgPath(), "github.com/filecoin-project/specs-actors/") { + return i.transformSpec(instance) + } else { + return i.transformLotus(instance) + } + +} + +func (*invoker) transformSpec(instance Invokee) (nativeCode, error) { + itype := reflect.TypeOf(instance) + exports := instance.Exports() + for i, m := range exports { + i := i + newErr := func(format string, args ...interface{}) error { + str := fmt.Sprintf(format, args...) + return fmt.Errorf("transform(%s) export(%d): %s", itype.Name(), i, str) + } + + if m == nil { + continue + } + + meth := reflect.ValueOf(m) + t := meth.Type() + if t.Kind() != reflect.Func { + return nil, newErr("is not a function") + } + if t.NumIn() != 2 { + return nil, newErr("wrong number of inputs should be: " + + "vmr.Runtime, ") + } + if t.In(0) != reflect.TypeOf((*vmr.Runtime)(nil)).Elem() { + return nil, newErr("first arguemnt should be vmr.Runtime") + } + if t.In(1).Kind() != reflect.Ptr { + return nil, newErr("second argument should be types.VMContext") + } + + if t.NumOut() != 1 { + return nil, newErr("wrong number of outputs should be: " + + "cbg.CBORMarshaler") + } + o0 := t.Out(0) + if !o0.Implements(reflect.TypeOf((*cbg.CBORMarshaler)(nil)).Elem()) { + return nil, newErr("output needs to implement cgb.CBORMarshaler") + + } + } + code := make(nativeCode, len(exports)) + for id, m := range exports { + meth := reflect.ValueOf(m) + code[id] = reflect.MakeFunc(reflect.TypeOf((invokeFunc)(nil)), + func(in []reflect.Value) []reflect.Value { + paramT := meth.Type().In(1).Elem() + param := reflect.New(paramT) + + inBytes := in[2].Interface().([]byte) + if len(inBytes) > 0 { + if err := DecodeParams(inBytes, param.Interface()); err != nil { + aerr := aerrors.Absorb(err, 1, "failed to decode parameters") + return []reflect.Value{ + reflect.ValueOf([]byte{}), + // Below is a hack, fixed in Go 1.13 + // https://git.io/fjXU6 + reflect.ValueOf(&aerr).Elem(), + } + } + } + shim := &runtimeShim{vmctx: in[1].Interface().(*VMContext)} + rval, aerror := shim.shimCall(func() interface{} { + ret := meth.Call([]reflect.Value{ + reflect.ValueOf(shim), + param, + }) + return ret[0].Interface() + }) + + return []reflect.Value{ + reflect.ValueOf(&rval).Elem(), + reflect.ValueOf(&aerror).Elem(), + } + }).Interface().(invokeFunc) + + } + return code, nil +} + +func (*invoker) transformLotus(instance Invokee) (nativeCode, error) { itype := reflect.TypeOf(instance) exports := instance.Exports() for i, m := range exports { diff --git a/chain/actors/spec_shim.go b/chain/vm/spec_shim.go similarity index 95% rename from chain/actors/spec_shim.go rename to chain/vm/spec_shim.go index caf39aa43..9bb3e717b 100644 --- a/chain/actors/spec_shim.go +++ b/chain/vm/spec_shim.go @@ -1,4 +1,4 @@ -package actors +package vm import ( "bytes" @@ -7,6 +7,7 @@ import ( "runtime/debug" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/specs-actors/actors/abi" @@ -21,10 +22,10 @@ type runtimeShim struct { vmr.Runtime } -func (rs *runtimeShim) shimCall(f func() interface{}) (rval []byte, aerr ActorError) { +func (rs *runtimeShim) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) { defer func() { if r := recover(); r != nil { - if ar, ok := r.(ActorError); ok { + if ar, ok := r.(aerrors.ActorError); ok { aerr = ar return } @@ -169,7 +170,7 @@ func (ssh *shimStateHandle) Construct(f func() vmr.CBORMarshaler) { if err != nil { panic(err) } - if err := ssh.rs.vmctx.Storage().Commit(EmptyCBOR, c); err != nil { + if err := ssh.rs.vmctx.Storage().Commit(actors.EmptyCBOR, c); err != nil { panic(err) } }