Merge branch 'master' into raulk/itests
This commit is contained in:
+206
-3
@@ -92,6 +92,7 @@ var clientCmd = &cli.Command{
|
||||
WithCategory("retrieval", clientFindCmd),
|
||||
WithCategory("retrieval", clientRetrieveCmd),
|
||||
WithCategory("retrieval", clientCancelRetrievalDealCmd),
|
||||
WithCategory("retrieval", clientListRetrievalsCmd),
|
||||
WithCategory("util", clientCommPCmd),
|
||||
WithCategory("util", clientCarGenCmd),
|
||||
WithCategory("util", clientBalancesCmd),
|
||||
@@ -1184,6 +1185,8 @@ var clientRetrieveCmd = &cli.Command{
|
||||
return xerrors.Errorf("error setting up retrieval: %w", err)
|
||||
}
|
||||
|
||||
var prevStatus retrievalmarket.DealStatus
|
||||
|
||||
for {
|
||||
select {
|
||||
case evt, ok := <-updates:
|
||||
@@ -1194,14 +1197,23 @@ var clientRetrieveCmd = &cli.Command{
|
||||
retrievalmarket.ClientEvents[evt.Event],
|
||||
retrievalmarket.DealStatuses[evt.Status],
|
||||
)
|
||||
} else {
|
||||
afmt.Println("Success")
|
||||
return nil
|
||||
prevStatus = evt.Status
|
||||
}
|
||||
|
||||
if evt.Err != "" {
|
||||
return xerrors.Errorf("retrieval failed: %s", evt.Err)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
if prevStatus == retrievalmarket.DealStatusCompleted {
|
||||
afmt.Println("Success")
|
||||
} else {
|
||||
afmt.Printf("saw final deal state %s instead of expected success state DealStatusCompleted\n",
|
||||
retrievalmarket.DealStatuses[prevStatus])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
case <-ctx.Done():
|
||||
return xerrors.Errorf("retrieval timed out")
|
||||
}
|
||||
@@ -1209,6 +1221,197 @@ var clientRetrieveCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var clientListRetrievalsCmd = &cli.Command{
|
||||
Name: "list-retrievals",
|
||||
Usage: "List retrieval market deals",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "print verbose deal details",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "color",
|
||||
Usage: "use color in display output",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "show-failed",
|
||||
Usage: "show failed/failing deals",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "completed",
|
||||
Usage: "show completed retrievals",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "watch",
|
||||
Usage: "watch deal updates in real-time, rather than a one time list",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
verbose := cctx.Bool("verbose")
|
||||
color := cctx.Bool("color")
|
||||
watch := cctx.Bool("watch")
|
||||
showFailed := cctx.Bool("show-failed")
|
||||
completed := cctx.Bool("completed")
|
||||
|
||||
localDeals, err := api.ClientListRetrievals(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if watch {
|
||||
updates, err := api.ClientGetRetrievalUpdates(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
tm.Clear()
|
||||
tm.MoveCursor(1, 1)
|
||||
|
||||
err = outputRetrievalDeals(ctx, tm.Screen, localDeals, verbose, color, showFailed, completed)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tm.Flush()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case updated := <-updates:
|
||||
var found bool
|
||||
for i, existing := range localDeals {
|
||||
if existing.ID == updated.ID {
|
||||
localDeals[i] = updated
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
localDeals = append(localDeals, updated)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputRetrievalDeals(ctx, cctx.App.Writer, localDeals, verbose, color, showFailed, completed)
|
||||
},
|
||||
}
|
||||
|
||||
func isTerminalError(status retrievalmarket.DealStatus) bool {
|
||||
// should patch this in go-fil-markets but to solve the problem immediate and not have buggy output
|
||||
return retrievalmarket.IsTerminalError(status) || status == retrievalmarket.DealStatusErrored || status == retrievalmarket.DealStatusCancelled
|
||||
}
|
||||
func outputRetrievalDeals(ctx context.Context, out io.Writer, localDeals []lapi.RetrievalInfo, verbose bool, color bool, showFailed bool, completed bool) error {
|
||||
var deals []api.RetrievalInfo
|
||||
for _, deal := range localDeals {
|
||||
if !showFailed && isTerminalError(deal.Status) {
|
||||
continue
|
||||
}
|
||||
if !completed && retrievalmarket.IsTerminalSuccess(deal.Status) {
|
||||
continue
|
||||
}
|
||||
deals = append(deals, deal)
|
||||
}
|
||||
|
||||
tableColumns := []tablewriter.Column{
|
||||
tablewriter.Col("PayloadCID"),
|
||||
tablewriter.Col("DealId"),
|
||||
tablewriter.Col("Provider"),
|
||||
tablewriter.Col("Status"),
|
||||
tablewriter.Col("PricePerByte"),
|
||||
tablewriter.Col("Received"),
|
||||
tablewriter.Col("TotalPaid"),
|
||||
}
|
||||
|
||||
if verbose {
|
||||
tableColumns = append(tableColumns,
|
||||
tablewriter.Col("PieceCID"),
|
||||
tablewriter.Col("UnsealPrice"),
|
||||
tablewriter.Col("BytesPaidFor"),
|
||||
tablewriter.Col("TransferChannelID"),
|
||||
tablewriter.Col("TransferStatus"),
|
||||
)
|
||||
}
|
||||
tableColumns = append(tableColumns, tablewriter.NewLineCol("Message"))
|
||||
|
||||
w := tablewriter.New(tableColumns...)
|
||||
|
||||
for _, d := range deals {
|
||||
w.Write(toRetrievalOutput(d, color, verbose))
|
||||
}
|
||||
|
||||
return w.Flush(out)
|
||||
}
|
||||
|
||||
func toRetrievalOutput(d api.RetrievalInfo, color bool, verbose bool) map[string]interface{} {
|
||||
|
||||
payloadCID := d.PayloadCID.String()
|
||||
provider := d.Provider.String()
|
||||
if !verbose {
|
||||
payloadCID = ellipsis(payloadCID, 8)
|
||||
provider = ellipsis(provider, 8)
|
||||
}
|
||||
|
||||
retrievalOutput := map[string]interface{}{
|
||||
"PayloadCID": payloadCID,
|
||||
"DealId": d.ID,
|
||||
"Provider": provider,
|
||||
"Status": retrievalStatusString(color, d.Status),
|
||||
"PricePerByte": types.FIL(d.PricePerByte),
|
||||
"Received": units.BytesSize(float64(d.BytesReceived)),
|
||||
"TotalPaid": types.FIL(d.TotalPaid),
|
||||
"Message": d.Message,
|
||||
}
|
||||
|
||||
if verbose {
|
||||
transferChannelID := ""
|
||||
if d.TransferChannelID != nil {
|
||||
transferChannelID = d.TransferChannelID.String()
|
||||
}
|
||||
transferStatus := ""
|
||||
if d.DataTransfer != nil {
|
||||
transferStatus = datatransfer.Statuses[d.DataTransfer.Status]
|
||||
}
|
||||
pieceCID := ""
|
||||
if d.PieceCID != nil {
|
||||
pieceCID = d.PieceCID.String()
|
||||
}
|
||||
|
||||
retrievalOutput["PieceCID"] = pieceCID
|
||||
retrievalOutput["UnsealPrice"] = types.FIL(d.UnsealPrice)
|
||||
retrievalOutput["BytesPaidFor"] = units.BytesSize(float64(d.BytesPaidFor))
|
||||
retrievalOutput["TransferChannelID"] = transferChannelID
|
||||
retrievalOutput["TransferStatus"] = transferStatus
|
||||
}
|
||||
return retrievalOutput
|
||||
}
|
||||
|
||||
func retrievalStatusString(c bool, status retrievalmarket.DealStatus) string {
|
||||
s := retrievalmarket.DealStatuses[status]
|
||||
if !c {
|
||||
return s
|
||||
}
|
||||
|
||||
if isTerminalError(status) {
|
||||
return color.RedString(s)
|
||||
}
|
||||
if retrievalmarket.IsTerminalSuccess(status) {
|
||||
return color.GreenString(s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
var clientInspectDealCmd = &cli.Command{
|
||||
Name: "inspect-deal",
|
||||
Usage: "Inspect detailed information about deal's lifecycle and the various stages it goes through",
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ var Commands = []*cli.Command{
|
||||
WithCategory("basic", walletCmd),
|
||||
WithCategory("basic", clientCmd),
|
||||
WithCategory("basic", multisigCmd),
|
||||
WithCategory("basic", verifRegCmd),
|
||||
WithCategory("basic", filplusCmd),
|
||||
WithCategory("basic", paychCmd),
|
||||
WithCategory("developer", AuthCmd),
|
||||
WithCategory("developer", MpoolCmd),
|
||||
|
||||
+9
-1
@@ -238,6 +238,9 @@ var disputerStartCmd = &cli.Command{
|
||||
|
||||
dpmsgs := make([]*types.Message, 0)
|
||||
|
||||
startTime := time.Now()
|
||||
proofsChecked := uint64(0)
|
||||
|
||||
// TODO: Parallelizeable
|
||||
for _, dl := range dls {
|
||||
fullDeadlines, err := api.StateMinerDeadlines(ctx, dl.miner, tsk)
|
||||
@@ -249,7 +252,10 @@ var disputerStartCmd = &cli.Command{
|
||||
return xerrors.Errorf("deadline index %d not found in deadlines", dl.index)
|
||||
}
|
||||
|
||||
ms, err := makeDisputeWindowedPosts(ctx, api, dl, fullDeadlines[dl.index].DisputableProofCount, fromAddr)
|
||||
disputableProofs := fullDeadlines[dl.index].DisputableProofCount
|
||||
proofsChecked += disputableProofs
|
||||
|
||||
ms, err := makeDisputeWindowedPosts(ctx, api, dl, disputableProofs, fromAddr)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to check for disputes: %w", err)
|
||||
}
|
||||
@@ -264,6 +270,8 @@ var disputerStartCmd = &cli.Command{
|
||||
deadlineMap[dClose+Confidence] = append(deadlineMap[dClose+Confidence], *dl)
|
||||
}
|
||||
|
||||
disputeLog.Infow("checked proofs", "count", proofsChecked, "duration", time.Since(startTime))
|
||||
|
||||
// TODO: Parallelizeable / can be integrated into the previous deadline-iterating for loop
|
||||
for _, dpmsg := range dpmsgs {
|
||||
disputeLog.Infow("disputing a PoSt", "miner", dpmsg.To)
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
verifreg4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/lotus/api/v0api"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/xerrors"
|
||||
@@ -15,6 +14,7 @@ import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/api/v0api"
|
||||
"github.com/filecoin-project/lotus/blockstore"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
@@ -24,26 +24,26 @@ import (
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
)
|
||||
|
||||
var verifRegCmd = &cli.Command{
|
||||
Name: "verifreg",
|
||||
Usage: "Interact with the verified registry actor",
|
||||
var filplusCmd = &cli.Command{
|
||||
Name: "filplus",
|
||||
Usage: "Interact with the verified registry actor used by Filplus",
|
||||
Flags: []cli.Flag{},
|
||||
Subcommands: []*cli.Command{
|
||||
verifRegVerifyClientCmd,
|
||||
verifRegListVerifiersCmd,
|
||||
verifRegListClientsCmd,
|
||||
verifRegCheckClientCmd,
|
||||
verifRegCheckVerifierCmd,
|
||||
filplusVerifyClientCmd,
|
||||
filplusListNotariesCmd,
|
||||
filplusListClientsCmd,
|
||||
filplusCheckClientCmd,
|
||||
filplusCheckNotaryCmd,
|
||||
},
|
||||
}
|
||||
|
||||
var verifRegVerifyClientCmd = &cli.Command{
|
||||
Name: "verify-client",
|
||||
var filplusVerifyClientCmd = &cli.Command{
|
||||
Name: "grant-datacap",
|
||||
Usage: "give allowance to the specified verified client address",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "from",
|
||||
Usage: "specify your verifier address to send the message from",
|
||||
Usage: "specify your notary address to send the message from",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
@@ -79,17 +79,17 @@ var verifRegVerifyClientCmd = &cli.Command{
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
found, dcap, err := checkVerifier(ctx, api, fromk)
|
||||
found, dcap, err := checkNotary(ctx, api, fromk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !found {
|
||||
return xerrors.New("sender address must be a verifier")
|
||||
return xerrors.New("sender address must be a notary")
|
||||
}
|
||||
|
||||
if dcap.Cmp(allowance.Int) < 0 {
|
||||
return xerrors.Errorf("cannot allot more allowance than verifier data cap: %s < %s", dcap, allowance)
|
||||
return xerrors.Errorf("cannot allot more allowance than notary data cap: %s < %s", dcap, allowance)
|
||||
}
|
||||
|
||||
// TODO: This should be abstracted over actor versions
|
||||
@@ -125,9 +125,9 @@ var verifRegVerifyClientCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var verifRegListVerifiersCmd = &cli.Command{
|
||||
Name: "list-verifiers",
|
||||
Usage: "list all verifiers",
|
||||
var filplusListNotariesCmd = &cli.Command{
|
||||
Name: "list-notaries",
|
||||
Usage: "list all notaries",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
@@ -155,7 +155,7 @@ var verifRegListVerifiersCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var verifRegListClientsCmd = &cli.Command{
|
||||
var filplusListClientsCmd = &cli.Command{
|
||||
Name: "list-clients",
|
||||
Usage: "list all verified clients",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
@@ -185,8 +185,8 @@ var verifRegListClientsCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var verifRegCheckClientCmd = &cli.Command{
|
||||
Name: "check-client",
|
||||
var filplusCheckClientCmd = &cli.Command{
|
||||
Name: "check-client-datacap",
|
||||
Usage: "check verified client remaining bytes",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if !cctx.Args().Present() {
|
||||
@@ -219,12 +219,12 @@ var verifRegCheckClientCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var verifRegCheckVerifierCmd = &cli.Command{
|
||||
Name: "check-verifier",
|
||||
Usage: "check verifiers remaining bytes",
|
||||
var filplusCheckNotaryCmd = &cli.Command{
|
||||
Name: "check-notaries-datacap",
|
||||
Usage: "check notaries remaining bytes",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if !cctx.Args().Present() {
|
||||
return fmt.Errorf("must specify verifier address to check")
|
||||
return fmt.Errorf("must specify notary address to check")
|
||||
}
|
||||
|
||||
vaddr, err := address.NewFromString(cctx.Args().First())
|
||||
@@ -239,7 +239,7 @@ var verifRegCheckVerifierCmd = &cli.Command{
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
found, dcap, err := checkVerifier(ctx, api, vaddr)
|
||||
found, dcap, err := checkNotary(ctx, api, vaddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -253,7 +253,7 @@ var verifRegCheckVerifierCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
func checkVerifier(ctx context.Context, api v0api.FullNode, vaddr address.Address) (bool, abi.StoragePower, error) {
|
||||
func checkNotary(ctx context.Context, api v0api.FullNode, vaddr address.Address) (bool, abi.StoragePower, error) {
|
||||
vid, err := api.StateLookupID(ctx, vaddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return false, big.Zero(), err
|
||||
+1
-1
@@ -23,7 +23,7 @@ var FetchParamCmd = &cli.Command{
|
||||
}
|
||||
sectorSize := uint64(sectorSizeInt)
|
||||
|
||||
err = paramfetch.GetParams(ReqContext(cctx), build.ParametersJSON(), sectorSize)
|
||||
err = paramfetch.GetParams(ReqContext(cctx), build.ParametersJSON(), build.SrsJSON(), sectorSize)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("fetching proof parameters: %w", err)
|
||||
}
|
||||
|
||||
+51
-132
@@ -3,6 +3,8 @@ package cli
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
@@ -22,7 +24,6 @@ import (
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
"github.com/multiformats/go-multihash"
|
||||
"github.com/urfave/cli/v2"
|
||||
@@ -31,7 +32,6 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
@@ -1521,7 +1521,7 @@ func printMsg(ctx context.Context, api v0api.FullNode, msg cid.Cid, mw *lapi.Msg
|
||||
var StateCallCmd = &cli.Command{
|
||||
Name: "call",
|
||||
Usage: "Invoke a method on an actor locally",
|
||||
ArgsUsage: "[toAddress methodId <param1 param2 ...> (optional)]",
|
||||
ArgsUsage: "[toAddress methodId params (optional)]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "from",
|
||||
@@ -1535,8 +1535,13 @@ var StateCallCmd = &cli.Command{
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ret",
|
||||
Usage: "specify how to parse output (auto, raw, addr, big)",
|
||||
Value: "auto",
|
||||
Usage: "specify how to parse output (raw, decoded, base64, hex)",
|
||||
Value: "decoded",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "encoding",
|
||||
Value: "base64",
|
||||
Usage: "specify params encoding to parse (base64, hex)",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
@@ -1577,14 +1582,23 @@ var StateCallCmd = &cli.Command{
|
||||
return fmt.Errorf("failed to parse 'value': %s", err)
|
||||
}
|
||||
|
||||
act, err := api.StateGetActor(ctx, toa, ts.Key())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to lookup target actor: %s", err)
|
||||
}
|
||||
|
||||
params, err := parseParamsForMethod(act.Code, method, cctx.Args().Slice()[2:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse params: %s", err)
|
||||
var params []byte
|
||||
// If params were passed in, decode them
|
||||
if cctx.Args().Len() > 2 {
|
||||
switch cctx.String("encoding") {
|
||||
case "base64":
|
||||
params, err = base64.StdEncoding.DecodeString(cctx.Args().Get(2))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("decoding base64 value: %w", err)
|
||||
}
|
||||
case "hex":
|
||||
params, err = hex.DecodeString(cctx.Args().Get(2))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("decoding hex value: %w", err)
|
||||
}
|
||||
default:
|
||||
return xerrors.Errorf("unrecognized encoding: %s", cctx.String("encoding"))
|
||||
}
|
||||
}
|
||||
|
||||
ret, err := api.StateCall(ctx, &types.Message{
|
||||
@@ -1595,137 +1609,42 @@ var StateCallCmd = &cli.Command{
|
||||
Params: params,
|
||||
}, ts.Key())
|
||||
if err != nil {
|
||||
return fmt.Errorf("state call failed: %s", err)
|
||||
return fmt.Errorf("state call failed: %w", err)
|
||||
}
|
||||
|
||||
if ret.MsgRct.ExitCode != 0 {
|
||||
return fmt.Errorf("invocation failed (exit: %d, gasUsed: %d): %s", ret.MsgRct.ExitCode, ret.MsgRct.GasUsed, ret.Error)
|
||||
}
|
||||
|
||||
s, err := formatOutput(cctx.String("ret"), ret.MsgRct.Return)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to format output: %s", err)
|
||||
}
|
||||
fmt.Println("Call receipt:")
|
||||
fmt.Printf("Exit code: %d\n", ret.MsgRct.ExitCode)
|
||||
fmt.Printf("Gas Used: %d\n", ret.MsgRct.GasUsed)
|
||||
|
||||
fmt.Printf("gas used: %d\n", ret.MsgRct.GasUsed)
|
||||
fmt.Printf("return: %s\n", s)
|
||||
switch cctx.String("ret") {
|
||||
case "decoded":
|
||||
act, err := api.StateGetActor(ctx, toa, ts.Key())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting actor: %w", err)
|
||||
}
|
||||
|
||||
retStr, err := jsonReturn(act.Code, abi.MethodNum(method), ret.MsgRct.Return)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("decoding return: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Return:\n%s\n", retStr)
|
||||
case "raw":
|
||||
fmt.Printf("Return: \n%s\n", ret.MsgRct.Return)
|
||||
case "hex":
|
||||
fmt.Printf("Return: \n%x\n", ret.MsgRct.Return)
|
||||
case "base64":
|
||||
fmt.Printf("Return: \n%s\n", base64.StdEncoding.EncodeToString(ret.MsgRct.Return))
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func formatOutput(t string, val []byte) (string, error) {
|
||||
switch t {
|
||||
case "raw", "hex":
|
||||
return fmt.Sprintf("%x", val), nil
|
||||
case "address", "addr", "a":
|
||||
a, err := address.NewFromBytes(val)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return a.String(), nil
|
||||
case "big", "int", "bigint":
|
||||
bi := types.BigFromBytes(val)
|
||||
return bi.String(), nil
|
||||
case "fil":
|
||||
bi := types.FIL(types.BigFromBytes(val))
|
||||
return bi.String(), nil
|
||||
case "pid", "peerid", "peer":
|
||||
pid, err := peer.IDFromBytes(val)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return pid.Pretty(), nil
|
||||
case "auto":
|
||||
if len(val) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
a, err := address.NewFromBytes(val)
|
||||
if err == nil {
|
||||
return "address: " + a.String(), nil
|
||||
}
|
||||
|
||||
pid, err := peer.IDFromBytes(val)
|
||||
if err == nil {
|
||||
return "peerID: " + pid.Pretty(), nil
|
||||
}
|
||||
|
||||
bi := types.BigFromBytes(val)
|
||||
return "bigint: " + bi.String(), nil
|
||||
default:
|
||||
return "", fmt.Errorf("unrecognized output type: %q", t)
|
||||
}
|
||||
}
|
||||
|
||||
func parseParamsForMethod(act cid.Cid, method uint64, args []string) ([]byte, error) {
|
||||
if len(args) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// TODO: consider moving this to a dedicated helper
|
||||
actMeta, ok := stmgr.MethodsMap[act]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown actor %s", act)
|
||||
}
|
||||
|
||||
methodMeta, ok := actMeta[abi.MethodNum(method)]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown method %d for actor %s", method, act)
|
||||
}
|
||||
|
||||
paramObj := methodMeta.Params.Elem()
|
||||
if paramObj.NumField() != len(args) {
|
||||
return nil, fmt.Errorf("not enough arguments given to call that method (expecting %d)", paramObj.NumField())
|
||||
}
|
||||
|
||||
p := reflect.New(paramObj)
|
||||
for i := 0; i < len(args); i++ {
|
||||
switch paramObj.Field(i).Type {
|
||||
case reflect.TypeOf(address.Address{}):
|
||||
a, err := address.NewFromString(args[i])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse address: %s", err)
|
||||
}
|
||||
p.Elem().Field(i).Set(reflect.ValueOf(a))
|
||||
case reflect.TypeOf(uint64(0)):
|
||||
val, err := strconv.ParseUint(args[i], 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.Elem().Field(i).Set(reflect.ValueOf(val))
|
||||
case reflect.TypeOf(abi.ChainEpoch(0)):
|
||||
val, err := strconv.ParseInt(args[i], 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.Elem().Field(i).Set(reflect.ValueOf(abi.ChainEpoch(val)))
|
||||
case reflect.TypeOf(big.Int{}):
|
||||
val, err := big.FromString(args[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.Elem().Field(i).Set(reflect.ValueOf(val))
|
||||
case reflect.TypeOf(peer.ID("")):
|
||||
pid, err := peer.Decode(args[i])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse peer ID: %s", err)
|
||||
}
|
||||
p.Elem().Field(i).Set(reflect.ValueOf(pid))
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported type for call (TODO): %s", paramObj.Field(i).Type)
|
||||
}
|
||||
}
|
||||
|
||||
m := p.Interface().(cbg.CBORMarshaler)
|
||||
buf := new(bytes.Buffer)
|
||||
if err := m.MarshalCBOR(buf); err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal param object: %s", err)
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var StateCircSupplyCmd = &cli.Command{
|
||||
Name: "circulating-supply",
|
||||
Usage: "Get the exact current circulating supply of Filecoin",
|
||||
|
||||
Reference in New Issue
Block a user