Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split Binary for simpler CLI usage #15

Merged
merged 3 commits into from
Sep 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions bitfield.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package statediff

// This class provides a wrapper around bitfield.BitField
// which json Marshal's to include a hint at the type to allow
// clients to provide cleaner rendering of such.

import (
"bytes"
"encoding/hex"
"encoding/json"
"github.com/filecoin-project/go-bitfield"
)

type JSONBitField struct {
bitfield.BitField
}

type jsonField struct {
T string `json:"_type"`
B string `json:"bytes"`
}

func (j JSONBitField) MarshalJSON() ([]byte, error) {
b := bytes.NewBuffer([]byte{})
if err := j.MarshalCBOR(b); err != nil {
return nil, err
}
return json.Marshal(jsonField{
T: "bitfield",
B: hex.EncodeToString(b.Bytes()),
})
}
5 changes: 3 additions & 2 deletions cmd/statediff/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/statediff"
"github.com/filecoin-project/statediff/lib"
)

var chainCmd = &cli.Command{
Name: "chain",
Description: "Examine the state delta of an API object",
Action: runChainCmd,
Flags: []cli.Flag{
&apiFlag,
&lib.ApiFlag,
&expandActorsFlag,
},
}
Expand Down Expand Up @@ -80,7 +81,7 @@ func runChainCmd(c *cli.Context) error {
return fmt.Errorf("no descriptor provided")
}

client, err := GetAPI(c)
client, err := lib.GetAPI(c)
if err != nil {
return err
}
Expand Down
4 changes: 0 additions & 4 deletions cmd/statediff/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:generate go run github.com/filecoin-project/statediff/build/gen "../../npm/app" static/app.js
//go:generate go run github.com/go-bindata/go-bindata/go-bindata -fs -prefix "static/" static/

package main

import (
Expand All @@ -26,7 +23,6 @@ func main() {
vectorCmd,
carCmd,
chainCmd,
exploreCmd,
},
}

Expand Down
File renamed without changes.
5 changes: 3 additions & 2 deletions cmd/statediff/explore.go → cmd/stateexplorer/explore.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"path"

"github.com/filecoin-project/statediff"
"github.com/filecoin-project/statediff/lib"
"github.com/filecoin-project/statediff/build"
"github.com/ipfs/go-cid"
"github.com/urfave/cli/v2"
Expand All @@ -31,14 +32,14 @@ var exploreCmd = &cli.Command{
Description: "Examine a state tree in a browser",
Action: runExploreCmd,
Flags: []cli.Flag{
&apiFlag,
&lib.ApiFlag,
&assetsFlag,
&bindFlag,
},
}

func runExploreCmd(c *cli.Context) error {
client, err := GetAPI(c)
client, err := lib.GetAPI(c)
if err != nil {
return err
}
Expand Down
33 changes: 33 additions & 0 deletions cmd/stateexplorer/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//go:generate go run github.com/filecoin-project/statediff/build/gen "../../npm/app" static/app.js
//go:generate go run github.com/go-bindata/go-bindata/go-bindata -fs -prefix "static/" static/

package main

import (
"log"
"os"
"sort"

"github.com/urfave/cli/v2"
)

func main() {
app := &cli.App{
Name: "stateexplorer",
Usage: "State Explorer 🗺",
Description: "State Explorer 🗺",
Commands: []*cli.Command{
exploreCmd,
},
}

sort.Sort(cli.CommandsByName(app.Commands))
for _, c := range app.Commands {
sort.Sort(cli.FlagsByName(c.Flags))
}

err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions cmd/statediff/api.go → lib/api.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// establish connection to a 'FullNode' filecoin API with cli configuration.
// Mostly with an eye towards ease of use for lotus users.
package main
package lib

import (
"fmt"
Expand All @@ -17,7 +17,7 @@ import (
"github.com/urfave/cli/v2"
)

var apiFlag = cli.StringFlag{
var ApiFlag = cli.StringFlag{
Name: "api",
Usage: "api endpoint, formatted as token:multiaddr",
Value: "",
Expand Down Expand Up @@ -46,7 +46,7 @@ func tryGetAPIFromHomeDir() ([]string, error) {

func GetAPI(c *cli.Context) (api.FullNode, error) {
var err error
api := c.String(apiFlag.Name)
api := c.String(ApiFlag.Name)
sp := strings.SplitN(api, ":", 2)
if len(sp) != 2 {
sp, err = tryGetAPIFromHomeDir()
Expand Down
34 changes: 25 additions & 9 deletions npm/app/components/jsonPrinter.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,34 @@ class jsonPrinter {
if (obj.length == 0) {
return '[]';
}
str += "[\n";
for (let i = 0; i < obj.length; i++) {
if (i > 0) {
str += ",\n";
// if all entries are numbers, we'll skip returns.
if (obj.every(n => typeof n == "number")) {
str += "[";
for (let i = 0; i < obj.length; i++) {
if (i > 0) {
str += ", ";
}
str += this.stringify(obj[i], path + "[" + i + "]")
if (i > 100 && !full) {
str += ` ... and ${obj.length -i} more`;
break
}
}
str += this.indent(this.stringify(obj[i], path + "[" + i + "]"));
if (i > 100 && !full) {
str += this.indent(` ... and ${obj.length - i} more`);
break;
str += "]";
} else {
str += "[\n";
for (let i = 0; i < obj.length; i++) {
if (i > 0) {
str += ",\n";
}
str += this.indent(this.stringify(obj[i], path + "[" + i + "]"));
if (i > 100 && !full) {
str += this.indent(` ... and ${obj.length - i} more`);
break;
}
}
str += "\n]";
}
str += "\n]";
} else if (Object.keys(obj).length == 1 && typeof obj["/"] == "string") {
// cid special case.
str += `<json-cid data-path="${path}">${obj["/"]}</json-cid>`;
Expand Down
74 changes: 73 additions & 1 deletion transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"context"
"fmt"
"regexp"

addr "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
Expand Down Expand Up @@ -55,6 +56,9 @@ const (
StorageMinerActorAllocatedSectors LotusType = "storageMinerActor.AllocatedSectors"
StorageMinerActorSectors LotusType = "storageMinerActor.Sectors"
StorageMinerActorDeadlines LotusType = "storageMinerActor.Deadlines"
StorageMinerActorDeadline LotusType = "storageMinerActor.Deadlines.Due"
StorageMinerActorDeadlinePartitions LotusType = "storageMinerActor.Deadlines.Due.Partitions"
StorageMinerActorDeadlineExpiry LotusType = "storageMinerActor.Deadlines.Due.ExpirationsEpochs"
StoragePowerActorState LotusType = "storagePowerActor"
StoragePowerActorCronEventQueue LotusType = "storagePowerCronEventQueue"
StoragePowerActorClaims LotusType = "storagePowerClaims"
Expand All @@ -65,8 +69,12 @@ const (
PaymentChannelActorState LotusType = "paymentChannelActor"
)

var simplifyingRe = regexp.MustCompile(`\[\d+\]`)

// Transform will unmarshal cbor data based on a provided type hint.
func Transform(ctx context.Context, c cid.Cid, store blockstore.Blockstore, as string) (interface{}, error) {
as = string(simplifyingRe.ReplaceAll([]byte(as), []byte("")))

// First select types which do their own store loading.
switch LotusType(as) {
case LotusTypeStateroot:
Expand All @@ -75,8 +83,14 @@ func Transform(ctx context.Context, c cid.Cid, store blockstore.Blockstore, as s
return transformInitActor(ctx, c, store)
case StorageMinerActorPreCommittedSectors:
return transformMinerActorPreCommittedSectors(ctx, c, store)
case StorageMinerActorPreCommittedSectorsExpiry:
return transformMinerActorPreCommittedSectorsExpiry(ctx, c, store)
case StorageMinerActorSectors:
return transformMinerActorSectors(ctx, c, store)
case StorageMinerActorDeadlinePartitions:
return transformMinerActorDeadlinePartitions(ctx, c, store)
case StorageMinerActorDeadlineExpiry:
return transformMinerActorDeadlineExpiry(ctx, c, store)
case StoragePowerActorCronEventQueue:
return transformPowerActorEventQueue(ctx, c, store)
case StoragePowerActorClaims:
Expand Down Expand Up @@ -148,11 +162,15 @@ func Transform(ctx context.Context, c cid.Cid, store blockstore.Blockstore, as s
case StorageMinerActorAllocatedSectors:
dest := bitfield.BitField{}
err := cbor.DecodeInto(data, &dest)
return dest, err
return JSONBitField{dest}, err
case StorageMinerActorDeadlines:
dest := storageMinerActor.Deadlines{}
err := cbor.DecodeInto(data, &dest)
return dest, err
case StorageMinerActorDeadline:
dest := storageMinerActor.Deadline{}
err := cbor.DecodeInto(data, &dest)
return dest, err
case StoragePowerActorState:
dest := storagePowerActor.State{}
err := cbor.DecodeInto(data, &dest)
Expand Down Expand Up @@ -243,6 +261,24 @@ func transformMinerActorPreCommittedSectors(ctx context.Context, c cid.Cid, stor
return m, nil
}

func transformMinerActorPreCommittedSectorsExpiry(ctx context.Context, c cid.Cid, store blockstore.Blockstore) (interface{}, error) {
cborStore := cbor.NewCborStore(store)
list, err := adt.AsArray(adt.WrapStore(ctx, cborStore), c)
if err != nil {
return nil, err
}

m := make(map[int64]JSONBitField)
value := bitfield.BitField{}
if err := list.ForEach(&value, func(k int64) error {
m[k] = JSONBitField{value}
return nil
}); err != nil {
return nil, err
}
return m, nil
}

func transformMinerActorSectors(ctx context.Context, c cid.Cid, store blockstore.Blockstore) (interface{}, error) {
cborStore := cbor.NewCborStore(store)
list, err := adt.AsArray(adt.WrapStore(ctx, cborStore), c)
Expand All @@ -261,6 +297,42 @@ func transformMinerActorSectors(ctx context.Context, c cid.Cid, store blockstore
return m, nil
}

func transformMinerActorDeadlinePartitions(ctx context.Context, c cid.Cid, store blockstore.Blockstore) (interface{}, error) {
cborStore := cbor.NewCborStore(store)
list, err := adt.AsArray(adt.WrapStore(ctx, cborStore), c)
if err != nil {
return nil, err
}

m := make(map[int64]storageMinerActor.Partition)
value := storageMinerActor.Partition{}
if err := list.ForEach(&value, func(k int64) error {
m[k] = value
return nil
}); err != nil {
return nil, err
}
return m, nil
}

func transformMinerActorDeadlineExpiry(ctx context.Context, c cid.Cid, store blockstore.Blockstore) (interface{}, error) {
cborStore := cbor.NewCborStore(store)
list, err := adt.AsArray(adt.WrapStore(ctx, cborStore), c)
if err != nil {
return nil, err
}

m := make(map[int64]JSONBitField)
value := bitfield.BitField{}
if err := list.ForEach(&value, func(k int64) error {
m[k] = JSONBitField{value}
return nil
}); err != nil {
return nil, err
}
return m, nil
}

func transformPowerActorEventQueue(ctx context.Context, c cid.Cid, store blockstore.Blockstore) (interface{}, error) {
cborStore := cbor.NewCborStore(store)
node, err := adt.AsMultimap(adt.WrapStore(ctx, cborStore), c)
Expand Down