Skip to content

Commit

Permalink
feat: add cmd to print actor codes and methods in CSV format to stdout (
Browse files Browse the repository at this point in the history
  • Loading branch information
kasteph authored Apr 18, 2023
1 parent fe4a939 commit 57d6749
Show file tree
Hide file tree
Showing 3 changed files with 270 additions and 42 deletions.
213 changes: 171 additions & 42 deletions commands/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@ import (
"strings"
"time"

"github.com/filecoin-project/lily/config"
"github.com/filecoin-project/lily/model"
"github.com/filecoin-project/lily/model/actors/common"
"github.com/filecoin-project/lily/storage"
"github.com/filecoin-project/lotus/chain/actors"

"github.com/filecoin-project/go-state-types/abi"
actorstypes "github.com/filecoin-project/go-state-types/actors"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/builtin"
"github.com/filecoin-project/go-state-types/manifest"
"github.com/filecoin-project/lotus/api"
lotusbuild "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
lotuscli "github.com/filecoin-project/lotus/cli"
"github.com/ipfs/go-cid"
Expand All @@ -28,6 +33,8 @@ import (
"github.com/filecoin-project/lily/lens/util"
)

var actorVersions = []int{0, 2, 3, 4, 5, 6, 7, 8, 9, 10}

var ChainCmd = &cli.Command{
Name: "chain",
Usage: "Interact with filecoin blockchain",
Expand All @@ -40,37 +47,170 @@ var ChainCmd = &cli.Command{
ChainListCmd,
ChainSetHeadCmd,
ChainActorCodesCmd,
ChainActorMethodsCmd,
ChainStateInspect,
ChainStateCompute,
ChainStateComputeRange,
},
}

type chainActorOpts struct {
persist bool
config string
storage string
}

var chainActorFlags chainActorOpts

var configFlag = &cli.StringFlag{
Name: "config",
Usage: "Specify path of config file to use.",
EnvVars: []string{"LILY_CONFIG"},
Destination: &chainActorFlags.config,
}

var storageFlag = &cli.StringFlag{
Name: "storage",
Usage: "Specify the storage to use, if persisting the displayed output.",
Destination: &chainActorFlags.storage,
}

var ChainActorCodesCmd = &cli.Command{
Name: "actor-codes",
Usage: "Print actor codes and names",
Usage: "Print actor codes and names.",
Flags: []cli.Flag{configFlag, storageFlag},
Action: func(cctx *cli.Context) error {
for _, a := range []string{manifest.AccountKey, manifest.CronKey, manifest.DatacapKey, manifest.InitKey, manifest.MarketKey, manifest.MinerKey, manifest.MultisigKey, manifest.PaychKey, manifest.PowerKey, manifest.RewardKey, manifest.SystemKey, manifest.VerifregKey} {
manifests := manifest.GetBuiltinActorsKeys(actorstypes.Version10)
t := table.NewWriter()
t.AppendHeader(table.Row{"name", "family", "code"})

// values that may be accessed if user wants to persist to Storage
var results common.ActorCodeList
var strg model.Storage
var ctx context.Context

if chainActorFlags.storage != "" {
results = common.ActorCodeList{}

cfg, err := config.FromFile(chainActorFlags.config)
if err != nil {
return err
}

md := storage.Metadata{
JobName: chainActorFlags.storage,
}

// context for db connection
ctx = context.Background()

sc, err := storage.NewCatalog(cfg.Storage)
if err != nil {
return err
}
strg, err = sc.Connect(ctx, chainActorFlags.storage, md)
if err != nil {
return err
}
}

for _, a := range manifests {
av := make(map[actorstypes.Version]cid.Cid)
for _, v := range []int{0, 2, 3, 4, 5, 6, 7, 8, 9} {
for _, v := range actorVersions {
code, ok := actors.GetActorCodeID(actorstypes.Version(v), a)
if !ok {
continue
}
av[actorstypes.Version(v)] = code
name, family, err := util.ActorNameAndFamilyFromCode(av[actorstypes.Version(v)])
if err != nil {
return err
}
t.AppendRow(table.Row{name, family, code})
results = append(results, &common.ActorCode{
CID: code.String(),
Code: name,
})

if chainActorFlags.storage != "" {
err := strg.PersistBatch(ctx, results)
if err != nil {
return err
}
}
}
}

fmt.Println(t.RenderCSV())
return nil
},
}

var ChainActorMethodsCmd = &cli.Command{
Name: "actor-methods",
Usage: "Print actor method numbers and their human readable names.",
Flags: []cli.Flag{configFlag, storageFlag},
Action: func(cctx *cli.Context) error {
manifests := manifest.GetBuiltinActorsKeys(actorstypes.Version10)
t := table.NewWriter()
t.AppendHeader(table.Row{"actor_family", "method_name", "method_number"})

// values that may be accessed if user wants to persist to Storage
var results common.ActorMethodList
var strg model.Storage
var ctx context.Context

if chainActorFlags.persist {
cfg, err := config.FromFile(chainActorFlags.config)
if err != nil {
return err
}
fmt.Printf("# %s\n", a)
fmt.Print("## Metadata\n")
if err := printSortedActorVersions(av); err != nil {

md := storage.Metadata{
JobName: chainActorFlags.storage,
}

// context for db connection
ctx = context.Background()

sc, err := storage.NewCatalog(cfg.Storage)
if err != nil {
return err
}
fmt.Println()
fmt.Print("## Methods\n")
if err := printActorMethods(a); err != nil {
strg, err = sc.Connect(ctx, chainActorFlags.storage, md)
if err != nil {
return err
}
fmt.Println()
}

for _, a := range manifests {
av := make(map[actorstypes.Version]cid.Cid)
for _, v := range actorVersions {
code, ok := actors.GetActorCodeID(actorstypes.Version(v), a)
if !ok {
continue
}
av[actorstypes.Version(v)] = code
}

var err error
if results, err = printActorMethods(t, a); err != nil {
return err
}

for _, result := range results {
t.AppendRow(table.Row{result.Family, result.Method, result.MethodName})
t.AppendSeparator()
}

if chainActorFlags.persist {
err := strg.PersistBatch(ctx, results)
if err != nil {
return err
}
}
}
fmt.Println(t.RenderCSV())
return nil
},
}
Expand Down Expand Up @@ -713,33 +853,12 @@ func parseTipSet(ctx context.Context, api lily.LilyAPI, vals []string) (*types.T
return types.NewTipSet(headers)
}

func printSortedActorVersions(av map[actorstypes.Version]cid.Cid) error {
t := table.NewWriter()
t.AppendHeader(table.Row{"Version", "Name", "Family", "Code"})
var versions []int
for v := range av {
versions = append(versions, int(v))
}
sort.Ints(versions)
for _, v := range versions {
name, family, err := util.ActorNameAndFamilyFromCode(av[actorstypes.Version(v)])
if err != nil {
return err
}
t.AppendRow(table.Row{v, name, family, av[actorstypes.Version(v)]})
t.AppendSeparator()
}
fmt.Println(t.RenderMarkdown())
return nil
}

func printActorMethods(actorKey string) error {
t := table.NewWriter()
t.AppendHeader(table.Row{"Method Name", "Method Number"})
func printActorMethods(t table.Writer, actorKey string) (common.ActorMethodList, error) {
var (
methodName string
methodNumber any
methodNumber uint64
correspondingMethods interface{}
actorMethodList = common.ActorMethodList{}
)

switch actorKey {
Expand All @@ -749,6 +868,12 @@ func printActorMethods(actorKey string) error {
correspondingMethods = builtin.MethodsCron
case manifest.DatacapKey:
correspondingMethods = builtin.MethodsDatacap
case manifest.EamKey:
correspondingMethods = builtin.MethodsEAM
case manifest.EthAccountKey:
correspondingMethods = builtin.MethodsEthAccount
case manifest.EvmKey:
correspondingMethods = builtin.MethodsEVM
case manifest.MarketKey:
correspondingMethods = builtin.MethodsMarket
case manifest.MinerKey:
Expand All @@ -759,6 +884,8 @@ func printActorMethods(actorKey string) error {
correspondingMethods = builtin.MethodsMultisig
case manifest.PaychKey:
correspondingMethods = builtin.MethodsPaych
case manifest.PlaceholderKey:
correspondingMethods = builtin.MethodsPlaceholder
case manifest.PowerKey:
correspondingMethods = builtin.MethodsPower
case manifest.RewardKey:
Expand All @@ -768,21 +895,23 @@ func printActorMethods(actorKey string) error {
case manifest.VerifregKey:
correspondingMethods = builtin.MethodsVerifiedRegistry
default:
return fmt.Errorf("unknown actor key: %s", actorKey)
return nil, fmt.Errorf("unknown actor key: %s", actorKey)
}

// Check if correspondingMethods is nil
if correspondingMethods == nil {
return nil
return nil, nil
}

for i := 0; i < reflect.TypeOf(correspondingMethods).NumField(); i++ {
methodName = reflect.TypeOf(correspondingMethods).Field(i).Name
methodNumber = reflect.ValueOf(correspondingMethods).Field(i).Interface()
t.AppendRow(table.Row{methodName, methodNumber})
t.AppendSeparator()
methodNumber = reflect.ValueOf(correspondingMethods).Field(i).Uint()
actorMethodList = append(actorMethodList, &common.ActorMethod{
Family: actorKey,
MethodName: methodName,
Method: methodNumber,
})
}

fmt.Println(t.RenderMarkdown())
return nil
return actorMethodList, nil
}
69 changes: 69 additions & 0 deletions model/actors/common/actors.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,72 @@ func (states ActorStateList) Persist(ctx context.Context, s model.StorageBatch,
metrics.RecordCount(ctx, metrics.PersistModel, len(states))
return s.PersistModel(ctx, states)
}

type ActorCode struct {
// CID of the actor from builtin actors.
CID string `pg:",pk,notnull"`
// Human-readable identifier for the actor.
Code string `pg:",pk,notnull"`
}

type ActorCodeList []*ActorCode

func (a *ActorCode) Persist(ctx context.Context, s model.StorageBatch, version model.Version) error {
if a == nil {
// Nothing to do
return nil
}

ctx, span := otel.Tracer("").Start(ctx, "ActorCode.Persist")
defer span.End()

ctx, _ = tag.New(ctx, tag.Upsert(metrics.Table, "actor_codes"))
metrics.RecordCount(ctx, metrics.PersistModel, 1)
stop := metrics.Timer(ctx, metrics.PersistDuration)
defer stop()

return s.PersistModel(ctx, a)
}

func (acl ActorCodeList) Persist(ctx context.Context, s model.StorageBatch, version model.Version) error {
ctx, _ = tag.New(ctx, tag.Upsert(metrics.Table, "actor_codes"))
stop := metrics.Timer(ctx, metrics.PersistDuration)
defer stop()

metrics.RecordCount(ctx, metrics.PersistModel, len(acl))
return s.PersistModel(ctx, acl)
}

type ActorMethod struct {
Family string `pg:",pk,notnull"`
MethodName string `pg:",notnull"`
Method uint64 `pg:",pk,notnull"`
}

type ActorMethodList []*ActorMethod

func (a *ActorMethod) Persist(ctx context.Context, s model.StorageBatch, version model.Version) error {
if a == nil {
// Nothing to do
return nil
}

ctx, span := otel.Tracer("").Start(ctx, "ActorMethod.Persist")
defer span.End()

ctx, _ = tag.New(ctx, tag.Upsert(metrics.Table, "actor_methods"))
metrics.RecordCount(ctx, metrics.PersistModel, 1)
stop := metrics.Timer(ctx, metrics.PersistDuration)
defer stop()

return s.PersistModel(ctx, a)
}

func (acl ActorMethodList) Persist(ctx context.Context, s model.StorageBatch, version model.Version) error {
ctx, _ = tag.New(ctx, tag.Upsert(metrics.Table, "actor_methods"))
stop := metrics.Timer(ctx, metrics.PersistDuration)
defer stop()

metrics.RecordCount(ctx, metrics.PersistModel, len(acl))
return s.PersistModel(ctx, acl)
}
Loading

0 comments on commit 57d6749

Please sign in to comment.