Merge pull request #9520 from filecoin-project/asr/invoker-method-name
feat: Invoker: Use MethodMeta from go-state-types
This commit is contained in:
commit
84050170b9
@ -1,9 +1,14 @@
|
||||
package builtin
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
"github.com/filecoin-project/go-state-types/builtin"
|
||||
account8 "github.com/filecoin-project/go-state-types/builtin/v8/account"
|
||||
cron8 "github.com/filecoin-project/go-state-types/builtin/v8/cron"
|
||||
_init8 "github.com/filecoin-project/go-state-types/builtin/v8/init"
|
||||
@ -36,14 +41,14 @@ import (
|
||||
type RegistryEntry struct {
|
||||
state cbor.Er
|
||||
code cid.Cid
|
||||
methods map[uint64]interface{}
|
||||
methods map[uint64]builtin.MethodMeta
|
||||
}
|
||||
|
||||
func (r RegistryEntry) State() cbor.Er {
|
||||
return r.state
|
||||
}
|
||||
|
||||
func (r RegistryEntry) Exports() map[uint64]interface{} {
|
||||
func (r RegistryEntry) Exports() map[uint64]builtin.MethodMeta {
|
||||
return r.methods
|
||||
}
|
||||
|
||||
@ -55,9 +60,11 @@ func MakeRegistryLegacy(actors []rtt.VMActor) []RegistryEntry {
|
||||
registry := make([]RegistryEntry, 0)
|
||||
|
||||
for _, actor := range actors {
|
||||
methodMap := make(map[uint64]interface{})
|
||||
methodMap := make(map[uint64]builtin.MethodMeta)
|
||||
for methodNum, method := range actor.Exports() {
|
||||
methodMap[uint64(methodNum)] = method
|
||||
if method != nil {
|
||||
methodMap[uint64(methodNum)] = makeMethodMeta(method)
|
||||
}
|
||||
}
|
||||
registry = append(registry, RegistryEntry{
|
||||
code: actor.Code(),
|
||||
@ -69,6 +76,20 @@ func MakeRegistryLegacy(actors []rtt.VMActor) []RegistryEntry {
|
||||
return registry
|
||||
}
|
||||
|
||||
func makeMethodMeta(method interface{}) builtin.MethodMeta {
|
||||
ev := reflect.ValueOf(method)
|
||||
// Extract the method names using reflection. These
|
||||
// method names always match the field names in the
|
||||
// `builtin.Method*` structs (tested in the specs-actors
|
||||
// tests).
|
||||
fnName := runtime.FuncForPC(ev.Pointer()).Name()
|
||||
fnName = strings.TrimSuffix(fnName[strings.LastIndexByte(fnName, '.')+1:], "-fm")
|
||||
return builtin.MethodMeta{
|
||||
Name: fnName,
|
||||
Method: method,
|
||||
}
|
||||
}
|
||||
|
||||
func MakeRegistry(av actorstypes.Version) []RegistryEntry {
|
||||
if av < actorstypes.Version8 {
|
||||
panic("expected version v8 and up only, use specs-actors for v0-7")
|
||||
|
@ -3,6 +3,11 @@ package builtin
|
||||
import (
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
"github.com/ipfs/go-cid"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/builtin"
|
||||
{{range .versions}}
|
||||
{{if (ge . 8)}}
|
||||
account{{.}} "github.com/filecoin-project/go-state-types/builtin/v{{.}}/account"
|
||||
@ -29,14 +34,14 @@ import (
|
||||
type RegistryEntry struct {
|
||||
state cbor.Er
|
||||
code cid.Cid
|
||||
methods map[uint64]interface{}
|
||||
methods map[uint64]builtin.MethodMeta
|
||||
}
|
||||
|
||||
func (r RegistryEntry) State() cbor.Er {
|
||||
return r.state
|
||||
}
|
||||
|
||||
func (r RegistryEntry) Exports() map[uint64]interface{} {
|
||||
func (r RegistryEntry) Exports() map[uint64]builtin.MethodMeta {
|
||||
return r.methods
|
||||
}
|
||||
|
||||
@ -48,10 +53,12 @@ func MakeRegistryLegacy(actors []rtt.VMActor) []RegistryEntry {
|
||||
registry := make([]RegistryEntry, 0)
|
||||
|
||||
for _, actor := range actors {
|
||||
methodMap := make(map[uint64]interface{})
|
||||
methodMap := make(map[uint64]builtin.MethodMeta)
|
||||
for methodNum, method := range actor.Exports() {
|
||||
methodMap[uint64(methodNum)] = method
|
||||
}
|
||||
if method != nil {
|
||||
methodMap[uint64(methodNum)] = makeMethodMeta(method)
|
||||
}
|
||||
}
|
||||
registry = append(registry, RegistryEntry{
|
||||
code: actor.Code(),
|
||||
methods: methodMap,
|
||||
@ -62,6 +69,20 @@ func MakeRegistryLegacy(actors []rtt.VMActor) []RegistryEntry {
|
||||
return registry
|
||||
}
|
||||
|
||||
func makeMethodMeta(method interface{}) builtin.MethodMeta {
|
||||
ev := reflect.ValueOf(method)
|
||||
// Extract the method names using reflection. These
|
||||
// method names always match the field names in the
|
||||
// `builtin.Method*` structs (tested in the specs-actors
|
||||
// tests).
|
||||
fnName := runtime.FuncForPC(ev.Pointer()).Name()
|
||||
fnName = strings.TrimSuffix(fnName[strings.LastIndexByte(fnName, '.')+1:], "-fm")
|
||||
return builtin.MethodMeta{
|
||||
Name: fnName,
|
||||
Method: method,
|
||||
}
|
||||
}
|
||||
|
||||
func MakeRegistry(av actorstypes.Version) []RegistryEntry {
|
||||
if av < actorstypes.Version8 {
|
||||
panic("expected version v8 and up only, use specs-actors for v0-7")
|
||||
|
@ -38,7 +38,6 @@ func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, me
|
||||
return nil, fmt.Errorf("unknown method %d for actor %s", method, act.Code)
|
||||
}
|
||||
|
||||
fmt.Println("found ", m.Ret, " and ", m.Params, " for ", m.Num)
|
||||
return reflect.New(m.Ret.Elem()).Interface().(cbg.CBORUnmarshaler), nil
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
@ -13,6 +12,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
builtinst "github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
vmr "github.com/filecoin-project/specs-actors/v7/actors/runtime"
|
||||
@ -24,7 +24,7 @@ import (
|
||||
)
|
||||
|
||||
type MethodMeta struct {
|
||||
Num string
|
||||
Name string
|
||||
|
||||
Params reflect.Type
|
||||
Ret reflect.Type
|
||||
@ -90,10 +90,15 @@ func (ar *ActorRegistry) Register(av actorstypes.Version, pred ActorPredicate, v
|
||||
pred = func(vmr.Runtime, cid.Cid) error { return nil }
|
||||
}
|
||||
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))
|
||||
|
||||
var code nativeCode
|
||||
var err error
|
||||
if av <= actorstypes.Version7 {
|
||||
// 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))
|
||||
}
|
||||
}
|
||||
|
||||
ai := &actorInfo{
|
||||
@ -123,7 +128,7 @@ func (ar *ActorRegistry) Register(av actorstypes.Version, pred ActorPredicate, v
|
||||
|
||||
// Explicitly add send, it's special.
|
||||
methods[builtin.MethodSend] = MethodMeta{
|
||||
Num: "0",
|
||||
Name: "Send",
|
||||
Params: reflect.TypeOf(new(abi.EmptyValue)),
|
||||
Ret: reflect.TypeOf(new(abi.EmptyValue)),
|
||||
}
|
||||
@ -131,18 +136,27 @@ func (ar *ActorRegistry) Register(av actorstypes.Version, pred ActorPredicate, v
|
||||
// Iterate over exported methods. Some of these _may_ be nil and
|
||||
// must be skipped.
|
||||
for number, export := range exports {
|
||||
if export == nil {
|
||||
if export.Method == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ev := reflect.ValueOf(export)
|
||||
ev := reflect.ValueOf(export.Method)
|
||||
et := ev.Type()
|
||||
|
||||
methods[abi.MethodNum(number)] = MethodMeta{
|
||||
Num: strconv.Itoa(int(number)),
|
||||
Params: et.In(1),
|
||||
Ret: et.Out(0),
|
||||
mm := MethodMeta{
|
||||
Name: export.Name,
|
||||
Ret: et.Out(0),
|
||||
}
|
||||
|
||||
if av <= actorstypes.Version7 {
|
||||
// methods exported from specs-actors have the runtime as the first param, so we want et.In(1)
|
||||
mm.Params = et.In(1)
|
||||
} else {
|
||||
// methods exported from go-state-types do not, so we want et.In(0)
|
||||
mm.Params = et.In(0)
|
||||
}
|
||||
|
||||
methods[abi.MethodNum(number)] = mm
|
||||
}
|
||||
if realCode.Defined() {
|
||||
ar.Methods[realCode] = methods
|
||||
@ -171,15 +185,16 @@ func (ar *ActorRegistry) Create(codeCid cid.Cid, rt vmr.Runtime) (*types.Actor,
|
||||
}
|
||||
|
||||
type invokee interface {
|
||||
Exports() map[uint64]interface{}
|
||||
Exports() map[uint64]builtinst.MethodMeta
|
||||
}
|
||||
|
||||
func (*ActorRegistry) transform(instance invokee) (nativeCode, error) {
|
||||
itype := reflect.TypeOf(instance)
|
||||
exports := instance.Exports()
|
||||
runtimeType := reflect.TypeOf((*vmr.Runtime)(nil)).Elem()
|
||||
for i, m := range exports {
|
||||
for i, e := range exports {
|
||||
i := i
|
||||
m := e.Method
|
||||
newErr := func(format string, args ...interface{}) error {
|
||||
str := fmt.Sprintf(format, args...)
|
||||
return fmt.Errorf("transform(%s) export(%d): %s", itype.Name(), i, str)
|
||||
@ -215,7 +230,8 @@ func (*ActorRegistry) transform(instance invokee) (nativeCode, error) {
|
||||
}
|
||||
}
|
||||
code := make(nativeCode, len(exports))
|
||||
for id, m := range exports {
|
||||
for id, e := range exports {
|
||||
m := e.Method
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
cid "github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"github.com/stretchr/testify/assert"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
@ -13,15 +14,28 @@ import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
cbor2 "github.com/filecoin-project/go-state-types/cbor"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
"github.com/filecoin-project/go-state-types/rt"
|
||||
runtime2 "github.com/filecoin-project/specs-actors/v2/actors/runtime"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
)
|
||||
|
||||
type basicContract struct{}
|
||||
|
||||
func (b basicContract) Code() cid.Cid {
|
||||
return cid.Undef
|
||||
}
|
||||
|
||||
func (b basicContract) State() cbor2.Er {
|
||||
// works well enough as a dummy state
|
||||
return new(basicParams)
|
||||
}
|
||||
|
||||
type basicParams struct {
|
||||
B byte
|
||||
}
|
||||
@ -49,19 +63,19 @@ func init() {
|
||||
cbor.RegisterCborType(basicParams{})
|
||||
}
|
||||
|
||||
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,
|
||||
func (b basicContract) Exports() []interface{} {
|
||||
return []interface{}{
|
||||
b.InvokeSomething0,
|
||||
b.BadParam,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
b.InvokeSomething10,
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,7 +121,8 @@ func (*basicRtMessage) ValueReceived() abi.TokenAmount {
|
||||
func TestInvokerBasic(t *testing.T) {
|
||||
//stm: @INVOKER_TRANSFORM_001
|
||||
inv := ActorRegistry{}
|
||||
code, err := inv.transform(basicContract{})
|
||||
registry := builtin.MakeRegistryLegacy([]rt.VMActor{basicContract{}})
|
||||
code, err := inv.transform(registry[0])
|
||||
assert.NoError(t, err)
|
||||
|
||||
{
|
||||
|
@ -494,8 +494,8 @@ var ChainInspectUsage = &cli.Command{
|
||||
|
||||
mm := filcns.NewActorRegistry().Methods[code][m.Message.Method] // TODO: use remote map
|
||||
|
||||
byMethod[mm.Num] += m.Message.GasLimit
|
||||
byMethodC[mm.Num]++
|
||||
byMethod[mm.Name] += m.Message.GasLimit
|
||||
byMethodC[mm.Name]++
|
||||
}
|
||||
|
||||
type keyGasPair struct {
|
||||
|
@ -327,8 +327,7 @@ func TestInspectUsage(t *testing.T) {
|
||||
// check for gas by sender
|
||||
assert.Contains(t, out, "By Sender")
|
||||
// check for gas by method
|
||||
methodStr := fmt.Sprintf("By Method:\n%d", builtin.MethodSend)
|
||||
assert.Contains(t, out, methodStr)
|
||||
assert.Contains(t, out, "By Method:\nSend")
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -341,7 +341,7 @@ var msigInspectCmd = &cli.Command{
|
||||
paramStr = string(b)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), method.Num, tx.Method, paramStr)
|
||||
fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), method.Name, tx.Method, paramStr)
|
||||
}
|
||||
}
|
||||
if err := w.Flush(); err != nil {
|
||||
|
@ -1384,7 +1384,7 @@ func codeStr(c cid.Cid) string {
|
||||
}
|
||||
|
||||
func getMethod(code cid.Cid, method abi.MethodNum) string {
|
||||
return filcns.NewActorRegistry().Methods[code][method].Num // todo: use remote
|
||||
return filcns.NewActorRegistry().Methods[code][method].Name // todo: use remote
|
||||
}
|
||||
|
||||
func toFil(f types.BigInt) types.FIL {
|
||||
|
@ -141,7 +141,7 @@ func printMessage(cctx *cli.Context, msg *types.Message) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Println("Method:", filcns.NewActorRegistry().Methods[toact.Code][msg.Method].Num) // todo use remote
|
||||
fmt.Println("Method:", filcns.NewActorRegistry().Methods[toact.Code][msg.Method].Name) // todo use remote
|
||||
p, err := lcli.JsonParams(toact.Code, msg.Method, msg.Params)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -103,7 +103,7 @@ func (c *InteractiveWallet) WalletSign(ctx context.Context, k address.Address, m
|
||||
return xerrors.Errorf("looking up dest actor: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Method:", filcns.NewActorRegistry().Methods[toact.Code][cmsg.Method].Num)
|
||||
fmt.Println("Method:", filcns.NewActorRegistry().Methods[toact.Code][cmsg.Method].Name)
|
||||
p, err := lcli.JsonParams(toact.Code, cmsg.Method, cmsg.Params)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -125,7 +125,7 @@ func (c *InteractiveWallet) WalletSign(ctx context.Context, k address.Address, m
|
||||
return xerrors.Errorf("looking up msig dest actor: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("\tMultiSig Proposal Method:", filcns.NewActorRegistry().Methods[toact.Code][mp.Method].Num) // todo use remote
|
||||
fmt.Println("\tMultiSig Proposal Method:", filcns.NewActorRegistry().Methods[toact.Code][mp.Method].Name) // todo use remote
|
||||
p, err := lcli.JsonParams(toact.Code, mp.Method, mp.Params)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -164,7 +164,7 @@ func runExtractMany(c *cli.Context) error {
|
||||
} else if methodnum >= len(m) {
|
||||
return fmt.Errorf("unrecognized method number for actor %s: %d", actorcode, methodnum)
|
||||
} else {
|
||||
methodname = m[abi.MethodNum(methodnum)].Num
|
||||
methodname = m[abi.MethodNum(methodnum)].Name
|
||||
}
|
||||
|
||||
// exitcode string representations are of kind ErrType(0); strip out
|
||||
|
2
go.mod
2
go.mod
@ -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.9.1
|
||||
github.com/filecoin-project/go-state-types v0.9.2
|
||||
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
4
go.sum
@ -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.9.1 h1:Dr++Hy+tm8RC5jLQBPfFIvThPCa6uEJ4NwlCWh3V85Q=
|
||||
github.com/filecoin-project/go-state-types v0.9.1/go.mod h1:+HCZifUV+e8TlQkgll22Ucuiq8OrVJkK+4Kh4u75iiw=
|
||||
github.com/filecoin-project/go-state-types v0.9.2 h1:zbhib/addhqVihN7yZPkBMvkpS6v5PQFtBllDIxdUS4=
|
||||
github.com/filecoin-project/go-state-types v0.9.2/go.mod h1:+HCZifUV+e8TlQkgll22Ucuiq8OrVJkK+4Kh4u75iiw=
|
||||
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=
|
||||
|
Loading…
Reference in New Issue
Block a user