Merge branch 'master' into raulk/itests

This commit is contained in:
Raúl Kripalani
2021-06-07 23:17:44 +01:00
277 changed files with 11198 additions and 1828 deletions
+206 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+27 -27
View File
@@ -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
View File
@@ -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
View File
@@ -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",