diff --git a/api/api_wallet.go b/api/api_wallet.go index 891b2fabb..973aaaf6d 100644 --- a/api/api_wallet.go +++ b/api/api_wallet.go @@ -35,13 +35,13 @@ type MsgMeta struct { } type Wallet interface { - WalletNew(context.Context, types.KeyType) (address.Address, error) - WalletHas(context.Context, address.Address) (bool, error) - WalletList(context.Context) ([]address.Address, error) + WalletNew(context.Context, types.KeyType) (address.Address, error) //perm:admin + WalletHas(context.Context, address.Address) (bool, error) //perm:admin + WalletList(context.Context) ([]address.Address, error) //perm:admin - WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta MsgMeta) (*crypto.Signature, error) + WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta MsgMeta) (*crypto.Signature, error) //perm:admin - WalletExport(context.Context, address.Address) (*types.KeyInfo, error) - WalletImport(context.Context, *types.KeyInfo) (address.Address, error) - WalletDelete(context.Context, address.Address) error + WalletExport(context.Context, address.Address) (*types.KeyInfo, error) //perm:admin + WalletImport(context.Context, *types.KeyInfo) (address.Address, error) //perm:admin + WalletDelete(context.Context, address.Address) error //perm:admin } diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 4c40afc33..ff4af8043 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -739,19 +739,19 @@ type StorageMinerStub struct { type WalletStruct struct { Internal struct { - WalletDelete func(p0 context.Context, p1 address.Address) error `` + WalletDelete func(p0 context.Context, p1 address.Address) error `perm:"admin"` - WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `` + WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `perm:"admin"` - WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `` + WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `perm:"admin"` - WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `` + WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `perm:"admin"` - WalletList func(p0 context.Context) ([]address.Address, error) `` + WalletList func(p0 context.Context) ([]address.Address, error) `perm:"admin"` - WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `` + WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"admin"` - WalletSign func(p0 context.Context, p1 address.Address, p2 []byte, p3 MsgMeta) (*crypto.Signature, error) `` + WalletSign func(p0 context.Context, p1 address.Address, p2 []byte, p3 MsgMeta) (*crypto.Signature, error) `perm:"admin"` } } diff --git a/api/test/deals.go b/api/test/deals.go index e3432ff0d..aa7e23bcc 100644 --- a/api/test/deals.go +++ b/api/test/deals.go @@ -8,6 +8,7 @@ import ( "math/rand" "os" "path/filepath" + "sort" "testing" "time" @@ -18,6 +19,7 @@ import ( "github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin/market" @@ -51,7 +53,7 @@ func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, sta } func MakeDeal(t *testing.T, ctx context.Context, rseed int, client api.FullNode, miner TestStorageNode, carExport, fastRet bool, startEpoch abi.ChainEpoch) { - res, data, err := CreateClientFile(ctx, client, rseed) + res, data, err := CreateClientFile(ctx, client, rseed, 0) if err != nil { t.Fatal(err) } @@ -63,7 +65,7 @@ func MakeDeal(t *testing.T, ctx context.Context, rseed int, client api.FullNode, // TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this time.Sleep(time.Second) - waitDealSealed(t, ctx, miner, client, deal, false) + waitDealSealed(t, ctx, miner, client, deal, false, false, nil) // Retrieval info, err := client.ClientGetDealInfo(ctx, *deal) @@ -72,8 +74,11 @@ func MakeDeal(t *testing.T, ctx context.Context, rseed int, client api.FullNode, testRetrieval(t, ctx, client, fcid, &info.PieceCID, carExport, data) } -func CreateClientFile(ctx context.Context, client api.FullNode, rseed int) (*api.ImportRes, []byte, error) { - data := make([]byte, 1600) +func CreateClientFile(ctx context.Context, client api.FullNode, rseed, size int) (*api.ImportRes, []byte, error) { + if size == 0 { + size = 1600 + } + data := make([]byte, size) rand.New(rand.NewSource(int64(rseed))).Read(data) dir, err := ioutil.TempDir(os.TempDir(), "test-make-deal-") @@ -119,7 +124,7 @@ func TestPublishDealsBatching(t *testing.T, b APIBuilder, blocktime time.Duratio // Starts a deal and waits until it's published runDealTillPublish := func(rseed int) { - res, _, err := CreateClientFile(s.ctx, s.client, rseed) + res, _, err := CreateClientFile(s.ctx, s.client, rseed, 0) require.NoError(t, err) upds, err := client.ClientGetDealUpdates(s.ctx) @@ -186,68 +191,109 @@ func TestPublishDealsBatching(t *testing.T, b APIBuilder, blocktime time.Duratio } func TestBatchDealInput(t *testing.T, b APIBuilder, blocktime time.Duration, startEpoch abi.ChainEpoch) { - publishPeriod := 10 * time.Second - maxDealsPerMsg := uint64(4) + run := func(piece, deals, expectSectors int) func(t *testing.T) { + return func(t *testing.T) { + publishPeriod := 10 * time.Second + maxDealsPerMsg := uint64(deals) - // Set max deals per publish deals message to maxDealsPerMsg - minerDef := []StorageMiner{{ - Full: 0, - Opts: node.Options( - node.Override( - new(*storageadapter.DealPublisher), - storageadapter.NewDealPublisher(nil, storageadapter.PublishMsgConfig{ - Period: publishPeriod, - MaxDealsPerMsg: maxDealsPerMsg, - })), - node.Override(new(dtypes.GetSealingConfigFunc), func() (dtypes.GetSealingConfigFunc, error) { - return func() (sealiface.Config, error) { - return sealiface.Config{ - MaxWaitDealsSectors: 1, - MaxSealingSectors: 1, - MaxSealingSectorsForDeals: 2, - AlwaysKeepUnsealedCopy: true, - }, nil - }, nil - }), - ), - Preseal: PresealGenesis, - }} + // Set max deals per publish deals message to maxDealsPerMsg + minerDef := []StorageMiner{{ + Full: 0, + Opts: node.Options( + node.Override( + new(*storageadapter.DealPublisher), + storageadapter.NewDealPublisher(nil, storageadapter.PublishMsgConfig{ + Period: publishPeriod, + MaxDealsPerMsg: maxDealsPerMsg, + })), + node.Override(new(dtypes.GetSealingConfigFunc), func() (dtypes.GetSealingConfigFunc, error) { + return func() (sealiface.Config, error) { + return sealiface.Config{ + MaxWaitDealsSectors: 2, + MaxSealingSectors: 1, + MaxSealingSectorsForDeals: 3, + AlwaysKeepUnsealedCopy: true, + WaitDealsDelay: time.Hour, + }, nil + }, nil + }), + ), + Preseal: PresealGenesis, + }} - // Create a connect client and miner node - n, sn := b(t, OneFull, minerDef) - client := n[0].FullNode.(*impl.FullNodeAPI) - miner := sn[0] - s := connectAndStartMining(t, b, blocktime, client, miner) - defer s.blockMiner.Stop() + // Create a connect client and miner node + n, sn := b(t, OneFull, minerDef) + client := n[0].FullNode.(*impl.FullNodeAPI) + miner := sn[0] + s := connectAndStartMining(t, b, blocktime, client, miner) + defer s.blockMiner.Stop() - // Starts a deal and waits until it's published - runDealTillSeal := func(rseed int) { - res, _, err := CreateClientFile(s.ctx, s.client, rseed) - require.NoError(t, err) + err := miner.MarketSetAsk(s.ctx, big.Zero(), big.Zero(), 200, 128, 32<<30) + require.NoError(t, err) - dc := startDeal(t, s.ctx, s.miner, s.client, res.Root, false, startEpoch) - waitDealSealed(t, s.ctx, s.miner, s.client, dc, false) + checkNoPadding := func() { + sl, err := sn[0].SectorsList(s.ctx) + require.NoError(t, err) + + sort.Slice(sl, func(i, j int) bool { + return sl[i] < sl[j] + }) + + for _, snum := range sl { + si, err := sn[0].SectorsStatus(s.ctx, snum, false) + require.NoError(t, err) + + // fmt.Printf("S %d: %+v %s\n", snum, si.Deals, si.State) + + for _, deal := range si.Deals { + if deal == 0 { + fmt.Printf("sector %d had a padding piece!\n", snum) + } + } + } + } + + // Starts a deal and waits until it's published + runDealTillSeal := func(rseed int) { + res, _, err := CreateClientFile(s.ctx, s.client, rseed, piece) + require.NoError(t, err) + + dc := startDeal(t, s.ctx, s.miner, s.client, res.Root, false, startEpoch) + waitDealSealed(t, s.ctx, s.miner, s.client, dc, false, true, checkNoPadding) + } + + // Run maxDealsPerMsg deals in parallel + done := make(chan struct{}, maxDealsPerMsg) + for rseed := 0; rseed < int(maxDealsPerMsg); rseed++ { + rseed := rseed + go func() { + runDealTillSeal(rseed) + done <- struct{}{} + }() + } + + // Wait for maxDealsPerMsg of the deals to be published + for i := 0; i < int(maxDealsPerMsg); i++ { + <-done + } + + checkNoPadding() + + sl, err := sn[0].SectorsList(s.ctx) + require.NoError(t, err) + require.Equal(t, len(sl), expectSectors) + } } - // Run maxDealsPerMsg+1 deals in parallel - done := make(chan struct{}, maxDealsPerMsg+1) - for rseed := 1; rseed <= int(maxDealsPerMsg+1); rseed++ { - rseed := rseed - go func() { - runDealTillSeal(rseed) - done <- struct{}{} - }() - } + t.Run("4-p1600B", run(1600, 4, 4)) + t.Run("4-p513B", run(513, 4, 2)) + if !testing.Short() { + t.Run("32-p257B", run(257, 32, 8)) + t.Run("32-p10B", run(10, 32, 2)) - // Wait for maxDealsPerMsg of the deals to be published - for i := 0; i < int(maxDealsPerMsg); i++ { - <-done + // fixme: this appears to break data-transfer / markets in some really creative ways + //t.Run("128-p10B", run(10, 128, 8)) } - - sl, err := sn[0].SectorsList(s.ctx) - require.NoError(t, err) - require.GreaterOrEqual(t, len(sl), 4) - require.LessOrEqual(t, len(sl), 5) } func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, startEpoch abi.ChainEpoch) { @@ -303,12 +349,12 @@ func TestSecondDealRetrieval(t *testing.T, b APIBuilder, blocktime time.Duration // TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this time.Sleep(time.Second) - waitDealSealed(t, s.ctx, s.miner, s.client, deal1, true) + waitDealSealed(t, s.ctx, s.miner, s.client, deal1, true, false, nil) deal2 := startDeal(t, s.ctx, s.miner, s.client, fcid2, true, 0) time.Sleep(time.Second) - waitDealSealed(t, s.ctx, s.miner, s.client, deal2, false) + waitDealSealed(t, s.ctx, s.miner, s.client, deal2, false, false, nil) // Retrieval info, err := s.client.ClientGetDealInfo(s.ctx, *deal2) @@ -364,7 +410,7 @@ func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client return deal } -func waitDealSealed(t *testing.T, ctx context.Context, miner TestStorageNode, client api.FullNode, deal *cid.Cid, noseal bool) { +func waitDealSealed(t *testing.T, ctx context.Context, miner TestStorageNode, client api.FullNode, deal *cid.Cid, noseal, noSealStart bool, cb func()) { loop: for { di, err := client.ClientGetDealInfo(ctx, *deal) @@ -376,7 +422,9 @@ loop: if noseal { return } - startSealingWaiting(t, ctx, miner) + if !noSealStart { + startSealingWaiting(t, ctx, miner) + } case storagemarket.StorageDealProposalRejected: t.Fatal("deal rejected") case storagemarket.StorageDealFailing: @@ -387,8 +435,25 @@ loop: fmt.Println("COMPLETE", di) break loop } - fmt.Println("Deal state: ", storagemarket.DealStates[di.State]) + + mds, err := miner.MarketListIncompleteDeals(ctx) + if err != nil { + t.Fatal(err) + } + + var minerState storagemarket.StorageDealStatus + for _, md := range mds { + if md.DealID == di.DealID { + minerState = md.State + break + } + } + + fmt.Printf("Deal %d state: client:%s provider:%s\n", di.DealID, storagemarket.DealStates[di.State], storagemarket.DealStates[minerState]) time.Sleep(time.Second / 2) + if cb != nil { + cb() + } } } @@ -430,7 +495,7 @@ func startSealingWaiting(t *testing.T, ctx context.Context, miner TestStorageNod si, err := miner.SectorsStatus(ctx, snum, false) require.NoError(t, err) - t.Logf("Sector state: %s", si.State) + t.Logf("Sector %d state: %s", snum, si.State) if si.State == api.SectorState(sealing.WaitDeals) { require.NoError(t, miner.SectorStartSealing(ctx, snum)) } diff --git a/api/test/mining.go b/api/test/mining.go index 4a4f1e1a4..d6dea9abf 100644 --- a/api/test/mining.go +++ b/api/test/mining.go @@ -194,7 +194,7 @@ func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExpo // TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this time.Sleep(time.Second) - waitDealSealed(t, ctx, provider, client, deal, false) + waitDealSealed(t, ctx, provider, client, deal, false, false, nil) <-minedTwo diff --git a/chain/events/events_called.go b/chain/events/events_called.go index 1a619c195..2fe6853eb 100644 --- a/chain/events/events_called.go +++ b/chain/events/events_called.go @@ -144,8 +144,10 @@ func (e *hcEvents) processHeadChangeEvent(rev, app []*types.TipSet) error { // Queue up calls until there have been enough blocks to reach // confidence on the message calls - for tid, data := range newCalls { - e.queueForConfidence(tid, data, nil, ts) + for tid, calls := range newCalls { + for _, data := range calls { + e.queueForConfidence(tid, data, nil, ts) + } } for at := e.lastTs.Height(); at <= ts.Height(); at++ { @@ -474,7 +476,7 @@ func newMessageEvents(ctx context.Context, hcAPI headChangeAPI, cs EventAPI) mes } // Check if there are any new actor calls -func (me *messageEvents) checkNewCalls(ts *types.TipSet) (map[triggerID]eventData, error) { +func (me *messageEvents) checkNewCalls(ts *types.TipSet) (map[triggerID][]eventData, error) { pts, err := me.cs.ChainGetTipSet(me.ctx, ts.Parents()) // we actually care about messages in the parent tipset here if err != nil { log.Errorf("getting parent tipset in checkNewCalls: %s", err) @@ -485,7 +487,7 @@ func (me *messageEvents) checkNewCalls(ts *types.TipSet) (map[triggerID]eventDat defer me.lk.RUnlock() // For each message in the tipset - res := make(map[triggerID]eventData) + res := make(map[triggerID][]eventData) me.messagesForTs(pts, func(msg *types.Message) { // TODO: provide receipts @@ -500,7 +502,7 @@ func (me *messageEvents) checkNewCalls(ts *types.TipSet) (map[triggerID]eventDat // If there was a match, include the message in the results for the // trigger if matched { - res[tid] = msg + res[tid] = append(res[tid], msg) } } }) diff --git a/chain/events/events_test.go b/chain/events/events_test.go index 0aab626dd..e18d5ba7c 100644 --- a/chain/events/events_test.go +++ b/chain/events/events_test.go @@ -1323,3 +1323,62 @@ func TestStateChangedTimeout(t *testing.T) { fcs.advance(0, 5, nil) require.False(t, called) } + +func TestCalledMultiplePerEpoch(t *testing.T) { + fcs := &fakeCS{ + t: t, + h: 1, + + msgs: map[cid.Cid]fakeMsg{}, + blkMsgs: map[cid.Cid]cid.Cid{}, + tsc: newTSCache(2*build.ForkLengthThreshold, nil), + } + require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) + + events := NewEvents(context.Background(), fcs) + + t0123, err := address.NewFromString("t0123") + require.NoError(t, err) + + at := 0 + + err = events.Called(func(ts *types.TipSet) (d bool, m bool, e error) { + return false, true, nil + }, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (bool, error) { + switch at { + case 0: + require.Equal(t, uint64(1), msg.Nonce) + require.Equal(t, abi.ChainEpoch(4), ts.Height()) + case 1: + require.Equal(t, uint64(2), msg.Nonce) + require.Equal(t, abi.ChainEpoch(4), ts.Height()) + default: + t.Fatal("apply should only get called twice, at: ", at) + } + at++ + return true, nil + }, func(_ context.Context, ts *types.TipSet) error { + switch at { + case 2: + require.Equal(t, abi.ChainEpoch(4), ts.Height()) + case 3: + require.Equal(t, abi.ChainEpoch(4), ts.Height()) + default: + t.Fatal("revert should only get called twice, at: ", at) + } + at++ + return nil + }, 3, 20, matchAddrMethod(t0123, 5)) + require.NoError(t, err) + + fcs.advance(0, 10, map[int]cid.Cid{ + 1: fcs.fakeMsgs(fakeMsg{ + bmsgs: []*types.Message{ + {To: t0123, From: t0123, Method: 5, Nonce: 1}, + {To: t0123, From: t0123, Method: 5, Nonce: 2}, + }, + }), + }) + + fcs.advance(9, 1, nil) +} diff --git a/cli/state.go b/cli/state.go index 63e923485..6c3c4b111 100644 --- a/cli/state.go +++ b/cli/state.go @@ -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 (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", diff --git a/cli/test/client.go b/cli/test/client.go index 4a49f732a..2a48b7b64 100644 --- a/cli/test/client.go +++ b/cli/test/client.go @@ -44,7 +44,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) // Create a deal (non-interactive) // client deal --start-epoch= 1000000attofil - res, _, err := test.CreateClientFile(ctx, clientNode, 1) + res, _, err := test.CreateClientFile(ctx, clientNode, 1, 0) require.NoError(t, err) startEpoch := fmt.Sprintf("--start-epoch=%d", 2<<12) dataCid := res.Root @@ -60,7 +60,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) // // "no" (verified client) // "yes" (confirm deal) - res, _, err = test.CreateClientFile(ctx, clientNode, 2) + res, _, err = test.CreateClientFile(ctx, clientNode, 2, 0) require.NoError(t, err) dataCid2 := res.Root duration = fmt.Sprintf("%d", build.MinDealDuration/builtin.EpochsInDay) diff --git a/cmd/lotus-wallet/main.go b/cmd/lotus-wallet/main.go index 2c86c6180..3e3aa1a58 100644 --- a/cmd/lotus-wallet/main.go +++ b/cmd/lotus-wallet/main.go @@ -2,27 +2,33 @@ package main import ( "context" + "fmt" "net" "net/http" "os" "github.com/filecoin-project/lotus/api/v0api" + "github.com/gbrlsnchs/jwt/v3" "github.com/gorilla/mux" logging "github.com/ipfs/go-log/v2" "github.com/urfave/cli/v2" "go.opencensus.io/stats/view" "go.opencensus.io/tag" + "golang.org/x/xerrors" "github.com/filecoin-project/go-jsonrpc" + "github.com/filecoin-project/go-jsonrpc/auth" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/lib/lotuslog" "github.com/filecoin-project/lotus/metrics" + "github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/repo" ) @@ -30,17 +36,33 @@ var log = logging.Logger("main") const FlagWalletRepo = "wallet-repo" +type jwtPayload struct { + Allow []auth.Permission +} + func main() { lotuslog.SetupLogLevels() local := []*cli.Command{ runCmd, + getApiKeyCmd, } app := &cli.App{ Name: "lotus-wallet", Usage: "Basic external wallet", Version: build.UserVersion(), + Description: ` +lotus-wallet provides a remote wallet service for lotus. + +To configure your lotus node to use a remote wallet: +* Run 'lotus-wallet get-api-key' to generate API key +* Start lotus-wallet using 'lotus-wallet run' (see --help for additional flags) +* Edit lotus config (~/.lotus/config.toml) + * Find the '[Wallet]' section + * Set 'RemoteBackend' to '[api key]:http://[wallet ip]:[wallet port]' + (the default port is 1777) +* Start (or restart) the lotus daemon`, Flags: []cli.Flag{ &cli.StringFlag{ Name: FlagWalletRepo, @@ -65,6 +87,35 @@ func main() { } } +var getApiKeyCmd = &cli.Command{ + Name: "get-api-key", + Usage: "Generate API Key", + Action: func(cctx *cli.Context) error { + lr, ks, err := openRepo(cctx) + if err != nil { + return err + } + defer lr.Close() // nolint + + p := jwtPayload{ + Allow: []auth.Permission{api.PermAdmin}, + } + + authKey, err := modules.APISecret(ks, lr) + if err != nil { + return xerrors.Errorf("setting up api secret: %w", err) + } + + k, err := jwt.Sign(&p, (*jwt.HMACSHA)(authKey)) + if err != nil { + return xerrors.Errorf("jwt sign: %w", err) + } + + fmt.Println(string(k)) + return nil + }, +} + var runCmd = &cli.Command{ Name: "run", Usage: "Start lotus wallet", @@ -86,7 +137,13 @@ var runCmd = &cli.Command{ Name: "offline", Usage: "don't query chain state in interactive mode", }, + &cli.BoolFlag{ + Name: "disable-auth", + Usage: "(insecure) disable api auth", + Hidden: true, + }, }, + Description: "For setup instructions see 'lotus-wallet --help'", Action: func(cctx *cli.Context) error { log.Info("Starting lotus wallet") @@ -101,31 +158,11 @@ var runCmd = &cli.Command{ log.Fatalf("Cannot register the view: %v", err) } - repoPath := cctx.String(FlagWalletRepo) - r, err := repo.NewFS(repoPath) - if err != nil { - return err - } - - ok, err := r.Exists() - if err != nil { - return err - } - if !ok { - if err := r.Init(repo.Worker); err != nil { - return err - } - } - - lr, err := r.Lock(repo.Wallet) - if err != nil { - return err - } - - ks, err := lr.KeyStore() + lr, ks, err := openRepo(cctx) if err != nil { return err } + defer lr.Close() // nolint lw, err := wallet.NewWallet(ks) if err != nil { @@ -167,19 +204,43 @@ var runCmd = &cli.Command{ w = &LoggedWallet{under: w} } + rpcApi := metrics.MetricedWalletAPI(w) + if !cctx.Bool("disable-auth") { + rpcApi = api.PermissionedWalletAPI(rpcApi) + } + rpcServer := jsonrpc.NewServer() - rpcServer.Register("Filecoin", metrics.MetricedWalletAPI(w)) + rpcServer.Register("Filecoin", rpcApi) mux.Handle("/rpc/v0", rpcServer) mux.PathPrefix("/").Handler(http.DefaultServeMux) // pprof - /*ah := &auth.Handler{ - Verify: nodeApi.AuthVerify, - Next: mux.ServeHTTP, - }*/ + var handler http.Handler = mux + + if !cctx.Bool("disable-auth") { + authKey, err := modules.APISecret(ks, lr) + if err != nil { + return xerrors.Errorf("setting up api secret: %w", err) + } + + authVerify := func(ctx context.Context, token string) ([]auth.Permission, error) { + var payload jwtPayload + if _, err := jwt.Verify([]byte(token), (*jwt.HMACSHA)(authKey), &payload); err != nil { + return nil, xerrors.Errorf("JWT Verification failed: %w", err) + } + + return payload.Allow, nil + } + + log.Info("API auth enabled, use 'lotus-wallet get-api-key' to get API key") + handler = &auth.Handler{ + Verify: authVerify, + Next: mux.ServeHTTP, + } + } srv := &http.Server{ - Handler: mux, + Handler: handler, BaseContext: func(listener net.Listener) context.Context { ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-wallet")) return ctx @@ -203,3 +264,33 @@ var runCmd = &cli.Command{ return srv.Serve(nl) }, } + +func openRepo(cctx *cli.Context) (repo.LockedRepo, types.KeyStore, error) { + repoPath := cctx.String(FlagWalletRepo) + r, err := repo.NewFS(repoPath) + if err != nil { + return nil, nil, err + } + + ok, err := r.Exists() + if err != nil { + return nil, nil, err + } + if !ok { + if err := r.Init(repo.Worker); err != nil { + return nil, nil, err + } + } + + lr, err := r.Lock(repo.Wallet) + if err != nil { + return nil, nil, err + } + + ks, err := lr.KeyStore() + if err != nil { + return nil, nil, err + } + + return lr, ks, nil +} diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index f9eb3aac1..8e7e45f51 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -1756,13 +1756,14 @@ NAME: lotus state call - Invoke a method on an actor locally USAGE: - lotus state call [command options] [toAddress methodId (optional)] + lotus state call [command options] [toAddress methodId params (optional)] OPTIONS: - --from value (default: "f00") - --value value specify value field for invocation (default: "0") - --ret value specify how to parse output (auto, raw, addr, big) (default: "auto") - --help, -h show help (default: false) + --from value (default: "f00") + --value value specify value field for invocation (default: "0") + --ret value specify how to parse output (raw, decoded, base64, hex) (default: "decoded") + --encoding value specify params encoding to parse (base64, hex) (default: "base64") + --help, -h show help (default: false) ``` diff --git a/documentation/misc/RELEASE_ISSUE_TEMPLATE.md b/documentation/misc/RELEASE_ISSUE_TEMPLATE.md index 859da43e0..0dc6cca3d 100644 --- a/documentation/misc/RELEASE_ISSUE_TEMPLATE.md +++ b/documentation/misc/RELEASE_ISSUE_TEMPLATE.md @@ -20,6 +20,8 @@ We're happy to announce Lotus X.Y.Z... ## ✅ Release Checklist +**Note for whomever is owning the release:** please capture notes as comments in this issue for anything you noticed that could be improved for future releases. There is a *Post Release* step below for incorporating changes back into the [RELEASE_ISSUE_TEMPLATE](https://github.com/filecoin-project/lotus/blob/master/documentation/misc/RELEASE_ISSUE_TEMPLATE.md), and this is easier done by collecting notes from along the way rather than just thinking about it at the end. + First steps: - [ ] Fork a new branch (`release/vX.Y.Z`) from `master` and make any further release related changes to this branch. If any "non-trivial" changes get added to the release, uncheck all the checkboxes and return to this stage. @@ -40,6 +42,9 @@ Testing an RC: - [ ] Testground tests - [ ] **Stage 1 - Internal Testing** + - Binaries + - [ ] Ensure the RC release has downloadable binaries + - [ ] Validate the binary is able to run on at least one platform - Upgrade our testnet infra - [ ] 1 bootstrap node - [ ] 1 miner @@ -100,7 +105,8 @@ Testing an RC: - [ ] **Post-Release** - [ ] Merge the `releases` branch back into `master`, ignoring the changes to `version.go` (keep the `-dev` version from master). - - [ ] Create an issue using this release issue template for the _next_ release. + - [ ] Update [RELEASE_ISSUE_TEMPLATE.md](https://github.com/filecoin-project/lotus/blob/master/documentation/misc/RELEASE_ISSUE_TEMPLATE.md) with any improvements determined from this latest release iteration. + - [ ] Create an issue using [RELEASE_ISSUE_TEMPLATE.md](https://github.com/filecoin-project/lotus/blob/master/documentation/misc/RELEASE_ISSUE_TEMPLATE.md) for the _next_ release. ## ❤️ Contributors diff --git a/extern/storage-sealing/fsm.go b/extern/storage-sealing/fsm.go index 3702ca063..640aaf19a 100644 --- a/extern/storage-sealing/fsm.go +++ b/extern/storage-sealing/fsm.go @@ -51,6 +51,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto AddPiece: planOne( on(SectorPieceAdded{}, WaitDeals), apply(SectorStartPacking{}), + apply(SectorAddPiece{}), on(SectorAddPieceFailed{}, AddPieceFailed), ), Packing: planOne(on(SectorPacked{}, GetTicket)), @@ -217,6 +218,8 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto func (m *Sealing) logEvents(events []statemachine.Event, state *SectorInfo) { for _, event := range events { + log.Debugw("sector event", "sector", state.SectorNumber, "type", fmt.Sprintf("%T", event.User), "event", event.User) + e, err := json.Marshal(event) if err != nil { log.Errorf("marshaling event for logging: %+v", err) @@ -227,6 +230,10 @@ func (m *Sealing) logEvents(events []statemachine.Event, state *SectorInfo) { continue // don't log on every fsm restart } + if len(e) > 8000 { + e = []byte(string(e[:8000]) + "... truncated") + } + l := Log{ Timestamp: uint64(time.Now().Unix()), Message: string(e), @@ -566,6 +573,7 @@ func onReturning(mut mutator) func() (mutator, func(*SectorInfo) (bool, error)) func planOne(ts ...func() (mut mutator, next func(*SectorInfo) (more bool, err error))) func(events []statemachine.Event, state *SectorInfo) (uint64, error) { return func(events []statemachine.Event, state *SectorInfo) (uint64, error) { + eloop: for i, event := range events { if gm, ok := event.User.(globalMutator); ok { gm.applyGlobal(state) @@ -588,6 +596,8 @@ func planOne(ts ...func() (mut mutator, next func(*SectorInfo) (more bool, err e if err != nil || !more { return uint64(i + 1), err } + + continue eloop } _, ok := event.User.(Ignorable) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index 44d2e8275..bf66382d3 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -27,6 +27,18 @@ func (m *Sealing) handleWaitDeals(ctx statemachine.Context, sector SectorInfo) e m.inputLk.Lock() + if m.creating != nil && *m.creating == sector.SectorNumber { + m.creating = nil + } + + sid := m.minerSectorID(sector.SectorNumber) + + if len(m.assignedPieces[sid]) > 0 { + m.inputLk.Unlock() + // got assigned more pieces in the AddPiece state + return ctx.Send(SectorAddPiece{}) + } + started, err := m.maybeStartSealing(ctx, sector, used) if err != nil || started { delete(m.openSectors, m.minerSectorID(sector.SectorNumber)) @@ -36,16 +48,16 @@ func (m *Sealing) handleWaitDeals(ctx statemachine.Context, sector SectorInfo) e return err } - m.openSectors[m.minerSectorID(sector.SectorNumber)] = &openSector{ - used: used, - maybeAccept: func(cid cid.Cid) error { - // todo check deal start deadline (configurable) + if _, has := m.openSectors[sid]; !has { + m.openSectors[sid] = &openSector{ + used: used, + maybeAccept: func(cid cid.Cid) error { + // todo check deal start deadline (configurable) + m.assignedPieces[sid] = append(m.assignedPieces[sid], cid) - sid := m.minerSectorID(sector.SectorNumber) - m.assignedPieces[sid] = append(m.assignedPieces[sid], cid) - - return ctx.Send(SectorAddPiece{}) - }, + return ctx.Send(SectorAddPiece{}) + }, + } } go func() { @@ -350,11 +362,19 @@ func (m *Sealing) updateInput(ctx context.Context, sp abi.RegisteredSealProof) e continue } + avail := abi.PaddedPieceSize(ssize).Unpadded() - m.openSectors[mt.sector].used + + if mt.size > avail { + continue + } + err := m.openSectors[mt.sector].maybeAccept(mt.deal) if err != nil { m.pendingPieces[mt.deal].accepted(mt.sector.Number, 0, err) // non-error case in handleAddPiece } + m.openSectors[mt.sector].used += mt.padding + mt.size + m.pendingPieces[mt.deal].assigned = true delete(toAssign, mt.deal) @@ -362,8 +382,6 @@ func (m *Sealing) updateInput(ctx context.Context, sp abi.RegisteredSealProof) e log.Errorf("sector %d rejected deal %s: %+v", mt.sector, mt.deal, err) continue } - - delete(m.openSectors, mt.sector) } if len(toAssign) > 0 { @@ -376,6 +394,10 @@ func (m *Sealing) updateInput(ctx context.Context, sp abi.RegisteredSealProof) e } func (m *Sealing) tryCreateDealSector(ctx context.Context, sp abi.RegisteredSealProof) error { + if m.creating != nil { + return nil // new sector is being created right now + } + cfg, err := m.getConfig() if err != nil { return xerrors.Errorf("getting storage config: %w", err) @@ -394,6 +416,8 @@ func (m *Sealing) tryCreateDealSector(ctx context.Context, sp abi.RegisteredSeal return err } + m.creating = &sid + log.Infow("Creating sector", "number", sid, "type", "deal", "proofType", sp) return m.sectors.Send(uint64(sid), SectorStart{ ID: sid, @@ -422,6 +446,7 @@ func (m *Sealing) createSector(ctx context.Context, cfg sealiface.Config, sp abi } func (m *Sealing) StartPacking(sid abi.SectorNumber) error { + log.Infow("starting to seal deal sector", "sector", sid, "trigger", "user") return m.sectors.Send(uint64(sid), SectorStartPacking{}) } diff --git a/extern/storage-sealing/sealing.go b/extern/storage-sealing/sealing.go index fc452cc6f..eb2d30f82 100644 --- a/extern/storage-sealing/sealing.go +++ b/extern/storage-sealing/sealing.go @@ -93,6 +93,7 @@ type Sealing struct { sectorTimers map[abi.SectorID]*time.Timer pendingPieces map[cid.Cid]*pendingPiece assignedPieces map[abi.SectorID][]cid.Cid + creating *abi.SectorNumber // used to prevent a race where we could create a new sector more than once upgradeLk sync.Mutex toUpgrade map[abi.SectorNumber]struct{} diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index 9d61fd72d..01c0bc644 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -37,7 +37,7 @@ func (m *Sealing) handlePacking(ctx statemachine.Context, sector SectorInfo) err } // todo: return to the sealing queue (this is extremely unlikely to happen) - pp.accepted(sector.SectorNumber, 0, xerrors.Errorf("sector entered packing state early")) + pp.accepted(sector.SectorNumber, 0, xerrors.Errorf("sector %d entered packing state early", sector.SectorNumber)) } delete(m.openSectors, m.minerSectorID(sector.SectorNumber)) diff --git a/miner/miner.go b/miner/miner.go index 62bec5b55..ee7d40c4f 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -419,7 +419,7 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) // 1. func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *types.BlockMsg, err error) { log.Debugw("attempting to mine a block", "tipset", types.LogCids(base.TipSet.Cids())) - start := build.Clock.Now() + tStart := build.Clock.Now() round := base.TipSet.Height() + base.NullRounds + 1 @@ -428,6 +428,9 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *type var mbi *api.MiningBaseInfo var rbase types.BeaconEntry defer func() { + + var hasMinPower bool + // mbi can be nil if we are deep in penalty and there are 0 eligible sectors // in the current deadline. If this case - put together a dummy one for reporting // https://github.com/filecoin-project/lotus/blob/v1.9.0/chain/stmgr/utils.go#L500-L502 @@ -435,17 +438,24 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *type mbi = &api.MiningBaseInfo{ NetworkPower: big.NewInt(-1), // we do not know how big the network is at this point EligibleForMining: false, - MinerPower: big.NewInt(0), // but we do know we do not have anything + MinerPower: big.NewInt(0), // but we do know we do not have anything eligible + } + + // try to opportunistically pull actual power and plug it into the fake mbi + if pow, err := m.api.StateMinerPower(ctx, m.address, base.TipSet.Key()); err == nil && pow != nil { + hasMinPower = pow.HasMinPower + mbi.MinerPower = pow.MinerPower.QualityAdjPower + mbi.NetworkPower = pow.TotalPower.QualityAdjPower } } - isLate := uint64(start.Unix()) > (base.TipSet.MinTimestamp() + uint64(base.NullRounds*builtin.EpochDurationSeconds) + build.PropagationDelaySecs) + isLate := uint64(tStart.Unix()) > (base.TipSet.MinTimestamp() + uint64(base.NullRounds*builtin.EpochDurationSeconds) + build.PropagationDelaySecs) logStruct := []interface{}{ - "tookMilliseconds", (build.Clock.Now().UnixNano() - start.UnixNano()) / 1_000_000, + "tookMilliseconds", (build.Clock.Now().UnixNano() - tStart.UnixNano()) / 1_000_000, "forRound", int64(round), "baseEpoch", int64(base.TipSet.Height()), - "baseDeltaSeconds", uint64(start.Unix()) - base.TipSet.MinTimestamp(), + "baseDeltaSeconds", uint64(tStart.Unix()) - base.TipSet.MinTimestamp(), "nullRounds", int64(base.NullRounds), "lateStart", isLate, "beaconEpoch", rbase.Round, @@ -459,7 +469,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *type if err != nil { log.Errorw("completed mineOne", logStruct...) - } else if isLate { + } else if isLate || (hasMinPower && !mbi.EligibleForMining) { log.Warnw("completed mineOne", logStruct...) } else { log.Infow("completed mineOne", logStruct...) @@ -480,16 +490,10 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *type return nil, nil } - tMBI := build.Clock.Now() - - beaconPrev := mbi.PrevBeaconEntry - - tDrand := build.Clock.Now() - bvals := mbi.BeaconEntries - tPowercheck := build.Clock.Now() - rbase = beaconPrev + bvals := mbi.BeaconEntries + rbase = mbi.PrevBeaconEntry if len(bvals) > 0 { rbase = bvals[len(bvals)-1] } @@ -553,7 +557,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *type } tCreateBlock := build.Clock.Now() - dur := tCreateBlock.Sub(start) + dur := tCreateBlock.Sub(tStart) parentMiners := make([]address.Address, len(base.TipSet.Blocks())) for i, header := range base.TipSet.Blocks() { parentMiners[i] = header.Miner @@ -561,9 +565,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *type log.Infow("mined new block", "cid", minedBlock.Cid(), "height", int64(minedBlock.Header.Height), "miner", minedBlock.Header.Miner, "parents", parentMiners, "parentTipset", base.TipSet.Key().String(), "took", dur) if dur > time.Second*time.Duration(build.BlockDelaySecs) { log.Warnw("CAUTION: block production took longer than the block delay. Your computer may not be fast enough to keep up", - "tMinerBaseInfo ", tMBI.Sub(start), - "tDrand ", tDrand.Sub(tMBI), - "tPowercheck ", tPowercheck.Sub(tDrand), + "tPowercheck ", tPowercheck.Sub(tStart), "tTicket ", tTicket.Sub(tPowercheck), "tSeed ", tSeed.Sub(tTicket), "tProof ", tProof.Sub(tSeed), diff --git a/node/hello/hello.go b/node/hello/hello.go index d4c631206..daa088dcf 100644 --- a/node/hello/hello.go +++ b/node/hello/hello.go @@ -77,7 +77,7 @@ func (hs *Service) HandleStream(s inet.Stream) { "hash", hmsg.GenesisHash) if hmsg.GenesisHash != hs.syncer.Genesis.Cids()[0] { - log.Warnf("other peer has different genesis! (%s)", hmsg.GenesisHash) + log.Debugf("other peer has different genesis! (%s)", hmsg.GenesisHash) _ = s.Conn().Close() return } diff --git a/node/impl/storminer.go b/node/impl/storminer.go index daf91b44d..a8bfe0884 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -244,13 +244,13 @@ func (sm *StorageMinerAPI) SectorsList(context.Context) ([]abi.SectorNumber, err return nil, err } - out := make([]abi.SectorNumber, len(sectors)) - for i, sector := range sectors { + out := make([]abi.SectorNumber, 0, len(sectors)) + for _, sector := range sectors { if sector.State == sealing.UndefinedSectorState { continue // sector ID not set yet } - out[i] = sector.SectorNumber + out = append(out, sector.SectorNumber) } return out, nil } diff --git a/node/node_test.go b/node/node_test.go index 45779fe06..eaeeba875 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -66,6 +66,7 @@ func TestBatchDealInput(t *testing.T) { logging.SetLogLevel("chain", "ERROR") logging.SetLogLevel("sub", "ERROR") logging.SetLogLevel("storageminer", "ERROR") + logging.SetLogLevel("sectors", "DEBUG") blockTime := 10 * time.Millisecond