diff --git a/chain/actors/manifest.go b/chain/actors/manifest.go index 23caa184b..322052494 100644 --- a/chain/actors/manifest.go +++ b/chain/actors/manifest.go @@ -2,6 +2,7 @@ package actors import ( "context" + "strings" "sync" "golang.org/x/xerrors" @@ -97,3 +98,12 @@ func GetActorMetaByCode(c cid.Cid) (string, Version, bool) { return entry.name, entry.version, true } + +func CanonicalName(name string) string { + idx := strings.LastIndex(name, "/") + if idx >= 0 { + return name[idx+1:] + } + + return name +} diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index 25d709cc6..987fe9ba0 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -53,18 +53,18 @@ func NewActorRegistry() *vm.ActorRegistry { // TODO: define all these properties on the actors themselves, in specs-actors. /* inline-gen template {{range .actorVersions}} - inv.Register(vm.ActorsVersionPredicate(actors.Version{{.}}), exported{{.}}.BuiltinActors()...){{end}} + inv.Register(actors.Version{{.}}, vm.ActorsVersionPredicate(actors.Version{{.}}), exported{{.}}.BuiltinActors()...){{end}} /* inline-gen start */ - inv.Register(vm.ActorsVersionPredicate(actors.Version0), exported0.BuiltinActors()...) - inv.Register(vm.ActorsVersionPredicate(actors.Version2), exported2.BuiltinActors()...) - inv.Register(vm.ActorsVersionPredicate(actors.Version3), exported3.BuiltinActors()...) - inv.Register(vm.ActorsVersionPredicate(actors.Version4), exported4.BuiltinActors()...) - inv.Register(vm.ActorsVersionPredicate(actors.Version5), exported5.BuiltinActors()...) - inv.Register(vm.ActorsVersionPredicate(actors.Version6), exported6.BuiltinActors()...) - inv.Register(vm.ActorsVersionPredicate(actors.Version7), exported7.BuiltinActors()...) - inv.Register(vm.ActorsVersionPredicate(actors.Version8), exported8.BuiltinActors()...) + inv.Register(actors.Version0, vm.ActorsVersionPredicate(actors.Version0), exported0.BuiltinActors()...) + inv.Register(actors.Version2, vm.ActorsVersionPredicate(actors.Version2), exported2.BuiltinActors()...) + inv.Register(actors.Version3, vm.ActorsVersionPredicate(actors.Version3), exported3.BuiltinActors()...) + inv.Register(actors.Version4, vm.ActorsVersionPredicate(actors.Version4), exported4.BuiltinActors()...) + inv.Register(actors.Version5, vm.ActorsVersionPredicate(actors.Version5), exported5.BuiltinActors()...) + inv.Register(actors.Version6, vm.ActorsVersionPredicate(actors.Version6), exported6.BuiltinActors()...) + inv.Register(actors.Version7, vm.ActorsVersionPredicate(actors.Version7), exported7.BuiltinActors()...) + inv.Register(actors.Version8, vm.ActorsVersionPredicate(actors.Version8), exported8.BuiltinActors()...) /* inline-gen end */ diff --git a/chain/vm/invoker.go b/chain/vm/invoker.go index 8a7a4c8c9..5093d5d13 100644 --- a/chain/vm/invoker.go +++ b/chain/vm/invoker.go @@ -89,22 +89,36 @@ func (ar *ActorRegistry) Invoke(codeCid cid.Cid, rt vmr.Runtime, method abi.Meth } -func (ar *ActorRegistry) Register(pred ActorPredicate, actors ...rtt.VMActor) { +func (ar *ActorRegistry) Register(av actors.Version, pred ActorPredicate, vmactors ...rtt.VMActor) { if pred == nil { pred = func(vmr.Runtime, rtt.VMActor) error { return nil } } - for _, a := range actors { + for _, a := range vmactors { // register in the `actors` map (for the invoker) code, err := ar.transform(a) if err != nil { panic(xerrors.Errorf("%s: %w", string(a.Code().Hash()), err)) } - ar.actors[a.Code()] = &actorInfo{ + + ai := &actorInfo{ methods: code, vmActor: a, predicate: pred, } + ac := a.Code() + ar.actors[ac] = ai + + // necessary to make genesis work for testing + if av >= actors.Version8 { + name := actors.CanonicalName(builtin.ActorNameByCode(ac)) + + ac, ok := actors.GetActorCodeID(av, name) + if ok { + ar.actors[ac] = ai + } + } + // register in the `Methods` map (used by statemanager utils) exports := a.Exports() methods := make(map[abi.MethodNum]MethodMeta, len(exports)) diff --git a/chain/vm/runtime.go b/chain/vm/runtime.go index 9c4344a02..39617f91c 100644 --- a/chain/vm/runtime.go +++ b/chain/vm/runtime.go @@ -26,11 +26,14 @@ import ( rt8 "github.com/filecoin-project/specs-actors/v8/actors/runtime" "github.com/ipfs/go-cid" ipldcbor "github.com/ipfs/go-ipld-cbor" + mh "github.com/multiformats/go-multihash" "go.opencensus.io/trace" "golang.org/x/xerrors" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/aerrors" + "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/types" ) @@ -222,6 +225,23 @@ func (rt *Runtime) GetActorCodeCID(addr address.Address) (ret cid.Cid, ok bool) panic(aerrors.Fatalf("failed to get actor: %s", err)) } + // required for genesis/testing + if nv := rt.NetworkVersion(); nv >= network.Version16 { + name, av, ok := actors.GetActorMetaByCode(act.Code) + + if ok { + // lies, lies, lies + builder := cid.V1Builder{Codec: cid.Raw, MhType: mh.IDENTITY} + synthetic := fmt.Sprintf("fil/%d/%s", av, name) + syntheticCid, err := builder.Sum([]byte(synthetic)) + if err != nil { + panic(aerrors.Fatalf("failed to generate synthetic CID: %s", err)) + } + + return syntheticCid, true + } + } + return act.Code, true } @@ -367,6 +387,20 @@ func (rt *Runtime) ValidateImmediateCallerType(ts ...cid.Cid) { if t == callerCid { return } + + // this really only for genesis in tests; nv16 will be running on FVM anyway. + if nv := rt.NetworkVersion(); nv >= network.Version16 { + av, err := actors.VersionForNetwork(nv) + if err != nil { + panic(aerrors.Fatalf("failed to get actors version for network version %d", nv)) + } + + name := actors.CanonicalName(builtin.ActorNameByCode(t)) + ac, ok := actors.GetActorCodeID(av, name) + if ok && ac == callerCid { + return + } + } } rt.Abortf(exitcode.SysErrForbidden, "caller cid type %q was not one of %v", callerCid, ts) }