chore: actors: Allow builtin-actors to return a map of methods (#9342)

* Allow builtin-actors to return a map of methods

* go mod

* Fix tests

* Fix tests, check carefully please
This commit is contained in:
Geoff Stuart 2022-09-21 10:56:58 -04:00 committed by GitHub
parent 99db94f476
commit 94add978b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 94 additions and 58 deletions

View File

@ -32,19 +32,17 @@ import (
"github.com/filecoin-project/lotus/chain/actors"
)
var _ rtt.VMActor = (*RegistryEntry)(nil)
type RegistryEntry struct {
state cbor.Er
code cid.Cid
methods []interface{}
methods map[uint64]interface{}
}
func (r RegistryEntry) State() cbor.Er {
return r.state
}
func (r RegistryEntry) Exports() []interface{} {
func (r RegistryEntry) Exports() map[uint64]interface{} {
return r.methods
}
@ -52,11 +50,29 @@ func (r RegistryEntry) Code() cid.Cid {
return r.code
}
func MakeRegistry(av actorstypes.Version) []rtt.VMActor {
func MakeRegistryLegacy(actors []rtt.VMActor) []RegistryEntry {
registry := make([]RegistryEntry, 0)
for _, actor := range actors {
methodMap := make(map[uint64]interface{})
for methodNum, method := range actor.Exports() {
methodMap[uint64(methodNum)] = method
}
registry = append(registry, RegistryEntry{
code: actor.Code(),
methods: methodMap,
state: actor.State(),
})
}
return registry
}
func MakeRegistry(av actorstypes.Version) []RegistryEntry {
if av < actorstypes.Version8 {
panic("expected version v8 and up only, use specs-actors for v0-7")
}
registry := make([]rtt.VMActor, 0)
registry := make([]RegistryEntry, 0)
codeIDs, err := actors.GetActorCodeIDs(av)
if err != nil {

View File

@ -23,19 +23,17 @@ import (
"github.com/filecoin-project/lotus/chain/actors"
)
var _ rtt.VMActor = (*RegistryEntry)(nil)
type RegistryEntry struct {
state cbor.Er
code cid.Cid
methods []interface{}
methods map[uint64]interface{}
}
func (r RegistryEntry) State() cbor.Er {
return r.state
}
func (r RegistryEntry) Exports() []interface{} {
func (r RegistryEntry) Exports() map[uint64]interface{} {
return r.methods
}
@ -43,11 +41,29 @@ func (r RegistryEntry) Code() cid.Cid {
return r.code
}
func MakeRegistry(av actorstypes.Version) []rtt.VMActor {
func MakeRegistryLegacy(actors []rtt.VMActor) []RegistryEntry {
registry := make([]RegistryEntry, 0)
for _, actor := range actors {
methodMap := make(map[uint64]interface{})
for methodNum, method := range actor.Exports() {
methodMap[uint64(methodNum)] = method
}
registry = append(registry, RegistryEntry{
code: actor.Code(),
methods: methodMap,
state: actor.State(),
})
}
return registry
}
func MakeRegistry(av actorstypes.Version) []RegistryEntry {
if av < actorstypes.Version8 {
panic("expected version v8 and up only, use specs-actors for v0-7")
}
registry := make([]rtt.VMActor, 0)
registry := make([]RegistryEntry, 0)
codeIDs, err := actors.GetActorCodeIDs(av)
if err != nil {

View File

@ -39,15 +39,15 @@ import (
func NewActorRegistry() *vm.ActorRegistry {
inv := vm.NewActorRegistry()
inv.Register(actorstypes.Version0, vm.ActorsVersionPredicate(actorstypes.Version0), exported0.BuiltinActors()...)
inv.Register(actorstypes.Version2, vm.ActorsVersionPredicate(actorstypes.Version2), exported2.BuiltinActors()...)
inv.Register(actorstypes.Version3, vm.ActorsVersionPredicate(actorstypes.Version3), exported3.BuiltinActors()...)
inv.Register(actorstypes.Version4, vm.ActorsVersionPredicate(actorstypes.Version4), exported4.BuiltinActors()...)
inv.Register(actorstypes.Version5, vm.ActorsVersionPredicate(actorstypes.Version5), exported5.BuiltinActors()...)
inv.Register(actorstypes.Version6, vm.ActorsVersionPredicate(actorstypes.Version6), exported6.BuiltinActors()...)
inv.Register(actorstypes.Version7, vm.ActorsVersionPredicate(actorstypes.Version7), exported7.BuiltinActors()...)
inv.Register(actorstypes.Version8, vm.ActorsVersionPredicate(actorstypes.Version8), builtin.MakeRegistry(actorstypes.Version8)...)
inv.Register(actorstypes.Version9, vm.ActorsVersionPredicate(actorstypes.Version9), builtin.MakeRegistry(actorstypes.Version9)...)
inv.Register(actorstypes.Version0, vm.ActorsVersionPredicate(actorstypes.Version0), builtin.MakeRegistryLegacy(exported0.BuiltinActors()))
inv.Register(actorstypes.Version2, vm.ActorsVersionPredicate(actorstypes.Version2), builtin.MakeRegistryLegacy(exported2.BuiltinActors()))
inv.Register(actorstypes.Version3, vm.ActorsVersionPredicate(actorstypes.Version3), builtin.MakeRegistryLegacy(exported3.BuiltinActors()))
inv.Register(actorstypes.Version4, vm.ActorsVersionPredicate(actorstypes.Version4), builtin.MakeRegistryLegacy(exported4.BuiltinActors()))
inv.Register(actorstypes.Version5, vm.ActorsVersionPredicate(actorstypes.Version5), builtin.MakeRegistryLegacy(exported5.BuiltinActors()))
inv.Register(actorstypes.Version6, vm.ActorsVersionPredicate(actorstypes.Version6), builtin.MakeRegistryLegacy(exported6.BuiltinActors()))
inv.Register(actorstypes.Version7, vm.ActorsVersionPredicate(actorstypes.Version7), builtin.MakeRegistryLegacy(exported7.BuiltinActors()))
inv.Register(actorstypes.Version8, vm.ActorsVersionPredicate(actorstypes.Version8), builtin.MakeRegistry(actorstypes.Version8))
inv.Register(actorstypes.Version9, vm.ActorsVersionPredicate(actorstypes.Version9), builtin.MakeRegistry(actorstypes.Version9))
return inv
}

View File

@ -20,6 +20,7 @@ import (
actorstypes "github.com/filecoin-project/go-state-types/actors"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/go-state-types/network"
rtt "github.com/filecoin-project/go-state-types/rt"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init"
rt2 "github.com/filecoin-project/specs-actors/v2/actors/runtime"
@ -27,6 +28,7 @@ import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/actors/builtin"
_init "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/consensus/filcns"
@ -168,7 +170,8 @@ func TestForkHeightTriggers(t *testing.T) {
}
inv := filcns.NewActorRegistry()
inv.Register(actorstypes.Version0, nil, testActor{})
registry := builtin.MakeRegistryLegacy([]rtt.VMActor{testActor{}})
inv.Register(actorstypes.Version0, nil, registry)
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) {
nvm, err := vm.NewLegacyVM(ctx, vmopt)
@ -285,7 +288,8 @@ func testForkRefuseCall(t *testing.T, nullsBefore, nullsAfter int) {
}
inv := filcns.NewActorRegistry()
inv.Register(actorstypes.Version0, nil, testActor{})
registry := builtin.MakeRegistryLegacy([]rtt.VMActor{testActor{}})
inv.Register(actorstypes.Version0, nil, registry)
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) {
nvm, err := vm.NewLegacyVM(ctx, vmopt)
@ -506,7 +510,8 @@ func TestForkPreMigration(t *testing.T) {
}()
inv := filcns.NewActorRegistry()
inv.Register(actorstypes.Version0, nil, testActor{})
registry := builtin.MakeRegistryLegacy([]rtt.VMActor{testActor{}})
inv.Register(actorstypes.Version0, nil, registry)
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) {
nvm, err := vm.NewLegacyVM(ctx, vmopt)

View File

@ -15,7 +15,6 @@ import (
actorstypes "github.com/filecoin-project/go-state-types/actors"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-state-types/network"
rtt "github.com/filecoin-project/go-state-types/rt"
vmr "github.com/filecoin-project/specs-actors/v7/actors/runtime"
"github.com/filecoin-project/lotus/chain/actors"
@ -38,27 +37,27 @@ type ActorRegistry struct {
}
// An ActorPredicate returns an error if the given actor is not valid for the given runtime environment (e.g., chain height, version, etc.).
type ActorPredicate func(vmr.Runtime, rtt.VMActor) error
type ActorPredicate func(vmr.Runtime, cid.Cid) error
func ActorsVersionPredicate(ver actorstypes.Version) ActorPredicate {
return func(rt vmr.Runtime, v rtt.VMActor) error {
return func(rt vmr.Runtime, codeCid cid.Cid) error {
aver, err := actorstypes.VersionForNetwork(rt.NetworkVersion())
if err != nil {
return xerrors.Errorf("unsupported network version: %w", err)
}
if aver != ver {
return xerrors.Errorf("actor %s is a version %d actor; chain only supports actor version %d at height %d and nver %d", v.Code(), ver, aver, rt.CurrEpoch(), rt.NetworkVersion())
return xerrors.Errorf("actor %s is a version %d actor; chain only supports actor version %d at height %d and nver %d", codeCid, ver, aver, rt.CurrEpoch(), rt.NetworkVersion())
}
return nil
}
}
type invokeFunc func(rt vmr.Runtime, params []byte) ([]byte, aerrors.ActorError)
type nativeCode []invokeFunc
type nativeCode map[uint64]invokeFunc
type actorInfo struct {
methods nativeCode
vmActor rtt.VMActor
vmActor builtin.RegistryEntry
// TODO: consider making this a network version range?
predicate ActorPredicate
}
@ -76,19 +75,19 @@ func (ar *ActorRegistry) Invoke(codeCid cid.Cid, rt vmr.Runtime, method abi.Meth
log.Errorf("no code for actor %s (Addr: %s)", codeCid, rt.Receiver())
return nil, aerrors.Newf(exitcode.SysErrorIllegalActor, "no code for actor %s(%d)(%s)", codeCid, method, hex.EncodeToString(params))
}
if err := act.predicate(rt, act.vmActor); err != nil {
if err := act.predicate(rt, codeCid); err != nil {
return nil, aerrors.Newf(exitcode.SysErrorIllegalActor, "unsupported actor: %s", err)
}
if method >= abi.MethodNum(len(act.methods)) || act.methods[method] == nil {
if act.methods[uint64(method)] == nil {
return nil, aerrors.Newf(exitcode.SysErrInvalidMethod, "no method %d on actor", method)
}
return act.methods[method](rt, params)
return act.methods[uint64(method)](rt, params)
}
func (ar *ActorRegistry) Register(av actorstypes.Version, pred ActorPredicate, vmactors ...rtt.VMActor) {
func (ar *ActorRegistry) Register(av actorstypes.Version, pred ActorPredicate, vmactors []builtin.RegistryEntry) {
if pred == nil {
pred = func(vmr.Runtime, rtt.VMActor) error { return nil }
pred = func(vmr.Runtime, cid.Cid) error { return nil }
}
for _, a := range vmactors {
// register in the `actors` map (for the invoker)
@ -140,7 +139,7 @@ func (ar *ActorRegistry) Register(av actorstypes.Version, pred ActorPredicate, v
et := ev.Type()
methods[abi.MethodNum(number)] = MethodMeta{
Num: strconv.Itoa(number),
Num: strconv.Itoa(int(number)),
Params: et.In(1),
Ret: et.Out(0),
}
@ -159,13 +158,10 @@ func (ar *ActorRegistry) Create(codeCid cid.Cid, rt vmr.Runtime) (*types.Actor,
return nil, aerrors.Newf(exitcode.SysErrorIllegalArgument, "Can only create built-in actors.")
}
if err := act.predicate(rt, act.vmActor); err != nil {
if err := act.predicate(rt, codeCid); err != nil {
return nil, aerrors.Newf(exitcode.SysErrorIllegalArgument, "Cannot create actor: %w", err)
}
if rtt.IsSingletonActor(act.vmActor) {
return nil, aerrors.Newf(exitcode.SysErrorIllegalArgument, "Can only have one instance of singleton actors.")
}
return &types.Actor{
Code: codeCid,
Head: EmptyObjectCid,
@ -175,7 +171,7 @@ func (ar *ActorRegistry) Create(codeCid cid.Cid, rt vmr.Runtime) (*types.Actor,
}
type invokee interface {
Exports() []interface{}
Exports() map[uint64]interface{}
}
func (*ActorRegistry) transform(instance invokee) (nativeCode, error) {

View File

@ -49,19 +49,19 @@ func init() {
cbor.RegisterCborType(basicParams{})
}
func (b basicContract) Exports() []interface{} {
return []interface{}{
b.InvokeSomething0,
b.BadParam,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
b.InvokeSomething10,
func (b basicContract) Exports() map[uint64]interface{} {
return map[uint64]interface{}{
0: b.InvokeSomething0,
1: b.BadParam,
2: nil,
3: nil,
4: nil,
5: nil,
6: nil,
7: nil,
8: nil,
9: nil,
10: b.InvokeSomething10,
}
}

View File

@ -15,9 +15,11 @@ import (
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/network"
rtt "github.com/filecoin-project/go-state-types/rt"
"github.com/filecoin-project/test-vectors/schema"
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/consensus/filcns"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr"
@ -250,7 +252,8 @@ func (d *Driver) ExecuteMessage(bs blockstore.Blockstore, params ExecuteMessageP
// register the chaos actor if required by the vector.
if chaosOn, ok := d.selector["chaos_actor"]; ok && chaosOn == "true" {
av, _ := actorstypes.VersionForNetwork(params.NetworkVersion)
invoker.Register(av, nil, chaos.Actor{})
registry := builtin.MakeRegistryLegacy([]rtt.VMActor{chaos.Actor{}})
invoker.Register(av, nil, registry)
}
lvm.SetInvoker(invoker)

2
go.mod
View File

@ -42,7 +42,7 @@ require (
github.com/filecoin-project/go-legs v0.4.4
github.com/filecoin-project/go-padreader v0.0.1
github.com/filecoin-project/go-paramfetch v0.0.4
github.com/filecoin-project/go-state-types v0.1.12-beta
github.com/filecoin-project/go-state-types v0.1.12-beta.0.20220920181425-d683559e386b
github.com/filecoin-project/go-statemachine v1.0.2
github.com/filecoin-project/go-statestore v0.2.0
github.com/filecoin-project/go-storedcounter v0.1.0

4
go.sum
View File

@ -343,8 +343,8 @@ github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psS
github.com/filecoin-project/go-state-types v0.1.6/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
github.com/filecoin-project/go-state-types v0.1.8/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
github.com/filecoin-project/go-state-types v0.1.10/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
github.com/filecoin-project/go-state-types v0.1.12-beta h1:QZE00g75shqwhPn0/bZL38sFxVAqnXC7zjmYltRdhxI=
github.com/filecoin-project/go-state-types v0.1.12-beta/go.mod h1:n/kujdC9JphvYTrmaD1+vJpvDPy/DwzckoMzP0nBKWI=
github.com/filecoin-project/go-state-types v0.1.12-beta.0.20220920181425-d683559e386b h1:s4F3e3EBo56j+4xmrzmoAIvtgvDwLn4nsIf5bqcU0Qg=
github.com/filecoin-project/go-state-types v0.1.12-beta.0.20220920181425-d683559e386b/go.mod h1:n/kujdC9JphvYTrmaD1+vJpvDPy/DwzckoMzP0nBKWI=
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc=
github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54=