Merge branch 'master' into sbansal/nonce-coordination-and-consensus-for-chain-nodes

This commit is contained in:
Shrenuj Bansal
2022-11-11 14:41:38 -05:00
261 changed files with 7497 additions and 19074 deletions
+3 -2
View File
@@ -62,6 +62,7 @@ var ChainCmd = &cli.Command{
ChainDecodeCmd,
ChainEncodeCmd,
ChainDisputeSetCmd,
ChainPruneCmd,
},
}
@@ -494,8 +495,8 @@ var ChainInspectUsage = &cli.Command{
mm := filcns.NewActorRegistry().Methods[code][m.Message.Method] // TODO: use remote map
byMethod[mm.Num] += m.Message.GasLimit
byMethodC[mm.Num]++
byMethod[mm.Name] += m.Message.GasLimit
byMethodC[mm.Name]++
}
type keyGasPair struct {
+1 -2
View File
@@ -327,8 +327,7 @@ func TestInspectUsage(t *testing.T) {
// check for gas by sender
assert.Contains(t, out, "By Sender")
// check for gas by method
methodStr := fmt.Sprintf("By Method:\n%d", builtin.MethodSend)
assert.Contains(t, out, methodStr)
assert.Contains(t, out, "By Method:\nSend")
})
}
+4 -63
View File
@@ -3,14 +3,9 @@ package cli
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
"path"
"sort"
"strings"
"time"
@@ -29,8 +24,6 @@ import (
"github.com/ipld/go-ipld-prime/traversal/selector/builder"
selectorparse "github.com/ipld/go-ipld-prime/traversal/selector/parse"
textselector "github.com/ipld/go-ipld-selector-text-lite"
"github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
@@ -40,6 +33,7 @@ import (
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
cliutil "github.com/filecoin-project/lotus/cli/util"
"github.com/filecoin-project/lotus/markets/utils"
"github.com/filecoin-project/lotus/node/repo"
)
@@ -337,60 +331,6 @@ Examples:
},
}
func ClientExportStream(apiAddr string, apiAuth http.Header, eref lapi.ExportRef, car bool) (io.ReadCloser, error) {
rj, err := json.Marshal(eref)
if err != nil {
return nil, xerrors.Errorf("marshaling export ref: %w", err)
}
ma, err := multiaddr.NewMultiaddr(apiAddr)
if err == nil {
_, addr, err := manet.DialArgs(ma)
if err != nil {
return nil, err
}
// todo: make cliutil helpers for this
apiAddr = "http://" + addr
}
aa, err := url.Parse(apiAddr)
if err != nil {
return nil, xerrors.Errorf("parsing api address: %w", err)
}
switch aa.Scheme {
case "ws":
aa.Scheme = "http"
case "wss":
aa.Scheme = "https"
}
aa.Path = path.Join(aa.Path, "rest/v0/export")
req, err := http.NewRequest("GET", fmt.Sprintf("%s?car=%t&export=%s", aa, car, url.QueryEscape(string(rj))), nil)
if err != nil {
return nil, err
}
req.Header = apiAuth
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
em, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, xerrors.Errorf("reading error body: %w", err)
}
resp.Body.Close() // nolint
return nil, xerrors.Errorf("getting root car: http %d: %s", resp.StatusCode, string(em))
}
return resp.Body, nil
}
var clientRetrieveCatCmd = &cli.Command{
Name: "cat",
Usage: "Show data from network",
@@ -440,7 +380,7 @@ var clientRetrieveCatCmd = &cli.Command{
eref.DAGs = append(eref.DAGs, lapi.DagSpec{DataSelector: &sel})
}
rc, err := ClientExportStream(ainfo.Addr, ainfo.AuthHeader(), *eref, false)
rc, err := cliutil.ClientExportStream(ainfo.Addr, ainfo.AuthHeader(), *eref, false)
if err != nil {
return err
}
@@ -528,7 +468,7 @@ var clientRetrieveLsCmd = &cli.Command{
DataSelector: &dataSelector,
})
rc, err := ClientExportStream(ainfo.Addr, ainfo.AuthHeader(), *eref, true)
rc, err := cliutil.ClientExportStream(ainfo.Addr, ainfo.AuthHeader(), *eref, true)
if err != nil {
return xerrors.Errorf("export: %w", err)
}
@@ -583,6 +523,7 @@ var clientRetrieveLsCmd = &cli.Command{
dserv,
roots[0],
sel,
nil,
func(p traversal.Progress, n ipld.Node, r traversal.VisitReason) error {
if r == traversal.VisitReason_SelectionMatch {
fmt.Println(p.Path)
+234 -16
View File
@@ -5,6 +5,8 @@ import (
"context"
"encoding/hex"
"fmt"
"os"
"strconv"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/urfave/cli/v2"
@@ -12,6 +14,7 @@ import (
"github.com/filecoin-project/go-address"
"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"
verifregtypes8 "github.com/filecoin-project/go-state-types/builtin/v8/verifreg"
verifregtypes9 "github.com/filecoin-project/go-state-types/builtin/v9/verifreg"
@@ -22,8 +25,10 @@ import (
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin/datacap"
"github.com/filecoin-project/lotus/chain/actors/builtin/verifreg"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/tablewriter"
)
var filplusCmd = &cli.Command{
@@ -37,12 +42,15 @@ var filplusCmd = &cli.Command{
filplusCheckClientCmd,
filplusCheckNotaryCmd,
filplusSignRemoveDataCapProposal,
filplusListAllocationsCmd,
filplusRemoveExpiredAllocationsCmd,
},
}
var filplusVerifyClientCmd = &cli.Command{
Name: "grant-datacap",
Usage: "give allowance to the specified verified client address",
Name: "grant-datacap",
Usage: "give allowance to the specified verified client address",
ArgsUsage: "[clientAddress datacap]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
@@ -132,6 +140,10 @@ var filplusListNotariesCmd = &cli.Command{
Name: "list-notaries",
Usage: "list all notaries",
Action: func(cctx *cli.Context) error {
if cctx.NArg() != 0 {
return IncorrectNumArgs(cctx)
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
@@ -162,6 +174,10 @@ var filplusListClientsCmd = &cli.Command{
Name: "list-clients",
Usage: "list all verified clients",
Action: func(cctx *cli.Context) error {
if cctx.NArg() != 0 {
return IncorrectNumArgs(cctx)
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
@@ -169,15 +185,40 @@ var filplusListClientsCmd = &cli.Command{
defer closer()
ctx := ReqContext(cctx)
act, err := api.StateGetActor(ctx, verifreg.Address, types.EmptyTSK)
apibs := blockstore.NewAPIBlockstore(api)
store := adt.WrapStore(ctx, cbor.NewCborStore(apibs))
nv, err := api.StateNetworkVersion(ctx, types.EmptyTSK)
if err != nil {
return err
}
apibs := blockstore.NewAPIBlockstore(api)
store := adt.WrapStore(ctx, cbor.NewCborStore(apibs))
av, err := actorstypes.VersionForNetwork(nv)
if err != nil {
return err
}
st, err := verifreg.Load(store, act)
if av <= 8 {
act, err := api.StateGetActor(ctx, verifreg.Address, types.EmptyTSK)
if err != nil {
return err
}
st, err := verifreg.Load(store, act)
if err != nil {
return err
}
return st.ForEachClient(func(addr address.Address, dcap abi.StoragePower) error {
_, err := fmt.Printf("%s: %s\n", addr, dcap)
return err
})
}
act, err := api.StateGetActor(ctx, datacap.Address, types.EmptyTSK)
if err != nil {
return err
}
st, err := datacap.Load(store, act)
if err != nil {
return err
}
@@ -188,11 +229,186 @@ var filplusListClientsCmd = &cli.Command{
},
}
var filplusCheckClientCmd = &cli.Command{
Name: "check-client-datacap",
Usage: "check verified client remaining bytes",
var filplusListAllocationsCmd = &cli.Command{
Name: "list-allocations",
Usage: "List allocations made by client",
ArgsUsage: "clientAddress",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "expired",
Usage: "list only expired allocations",
},
},
Action: func(cctx *cli.Context) error {
if !cctx.Args().Present() {
if cctx.NArg() != 1 {
return IncorrectNumArgs(cctx)
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
clientAddr, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return err
}
clientIdAddr, err := api.StateLookupID(ctx, clientAddr, types.EmptyTSK)
if err != nil {
return err
}
store := adt.WrapStore(ctx, cbor.NewCborStore(blockstore.NewAPIBlockstore(api)))
verifregActor, err := api.StateGetActor(ctx, verifreg.Address, types.EmptyTSK)
if err != nil {
return err
}
verifregState, err := verifreg.Load(store, verifregActor)
if err != nil {
return err
}
ts, err := api.ChainHead(ctx)
if err != nil {
return err
}
allocationsMap, err := verifregState.GetAllocations(clientIdAddr)
if err != nil {
return err
}
tw := tablewriter.New(
tablewriter.Col("ID"),
tablewriter.Col("Provider"),
tablewriter.Col("Data"),
tablewriter.Col("Size"),
tablewriter.Col("TermMin"),
tablewriter.Col("TermMax"),
tablewriter.Col("Expiration"),
)
for allocationId, allocation := range allocationsMap {
if ts.Height() > allocation.Expiration || !cctx.IsSet("expired") {
tw.Write(map[string]interface{}{
"ID": allocationId,
"Provider": allocation.Provider,
"Data": allocation.Data,
"Size": allocation.Size,
"TermMin": allocation.TermMin,
"TermMax": allocation.TermMax,
"Expiration": allocation.Expiration,
})
}
}
return tw.Flush(os.Stdout)
},
}
var filplusRemoveExpiredAllocationsCmd = &cli.Command{
Name: "remove-expired-allocations",
Usage: "remove expired allocations (if no allocations are specified all eligible allocations are removed)",
ArgsUsage: "clientAddress Optional[...allocationId]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
Usage: "optionally specify the account to send the message from",
},
},
Action: func(cctx *cli.Context) error {
if cctx.NArg() < 1 {
return IncorrectNumArgs(cctx)
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
args := cctx.Args().Slice()
clientAddr, err := address.NewFromString(args[0])
if err != nil {
return err
}
clientIdAddr, err := api.StateLookupID(ctx, clientAddr, types.EmptyTSK)
if err != nil {
return err
}
clientId, err := address.IDFromAddress(clientIdAddr)
if err != nil {
return err
}
fromAddr := clientIdAddr
if from := cctx.String("from"); from != "" {
addr, err := address.NewFromString(from)
if err != nil {
return err
}
fromAddr = addr
}
allocationIDs := make([]verifregtypes9.AllocationId, len(args)-1)
for i, allocationString := range args[1:] {
id, err := strconv.ParseUint(allocationString, 10, 64)
if err != nil {
return err
}
allocationIDs[i] = verifregtypes9.AllocationId(id)
}
params, err := actors.SerializeParams(&verifregtypes9.RemoveExpiredAllocationsParams{
Client: abi.ActorID(clientId),
AllocationIds: allocationIDs,
})
if err != nil {
return err
}
msg := &types.Message{
To: verifreg.Address,
From: fromAddr,
Method: verifreg.Methods.RemoveExpiredAllocations,
Params: params,
}
smsg, err := api.MpoolPushMessage(ctx, msg, nil)
if err != nil {
return err
}
fmt.Printf("message sent, now waiting on cid: %s\n", smsg.Cid())
mwait, err := api.StateWaitMsg(ctx, smsg.Cid(), build.MessageConfidence)
if err != nil {
return err
}
if mwait.Receipt.ExitCode.IsError() {
return fmt.Errorf("failed to remove expired allocations: %d", mwait.Receipt.ExitCode)
}
return nil
},
}
var filplusCheckClientCmd = &cli.Command{
Name: "check-client-datacap",
Usage: "check verified client remaining bytes",
ArgsUsage: "clientAddress",
Action: func(cctx *cli.Context) error {
if cctx.NArg() != 1 {
return fmt.Errorf("must specify client address to check")
}
@@ -223,10 +439,11 @@ var filplusCheckClientCmd = &cli.Command{
}
var filplusCheckNotaryCmd = &cli.Command{
Name: "check-notary-datacap",
Usage: "check a notary's remaining bytes",
Name: "check-notary-datacap",
Usage: "check a notary's remaining bytes",
ArgsUsage: "notaryAddress",
Action: func(cctx *cli.Context) error {
if !cctx.Args().Present() {
if cctx.NArg() != 1 {
return fmt.Errorf("must specify notary address to check")
}
@@ -279,8 +496,9 @@ func checkNotary(ctx context.Context, api v0api.FullNode, vaddr address.Address)
}
var filplusSignRemoveDataCapProposal = &cli.Command{
Name: "sign-remove-data-cap-proposal",
Usage: "allows a notary to sign a Remove Data Cap Proposal",
Name: "sign-remove-data-cap-proposal",
Usage: "allows a notary to sign a Remove Data Cap Proposal",
ArgsUsage: "[verifierAddress clientAddress allowanceToRemove]",
Flags: []cli.Flag{
&cli.Int64Flag{
Name: "id",
@@ -336,7 +554,7 @@ var filplusSignRemoveDataCapProposal = &cli.Command{
return err
}
_, dataCap, err := st.VerifiedClientDataCap(clientIdAddr)
dataCap, err := api.StateVerifiedClientStatus(ctx, clientIdAddr, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("failed to find verified client data cap: %w", err)
}
+1 -1
View File
@@ -341,7 +341,7 @@ var msigInspectCmd = &cli.Command{
paramStr = string(b)
}
fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), method.Num, tx.Method, paramStr)
fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), method.Name, tx.Method, paramStr)
}
}
if err := w.Flush(); err != nil {
+5 -4
View File
@@ -46,6 +46,7 @@ import (
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
cliutil "github.com/filecoin-project/lotus/cli/util"
)
var StateCmd = &cli.Command{
@@ -230,7 +231,7 @@ var StateMinerInfo = &cli.Command{
return xerrors.Errorf("getting miner info: %w", err)
}
fmt.Printf("Proving Period Start:\t%s\n", EpochTime(cd.CurrentEpoch, cd.PeriodStart))
fmt.Printf("Proving Period Start:\t%s\n", cliutil.EpochTime(cd.CurrentEpoch, cd.PeriodStart))
return nil
},
@@ -1407,7 +1408,7 @@ func codeStr(c cid.Cid) string {
}
func getMethod(code cid.Cid, method abi.MethodNum) string {
return filcns.NewActorRegistry().Methods[code][method].Num // todo: use remote
return filcns.NewActorRegistry().Methods[code][method].Name // todo: use remote
}
func toFil(f types.BigInt) types.FIL {
@@ -1816,8 +1817,8 @@ var StateSectorCmd = &cli.Command{
}
fmt.Println("DealIDs: ", si.DealIDs)
fmt.Println()
fmt.Println("Activation: ", EpochTimeTs(ts.Height(), si.Activation, ts))
fmt.Println("Expiration: ", EpochTimeTs(ts.Height(), si.Expiration, ts))
fmt.Println("Activation: ", cliutil.EpochTimeTs(ts.Height(), si.Activation, ts))
fmt.Println("Expiration: ", cliutil.EpochTimeTs(ts.Height(), si.Expiration, ts))
fmt.Println()
fmt.Println("DealWeight: ", si.DealWeight)
fmt.Println("VerifiedDealWeight: ", si.VerifiedDealWeight)
-39
View File
@@ -2,19 +2,13 @@ package cli
import (
"context"
"fmt"
"os"
"time"
"github.com/fatih/color"
"github.com/hako/durafmt"
"github.com/ipfs/go-cid"
"github.com/mattn/go-isatty"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
)
@@ -43,36 +37,3 @@ func parseTipSet(ctx context.Context, api v0api.FullNode, vals []string) (*types
return types.NewTipSet(headers)
}
func EpochTime(curr, e abi.ChainEpoch) string {
switch {
case curr > e:
return fmt.Sprintf("%d (%s ago)", e, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(curr-e))).LimitFirstN(2))
case curr == e:
return fmt.Sprintf("%d (now)", e)
case curr < e:
return fmt.Sprintf("%d (in %s)", e, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(e-curr))).LimitFirstN(2))
}
panic("math broke")
}
// EpochTimeTs is like EpochTime, but also outputs absolute time. `ts` is only
// used to provide a timestamp at some epoch to calculate time from. It can be
// a genesis tipset.
//
// Example output: `1944975 (01 Jul 22 08:07 CEST, 10 hours 29 minutes ago)`
func EpochTimeTs(curr, e abi.ChainEpoch, ts *types.TipSet) string {
timeStr := time.Unix(int64(ts.MinTimestamp()+(uint64(e-ts.Height())*build.BlockDelaySecs)), 0).Format(time.RFC822)
switch {
case curr > e:
return fmt.Sprintf("%d (%s, %s ago)", e, timeStr, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(curr-e))).LimitFirstN(2))
case curr == e:
return fmt.Sprintf("%d (%s, now)", e, timeStr)
case curr < e:
return fmt.Sprintf("%d (%s, in %s)", e, timeStr, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(e-curr))).LimitFirstN(2))
}
panic("math broke")
}
+46
View File
@@ -0,0 +1,46 @@
package cliutil
import (
"fmt"
"time"
"github.com/hako/durafmt"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
)
func EpochTime(curr, e abi.ChainEpoch) string {
switch {
case curr > e:
return fmt.Sprintf("%d (%s ago)", e, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(curr-e))).LimitFirstN(2))
case curr == e:
return fmt.Sprintf("%d (now)", e)
case curr < e:
return fmt.Sprintf("%d (in %s)", e, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(e-curr))).LimitFirstN(2))
}
panic("math broke")
}
// EpochTimeTs is like EpochTime, but also outputs absolute time. `ts` is only
// used to provide a timestamp at some epoch to calculate time from. It can be
// a genesis tipset.
//
// Example output: `1944975 (01 Jul 22 08:07 CEST, 10 hours 29 minutes ago)`
func EpochTimeTs(curr, e abi.ChainEpoch, ts *types.TipSet) string {
timeStr := time.Unix(int64(ts.MinTimestamp()+(uint64(e-ts.Height())*build.BlockDelaySecs)), 0).Format(time.RFC822)
switch {
case curr > e:
return fmt.Sprintf("%d (%s, %s ago)", e, timeStr, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(curr-e))).LimitFirstN(2))
case curr == e:
return fmt.Sprintf("%d (%s, now)", e, timeStr)
case curr < e:
return fmt.Sprintf("%d (%s, in %s)", e, timeStr, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(e-curr))).LimitFirstN(2))
}
panic("math broke")
}
+78
View File
@@ -0,0 +1,78 @@
package cliutil
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"path"
"github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api"
)
func ApiAddrToUrl(apiAddr string) (*url.URL, error) {
ma, err := multiaddr.NewMultiaddr(apiAddr)
if err == nil {
_, addr, err := manet.DialArgs(ma)
if err != nil {
return nil, err
}
// todo: make cliutil helpers for this
apiAddr = "http://" + addr
}
aa, err := url.Parse(apiAddr)
if err != nil {
return nil, xerrors.Errorf("parsing api address: %w", err)
}
switch aa.Scheme {
case "ws":
aa.Scheme = "http"
case "wss":
aa.Scheme = "https"
}
return aa, nil
}
func ClientExportStream(apiAddr string, apiAuth http.Header, eref api.ExportRef, car bool) (io.ReadCloser, error) {
rj, err := json.Marshal(eref)
if err != nil {
return nil, xerrors.Errorf("marshaling export ref: %w", err)
}
aa, err := ApiAddrToUrl(apiAddr)
if err != nil {
return nil, err
}
aa.Path = path.Join(aa.Path, "rest/v0/export")
req, err := http.NewRequest("GET", fmt.Sprintf("%s?car=%t&export=%s", aa, car, url.QueryEscape(string(rj))), nil)
if err != nil {
return nil, err
}
req.Header = apiAuth
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
em, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, xerrors.Errorf("reading error body: %w", err)
}
resp.Body.Close() // nolint
return nil, xerrors.Errorf("getting root car: http %d: %s", resp.StatusCode, string(em))
}
return resp.Body, nil
}