From cdd37bda1c8f6120e04d03b01766abc5d3258a58 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Fri, 6 Mar 2020 18:47:19 -0800 Subject: [PATCH] add some type info to chain get --- api/api_full.go | 7 ++++++- api/apistruct/struct.go | 8 ++++---- cli/chain.go | 44 +++++++++++++++++++++++++++++++++++++++-- node/impl/full/chain.go | 7 +++++-- 4 files changed, 57 insertions(+), 9 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index d6fa9e7ab..9661a7b9c 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -46,7 +46,7 @@ type FullNode interface { ChainSetHead(context.Context, types.TipSetKey) error ChainGetGenesis(context.Context) (*types.TipSet, error) ChainTipSetWeight(context.Context, types.TipSetKey) (types.BigInt, error) - ChainGetNode(ctx context.Context, p string) (interface{}, error) + ChainGetNode(ctx context.Context, p string) (*IpldObject, error) ChainGetMessage(context.Context, cid.Cid) (*types.Message, error) ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*store.HeadChange, error) ChainExport(context.Context, types.TipSetKey) (<-chan []byte, error) @@ -318,6 +318,11 @@ type StartDealParams struct { BlocksDuration uint64 } +type IpldObject struct { + Cid cid.Cid + Obj interface{} +} + type ActiveSync struct { Base *types.TipSet Target *types.TipSet diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 430f131e4..5d673482a 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -63,7 +63,7 @@ type FullNodeStruct struct { ChainSetHead func(context.Context, types.TipSetKey) error `perm:"admin"` ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"` ChainTipSetWeight func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"` - ChainGetNode func(ctx context.Context, p string) (interface{}, error) `perm:"read"` + ChainGetNode func(ctx context.Context, p string) (*api.IpldObject, error) `perm:"read"` ChainGetMessage func(context.Context, cid.Cid) (*types.Message, error) `perm:"read"` ChainGetPath func(context.Context, types.TipSetKey, types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"` ChainExport func(context.Context, types.TipSetKey) (<-chan []byte, error) `perm:"read"` @@ -93,14 +93,14 @@ type FullNodeStruct struct { WalletExport func(context.Context, address.Address) (*types.KeyInfo, error) `perm:"admin"` WalletImport func(context.Context, *types.KeyInfo) (address.Address, error) `perm:"admin"` - ClientImport func(ctx context.Context, ref api.FileRef) (cid.Cid, error) `perm:"admin"` + ClientImport func(ctx context.Context, ref api.FileRef) (cid.Cid, error) `perm:"admin"` ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"` ClientHasLocal func(ctx context.Context, root cid.Cid) (bool, error) `perm:"write"` ClientFindData func(ctx context.Context, root cid.Cid) ([]api.QueryOffer, error) `perm:"read"` ClientStartDeal func(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) `perm:"admin"` ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"` ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"` - ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref api.FileRef) error `perm:"admin"` + ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref api.FileRef) error `perm:"admin"` ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) `perm:"read"` StateMinerSectors func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"` @@ -392,7 +392,7 @@ func (c *FullNodeStruct) ChainTipSetWeight(ctx context.Context, tsk types.TipSet return c.Internal.ChainTipSetWeight(ctx, tsk) } -func (c *FullNodeStruct) ChainGetNode(ctx context.Context, p string) (interface{}, error) { +func (c *FullNodeStruct) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) { return c.Internal.ChainGetNode(ctx, p) } diff --git a/cli/chain.go b/cli/chain.go index 41a01b047..61c6fd221 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -16,6 +16,7 @@ import ( "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin/power" cid "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" "gopkg.in/urfave/cli.v2" @@ -361,6 +362,12 @@ var chainGetCmd = &cli.Command{ Name: "get", Usage: "Get chain DAG node by path", ArgsUsage: "[path]", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "as-type", + Usage: "specify type to interpret output as", + }, + }, Description: `Get ipld node under a specified path: lotus chain get /ipfs/[cid]/some/path @@ -379,12 +386,45 @@ var chainGetCmd = &cli.Command{ defer closer() ctx := ReqContext(cctx) - nd, err := api.ChainGetNode(ctx, cctx.Args().First()) + obj, err := api.ChainGetNode(ctx, cctx.Args().First()) if err != nil { return err } - b, err := json.MarshalIndent(nd, "", "\t") + t := strings.ToLower(cctx.String("as-type")) + if t == "" { + b, err := json.MarshalIndent(obj.Obj, "", "\t") + if err != nil { + return err + } + fmt.Println(string(b)) + return nil + } + + var cbu cbg.CBORUnmarshaler + switch t { + case "block": + cbu = new(types.BlockHeader) + case "message": + cbu = new(types.Message) + case "smessage", "signedmessage": + cbu = new(types.SignedMessage) + case "actor": + cbu = new(types.Actor) + default: + return fmt.Errorf("unknown type: %q", t) + } + + raw, err := api.ChainReadObj(ctx, obj.Cid) + if err != nil { + return err + } + + if err := cbu.UnmarshalCBOR(bytes.NewReader(raw)); err != nil { + return fmt.Errorf("failed to unmarshal as %q", t) + } + + b, err := json.MarshalIndent(cbu, "", "\t") if err != nil { return err } diff --git a/node/impl/full/chain.go b/node/impl/full/chain.go index e88b39d9f..94b2023bb 100644 --- a/node/impl/full/chain.go +++ b/node/impl/full/chain.go @@ -306,7 +306,7 @@ func resolveOnce(bs blockstore.Blockstore) func(ctx context.Context, ds ipld.Nod } } -func (a *ChainAPI) ChainGetNode(ctx context.Context, p string) (interface{}, error) { +func (a *ChainAPI) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) { ip, err := path.ParsePath(p) if err != nil { return nil, xerrors.Errorf("parsing path: %w", err) @@ -327,7 +327,10 @@ func (a *ChainAPI) ChainGetNode(ctx context.Context, p string) (interface{}, err return nil, err } - return node, nil + return &api.IpldObject{ + Cid: node.Cid(), + Obj: node, + }, nil } func (a *ChainAPI) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {