From 2d123aab4747d0a2a36163c50b833a547cfcb3a3 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Mon, 28 Jun 2021 22:16:03 -0400 Subject: [PATCH 01/51] Lotus version 1.11.0 --- CHANGELOG.md | 4 ++++ build/version.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11f7d300b..718e86f9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Lotus changelog +# 1.11.0-rc1 / 2021-06-28 + +This is the first release candidate for the optional Lotus v1.11.0 release that introduces several months of bugfixes and feature development. A more detailed changelog will follow. + # 1.10.0 / 2021-06-23 This is a mandatory release of Lotus that introduces Filecoin network v13, codenamed the HyperDrive upgrade. The diff --git a/build/version.go b/build/version.go index 5a4a494fc..49ec3f446 100644 --- a/build/version.go +++ b/build/version.go @@ -34,7 +34,7 @@ func buildType() string { } // BuildVersion is the local build version, set by build system -const BuildVersion = "1.11.0-dev" +const BuildVersion = "1.11.0-rc1" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { From af1dd7d2edf96743650114ba62652f75876a3b55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 1 Jul 2021 12:15:58 +0200 Subject: [PATCH 02/51] commit batch: Initialize the FailedSectors map --- extern/storage-sealing/commit_batch.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/extern/storage-sealing/commit_batch.go b/extern/storage-sealing/commit_batch.go index 097d55a1a..f16f1d208 100644 --- a/extern/storage-sealing/commit_batch.go +++ b/extern/storage-sealing/commit_batch.go @@ -229,7 +229,9 @@ func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBa total := len(b.todo) - var res sealiface.CommitBatchRes + res := sealiface.CommitBatchRes{ + FailedSectors: map[abi.SectorNumber]string{}, + } params := miner5.ProveCommitAggregateParams{ SectorNumbers: bitfield.New(), @@ -341,7 +343,8 @@ func (b *CommitBatcher) processIndividually() ([]sealiface.CommitBatchRes, error for sn, info := range b.todo { r := sealiface.CommitBatchRes{ - Sectors: []abi.SectorNumber{sn}, + Sectors: []abi.SectorNumber{sn}, + FailedSectors: map[abi.SectorNumber]string{}, } mcid, err := b.processSingle(mi, sn, info, tok) From a4f65bed41b8b51bff5667c9e08c36b807b51116 Mon Sep 17 00:00:00 2001 From: Jerry <1032246642@qq.com> Date: Tue, 29 Jun 2021 14:06:41 +0800 Subject: [PATCH 03/51] fix: miner balance is not enough, so that ProveCommitAggregate msg exec failed --- extern/storage-sealing/commit_batch.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/extern/storage-sealing/commit_batch.go b/extern/storage-sealing/commit_batch.go index f16f1d208..e4cfc8915 100644 --- a/extern/storage-sealing/commit_batch.go +++ b/extern/storage-sealing/commit_batch.go @@ -309,14 +309,16 @@ func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBa aggFee := policy.AggregateNetworkFee(nv, len(infos), bf) - goodFunds := big.Add(maxFee, big.Add(collateral, aggFee)) + needFunds := big.Add(collateral, aggFee) - from, _, err := b.addrSel(b.mctx, mi, api.CommitAddr, goodFunds, collateral) + goodFunds := big.Add(maxFee, needFunds) + + from, _, err := b.addrSel(b.mctx, mi, api.CommitAddr, goodFunds, needFunds) if err != nil { return []sealiface.CommitBatchRes{res}, xerrors.Errorf("no good address found: %w", err) } - mcid, err := b.api.SendMsg(b.mctx, from, b.maddr, miner.Methods.ProveCommitAggregate, collateral, maxFee, enc.Bytes()) + mcid, err := b.api.SendMsg(b.mctx, from, b.maddr, miner.Methods.ProveCommitAggregate, needFunds, maxFee, enc.Bytes()) if err != nil { return []sealiface.CommitBatchRes{res}, xerrors.Errorf("sending message failed: %w", err) } From c164a9fbdc48f34ec7ac746d3c486221a2e82bcf Mon Sep 17 00:00:00 2001 From: Jerry <1032246642@qq.com> Date: Tue, 29 Jun 2021 14:36:26 +0800 Subject: [PATCH 04/51] ensure agg fee is adequate --- extern/storage-sealing/commit_batch.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/extern/storage-sealing/commit_batch.go b/extern/storage-sealing/commit_batch.go index e4cfc8915..740e98fca 100644 --- a/extern/storage-sealing/commit_batch.go +++ b/extern/storage-sealing/commit_batch.go @@ -32,6 +32,9 @@ import ( const arp = abi.RegisteredAggregationProof_SnarkPackV1 +var aggFeeNum = big.NewInt(110) +var aggFeeDen = big.NewInt(100) + //go:generate go run github.com/golang/mock/mockgen -destination=mocks/mock_commit_batcher.go -package=mocks . CommitBatcherApi type CommitBatcherApi interface { @@ -307,7 +310,7 @@ func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBa return []sealiface.CommitBatchRes{res}, xerrors.Errorf("getting network version: %s", err) } - aggFee := policy.AggregateNetworkFee(nv, len(infos), bf) + aggFee := big.Div(big.Mul(policy.AggregateNetworkFee(nv, len(infos), bf), aggFeeNum), aggFeeDen) needFunds := big.Add(collateral, aggFee) From 10e00b1ba981f17e3ad747f542bc56f3c0cca217 Mon Sep 17 00:00:00 2001 From: wangchao Date: Mon, 28 Jun 2021 17:50:31 +0800 Subject: [PATCH 05/51] remove precommit check in handleCommitFailed --- extern/storage-sealing/states_failed.go | 28 +------------------------ 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/extern/storage-sealing/states_failed.go b/extern/storage-sealing/states_failed.go index 7bef19b92..3a0177978 100644 --- a/extern/storage-sealing/states_failed.go +++ b/extern/storage-sealing/states_failed.go @@ -182,7 +182,7 @@ func (m *Sealing) handleComputeProofFailed(ctx statemachine.Context, sector Sect } func (m *Sealing) handleCommitFailed(ctx statemachine.Context, sector SectorInfo) error { - tok, height, err := m.api.ChainHead(ctx.Context()) + tok, _, err := m.api.ChainHead(ctx.Context()) if err != nil { log.Errorf("handleCommitting: api error, not proceeding: %+v", err) return nil @@ -216,32 +216,6 @@ func (m *Sealing) handleCommitFailed(ctx statemachine.Context, sector SectorInfo } } - if err := checkPrecommit(ctx.Context(), m.maddr, sector, tok, height, m.api); err != nil { - switch err.(type) { - case *ErrApi: - log.Errorf("handleCommitFailed: api error, not proceeding: %+v", err) - return nil - case *ErrBadCommD: - return ctx.Send(SectorSealPreCommit1Failed{xerrors.Errorf("bad CommD error: %w", err)}) - case *ErrExpiredTicket: - return ctx.Send(SectorTicketExpired{xerrors.Errorf("ticket expired error, removing sector: %w", err)}) - case *ErrBadTicket: - return ctx.Send(SectorTicketExpired{xerrors.Errorf("expired ticket, removing sector: %w", err)}) - case *ErrInvalidDeals: - log.Warnf("invalid deals in sector %d: %v", sector.SectorNumber, err) - return ctx.Send(SectorInvalidDealIDs{Return: RetCommitFailed}) - case *ErrExpiredDeals: - return ctx.Send(SectorDealsExpired{xerrors.Errorf("sector deals expired: %w", err)}) - case nil: - return ctx.Send(SectorChainPreCommitFailed{xerrors.Errorf("no precommit: %w", err)}) - case *ErrPrecommitOnChain: - // noop, this is expected - case *ErrSectorNumberAllocated: - // noop, already committed? - default: - return xerrors.Errorf("checkPrecommit sanity check error (%T): %w", err, err) - } - } if err := m.checkCommit(ctx.Context(), sector, sector.Proof, tok); err != nil { switch err.(type) { From 5f3b21269d72f08956be7a491606729691e03b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 30 Jun 2021 15:19:29 +0200 Subject: [PATCH 06/51] gofmt --- extern/storage-sealing/states_failed.go | 1 - 1 file changed, 1 deletion(-) diff --git a/extern/storage-sealing/states_failed.go b/extern/storage-sealing/states_failed.go index 3a0177978..201c4456f 100644 --- a/extern/storage-sealing/states_failed.go +++ b/extern/storage-sealing/states_failed.go @@ -216,7 +216,6 @@ func (m *Sealing) handleCommitFailed(ctx statemachine.Context, sector SectorInfo } } - if err := m.checkCommit(ctx.Context(), sector, sector.Proof, tok); err != nil { switch err.(type) { case *ErrApi: From e9f3a2f4861c5f43c313dc719a26b1e55949c1ec Mon Sep 17 00:00:00 2001 From: johnli-helloworld Date: Fri, 25 Jun 2021 17:25:17 +0800 Subject: [PATCH 07/51] handleSubmitCommitAggregate() exception handling --- extern/storage-sealing/fsm.go | 1 + extern/storage-sealing/states_sealing.go | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/extern/storage-sealing/fsm.go b/extern/storage-sealing/fsm.go index d3e1e9d52..d04aef790 100644 --- a/extern/storage-sealing/fsm.go +++ b/extern/storage-sealing/fsm.go @@ -115,6 +115,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto SubmitCommitAggregate: planOne( on(SectorCommitAggregateSent{}, CommitWait), on(SectorCommitFailed{}, CommitFailed), + on(SectorRetrySubmitCommit{}, SubmitCommit), ), CommitWait: planOne( on(SectorProving{}, FinalizeSector), diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index 360eeafa6..bd566cdcd 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -624,11 +624,21 @@ func (m *Sealing) handleSubmitCommitAggregate(ctx statemachine.Context, sector S Spt: sector.SectorType, }) if err != nil { - return ctx.Send(SectorCommitFailed{xerrors.Errorf("queuing commit for aggregation failed: %w", err)}) + return ctx.Send(SectorRetrySubmitCommit{}) } if res.Error != "" { - return ctx.Send(SectorCommitFailed{xerrors.Errorf("aggregate error: %s", res.Error)}) + tok, _, err := m.api.ChainHead(ctx.Context()) + if err != nil { + log.Errorf("handleSubmitCommit: api error, not proceeding: %+v", err) + return nil + } + + if err := m.checkCommit(ctx.Context(), sector, sector.Proof, tok); err != nil { + return ctx.Send(SectorCommitFailed{xerrors.Errorf("commit check error: %w", err)}) + } + + return ctx.Send(SectorRetrySubmitCommit{}) } if e, found := res.FailedSectors[sector.SectorNumber]; found { From 22f183e8effd96e995ee06801c9e22a8062b23b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 1 Jul 2021 13:33:54 +0200 Subject: [PATCH 08/51] commit batch: AggregateAboveBaseFee config --- chain/types/fil.go | 5 ++ extern/storage-sealing/commit_batch.go | 20 +++++- extern/storage-sealing/commit_batch_test.go | 72 +++++++++++++++++---- extern/storage-sealing/sealiface/config.go | 8 ++- node/config/def.go | 6 ++ node/modules/storageminer.go | 22 ++++--- 6 files changed, 108 insertions(+), 25 deletions(-) diff --git a/chain/types/fil.go b/chain/types/fil.go index 7438410c8..21125e6d6 100644 --- a/chain/types/fil.go +++ b/chain/types/fil.go @@ -23,6 +23,11 @@ func (f FIL) Unitless() string { return strings.TrimRight(strings.TrimRight(r.FloatString(18), "0"), ".") } +var AttoFil = NewInt(1) +var FemtoFil = BigMul(AttoFil, NewInt(1000)) +var PicoFil = BigMul(FemtoFil, NewInt(1000)) +var NanoFil = BigMul(PicoFil, NewInt(1000)) + var unitPrefixes = []string{"a", "f", "p", "n", "μ", "m"} func (f FIL) Short() string { diff --git a/extern/storage-sealing/commit_batch.go b/extern/storage-sealing/commit_batch.go index 740e98fca..6eaa3e908 100644 --- a/extern/storage-sealing/commit_batch.go +++ b/extern/storage-sealing/commit_batch.go @@ -196,7 +196,25 @@ func (b *CommitBatcher) maybeStartBatch(notif bool) ([]sealiface.CommitBatchRes, var res []sealiface.CommitBatchRes - if total < cfg.MinCommitBatch || total < miner5.MinAggregatedSectors { + individual := (total < cfg.MinCommitBatch) || (total < miner5.MinAggregatedSectors) + + if !individual && !cfg.AggregateAboveBaseFee.Equals(big.Zero()) { + tok, _, err := b.api.ChainHead(b.mctx) + if err != nil { + return nil, err + } + + bf, err := b.api.ChainBaseFee(b.mctx, tok) + if err != nil { + return nil, xerrors.Errorf("couldn't get base fee: %w", err) + } + + if bf.LessThan(cfg.AggregateAboveBaseFee) { + individual = true + } + } + + if individual { res, err = b.processIndividually() } else { res, err = b.processBatch(cfg) diff --git a/extern/storage-sealing/commit_batch_test.go b/extern/storage-sealing/commit_batch_test.go index ad2bc8f6f..d7cf4a9a4 100644 --- a/extern/storage-sealing/commit_batch_test.go +++ b/extern/storage-sealing/commit_batch_test.go @@ -20,6 +20,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" sealing "github.com/filecoin-project/lotus/extern/storage-sealing" "github.com/filecoin-project/lotus/extern/storage-sealing/mocks" @@ -58,6 +59,8 @@ func TestCommitBatcher(t *testing.T) { CommitBatchWait: 24 * time.Hour, CommitBatchSlack: 1 * time.Hour, + AggregateAboveBaseFee: types.BigMul(types.PicoFil, types.NewInt(150)), // 0.15 nFIL + TerminateBatchMin: 1, TerminateBatchMax: 100, TerminateBatchWait: 5 * time.Minute, @@ -143,7 +146,7 @@ func TestCommitBatcher(t *testing.T) { } } - expectSend := func(expect []abi.SectorNumber) action { + expectSend := func(expect []abi.SectorNumber, aboveBalancer bool) action { return func(t *testing.T, s *mocks.MockCommitBatcherApi, pcb *sealing.CommitBatcher) promise { s.EXPECT().StateMinerInfo(gomock.Any(), gomock.Any(), gomock.Any()).Return(miner.MinerInfo{Owner: t0123, Worker: t0123}, nil) @@ -153,6 +156,22 @@ func TestCommitBatcher(t *testing.T) { batch = true ti = 1 } + + basefee := types.PicoFil + if aboveBalancer { + basefee = types.NanoFil + } + + if batch { + s.EXPECT().ChainHead(gomock.Any()).Return(nil, abi.ChainEpoch(1), nil) + s.EXPECT().ChainBaseFee(gomock.Any(), gomock.Any()).Return(basefee, nil) + } + + if !aboveBalancer { + batch = false + ti = len(expect) + } + s.EXPECT().ChainHead(gomock.Any()).Return(nil, abi.ChainEpoch(1), nil) s.EXPECT().StateSectorPreCommitInfo(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&miner.SectorPreCommitOnChainInfo{ PreCommitDeposit: big.Zero(), @@ -160,7 +179,7 @@ func TestCommitBatcher(t *testing.T) { s.EXPECT().StateMinerInitialPledgeCollateral(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(big.Zero(), nil).Times(len(expect)) if batch { s.EXPECT().StateNetworkVersion(gomock.Any(), gomock.Any()).Return(network.Version13, nil) - s.EXPECT().ChainBaseFee(gomock.Any(), gomock.Any()).Return(big.NewInt(2000), nil) + s.EXPECT().ChainBaseFee(gomock.Any(), gomock.Any()).Return(basefee, nil) } s.EXPECT().SendMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), funMatcher(func(i interface{}) bool { @@ -183,11 +202,11 @@ func TestCommitBatcher(t *testing.T) { } } - flush := func(expect []abi.SectorNumber) action { + flush := func(expect []abi.SectorNumber, aboveBalancer bool) action { return func(t *testing.T, s *mocks.MockCommitBatcherApi, pcb *sealing.CommitBatcher) promise { - _ = expectSend(expect)(t, s, pcb) + _ = expectSend(expect, aboveBalancer)(t, s, pcb) - batch := len(expect) >= minBatch + batch := len(expect) >= minBatch && aboveBalancer r, err := pcb.Flush(ctx) require.NoError(t, err) @@ -227,30 +246,57 @@ func TestCommitBatcher(t *testing.T) { tcs := map[string]struct { actions []action }{ - "addSingle": { + "addSingle-aboveBalancer": { actions: []action{ addSector(0), waitPending(1), - flush([]abi.SectorNumber{0}), + flush([]abi.SectorNumber{0}, true), }, }, - "addTwo": { + "addTwo-aboveBalancer": { actions: []action{ addSectors(getSectors(2)), waitPending(2), - flush(getSectors(2)), + flush(getSectors(2), true), }, }, - "addAte": { + "addAte-aboveBalancer": { actions: []action{ addSectors(getSectors(8)), waitPending(8), - flush(getSectors(8)), + flush(getSectors(8), true), }, }, - "addMax": { + "addMax-aboveBalancer": { actions: []action{ - expectSend(getSectors(maxBatch)), + expectSend(getSectors(maxBatch), true), + addSectors(getSectors(maxBatch)), + }, + }, + "addSingle-belowBalancer": { + actions: []action{ + addSector(0), + waitPending(1), + flush([]abi.SectorNumber{0}, false), + }, + }, + "addTwo-belowBalancer": { + actions: []action{ + addSectors(getSectors(2)), + waitPending(2), + flush(getSectors(2), false), + }, + }, + "addAte-belowBalancer": { + actions: []action{ + addSectors(getSectors(8)), + waitPending(8), + flush(getSectors(8), false), + }, + }, + "addMax-belowBalancer": { + actions: []action{ + expectSend(getSectors(maxBatch), false), addSectors(getSectors(maxBatch)), }, }, diff --git a/extern/storage-sealing/sealiface/config.go b/extern/storage-sealing/sealiface/config.go index b237072d3..0410b92c0 100644 --- a/extern/storage-sealing/sealiface/config.go +++ b/extern/storage-sealing/sealiface/config.go @@ -1,6 +1,10 @@ package sealiface -import "time" +import ( + "time" + + "github.com/filecoin-project/go-state-types/abi" +) // this has to be in a separate package to not make lotus API depend on filecoin-ffi @@ -31,6 +35,8 @@ type Config struct { CommitBatchWait time.Duration CommitBatchSlack time.Duration + AggregateAboveBaseFee abi.TokenAmount + TerminateBatchMax uint64 TerminateBatchMin uint64 TerminateBatchWait time.Duration diff --git a/node/config/def.go b/node/config/def.go index b331b1f49..240fadbd9 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -144,6 +144,10 @@ type SealingConfig struct { // time buffer for forceful batch submission before sectors/deals in batch would start expiring CommitBatchSlack Duration + // network BaseFee below which to stop doing commit aggregation, instead + // submitting proofs to the chain individually + AggregateAboveBaseFee types.FIL + TerminateBatchMax uint64 TerminateBatchMin uint64 TerminateBatchWait Duration @@ -330,6 +334,8 @@ func DefaultStorageMiner() *StorageMiner { CommitBatchWait: Duration(24 * time.Hour), // this can be up to 30 days CommitBatchSlack: Duration(1 * time.Hour), // time buffer for forceful batch submission before sectors/deals in batch would start expiring, higher value will lower the chances for message fail due to expiration + AggregateAboveBaseFee: types.FIL(types.BigMul(types.PicoFil, types.NewInt(150))), // 0.15 nFIL + TerminateBatchMin: 1, TerminateBatchMax: 100, TerminateBatchWait: Duration(5 * time.Minute), diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 09b1e2dfd..3d1d08071 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -866,11 +866,12 @@ func NewSetSealConfigFunc(r repo.LockedRepo) (dtypes.SetSealingConfigFunc, error PreCommitBatchWait: config.Duration(cfg.PreCommitBatchWait), PreCommitBatchSlack: config.Duration(cfg.PreCommitBatchSlack), - AggregateCommits: cfg.AggregateCommits, - MinCommitBatch: cfg.MinCommitBatch, - MaxCommitBatch: cfg.MaxCommitBatch, - CommitBatchWait: config.Duration(cfg.CommitBatchWait), - CommitBatchSlack: config.Duration(cfg.CommitBatchSlack), + AggregateCommits: cfg.AggregateCommits, + MinCommitBatch: cfg.MinCommitBatch, + MaxCommitBatch: cfg.MaxCommitBatch, + CommitBatchWait: config.Duration(cfg.CommitBatchWait), + CommitBatchSlack: config.Duration(cfg.CommitBatchSlack), + AggregateAboveBaseFee: types.FIL(cfg.AggregateAboveBaseFee), TerminateBatchMax: cfg.TerminateBatchMax, TerminateBatchMin: cfg.TerminateBatchMin, @@ -897,11 +898,12 @@ func NewGetSealConfigFunc(r repo.LockedRepo) (dtypes.GetSealingConfigFunc, error PreCommitBatchWait: time.Duration(cfg.Sealing.PreCommitBatchWait), PreCommitBatchSlack: time.Duration(cfg.Sealing.PreCommitBatchSlack), - AggregateCommits: cfg.Sealing.AggregateCommits, - MinCommitBatch: cfg.Sealing.MinCommitBatch, - MaxCommitBatch: cfg.Sealing.MaxCommitBatch, - CommitBatchWait: time.Duration(cfg.Sealing.CommitBatchWait), - CommitBatchSlack: time.Duration(cfg.Sealing.CommitBatchSlack), + AggregateCommits: cfg.Sealing.AggregateCommits, + MinCommitBatch: cfg.Sealing.MinCommitBatch, + MaxCommitBatch: cfg.Sealing.MaxCommitBatch, + CommitBatchWait: time.Duration(cfg.Sealing.CommitBatchWait), + CommitBatchSlack: time.Duration(cfg.Sealing.CommitBatchSlack), + AggregateAboveBaseFee: types.BigInt(cfg.Sealing.AggregateAboveBaseFee), TerminateBatchMax: cfg.Sealing.TerminateBatchMax, TerminateBatchMin: cfg.Sealing.TerminateBatchMin, From 3875746f808fe17e558116c756e1c0a97f074820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 1 Jul 2021 13:51:11 +0200 Subject: [PATCH 09/51] commit batch: Regression test nil FailedSectors map --- extern/storage-sealing/commit_batch_test.go | 65 ++++++++++++++++----- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/extern/storage-sealing/commit_batch_test.go b/extern/storage-sealing/commit_batch_test.go index d7cf4a9a4..aea6d455e 100644 --- a/extern/storage-sealing/commit_batch_test.go +++ b/extern/storage-sealing/commit_batch_test.go @@ -146,7 +146,7 @@ func TestCommitBatcher(t *testing.T) { } } - expectSend := func(expect []abi.SectorNumber, aboveBalancer bool) action { + expectSend := func(expect []abi.SectorNumber, aboveBalancer, failOnePCI bool) action { return func(t *testing.T, s *mocks.MockCommitBatcherApi, pcb *sealing.CommitBatcher) promise { s.EXPECT().StateMinerInfo(gomock.Any(), gomock.Any(), gomock.Any()).Return(miner.MinerInfo{Owner: t0123, Worker: t0123}, nil) @@ -173,10 +173,20 @@ func TestCommitBatcher(t *testing.T) { } s.EXPECT().ChainHead(gomock.Any()).Return(nil, abi.ChainEpoch(1), nil) + + pciC := len(expect) + if failOnePCI { + s.EXPECT().StateSectorPreCommitInfo(gomock.Any(), gomock.Any(), abi.SectorNumber(1), gomock.Any()).Return(nil, nil).Times(1) // not found + pciC = len(expect) - 1 + if !batch { + ti-- + } + } s.EXPECT().StateSectorPreCommitInfo(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&miner.SectorPreCommitOnChainInfo{ PreCommitDeposit: big.Zero(), - }, nil).Times(len(expect)) - s.EXPECT().StateMinerInitialPledgeCollateral(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(big.Zero(), nil).Times(len(expect)) + }, nil).Times(pciC) + s.EXPECT().StateMinerInitialPledgeCollateral(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(big.Zero(), nil).Times(pciC) + if batch { s.EXPECT().StateNetworkVersion(gomock.Any(), gomock.Any()).Return(network.Version13, nil) s.EXPECT().ChainBaseFee(gomock.Any(), gomock.Any()).Return(basefee, nil) @@ -202,9 +212,9 @@ func TestCommitBatcher(t *testing.T) { } } - flush := func(expect []abi.SectorNumber, aboveBalancer bool) action { + flush := func(expect []abi.SectorNumber, aboveBalancer, failOnePCI bool) action { return func(t *testing.T, s *mocks.MockCommitBatcherApi, pcb *sealing.CommitBatcher) promise { - _ = expectSend(expect, aboveBalancer)(t, s, pcb) + _ = expectSend(expect, aboveBalancer, failOnePCI)(t, s, pcb) batch := len(expect) >= minBatch && aboveBalancer @@ -217,6 +227,13 @@ func TestCommitBatcher(t *testing.T) { return r[0].Sectors[i] < r[0].Sectors[j] }) require.Equal(t, expect, r[0].Sectors) + if !failOnePCI { + require.Len(t, r[0].FailedSectors, 0) + } else { + require.Len(t, r[0].FailedSectors, 1) + _, found := r[0].FailedSectors[1] + require.True(t, found) + } } else { require.Len(t, r, len(expect)) for _, res := range r { @@ -228,6 +245,13 @@ func TestCommitBatcher(t *testing.T) { }) for i, res := range r { require.Equal(t, abi.SectorNumber(i), res.Sectors[0]) + if failOnePCI && res.Sectors[0] == 1 { + require.Len(t, res.FailedSectors, 1) + _, found := res.FailedSectors[1] + require.True(t, found) + } else { + require.Empty(t, res.FailedSectors) + } } } @@ -250,26 +274,26 @@ func TestCommitBatcher(t *testing.T) { actions: []action{ addSector(0), waitPending(1), - flush([]abi.SectorNumber{0}, true), + flush([]abi.SectorNumber{0}, true, false), }, }, "addTwo-aboveBalancer": { actions: []action{ addSectors(getSectors(2)), waitPending(2), - flush(getSectors(2), true), + flush(getSectors(2), true, false), }, }, "addAte-aboveBalancer": { actions: []action{ addSectors(getSectors(8)), waitPending(8), - flush(getSectors(8), true), + flush(getSectors(8), true, false), }, }, "addMax-aboveBalancer": { actions: []action{ - expectSend(getSectors(maxBatch), true), + expectSend(getSectors(maxBatch), true, false), addSectors(getSectors(maxBatch)), }, }, @@ -277,29 +301,44 @@ func TestCommitBatcher(t *testing.T) { actions: []action{ addSector(0), waitPending(1), - flush([]abi.SectorNumber{0}, false), + flush([]abi.SectorNumber{0}, false, false), }, }, "addTwo-belowBalancer": { actions: []action{ addSectors(getSectors(2)), waitPending(2), - flush(getSectors(2), false), + flush(getSectors(2), false, false), }, }, "addAte-belowBalancer": { actions: []action{ addSectors(getSectors(8)), waitPending(8), - flush(getSectors(8), false), + flush(getSectors(8), false, false), }, }, "addMax-belowBalancer": { actions: []action{ - expectSend(getSectors(maxBatch), false), + expectSend(getSectors(maxBatch), false, false), addSectors(getSectors(maxBatch)), }, }, + + "addAte-aboveBalancer-failOne": { + actions: []action{ + addSectors(getSectors(8)), + waitPending(8), + flush(getSectors(8), true, true), + }, + }, + "addAte-belowBalancer-failOne": { + actions: []action{ + addSectors(getSectors(8)), + waitPending(8), + flush(getSectors(8), false, true), + }, + }, } for name, tc := range tcs { From 31c929e7b728e0e094acee9fc150007740746d78 Mon Sep 17 00:00:00 2001 From: llifezou Date: Wed, 30 Jun 2021 16:32:44 +0800 Subject: [PATCH 10/51] fix ticket expiration check, otherwise it may cause a large number of loops to retry GetTicket when retrying PreCommit1 --- extern/storage-sealing/states_sealing.go | 38 ++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index bd566cdcd..92613cbdc 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -105,6 +105,10 @@ func checkTicketExpired(ticket, head abi.ChainEpoch) bool { return head-ticket > MaxTicketAge // TODO: allow configuring expected seal durations } +func checkProveCommitExpired(preCommitEpoch, msd abi.ChainEpoch, currEpoch abi.ChainEpoch) bool { + return currEpoch > preCommitEpoch+msd +} + func (m *Sealing) getTicket(ctx statemachine.Context, sector SectorInfo) (abi.SealRandomness, abi.ChainEpoch, error) { tok, epoch, err := m.api.ChainHead(ctx.Context()) if err != nil { @@ -126,7 +130,14 @@ func (m *Sealing) getTicket(ctx statemachine.Context, sector SectorInfo) (abi.Se if pci != nil { ticketEpoch = pci.Info.SealRandEpoch - if checkTicketExpired(ticketEpoch, epoch) { + nv, err := m.api.StateNetworkVersion(ctx.Context(), tok) + if err != nil { + return nil, 0, xerrors.Errorf("getTicket: StateNetworkVersion: api error, not proceeding: %+v", err) + } + + msd := policy.GetMaxProveCommitDuration(actors.VersionForNetwork(nv), sector.SectorType) + + if checkProveCommitExpired(pci.PreCommitEpoch, msd, epoch) { return nil, 0, xerrors.Errorf("ticket expired for precommitted sector") } } @@ -182,14 +193,35 @@ func (m *Sealing) handlePreCommit1(ctx statemachine.Context, sector SectorInfo) } } - _, height, err := m.api.ChainHead(ctx.Context()) + tok, height, err := m.api.ChainHead(ctx.Context()) if err != nil { log.Errorf("handlePreCommit1: api error, not proceeding: %+v", err) return nil } if checkTicketExpired(sector.TicketEpoch, height) { - return ctx.Send(SectorOldTicket{}) // go get new ticket + pci, err := m.api.StateSectorPreCommitInfo(ctx.Context(), m.maddr, sector.SectorNumber, tok) + if err != nil { + log.Errorf("handlePreCommit1: StateSectorPreCommitInfo: api error, not proceeding: %+v", err) + return nil + } + + if pci == nil { + return ctx.Send(SectorOldTicket{}) // go get new ticket + } + + nv, err := m.api.StateNetworkVersion(ctx.Context(), tok) + if err != nil { + log.Errorf("handlePreCommit1: StateNetworkVersion: api error, not proceeding: %+v", err) + return nil + } + + msd := policy.GetMaxProveCommitDuration(actors.VersionForNetwork(nv), sector.SectorType) + + // if height > PreCommitEpoch + msd, there is no need to recalculate + if checkProveCommitExpired(pci.PreCommitEpoch, msd, height) { + return ctx.Send(SectorOldTicket{}) // will be removed + } } pc1o, err := m.sealer.SealPreCommit1(sector.sealingCtx(ctx.Context()), m.minerSector(sector.SectorType, sector.SectorNumber), sector.TicketValue, sector.pieceInfos()) From 21528c0a95b6e4f72c9af4411aa422fabcf52951 Mon Sep 17 00:00:00 2001 From: llifezou Date: Thu, 1 Jul 2021 10:53:42 +0800 Subject: [PATCH 11/51] fix getTicket: sector precommitted but expired case --- extern/storage-sealing/states_sealing.go | 37 ++++++++++++++---------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index 92613cbdc..1d0e092e9 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -109,22 +109,30 @@ func checkProveCommitExpired(preCommitEpoch, msd abi.ChainEpoch, currEpoch abi.C return currEpoch > preCommitEpoch+msd } -func (m *Sealing) getTicket(ctx statemachine.Context, sector SectorInfo) (abi.SealRandomness, abi.ChainEpoch, error) { +func (m *Sealing) getTicket(ctx statemachine.Context, sector SectorInfo) (abi.SealRandomness, abi.ChainEpoch, bool, error) { tok, epoch, err := m.api.ChainHead(ctx.Context()) if err != nil { - log.Errorf("handlePreCommit1: api error, not proceeding: %+v", err) - return nil, 0, nil + log.Errorf("getTicket: api error, not proceeding: %+v", err) + return nil, 0, false, nil + } + + // the reason why the StateMinerSectorAllocated function is placed here, if it is outside, + // if the MarshalCBOR function and StateSectorPreCommitInfo function return err, it will be executed + allocated, aerr := m.api.StateMinerSectorAllocated(ctx.Context(), m.maddr, sector.SectorNumber, nil) + if aerr != nil { + log.Errorf("getTicket: api error, checking if sector is allocated: %+v", aerr) + return nil, 0, false, nil } ticketEpoch := epoch - policy.SealRandomnessLookback buf := new(bytes.Buffer) if err := m.maddr.MarshalCBOR(buf); err != nil { - return nil, 0, err + return nil, 0, allocated, err } pci, err := m.api.StateSectorPreCommitInfo(ctx.Context(), m.maddr, sector.SectorNumber, tok) if err != nil { - return nil, 0, xerrors.Errorf("getting precommit info: %w", err) + return nil, 0, allocated, xerrors.Errorf("getting precommit info: %w", err) } if pci != nil { @@ -132,32 +140,31 @@ func (m *Sealing) getTicket(ctx statemachine.Context, sector SectorInfo) (abi.Se nv, err := m.api.StateNetworkVersion(ctx.Context(), tok) if err != nil { - return nil, 0, xerrors.Errorf("getTicket: StateNetworkVersion: api error, not proceeding: %+v", err) + return nil, 0, allocated, xerrors.Errorf("getTicket: StateNetworkVersion: api error, not proceeding: %+v", err) } msd := policy.GetMaxProveCommitDuration(actors.VersionForNetwork(nv), sector.SectorType) if checkProveCommitExpired(pci.PreCommitEpoch, msd, epoch) { - return nil, 0, xerrors.Errorf("ticket expired for precommitted sector") + return nil, 0, allocated, xerrors.Errorf("ticket expired for precommitted sector") } } + if allocated { // allocated is true, sector precommitted but expired, will SectorCommitFailed or SectorRemove + return nil, 0, allocated, xerrors.Errorf("Sector %s precommitted but expired", sector.SectorNumber) + } + rand, err := m.api.ChainGetRandomnessFromTickets(ctx.Context(), tok, crypto.DomainSeparationTag_SealRandomness, ticketEpoch, buf.Bytes()) if err != nil { - return nil, 0, err + return nil, 0, allocated, err } - return abi.SealRandomness(rand), ticketEpoch, nil + return abi.SealRandomness(rand), ticketEpoch, allocated, nil } func (m *Sealing) handleGetTicket(ctx statemachine.Context, sector SectorInfo) error { - ticketValue, ticketEpoch, err := m.getTicket(ctx, sector) + ticketValue, ticketEpoch, allocated, err := m.getTicket(ctx, sector) if err != nil { - allocated, aerr := m.api.StateMinerSectorAllocated(ctx.Context(), m.maddr, sector.SectorNumber, nil) - if aerr != nil { - log.Errorf("error checking if sector is allocated: %+v", aerr) - } - if allocated { if sector.CommitMessage != nil { // Some recovery paths with unfortunate timing lead here From 101d152540b3bd5f76f4606f9755bbc655824dcc Mon Sep 17 00:00:00 2001 From: llifezou <46102475+llifezou@users.noreply.github.com> Date: Fri, 2 Jul 2021 11:38:04 +0800 Subject: [PATCH 12/51] Update extern/storage-sealing/states_sealing.go fix log Co-authored-by: Aayush Rajasekaran --- extern/storage-sealing/states_sealing.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index 1d0e092e9..dcea02a99 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -151,7 +151,7 @@ func (m *Sealing) getTicket(ctx statemachine.Context, sector SectorInfo) (abi.Se } if allocated { // allocated is true, sector precommitted but expired, will SectorCommitFailed or SectorRemove - return nil, 0, allocated, xerrors.Errorf("Sector %s precommitted but expired", sector.SectorNumber) + return nil, 0, allocated, xerrors.Errorf("sector %s precommitted but expired", sector.SectorNumber) } rand, err := m.api.ChainGetRandomnessFromTickets(ctx.Context(), tok, crypto.DomainSeparationTag_SealRandomness, ticketEpoch, buf.Bytes()) From d5b7e81b095932b789f0f4195445a55fc19a69e3 Mon Sep 17 00:00:00 2001 From: llifezou <46102475+llifezou@users.noreply.github.com> Date: Fri, 2 Jul 2021 11:44:46 +0800 Subject: [PATCH 13/51] Update extern/storage-sealing/states_sealing.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix sector precommitted but expired judgment Co-authored-by: Łukasz Magiera --- extern/storage-sealing/states_sealing.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index dcea02a99..1442d82cc 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -150,7 +150,7 @@ func (m *Sealing) getTicket(ctx statemachine.Context, sector SectorInfo) (abi.Se } } - if allocated { // allocated is true, sector precommitted but expired, will SectorCommitFailed or SectorRemove + if pci == nil && allocated { // allocated is true, sector precommitted but expired, will SectorCommitFailed or SectorRemove return nil, 0, allocated, xerrors.Errorf("sector %s precommitted but expired", sector.SectorNumber) } From dbdbb6f0dd96e2f44d4c586eedad15925bc67af2 Mon Sep 17 00:00:00 2001 From: johnli-helloworld Date: Wed, 30 Jun 2021 16:56:40 +0800 Subject: [PATCH 14/51] to optimize the batchwait --- extern/storage-sealing/commit_batch.go | 22 ++++++++++++++++------ extern/storage-sealing/precommit_batch.go | 22 ++++++++++++++++------ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/extern/storage-sealing/commit_batch.go b/extern/storage-sealing/commit_batch.go index 6eaa3e908..63bd3c7db 100644 --- a/extern/storage-sealing/commit_batch.go +++ b/extern/storage-sealing/commit_batch.go @@ -106,6 +106,7 @@ func (b *CommitBatcher) run() { panic(err) } + timer := time.NewTimer(b.batchWait(cfg.CommitBatchWait, cfg.CommitBatchSlack)) for { if forceRes != nil { forceRes <- lastMsg @@ -121,7 +122,7 @@ func (b *CommitBatcher) run() { return case <-b.notify: sendAboveMax = true - case <-b.batchWait(cfg.CommitBatchWait, cfg.CommitBatchSlack): + case <-timer.C: // do nothing case fr := <-b.force: // user triggered forceRes = fr @@ -132,17 +133,26 @@ func (b *CommitBatcher) run() { if err != nil { log.Warnw("CommitBatcher processBatch error", "error", err) } + + if !timer.Stop() { + select { + case <-timer.C: + default: + } + } + + timer.Reset(b.batchWait(cfg.CommitBatchWait, cfg.CommitBatchSlack)) } } -func (b *CommitBatcher) batchWait(maxWait, slack time.Duration) <-chan time.Time { +func (b *CommitBatcher) batchWait(maxWait, slack time.Duration) time.Duration { now := time.Now() b.lk.Lock() defer b.lk.Unlock() if len(b.todo) == 0 { - return nil + return maxWait } var cutoff time.Time @@ -160,12 +170,12 @@ func (b *CommitBatcher) batchWait(maxWait, slack time.Duration) <-chan time.Time } if cutoff.IsZero() { - return time.After(maxWait) + return maxWait } cutoff = cutoff.Add(-slack) if cutoff.Before(now) { - return time.After(time.Nanosecond) // can't return 0 + return time.Nanosecond // can't return 0 } wait := cutoff.Sub(now) @@ -173,7 +183,7 @@ func (b *CommitBatcher) batchWait(maxWait, slack time.Duration) <-chan time.Time wait = maxWait } - return time.After(wait) + return wait } func (b *CommitBatcher) maybeStartBatch(notif bool) ([]sealiface.CommitBatchRes, error) { diff --git a/extern/storage-sealing/precommit_batch.go b/extern/storage-sealing/precommit_batch.go index 3dc3510c2..1b43bc6b9 100644 --- a/extern/storage-sealing/precommit_batch.go +++ b/extern/storage-sealing/precommit_batch.go @@ -88,6 +88,7 @@ func (b *PreCommitBatcher) run() { panic(err) } + timer := time.NewTimer(b.batchWait(cfg.CommitBatchWait, cfg.CommitBatchSlack)) for { if forceRes != nil { forceRes <- lastRes @@ -102,7 +103,7 @@ func (b *PreCommitBatcher) run() { return case <-b.notify: sendAboveMax = true - case <-b.batchWait(cfg.PreCommitBatchWait, cfg.PreCommitBatchSlack): + case <-timer.C: // do nothing case fr := <-b.force: // user triggered forceRes = fr @@ -113,17 +114,26 @@ func (b *PreCommitBatcher) run() { if err != nil { log.Warnw("PreCommitBatcher processBatch error", "error", err) } + + if !timer.Stop() { + select { + case <-timer.C: + default: + } + } + + timer.Reset(b.batchWait(cfg.CommitBatchWait, cfg.CommitBatchSlack)) } } -func (b *PreCommitBatcher) batchWait(maxWait, slack time.Duration) <-chan time.Time { +func (b *PreCommitBatcher) batchWait(maxWait, slack time.Duration) time.Duration { now := time.Now() b.lk.Lock() defer b.lk.Unlock() if len(b.todo) == 0 { - return nil + return maxWait } var cutoff time.Time @@ -141,12 +151,12 @@ func (b *PreCommitBatcher) batchWait(maxWait, slack time.Duration) <-chan time.T } if cutoff.IsZero() { - return time.After(maxWait) + return maxWait } cutoff = cutoff.Add(-slack) if cutoff.Before(now) { - return time.After(time.Nanosecond) // can't return 0 + return time.Nanosecond // can't return 0 } wait := cutoff.Sub(now) @@ -154,7 +164,7 @@ func (b *PreCommitBatcher) batchWait(maxWait, slack time.Duration) <-chan time.T wait = maxWait } - return time.After(wait) + return wait } func (b *PreCommitBatcher) maybeStartBatch(notif bool) ([]sealiface.PreCommitBatchRes, error) { From 57d70e58f3a53f9348a28ef63bae59918f78ff66 Mon Sep 17 00:00:00 2001 From: zhoutian527 Date: Fri, 2 Jul 2021 15:53:21 +0800 Subject: [PATCH 15/51] Fix: precommit_batch method used the wrong cfg.PreCommitBatchWait --- extern/storage-sealing/precommit_batch.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extern/storage-sealing/precommit_batch.go b/extern/storage-sealing/precommit_batch.go index 1b43bc6b9..8b132a2eb 100644 --- a/extern/storage-sealing/precommit_batch.go +++ b/extern/storage-sealing/precommit_batch.go @@ -88,7 +88,7 @@ func (b *PreCommitBatcher) run() { panic(err) } - timer := time.NewTimer(b.batchWait(cfg.CommitBatchWait, cfg.CommitBatchSlack)) + timer := time.NewTimer(b.batchWait(cfg.PreCommitBatchWait, cfg.PreCommitBatchSlack)) for { if forceRes != nil { forceRes <- lastRes @@ -122,7 +122,7 @@ func (b *PreCommitBatcher) run() { } } - timer.Reset(b.batchWait(cfg.CommitBatchWait, cfg.CommitBatchSlack)) + timer.Reset(b.batchWait(cfg.PreCommitBatchWait, cfg.PreCommitBatchSlack)) } } From da0920584cf791ab1916dea10464569e4d059ad4 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Fri, 2 Jul 2021 18:02:56 +0200 Subject: [PATCH 16/51] Fix tiny error in check-client-datacap --- cli/filplus.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/filplus.go b/cli/filplus.go index 53dc5092b..007071ea2 100644 --- a/cli/filplus.go +++ b/cli/filplus.go @@ -210,7 +210,7 @@ var filplusCheckClientCmd = &cli.Command{ return err } if dcap == nil { - return xerrors.Errorf("client %s is not a verified client", err) + return xerrors.Errorf("client %s is not a verified client", caddr) } fmt.Println(*dcap) From 6610965f8749e5de36dc1d0877f0faa096636fec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 1 Jul 2021 21:07:53 +0200 Subject: [PATCH 17/51] storage: Fix FinalizeSector with sectors in stoage paths --- .circleci/config.yml | 5 +++ cmd/lotus-seal-worker/storage.go | 2 +- cmd/lotus-storage-miner/storage.go | 2 +- extern/sector-storage/manager.go | 17 ++++++- itests/deals_test.go | 2 +- itests/kit/node_miner.go | 47 +++++++++++++++++++- itests/sector_finalize_early_test.go | 66 ++++++++++++++++++++++++++++ node/modules/storageminer.go | 52 ++++++++++++---------- 8 files changed, 164 insertions(+), 29 deletions(-) create mode 100644 itests/sector_finalize_early_test.go diff --git a/.circleci/config.yml b/.circleci/config.yml index 9f8f28b86..d151026f0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -826,6 +826,11 @@ workflows: suite: itest-sdr_upgrade target: "./itests/sdr_upgrade_test.go" + - test: + name: test-itest-sector_finalize_early + suite: itest-sector_finalize_early + target: "./itests/sector_finalize_early_test.go" + - test: name: test-itest-sector_pledge suite: itest-sector_pledge diff --git a/cmd/lotus-seal-worker/storage.go b/cmd/lotus-seal-worker/storage.go index afb566166..be662a6c3 100644 --- a/cmd/lotus-seal-worker/storage.go +++ b/cmd/lotus-seal-worker/storage.go @@ -101,7 +101,7 @@ var storageAttachCmd = &cli.Command{ } if !(cfg.CanStore || cfg.CanSeal) { - return xerrors.Errorf("must specify at least one of --store of --seal") + return xerrors.Errorf("must specify at least one of --store or --seal") } b, err := json.MarshalIndent(cfg, "", " ") diff --git a/cmd/lotus-storage-miner/storage.go b/cmd/lotus-storage-miner/storage.go index b4ab26ad3..f2068ea86 100644 --- a/cmd/lotus-storage-miner/storage.go +++ b/cmd/lotus-storage-miner/storage.go @@ -145,7 +145,7 @@ over time } if !(cfg.CanStore || cfg.CanSeal) { - return xerrors.Errorf("must specify at least one of --store of --seal") + return xerrors.Errorf("must specify at least one of --store or --seal") } b, err := json.MarshalIndent(cfg, "", " ") diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 136c00252..79eca74d6 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -528,10 +528,25 @@ func (m *Manager) FinalizeSector(ctx context.Context, sector storage.SectorRef, } } + pathType := storiface.PathStorage + { + sealedStores, err := m.index.StorageFindSector(ctx, sector.ID, storiface.FTSealed, 0, false) + if err != nil { + return xerrors.Errorf("finding sealed sector: %w", err) + } + + for _, store := range sealedStores { + if store.CanSeal { + pathType = storiface.PathSealing + break + } + } + } + selector := newExistingSelector(m.index, sector.ID, storiface.FTCache|storiface.FTSealed, false) err := m.sched.Schedule(ctx, sector, sealtasks.TTFinalize, selector, - m.schedFetch(sector, storiface.FTCache|storiface.FTSealed|unsealed, storiface.PathSealing, storiface.AcquireMove), + m.schedFetch(sector, storiface.FTCache|storiface.FTSealed|unsealed, pathType, storiface.AcquireMove), func(ctx context.Context, w Worker) error { _, err := m.waitSimpleCall(ctx)(w.FinalizeSector(ctx, sector, keepUnsealed)) return err diff --git a/itests/deals_test.go b/itests/deals_test.go index f8389bbd6..8aff414e0 100644 --- a/itests/deals_test.go +++ b/itests/deals_test.go @@ -14,7 +14,7 @@ func TestDealsWithSealingAndRPC(t *testing.T) { kit.QuietMiningLogs() - var blockTime = 1 * time.Second + var blockTime = 50 * time.Millisecond client, miner, ens := kit.EnsembleMinimal(t, kit.ThroughRPC()) // no mock proofs. ens.InterconnectAll().BeginMining(blockTime) diff --git a/itests/kit/node_miner.go b/itests/kit/node_miner.go index d3f0d2e3c..eea2bc0c1 100644 --- a/itests/kit/node_miner.go +++ b/itests/kit/node_miner.go @@ -2,22 +2,29 @@ package kit import ( "context" + "encoding/json" "fmt" + "io/ioutil" + "os" + "path/filepath" "strings" "testing" "time" + "github.com/google/uuid" + "github.com/stretchr/testify/require" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/wallet" + "github.com/filecoin-project/lotus/extern/sector-storage/stores" sealing "github.com/filecoin-project/lotus/extern/storage-sealing" "github.com/filecoin-project/lotus/miner" libp2pcrypto "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/peer" "github.com/multiformats/go-multiaddr" - "github.com/stretchr/testify/require" ) // TestMiner represents a miner enrolled in an Ensemble. @@ -119,3 +126,41 @@ func (tm *TestMiner) FlushSealingBatches(ctx context.Context) { fmt.Printf("COMMIT BATCH: %+v\n", cb) } } + +const metaFile = "sectorstore.json" + +func (tm *TestMiner) AddStorage(ctx context.Context, t *testing.T, weight uint64, seal, store bool) { + p, err := ioutil.TempDir("", "lotus-testsectors-") + require.NoError(t, err) + + if err := os.MkdirAll(p, 0755); err != nil { + if !os.IsExist(err) { + require.NoError(t, err) + } + } + + _, err = os.Stat(filepath.Join(p, metaFile)) + if !os.IsNotExist(err) { + require.NoError(t, err) + } + + cfg := &stores.LocalStorageMeta{ + ID: stores.ID(uuid.New().String()), + Weight: weight, + CanSeal: seal, + CanStore: store, + } + + if !(cfg.CanStore || cfg.CanSeal) { + t.Fatal("must specify at least one of CanStore or cfg.CanSeal") + } + + b, err := json.MarshalIndent(cfg, "", " ") + require.NoError(t, err) + + err = ioutil.WriteFile(filepath.Join(p, metaFile), b, 0644) + require.NoError(t, err) + + err = tm.StorageAddLocal(ctx, p) + require.NoError(t, err) +} diff --git a/itests/sector_finalize_early_test.go b/itests/sector_finalize_early_test.go new file mode 100644 index 000000000..3eb980f9e --- /dev/null +++ b/itests/sector_finalize_early_test.go @@ -0,0 +1,66 @@ +package itests + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/lotus/extern/storage-sealing/sealiface" + "github.com/filecoin-project/lotus/itests/kit" + "github.com/filecoin-project/lotus/node" + "github.com/filecoin-project/lotus/node/config" + "github.com/filecoin-project/lotus/node/modules" + "github.com/filecoin-project/lotus/node/modules/dtypes" + "github.com/filecoin-project/lotus/node/repo" +) + +func TestDealsWithFinalizeEarly(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode") + } + + kit.QuietMiningLogs() + + var blockTime = 50 * time.Millisecond + + client, miner, ens := kit.EnsembleMinimal(t, kit.ThroughRPC(), kit.ConstructorOpts( + node.ApplyIf(node.IsType(repo.StorageMiner), node.Override(new(dtypes.GetSealingConfigFunc), func() (dtypes.GetSealingConfigFunc, error) { + return func() (sealiface.Config, error) { + cf := config.DefaultStorageMiner() + cf.Sealing.FinalizeEarly = true + return modules.ToSealingConfig(cf), nil + }, nil + })))) // no mock proofs. + ens.InterconnectAll().BeginMining(blockTime) + dh := kit.NewDealHarness(t, client, miner) + + ctx := context.Background() + + miner.AddStorage(ctx, t, 1000000000, true, false) + miner.AddStorage(ctx, t, 1000000000, false, true) + + sl, err := miner.StorageList(ctx) + require.NoError(t, err) + for si, d := range sl { + i, err := miner.StorageInfo(ctx, si) + require.NoError(t, err) + + fmt.Printf("stor d:%d %+v\n", len(d), i) + } + + t.Run("single", func(t *testing.T) { + dh.RunConcurrentDeals(kit.RunConcurrentDealsOpts{N: 1}) + }) + + sl, err = miner.StorageList(ctx) + require.NoError(t, err) + for si, d := range sl { + i, err := miner.StorageInfo(ctx, si) + require.NoError(t, err) + + fmt.Printf("stor d:%d %+v\n", len(d), i) + } +} diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 3d1d08071..8508850d3 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -882,33 +882,37 @@ func NewSetSealConfigFunc(r repo.LockedRepo) (dtypes.SetSealingConfigFunc, error }, nil } +func ToSealingConfig(cfg *config.StorageMiner) sealiface.Config { + return sealiface.Config{ + MaxWaitDealsSectors: cfg.Sealing.MaxWaitDealsSectors, + MaxSealingSectors: cfg.Sealing.MaxSealingSectors, + MaxSealingSectorsForDeals: cfg.Sealing.MaxSealingSectorsForDeals, + WaitDealsDelay: time.Duration(cfg.Sealing.WaitDealsDelay), + AlwaysKeepUnsealedCopy: cfg.Sealing.AlwaysKeepUnsealedCopy, + FinalizeEarly: cfg.Sealing.FinalizeEarly, + + BatchPreCommits: cfg.Sealing.BatchPreCommits, + MaxPreCommitBatch: cfg.Sealing.MaxPreCommitBatch, + PreCommitBatchWait: time.Duration(cfg.Sealing.PreCommitBatchWait), + PreCommitBatchSlack: time.Duration(cfg.Sealing.PreCommitBatchSlack), + + AggregateCommits: cfg.Sealing.AggregateCommits, + MinCommitBatch: cfg.Sealing.MinCommitBatch, + MaxCommitBatch: cfg.Sealing.MaxCommitBatch, + CommitBatchWait: time.Duration(cfg.Sealing.CommitBatchWait), + CommitBatchSlack: time.Duration(cfg.Sealing.CommitBatchSlack), + AggregateAboveBaseFee: types.BigInt(cfg.Sealing.AggregateAboveBaseFee), + + TerminateBatchMax: cfg.Sealing.TerminateBatchMax, + TerminateBatchMin: cfg.Sealing.TerminateBatchMin, + TerminateBatchWait: time.Duration(cfg.Sealing.TerminateBatchWait), + } +} + func NewGetSealConfigFunc(r repo.LockedRepo) (dtypes.GetSealingConfigFunc, error) { return func() (out sealiface.Config, err error) { err = readCfg(r, func(cfg *config.StorageMiner) { - out = sealiface.Config{ - MaxWaitDealsSectors: cfg.Sealing.MaxWaitDealsSectors, - MaxSealingSectors: cfg.Sealing.MaxSealingSectors, - MaxSealingSectorsForDeals: cfg.Sealing.MaxSealingSectorsForDeals, - WaitDealsDelay: time.Duration(cfg.Sealing.WaitDealsDelay), - AlwaysKeepUnsealedCopy: cfg.Sealing.AlwaysKeepUnsealedCopy, - FinalizeEarly: cfg.Sealing.FinalizeEarly, - - BatchPreCommits: cfg.Sealing.BatchPreCommits, - MaxPreCommitBatch: cfg.Sealing.MaxPreCommitBatch, - PreCommitBatchWait: time.Duration(cfg.Sealing.PreCommitBatchWait), - PreCommitBatchSlack: time.Duration(cfg.Sealing.PreCommitBatchSlack), - - AggregateCommits: cfg.Sealing.AggregateCommits, - MinCommitBatch: cfg.Sealing.MinCommitBatch, - MaxCommitBatch: cfg.Sealing.MaxCommitBatch, - CommitBatchWait: time.Duration(cfg.Sealing.CommitBatchWait), - CommitBatchSlack: time.Duration(cfg.Sealing.CommitBatchSlack), - AggregateAboveBaseFee: types.BigInt(cfg.Sealing.AggregateAboveBaseFee), - - TerminateBatchMax: cfg.Sealing.TerminateBatchMax, - TerminateBatchMin: cfg.Sealing.TerminateBatchMin, - TerminateBatchWait: time.Duration(cfg.Sealing.TerminateBatchWait), - } + out = ToSealingConfig(cfg) }) return }, nil From 947c86bd77c01c80297386d68f965925f52c8c44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 2 Jul 2021 20:57:59 +0200 Subject: [PATCH 18/51] set version to v1.11.0-rc2 --- build/openrpc/full.json.gz | Bin 23439 -> 23439 bytes build/openrpc/miner.json.gz | Bin 8102 -> 8102 bytes build/openrpc/worker.json.gz | Bin 2513 -> 2513 bytes build/version.go | 2 +- documentation/en/cli-lotus-miner.md | 2 +- documentation/en/cli-lotus-worker.md | 2 +- documentation/en/cli-lotus.md | 2 +- 7 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 0cbb105e18b2e38b1576c3caadcd6f782ec7e8d4..b46c9ba5b3689df5e203ff5d4b9217f036db7442 100644 GIT binary patch delta 23 fcmeC*&e*@5aY7g4?2X-jqBv?-PW$b@l!XBRf{_Z2 delta 23 fcmeC*&e*@5aY7fP^v3Q#Q5^0n+ok=NvM>Mua-;~9 diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index fe77f76c469f2823f39e81872279e8225a81d3f7..fd98bad0d831c578aaee8647650fc35b33430b48 100644 GIT binary patch delta 21 dcmZ2xzs!C@2jlXMoucv_m2X~f{O)07003pw2;Kky delta 21 dcmZ2xzs!C@2jl9Eoucv_nXWV5{_bI9003i@2*3aU diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 38c9a073b725d0b2b4a0958e5a8b2503cfac09dc..c6d1eb204fede74e7b3e5a0c3907fac345db636f 100644 GIT binary patch delta 21 dcmca8d{KBp6XU^+&2F3=mCs+D>?&el003#B2{!-$ delta 21 dcmca8d{KBp6XUUs&2F3=n~UyD?kZwn003tq2)zIR diff --git a/build/version.go b/build/version.go index 49ec3f446..92f011424 100644 --- a/build/version.go +++ b/build/version.go @@ -34,7 +34,7 @@ func buildType() string { } // BuildVersion is the local build version, set by build system -const BuildVersion = "1.11.0-rc1" +const BuildVersion = "1.11.0-rc2" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index c8abb574b..42f964715 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -7,7 +7,7 @@ USAGE: lotus-miner [global options] command [command options] [arguments...] VERSION: - 1.11.0-dev + 1.11.0-rc2 COMMANDS: init Initialize a lotus miner repo diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index 0b29da503..b7e04e5f1 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -7,7 +7,7 @@ USAGE: lotus-worker [global options] command [command options] [arguments...] VERSION: - 1.11.0-dev + 1.11.0-rc2 COMMANDS: run Start lotus worker diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index a1583d522..1326c93f6 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -7,7 +7,7 @@ USAGE: lotus [global options] command [command options] [arguments...] VERSION: - 1.11.0-dev + 1.11.0-rc2 COMMANDS: daemon Start a lotus daemon process From 68bde3397773777b433e91ee0962b6d13245afb7 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Fri, 2 Jul 2021 15:58:56 -0400 Subject: [PATCH 19/51] update changelog and bump version to v1.11.0-rc2 --- CHANGELOG.md | 254 ++++++++++++++++++++++++++++++++++++++++++++++- build/version.go | 2 +- 2 files changed, 253 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 718e86f9d..6a9530820 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,258 @@ # Lotus changelog -# 1.11.0-rc1 / 2021-06-28 +# 1.11.0-rc2 / 2021-07-02 -This is the first release candidate for the optional Lotus v1.11.0 release that introduces several months of bugfixes and feature development. A more detailed changelog will follow. +This is the second release candidate for the optional Lotus v1.11.0 release that introduces several months of bugfixes +and feature development. A more detailed changelog will follow upon final release. + +- github.com/filecoin-project/lotus: + - update changelog and bump version to v1.11.0-rc2 + - Lotus version 1.11.0 + - gateway: Add support for Version method ([filecoin-project/lotus#6618](https://github.com/filecoin-project/lotus/pull/6618)) + - Miner SimultaneousTransfers config ([filecoin-project/lotus#6612](https://github.com/filecoin-project/lotus/pull/6612)) + - revamped integration test kit (aka. Operation Sparks Joy) ([filecoin-project/lotus#6329](https://github.com/filecoin-project/lotus/pull/6329)) + - downgrade libp2p/go-libp2p-yamux to v0.5.1. ([filecoin-project/lotus#6605](https://github.com/filecoin-project/lotus/pull/6605)) + - Fix wallet error messages ([filecoin-project/lotus#6594](https://github.com/filecoin-project/lotus/pull/6594)) + - Fix CircleCI gen ([filecoin-project/lotus#6589](https://github.com/filecoin-project/lotus/pull/6589)) + - Make query-ask CLI more graceful ([filecoin-project/lotus#6590](https://github.com/filecoin-project/lotus/pull/6590)) + - ([filecoin-project/lotus#6406](https://github.com/filecoin-project/lotus/pull/6406)) + - move with changed name ([filecoin-project/lotus#6587](https://github.com/filecoin-project/lotus/pull/6587)) + - scale up sector expiration to avoid sector expire in batch-pre-commit waitting ([filecoin-project/lotus#6566](https://github.com/filecoin-project/lotus/pull/6566)) + - Merge release branch into master ([filecoin-project/lotus#6583](https://github.com/filecoin-project/lotus/pull/6583)) + - ([filecoin-project/lotus#6582](https://github.com/filecoin-project/lotus/pull/6582)) + - fix circleci being out of sync. ([filecoin-project/lotus#6573](https://github.com/filecoin-project/lotus/pull/6573)) + - dynamic circleci config for streamlining test execution ([filecoin-project/lotus#6561](https://github.com/filecoin-project/lotus/pull/6561)) + - Merge 1.10 branch into master ([filecoin-project/lotus#6571](https://github.com/filecoin-project/lotus/pull/6571)) + - Fix helptext ([filecoin-project/lotus#6560](https://github.com/filecoin-project/lotus/pull/6560)) + - extern/storage: add ability to ignore worker resources when scheduling. ([filecoin-project/lotus#6542](https://github.com/filecoin-project/lotus/pull/6542)) + - Merge 1.10 branch into master ([filecoin-project/lotus#6540](https://github.com/filecoin-project/lotus/pull/6540)) + - Initial draft: basic build instructions on Readme ([filecoin-project/lotus#6498](https://github.com/filecoin-project/lotus/pull/6498)) + - fix commit finalize failed ([filecoin-project/lotus#6521](https://github.com/filecoin-project/lotus/pull/6521)) + - Dynamic Retrieval pricing ([filecoin-project/lotus#6175](https://github.com/filecoin-project/lotus/pull/6175)) + - Fix soup ([filecoin-project/lotus#6501](https://github.com/filecoin-project/lotus/pull/6501)) + - fix: pick the correct partitions-per-post limit ([filecoin-project/lotus#6502](https://github.com/filecoin-project/lotus/pull/6502)) + - Fix the build + - Adjust various CLI display ratios to arbitrary precision ([filecoin-project/lotus#6309](https://github.com/filecoin-project/lotus/pull/6309)) + - Add utils to use multisigs as miner owners ([filecoin-project/lotus#6490](https://github.com/filecoin-project/lotus/pull/6490)) + - Test multicore SDR support ([filecoin-project/lotus#6479](https://github.com/filecoin-project/lotus/pull/6479)) + - sealing: Fix restartSectors race ([filecoin-project/lotus#6495](https://github.com/filecoin-project/lotus/pull/6495)) + - Merge 1.10 into master ([filecoin-project/lotus#6487](https://github.com/filecoin-project/lotus/pull/6487)) + - Unit tests for sector batchers ([filecoin-project/lotus#6432](https://github.com/filecoin-project/lotus/pull/6432)) + - Merge 1.10 changes into master ([filecoin-project/lotus#6466](https://github.com/filecoin-project/lotus/pull/6466)) + - Update chain list with correct help instructions ([filecoin-project/lotus#6465](https://github.com/filecoin-project/lotus/pull/6465)) + - clean failed sectors in batch commit ([filecoin-project/lotus#6451](https://github.com/filecoin-project/lotus/pull/6451)) + - itests/kit: add guard to ensure imports from tests only. ([filecoin-project/lotus#6445](https://github.com/filecoin-project/lotus/pull/6445)) + - consolidate integration tests into `itests` package; create test kit; cleanup ([filecoin-project/lotus#6311](https://github.com/filecoin-project/lotus/pull/6311)) + - Remove rc changelog, compile the new changelog for final release only ([filecoin-project/lotus#6444](https://github.com/filecoin-project/lotus/pull/6444)) + - updated configuration comments for docs ([filecoin-project/lotus#6440](https://github.com/filecoin-project/lotus/pull/6440)) + - Set ntwk v13 HyperDrive Calibration upgrade epoch ([filecoin-project/lotus#6441](https://github.com/filecoin-project/lotus/pull/6441)) + - Merge release/v1.10.10 into master ([filecoin-project/lotus#6439](https://github.com/filecoin-project/lotus/pull/6439)) + - implement a command to export a car ([filecoin-project/lotus#6405](https://github.com/filecoin-project/lotus/pull/6405)) + - Merge v1.10 release branch into master ([filecoin-project/lotus#6435](https://github.com/filecoin-project/lotus/pull/6435)) + - Fee config for sector batching ([filecoin-project/lotus#6420](https://github.com/filecoin-project/lotus/pull/6420)) + - Fix: correct the change of message size limit ([filecoin-project/lotus#6430](https://github.com/filecoin-project/lotus/pull/6430)) + - UX: lotus state power CLI should fail if called with a not-miner ([filecoin-project/lotus#6425](https://github.com/filecoin-project/lotus/pull/6425)) + - network reset friday + - Increase message size limit ([filecoin-project/lotus#6419](https://github.com/filecoin-project/lotus/pull/6419)) + - polish(stmgr): define ExecMonitor for message application callback ([filecoin-project/lotus#6389](https://github.com/filecoin-project/lotus/pull/6389)) + - upgrade testground action version ([filecoin-project/lotus#6403](https://github.com/filecoin-project/lotus/pull/6403)) + - Fix logging of stringified CIDs double-encoded in hex ([filecoin-project/lotus#6413](https://github.com/filecoin-project/lotus/pull/6413)) + - Update libp2p to 0.14.2 ([filecoin-project/lotus#6404](https://github.com/filecoin-project/lotus/pull/6404)) + - Bypass task scheduler for reading unsealed pieces ([filecoin-project/lotus#6280](https://github.com/filecoin-project/lotus/pull/6280)) + - testplans: lotus-soup: use default WPoStChallengeWindow ([filecoin-project/lotus#6400](https://github.com/filecoin-project/lotus/pull/6400)) + - build snapcraft ([filecoin-project/lotus#6388](https://github.com/filecoin-project/lotus/pull/6388)) + - Fix the doc errors of the sealing config funcs ([filecoin-project/lotus#6399](https://github.com/filecoin-project/lotus/pull/6399)) + - Integration tests for offline deals ([filecoin-project/lotus#6081](https://github.com/filecoin-project/lotus/pull/6081)) + - Fix success handling in Retreival ([filecoin-project/lotus#5921](https://github.com/filecoin-project/lotus/pull/5921)) + - Fix some flaky tests ([filecoin-project/lotus#6397](https://github.com/filecoin-project/lotus/pull/6397)) + - build appimage in CI ([filecoin-project/lotus#6384](https://github.com/filecoin-project/lotus/pull/6384)) + - Add doc on gas balancing ([filecoin-project/lotus#6392](https://github.com/filecoin-project/lotus/pull/6392)) + - Add a command to list retrievals ([filecoin-project/lotus#6337](https://github.com/filecoin-project/lotus/pull/6337)) + - Add interop network ([filecoin-project/lotus#6387](https://github.com/filecoin-project/lotus/pull/6387)) + - Network version 13 (v1.11) ([filecoin-project/lotus#6342](https://github.com/filecoin-project/lotus/pull/6342)) + - Generate AppImage ([filecoin-project/lotus#6208](https://github.com/filecoin-project/lotus/pull/6208)) + - lotus-gateway: add check command ([filecoin-project/lotus#6373](https://github.com/filecoin-project/lotus/pull/6373)) + - Add a warning to the release issue template ([filecoin-project/lotus#6374](https://github.com/filecoin-project/lotus/pull/6374)) + - update to markets-v1.4.0 ([filecoin-project/lotus#6369](https://github.com/filecoin-project/lotus/pull/6369)) + - Add test for AddVerifiedClient ([filecoin-project/lotus#6317](https://github.com/filecoin-project/lotus/pull/6317)) + - Typo fix in error message: "pubusb" -> "pubsub" ([filecoin-project/lotus#6365](https://github.com/filecoin-project/lotus/pull/6365)) + - Improve the cli state call command ([filecoin-project/lotus#6226](https://github.com/filecoin-project/lotus/pull/6226)) + - Upscale mineOne message to a WARN on unexpected ineligibility ([filecoin-project/lotus#6358](https://github.com/filecoin-project/lotus/pull/6358)) + - storagefsm: Fix batch deal packing behavior ([filecoin-project/lotus#6041](https://github.com/filecoin-project/lotus/pull/6041)) + - Remove few useless variable assignments ([filecoin-project/lotus#6359](https://github.com/filecoin-project/lotus/pull/6359)) + - lotus-wallet: JWT Support ([filecoin-project/lotus#6360](https://github.com/filecoin-project/lotus/pull/6360)) + - Reduce noise from 'peer has different genesis' messages ([filecoin-project/lotus#6357](https://github.com/filecoin-project/lotus/pull/6357)) + - events: Fix handling of multiple matched events per epoch ([filecoin-project/lotus#6355](https://github.com/filecoin-project/lotus/pull/6355)) + - Update RELEASE_ISSUE_TEMPLATE.md ([filecoin-project/lotus#6236](https://github.com/filecoin-project/lotus/pull/6236)) + - Get current seal proof when necessary ([filecoin-project/lotus#6339](https://github.com/filecoin-project/lotus/pull/6339)) + - Allow starting networks from arbitrary actor versions ([filecoin-project/lotus#6333](https://github.com/filecoin-project/lotus/pull/6333)) + - Remove log line when tracing is not configured ([filecoin-project/lotus#6334](https://github.com/filecoin-project/lotus/pull/6334)) + - Revert "Allow starting networks from arbitrary actor versions" ([filecoin-project/lotus#6330](https://github.com/filecoin-project/lotus/pull/6330)) + - separate tracing environment variables ([filecoin-project/lotus#6323](https://github.com/filecoin-project/lotus/pull/6323)) + - Allow starting networks from arbitrary actor versions ([filecoin-project/lotus#6305](https://github.com/filecoin-project/lotus/pull/6305)) + - feat: log dispute rate ([filecoin-project/lotus#6322](https://github.com/filecoin-project/lotus/pull/6322)) + - Use new actor tags ([filecoin-project/lotus#6291](https://github.com/filecoin-project/lotus/pull/6291)) + - Fix logging around mineOne ([filecoin-project/lotus#6310](https://github.com/filecoin-project/lotus/pull/6310)) + - Fix shell completions ([filecoin-project/lotus#6316](https://github.com/filecoin-project/lotus/pull/6316)) + - Allow 8MB sectors in devnet ([filecoin-project/lotus#6312](https://github.com/filecoin-project/lotus/pull/6312)) + - fix ticket expired ([filecoin-project/lotus#6304](https://github.com/filecoin-project/lotus/pull/6304)) + - oh, snap! ([filecoin-project/lotus#6202](https://github.com/filecoin-project/lotus/pull/6202)) + - Move verifreg shed utils to CLI ([filecoin-project/lotus#6135](https://github.com/filecoin-project/lotus/pull/6135)) + - consider storiface.PathStorage when calculating storage requirements ([filecoin-project/lotus#6233](https://github.com/filecoin-project/lotus/pull/6233)) + - `storage` module: add go docs and minor code quality refactors ([filecoin-project/lotus#6259](https://github.com/filecoin-project/lotus/pull/6259)) + - Revert "chore: update go-libp2p" ([filecoin-project/lotus#6306](https://github.com/filecoin-project/lotus/pull/6306)) + - Increase data transfer timeouts ([filecoin-project/lotus#6300](https://github.com/filecoin-project/lotus/pull/6300)) + - gateway: spin off from cmd to package ([filecoin-project/lotus#6294](https://github.com/filecoin-project/lotus/pull/6294)) + - Update to markets 1.3 ([filecoin-project/lotus#6149](https://github.com/filecoin-project/lotus/pull/6149)) + - Add a shed util to count 64 GiB miner stats ([filecoin-project/lotus#6290](https://github.com/filecoin-project/lotus/pull/6290)) + - Delete CODEOWNERS ([filecoin-project/lotus#6289](https://github.com/filecoin-project/lotus/pull/6289)) + - Merge v1.9.0 to master ([filecoin-project/lotus#6275](https://github.com/filecoin-project/lotus/pull/6275)) + - Backport 6200 to master ([filecoin-project/lotus#6272](https://github.com/filecoin-project/lotus/pull/6272)) + - Introduce stateless offline dealflow, bypassing the FSM/deallists ([filecoin-project/lotus#5961](https://github.com/filecoin-project/lotus/pull/5961)) + - chore: update go-libp2p ([filecoin-project/lotus#6231](https://github.com/filecoin-project/lotus/pull/6231)) + - fix: wait-api should use GetAPI to acquire binary specific API ([filecoin-project/lotus#6246](https://github.com/filecoin-project/lotus/pull/6246)) + - Update RELEASE_ISSUE_TEMPLATE.md + - fix(ci): Updates to lotus CI build process ([filecoin-project/lotus#6256](https://github.com/filecoin-project/lotus/pull/6256)) + - add flags to control gateway lookback parameters ([filecoin-project/lotus#6247](https://github.com/filecoin-project/lotus/pull/6247)) + - Feat/nerpa v4 ([filecoin-project/lotus#6248](https://github.com/filecoin-project/lotus/pull/6248)) + - chore(ci): Enable build on RC tags ([filecoin-project/lotus#6238](https://github.com/filecoin-project/lotus/pull/6238)) + - Transplant some useful commands to lotus-shed actor ([filecoin-project/lotus#5913](https://github.com/filecoin-project/lotus/pull/5913)) + - wip actor wrapper codegen ([filecoin-project/lotus#6108](https://github.com/filecoin-project/lotus/pull/6108)) + - Robust message management ([filecoin-project/lotus#5822](https://github.com/filecoin-project/lotus/pull/5822)) + - Add a shed util to count miners by post type ([filecoin-project/lotus#6169](https://github.com/filecoin-project/lotus/pull/6169)) + - Introduce a release issue template ([filecoin-project/lotus#5826](https://github.com/filecoin-project/lotus/pull/5826)) + - cron-wc ([filecoin-project/lotus#6178](https://github.com/filecoin-project/lotus/pull/6178)) + - This is a 1:1 forward-port of PR#6183 from 1.9.x to master ([filecoin-project/lotus#6196](https://github.com/filecoin-project/lotus/pull/6196)) + - Allow creation of state tree v3s ([filecoin-project/lotus#6167](https://github.com/filecoin-project/lotus/pull/6167)) + - drand: fix beacon cache ([filecoin-project/lotus#6164](https://github.com/filecoin-project/lotus/pull/6164)) + - Update cli gen ([filecoin-project/lotus#6155](https://github.com/filecoin-project/lotus/pull/6155)) + - mpool: Cleanup pre-nv12 selection logic ([filecoin-project/lotus#6148](https://github.com/filecoin-project/lotus/pull/6148)) + - Update ffi to proofs v7 ([filecoin-project/lotus#6150](https://github.com/filecoin-project/lotus/pull/6150)) + - Generate CLI docs ([filecoin-project/lotus#6145](https://github.com/filecoin-project/lotus/pull/6145)) + - feat: allow checkpointing to forks ([filecoin-project/lotus#6107](https://github.com/filecoin-project/lotus/pull/6107)) + - attempt to do better padding on pieces being written into sectors ([filecoin-project/lotus#5988](https://github.com/filecoin-project/lotus/pull/5988)) + - remove duplicate ask and calculate ping before lock ([filecoin-project/lotus#5968](https://github.com/filecoin-project/lotus/pull/5968)) + - Add a command to get the fees of a deal ([filecoin-project/lotus#5307](https://github.com/filecoin-project/lotus/pull/5307)) + - flaky tests improvement: separate TestBatchDealInput from TestAPIDealFlow ([filecoin-project/lotus#6141](https://github.com/filecoin-project/lotus/pull/6141)) + - Testground checks on push ([filecoin-project/lotus#5887](https://github.com/filecoin-project/lotus/pull/5887)) + - Add a CLI tool for miner proving deadline ([filecoin-project/lotus#6132](https://github.com/filecoin-project/lotus/pull/6132)) + - Use EmptyTSK where appropriate ([filecoin-project/lotus#6134](https://github.com/filecoin-project/lotus/pull/6134)) + - fix: use a consistent tipset in commands ([filecoin-project/lotus#6142](https://github.com/filecoin-project/lotus/pull/6142)) + - go mod tidy for lotus-soup testplans ([filecoin-project/lotus#6124](https://github.com/filecoin-project/lotus/pull/6124)) + - fix testground payment channel tests: use 1 miner ([filecoin-project/lotus#6126](https://github.com/filecoin-project/lotus/pull/6126)) + - fix: use the parent state when listing actors ([filecoin-project/lotus#6143](https://github.com/filecoin-project/lotus/pull/6143)) + - Speed up StateListMessages in some cases ([filecoin-project/lotus#6007](https://github.com/filecoin-project/lotus/pull/6007)) + - Return total power when GetPowerRaw doesn't find miner claim ([filecoin-project/lotus#4938](https://github.com/filecoin-project/lotus/pull/4938)) + - fix(splitstore): fix a panic on revert-only head changes ([filecoin-project/lotus#6133](https://github.com/filecoin-project/lotus/pull/6133)) + - shed: command to list duplicate messages in tipsets (steb) ([filecoin-project/lotus#5847](https://github.com/filecoin-project/lotus/pull/5847)) + - upgrade `lotus-soup` testplans and reduce deals concurrency to a single miner ([filecoin-project/lotus#6122](https://github.com/filecoin-project/lotus/pull/6122)) + - Merge releases (1.8.0) into master ([filecoin-project/lotus#6118](https://github.com/filecoin-project/lotus/pull/6118)) +- github.com/filecoin-project/go-commp-utils (v0.1.0 -> v0.1.1-0.20210427191551-70bf140d31c7): + - add a padding helper function ([filecoin-project/go-commp-utils#3](https://github.com/filecoin-project/go-commp-utils/pull/3)) +- github.com/filecoin-project/go-data-transfer (v1.4.3 -> v1.6.0): + - release: v1.6.0 + - fix: option to disable accept and complete timeouts + - fix: disable restart ack timeout + - release: v1.5.0 + - Add isRestart param to validators (#197) ([filecoin-project/go-data-transfer#197](https://github.com/filecoin-project/go-data-transfer/pull/197)) + - fix: flaky TestChannelMonitorAutoRestart (#198) ([filecoin-project/go-data-transfer#198](https://github.com/filecoin-project/go-data-transfer/pull/198)) + - Channel monitor watches for errors instead of measuring data rate (#190) ([filecoin-project/go-data-transfer#190](https://github.com/filecoin-project/go-data-transfer/pull/190)) + - fix: prevent concurrent restarts for same channel (#195) ([filecoin-project/go-data-transfer#195](https://github.com/filecoin-project/go-data-transfer/pull/195)) + - fix: channel state machine event handling (#194) ([filecoin-project/go-data-transfer#194](https://github.com/filecoin-project/go-data-transfer/pull/194)) + - Dont double count data sent (#185) ([filecoin-project/go-data-transfer#185](https://github.com/filecoin-project/go-data-transfer/pull/185)) + - release: v1.4.3 (#189) ([filecoin-project/go-data-transfer#189](https://github.com/filecoin-project/go-data-transfer/pull/189)) +- github.com/filecoin-project/go-fil-markets (v1.2.5 -> v1.5.0): + - release: v1.5.0 + - Dynamic Retrieval Pricing (#542) ([filecoin-project/go-fil-markets#542](https://github.com/filecoin-project/go-fil-markets/pull/542)) + - release: v1.4.0 (#551) ([filecoin-project/go-fil-markets#551](https://github.com/filecoin-project/go-fil-markets/pull/551)) + - Update to go data transfer v1.6.0 (#550) ([filecoin-project/go-fil-markets#550](https://github.com/filecoin-project/go-fil-markets/pull/550)) + - fix first make error (#548) ([filecoin-project/go-fil-markets#548](https://github.com/filecoin-project/go-fil-markets/pull/548)) + - release: v1.3.0 (#544) ([filecoin-project/go-fil-markets#544](https://github.com/filecoin-project/go-fil-markets/pull/544)) + - fix restarts during data transfer for a retrieval deal (#540) ([filecoin-project/go-fil-markets#540](https://github.com/filecoin-project/go-fil-markets/pull/540)) + - Test Retrieval for offline deals (#541) ([filecoin-project/go-fil-markets#541](https://github.com/filecoin-project/go-fil-markets/pull/541)) + - Allow anonymous submodule checkout (#535) ([filecoin-project/go-fil-markets#535](https://github.com/filecoin-project/go-fil-markets/pull/535)) +- github.com/filecoin-project/specs-actors (v0.9.13 -> v0.9.14): + - Set ConsensusMinerMinPower to 10 TiB (#1427) ([filecoin-project/specs-actors#1427](https://github.com/filecoin-project/specs-actors/pull/1427)) +- github.com/filecoin-project/specs-actors/v2 (v2.3.5-0.20210114162132-5b58b773f4fb -> v2.3.5): + - Set ConsensusMinerMinPower to 10 TiB (#1428) ([filecoin-project/specs-actors#1428](https://github.com/filecoin-project/specs-actors/pull/1428)) + - v2 VM satisfies SimVM interface (#1355) ([filecoin-project/specs-actors#1355](https://github.com/filecoin-project/specs-actors/pull/1355)) +- github.com/filecoin-project/specs-actors/v3 (v3.1.0 -> v3.1.1): + - Set ConsensusMinerMinPower to 10 TiB for all PoStProofPolicies (#1429) ([filecoin-project/specs-actors#1429](https://github.com/filecoin-project/specs-actors/pull/1429)) +- github.com/filecoin-project/specs-actors/v4 (v4.0.0 -> v4.0.1): + - Set ConsensusMinerMinPower to 10 TiB for all PoStProofPolicies (#1430) ([filecoin-project/specs-actors#1430](https://github.com/filecoin-project/specs-actors/pull/1430)) + +Contributors + +| Contributor | Commits | Lines ± | Files Changed | +|-------------|---------|---------|---------------| +| Raúl Kripalani | 118 | +11972/-10860 | 472 | +| Łukasz Magiera | 65 | +10824/-4158 | 353 | +| aarshkshah1992 | 59 | +8057/-3355 | 224 | +| Aayush Rajasekaran | 41 | +8786/-1691 | 331 | +| Steven Allen | 106 | +7653/-2718 | 273 | +| dirkmc | 11 | +2580/-1371 | 77 | +| Dirk McCormick | 39 | +1865/-1194 | 79 | +| Jakub Sztandera | 19 | +1973/-485 | 81 | +| vyzo | 4 | +1748/-330 | 50 | +| Aarsh Shah | 5 | +1462/-213 | 27 | +| Cory Schwartz | 35 | +568/-206 | 59 | +| chadwick2143 | 3 | +739/-1 | 4 | +| Peter Rabbitson | 21 | +487/-164 | 36 | +| hannahhoward | 5 | +544/-5 | 19 | +| Jennifer Wang | 9 | +241/-174 | 19 | +| frrist | 1 | +137/-88 | 7 | +| Travis Person | 3 | +175/-6 | 7 | +| Alex Wade | 1 | +48/-129 | 1 | +| whyrusleeping | 8 | +161/-13 | 11 | +| lotus | 1 | +114/-46 | 1 | +| Anton Evangelatov | 8 | +107/-53 | 20 | +| Rjan | 4 | +115/-33 | 4 | +| ZenGround0 | 3 | +114/-1 | 4 | +| Aloxaf | 1 | +43/-61 | 7 | +| yaohcn | 4 | +89/-9 | 5 | +| mitchellsoo | 1 | +51/-0 | 1 | +| Mike Greenberg | 3 | +28/-18 | 4 | +| Jennifer | 6 | +9/-14 | 6 | +| Frank | 2 | +11/-10 | 2 | +| wangchao | 3 | +5/-4 | 4 | +| Steve Loeppky | 1 | +7/-1 | 1 | +| Lion | 1 | +4/-2 | 1 | +| Mimir | 1 | +2/-2 | 1 | +| raulk | 1 | +1/-1 | 1 | +| Jack Yao | 1 | +1/-1 | 1 | +| IPFSUnion | 1 | +1/-1 | 1 | + +# 1.10.1-rc1 / 2021-07-02 + +This is an optional, but **highly recommended** release of Lotus that have many bug fixes and improvements based on the feedbacks we got from the community since HyperDrive. + +## New Features +- commit batch: AggregateAboveBaseFee config #6650 + - `AggregateAboveBaseFee` is added to miner sealing configuration for setting the network base fee to start aggregating proofs. When the network base fee is lower than this value, the prove commits will be submitted individually via `ProveCommitSector`. According to the [Batch Incentive Alignment](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0013. md#batch-incentive-alignment) introduced in FIP-0013, we recommend miners to set this value to 0.15 nanoFIL(which is also the default) to avoid unexpected aggregation fee in burn and enjoy the most benefits of aggregation! + +## Bug Fixes +- storage: Fix FinalizeSector with sectors in storage paths #6652 +- Fix tiny error in check-client-datacap #6664 +- Fix: precommit_batch method used the wrong cfg.PreCommitBatchWait #6658 +- to optimize the batchwait #6636 +- fix getTicket: sector precommitted but expired case #6635 +- handleSubmitCommitAggregate() exception handling #6595 +- remove precommit check in handleCommitFailed #6634 +- ensure agg fee is adequate +- fix: miner balance is not enough, so that ProveCommitAggregate msg exec failed #6623 +- commit batch: Initialize the FailedSectors map #6647 + +Contributors + +| Contributor | Commits | Lines ± | Files Changed | +|-------------|---------|---------|---------------| +| Łukasz Magiera | 7 | +151/-56 | 21 | +| llifezou | 4 | +59/-20 | 4 | +| johnli-helloworld | 2 | +45/-14 | 4 | +| wangchao | 1 | +1/-27 | 1 | +| Jerry | 2 | +9/-4 | 2 | +| zhoutian527 | 1 | +2/-2 | 1 | +| Peter Rabbitson | 1 | +1/-1 | 1 | # 1.10.0 / 2021-06-23 diff --git a/build/version.go b/build/version.go index 49ec3f446..92f011424 100644 --- a/build/version.go +++ b/build/version.go @@ -34,7 +34,7 @@ func buildType() string { } // BuildVersion is the local build version, set by build system -const BuildVersion = "1.11.0-rc1" +const BuildVersion = "1.11.0-rc2" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { From e52c639f02767b280f2964af04eb6b2b38ee63da Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Thu, 22 Jul 2021 04:50:31 -0400 Subject: [PATCH 20/51] Release v1.11.0 --- CHANGELOG.md | 414 ++++++++++++--------------- build/openrpc/full.json.gz | Bin 23439 -> 23435 bytes build/openrpc/miner.json.gz | Bin 8102 -> 8098 bytes build/openrpc/worker.json.gz | Bin 2513 -> 2510 bytes build/version.go | 2 +- documentation/en/cli-lotus-miner.md | 4 +- documentation/en/cli-lotus-worker.md | 4 +- documentation/en/cli-lotus.md | 2 +- 8 files changed, 196 insertions(+), 230 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6891aaa9e..bbd03b031 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,239 +1,205 @@ # Lotus changelog -# 1.11.0-rc2 / 2021-07-02 +# 1.11.0 / 2021-07-22 -This is the second release candidate for the optional Lotus v1.11.0 release that introduces several months of bugfixes -and feature development. A more detailed changelog will follow upon final release. +This is a **highly recommended** release of Lotus that have many bug fixes, improvements and new features. -- github.com/filecoin-project/lotus: - - update changelog and bump version to v1.11.0-rc2 +## Highlights +- Miner SimultaneousTransfers config ([filecoin-project/lotus#6612](https://github.com/filecoin-project/lotus/pull/6612)) + - Set `SimultaneousTransfers` in lotus miner config to configure the maximum number of parallel online data transfers, including both storage and retrieval deals. +- Dynamic Retrieval pricing ([filecoin-project/lotus#6175](https://github.com/filecoin-project/lotus/pull/6175)) + - Customize your retrieval ask price, see a quick tutorial [here](https://github.com/filecoin-project/lotus/discussions/6780). +- Robust message management ([filecoin-project/lotus#5822](https://github.com/filecoin-project/lotus/pull/5822)) + - run `lotus mpool manage and follow the instructions! + - Demo available at https://www.youtube.com/watch?v=QDocpLQjZgQ. +- Add utils to use multisigs as miner owners ([filecoin-project/lotus#6490](https://github.com/filecoin-project/lotus/pull/6490)) + +## More New Features +- feat: implement lotus-sim ([filecoin-project/lotus#6406](https://github.com/filecoin-project/lotus/pull/6406)) +- implement a command to export a car ([filecoin-project/lotus#6405](https://github.com/filecoin-project/lotus/pull/6405)) +- Add a command to get the fees of a deal ([filecoin-project/lotus#5307](https://github.com/filecoin-project/lotus/pull/5307)) + - run `lotus-shed market get-deal-fees` +- Add a command to list retrievals ([filecoin-project/lotus#6337](https://github.com/filecoin-project/lotus/pull/6337)) + - run `lotus client list-retrievals` +- lotus-gateway: add check command ([filecoin-project/lotus#6373](https://github.com/filecoin-project/lotus/pull/6373)) +- lotus-wallet: JWT Support ([filecoin-project/lotus#6360](https://github.com/filecoin-project/lotus/pull/6360)) +- Allow starting networks from arbitrary actor versions ([filecoin-project/lotus#6305](https://github.com/filecoin-project/lotus/pull/6305)) +- oh, snap! ([filecoin-project/lotus#6202](https://github.com/filecoin-project/lotus/pull/6202)) +- Add a shed util to count 64 GiB miner stats ([filecoin-project/lotus#6290](https://github.com/filecoin-project/lotus/pull/6290)) +- Introduce stateless offline dealflow, bypassing the FSM/deallists ([filecoin-project/lotus#5961](https://github.com/filecoin-project/lotus/pull/5961)) +- Transplant some useful commands to lotus-shed actor ([filecoin-project/lotus#5913](https://github.com/filecoin-project/lotus/pull/5913)) + - run `lotus-shed actor` +- actor wrapper codegen ([filecoin-project/lotus#6108](https://github.com/filecoin-project/lotus/pull/6108)) +- Add a shed util to count miners by post type ([filecoin-project/lotus#6169](https://github.com/filecoin-project/lotus/pull/6169)) +- shed: command to list duplicate messages in tipsets (steb) ([filecoin-project/lotus#5847](https://github.com/filecoin-project/lotus/pull/5847)) +- feat: allow checkpointing to forks ([filecoin-project/lotus#6107](https://github.com/filecoin-project/lotus/pull/6107)) +- Add a CLI tool for miner proving deadline ([filecoin-project/lotus#6132](https://github.com/filecoin-project/lotus/pull/6132)) + - run `lotus state miner-proving-deadline` - - Lotus version 1.11.0 - - gateway: Add support for Version method ([filecoin-project/lotus#6618](https://github.com/filecoin-project/lotus/pull/6618)) - - Miner SimultaneousTransfers config ([filecoin-project/lotus#6612](https://github.com/filecoin-project/lotus/pull/6612)) - - revamped integration test kit (aka. Operation Sparks Joy) ([filecoin-project/lotus#6329](https://github.com/filecoin-project/lotus/pull/6329)) - - downgrade libp2p/go-libp2p-yamux to v0.5.1. ([filecoin-project/lotus#6605](https://github.com/filecoin-project/lotus/pull/6605)) - - Fix wallet error messages ([filecoin-project/lotus#6594](https://github.com/filecoin-project/lotus/pull/6594)) - - Fix CircleCI gen ([filecoin-project/lotus#6589](https://github.com/filecoin-project/lotus/pull/6589)) - - Make query-ask CLI more graceful ([filecoin-project/lotus#6590](https://github.com/filecoin-project/lotus/pull/6590)) - - ([filecoin-project/lotus#6406](https://github.com/filecoin-project/lotus/pull/6406)) - - move with changed name ([filecoin-project/lotus#6587](https://github.com/filecoin-project/lotus/pull/6587)) - - scale up sector expiration to avoid sector expire in batch-pre-commit waitting ([filecoin-project/lotus#6566](https://github.com/filecoin-project/lotus/pull/6566)) - - Merge release branch into master ([filecoin-project/lotus#6583](https://github.com/filecoin-project/lotus/pull/6583)) - - ([filecoin-project/lotus#6582](https://github.com/filecoin-project/lotus/pull/6582)) - - fix circleci being out of sync. ([filecoin-project/lotus#6573](https://github.com/filecoin-project/lotus/pull/6573)) - - dynamic circleci config for streamlining test execution ([filecoin-project/lotus#6561](https://github.com/filecoin-project/lotus/pull/6561)) - - Merge 1.10 branch into master ([filecoin-project/lotus#6571](https://github.com/filecoin-project/lotus/pull/6571)) - - Fix helptext ([filecoin-project/lotus#6560](https://github.com/filecoin-project/lotus/pull/6560)) - - extern/storage: add ability to ignore worker resources when scheduling. ([filecoin-project/lotus#6542](https://github.com/filecoin-project/lotus/pull/6542)) - - Merge 1.10 branch into master ([filecoin-project/lotus#6540](https://github.com/filecoin-project/lotus/pull/6540)) - - Initial draft: basic build instructions on Readme ([filecoin-project/lotus#6498](https://github.com/filecoin-project/lotus/pull/6498)) - - fix commit finalize failed ([filecoin-project/lotus#6521](https://github.com/filecoin-project/lotus/pull/6521)) - - Dynamic Retrieval pricing ([filecoin-project/lotus#6175](https://github.com/filecoin-project/lotus/pull/6175)) - - Fix soup ([filecoin-project/lotus#6501](https://github.com/filecoin-project/lotus/pull/6501)) - - fix: pick the correct partitions-per-post limit ([filecoin-project/lotus#6502](https://github.com/filecoin-project/lotus/pull/6502)) - - Fix the build - - Adjust various CLI display ratios to arbitrary precision ([filecoin-project/lotus#6309](https://github.com/filecoin-project/lotus/pull/6309)) - - Add utils to use multisigs as miner owners ([filecoin-project/lotus#6490](https://github.com/filecoin-project/lotus/pull/6490)) - - Test multicore SDR support ([filecoin-project/lotus#6479](https://github.com/filecoin-project/lotus/pull/6479)) - - sealing: Fix restartSectors race ([filecoin-project/lotus#6495](https://github.com/filecoin-project/lotus/pull/6495)) - - Merge 1.10 into master ([filecoin-project/lotus#6487](https://github.com/filecoin-project/lotus/pull/6487)) - - Unit tests for sector batchers ([filecoin-project/lotus#6432](https://github.com/filecoin-project/lotus/pull/6432)) - - Merge 1.10 changes into master ([filecoin-project/lotus#6466](https://github.com/filecoin-project/lotus/pull/6466)) - - Update chain list with correct help instructions ([filecoin-project/lotus#6465](https://github.com/filecoin-project/lotus/pull/6465)) - - clean failed sectors in batch commit ([filecoin-project/lotus#6451](https://github.com/filecoin-project/lotus/pull/6451)) - - itests/kit: add guard to ensure imports from tests only. ([filecoin-project/lotus#6445](https://github.com/filecoin-project/lotus/pull/6445)) - - consolidate integration tests into `itests` package; create test kit; cleanup ([filecoin-project/lotus#6311](https://github.com/filecoin-project/lotus/pull/6311)) - - Remove rc changelog, compile the new changelog for final release only ([filecoin-project/lotus#6444](https://github.com/filecoin-project/lotus/pull/6444)) - - updated configuration comments for docs ([filecoin-project/lotus#6440](https://github.com/filecoin-project/lotus/pull/6440)) - - Set ntwk v13 HyperDrive Calibration upgrade epoch ([filecoin-project/lotus#6441](https://github.com/filecoin-project/lotus/pull/6441)) - - Merge release/v1.10.10 into master ([filecoin-project/lotus#6439](https://github.com/filecoin-project/lotus/pull/6439)) - - implement a command to export a car ([filecoin-project/lotus#6405](https://github.com/filecoin-project/lotus/pull/6405)) - - Merge v1.10 release branch into master ([filecoin-project/lotus#6435](https://github.com/filecoin-project/lotus/pull/6435)) - - Fee config for sector batching ([filecoin-project/lotus#6420](https://github.com/filecoin-project/lotus/pull/6420)) - - Fix: correct the change of message size limit ([filecoin-project/lotus#6430](https://github.com/filecoin-project/lotus/pull/6430)) - - UX: lotus state power CLI should fail if called with a not-miner ([filecoin-project/lotus#6425](https://github.com/filecoin-project/lotus/pull/6425)) - - network reset friday - - Increase message size limit ([filecoin-project/lotus#6419](https://github.com/filecoin-project/lotus/pull/6419)) - - polish(stmgr): define ExecMonitor for message application callback ([filecoin-project/lotus#6389](https://github.com/filecoin-project/lotus/pull/6389)) - - upgrade testground action version ([filecoin-project/lotus#6403](https://github.com/filecoin-project/lotus/pull/6403)) - - Fix logging of stringified CIDs double-encoded in hex ([filecoin-project/lotus#6413](https://github.com/filecoin-project/lotus/pull/6413)) - - Update libp2p to 0.14.2 ([filecoin-project/lotus#6404](https://github.com/filecoin-project/lotus/pull/6404)) - - Bypass task scheduler for reading unsealed pieces ([filecoin-project/lotus#6280](https://github.com/filecoin-project/lotus/pull/6280)) - - testplans: lotus-soup: use default WPoStChallengeWindow ([filecoin-project/lotus#6400](https://github.com/filecoin-project/lotus/pull/6400)) - - build snapcraft ([filecoin-project/lotus#6388](https://github.com/filecoin-project/lotus/pull/6388)) - - Fix the doc errors of the sealing config funcs ([filecoin-project/lotus#6399](https://github.com/filecoin-project/lotus/pull/6399)) - - Integration tests for offline deals ([filecoin-project/lotus#6081](https://github.com/filecoin-project/lotus/pull/6081)) - - Fix success handling in Retreival ([filecoin-project/lotus#5921](https://github.com/filecoin-project/lotus/pull/5921)) - - Fix some flaky tests ([filecoin-project/lotus#6397](https://github.com/filecoin-project/lotus/pull/6397)) - - build appimage in CI ([filecoin-project/lotus#6384](https://github.com/filecoin-project/lotus/pull/6384)) - - Add doc on gas balancing ([filecoin-project/lotus#6392](https://github.com/filecoin-project/lotus/pull/6392)) - - Add a command to list retrievals ([filecoin-project/lotus#6337](https://github.com/filecoin-project/lotus/pull/6337)) - - Add interop network ([filecoin-project/lotus#6387](https://github.com/filecoin-project/lotus/pull/6387)) - - Network version 13 (v1.11) ([filecoin-project/lotus#6342](https://github.com/filecoin-project/lotus/pull/6342)) - - Generate AppImage ([filecoin-project/lotus#6208](https://github.com/filecoin-project/lotus/pull/6208)) - - lotus-gateway: add check command ([filecoin-project/lotus#6373](https://github.com/filecoin-project/lotus/pull/6373)) - - Add a warning to the release issue template ([filecoin-project/lotus#6374](https://github.com/filecoin-project/lotus/pull/6374)) - - update to markets-v1.4.0 ([filecoin-project/lotus#6369](https://github.com/filecoin-project/lotus/pull/6369)) - - Add test for AddVerifiedClient ([filecoin-project/lotus#6317](https://github.com/filecoin-project/lotus/pull/6317)) - - Typo fix in error message: "pubusb" -> "pubsub" ([filecoin-project/lotus#6365](https://github.com/filecoin-project/lotus/pull/6365)) - - Improve the cli state call command ([filecoin-project/lotus#6226](https://github.com/filecoin-project/lotus/pull/6226)) - - Upscale mineOne message to a WARN on unexpected ineligibility ([filecoin-project/lotus#6358](https://github.com/filecoin-project/lotus/pull/6358)) - - storagefsm: Fix batch deal packing behavior ([filecoin-project/lotus#6041](https://github.com/filecoin-project/lotus/pull/6041)) - - Remove few useless variable assignments ([filecoin-project/lotus#6359](https://github.com/filecoin-project/lotus/pull/6359)) - - lotus-wallet: JWT Support ([filecoin-project/lotus#6360](https://github.com/filecoin-project/lotus/pull/6360)) - - Reduce noise from 'peer has different genesis' messages ([filecoin-project/lotus#6357](https://github.com/filecoin-project/lotus/pull/6357)) - - events: Fix handling of multiple matched events per epoch ([filecoin-project/lotus#6355](https://github.com/filecoin-project/lotus/pull/6355)) - - Update RELEASE_ISSUE_TEMPLATE.md ([filecoin-project/lotus#6236](https://github.com/filecoin-project/lotus/pull/6236)) - - Get current seal proof when necessary ([filecoin-project/lotus#6339](https://github.com/filecoin-project/lotus/pull/6339)) - - Allow starting networks from arbitrary actor versions ([filecoin-project/lotus#6333](https://github.com/filecoin-project/lotus/pull/6333)) - - Remove log line when tracing is not configured ([filecoin-project/lotus#6334](https://github.com/filecoin-project/lotus/pull/6334)) - - Revert "Allow starting networks from arbitrary actor versions" ([filecoin-project/lotus#6330](https://github.com/filecoin-project/lotus/pull/6330)) - - separate tracing environment variables ([filecoin-project/lotus#6323](https://github.com/filecoin-project/lotus/pull/6323)) - - Allow starting networks from arbitrary actor versions ([filecoin-project/lotus#6305](https://github.com/filecoin-project/lotus/pull/6305)) - - feat: log dispute rate ([filecoin-project/lotus#6322](https://github.com/filecoin-project/lotus/pull/6322)) - - Use new actor tags ([filecoin-project/lotus#6291](https://github.com/filecoin-project/lotus/pull/6291)) - - Fix logging around mineOne ([filecoin-project/lotus#6310](https://github.com/filecoin-project/lotus/pull/6310)) - - Fix shell completions ([filecoin-project/lotus#6316](https://github.com/filecoin-project/lotus/pull/6316)) - - Allow 8MB sectors in devnet ([filecoin-project/lotus#6312](https://github.com/filecoin-project/lotus/pull/6312)) - - fix ticket expired ([filecoin-project/lotus#6304](https://github.com/filecoin-project/lotus/pull/6304)) - - oh, snap! ([filecoin-project/lotus#6202](https://github.com/filecoin-project/lotus/pull/6202)) - - Move verifreg shed utils to CLI ([filecoin-project/lotus#6135](https://github.com/filecoin-project/lotus/pull/6135)) - - consider storiface.PathStorage when calculating storage requirements ([filecoin-project/lotus#6233](https://github.com/filecoin-project/lotus/pull/6233)) - - `storage` module: add go docs and minor code quality refactors ([filecoin-project/lotus#6259](https://github.com/filecoin-project/lotus/pull/6259)) - - Revert "chore: update go-libp2p" ([filecoin-project/lotus#6306](https://github.com/filecoin-project/lotus/pull/6306)) - - Increase data transfer timeouts ([filecoin-project/lotus#6300](https://github.com/filecoin-project/lotus/pull/6300)) - - gateway: spin off from cmd to package ([filecoin-project/lotus#6294](https://github.com/filecoin-project/lotus/pull/6294)) - - Update to markets 1.3 ([filecoin-project/lotus#6149](https://github.com/filecoin-project/lotus/pull/6149)) - - Add a shed util to count 64 GiB miner stats ([filecoin-project/lotus#6290](https://github.com/filecoin-project/lotus/pull/6290)) - - Delete CODEOWNERS ([filecoin-project/lotus#6289](https://github.com/filecoin-project/lotus/pull/6289)) - - Merge v1.9.0 to master ([filecoin-project/lotus#6275](https://github.com/filecoin-project/lotus/pull/6275)) - - Backport 6200 to master ([filecoin-project/lotus#6272](https://github.com/filecoin-project/lotus/pull/6272)) - - Introduce stateless offline dealflow, bypassing the FSM/deallists ([filecoin-project/lotus#5961](https://github.com/filecoin-project/lotus/pull/5961)) - - chore: update go-libp2p ([filecoin-project/lotus#6231](https://github.com/filecoin-project/lotus/pull/6231)) - - fix: wait-api should use GetAPI to acquire binary specific API ([filecoin-project/lotus#6246](https://github.com/filecoin-project/lotus/pull/6246)) - - Update RELEASE_ISSUE_TEMPLATE.md - - fix(ci): Updates to lotus CI build process ([filecoin-project/lotus#6256](https://github.com/filecoin-project/lotus/pull/6256)) - - add flags to control gateway lookback parameters ([filecoin-project/lotus#6247](https://github.com/filecoin-project/lotus/pull/6247)) - - Feat/nerpa v4 ([filecoin-project/lotus#6248](https://github.com/filecoin-project/lotus/pull/6248)) - - chore(ci): Enable build on RC tags ([filecoin-project/lotus#6238](https://github.com/filecoin-project/lotus/pull/6238)) - - Transplant some useful commands to lotus-shed actor ([filecoin-project/lotus#5913](https://github.com/filecoin-project/lotus/pull/5913)) - - wip actor wrapper codegen ([filecoin-project/lotus#6108](https://github.com/filecoin-project/lotus/pull/6108)) - - Robust message management ([filecoin-project/lotus#5822](https://github.com/filecoin-project/lotus/pull/5822)) - - Add a shed util to count miners by post type ([filecoin-project/lotus#6169](https://github.com/filecoin-project/lotus/pull/6169)) - - Introduce a release issue template ([filecoin-project/lotus#5826](https://github.com/filecoin-project/lotus/pull/5826)) - - cron-wc ([filecoin-project/lotus#6178](https://github.com/filecoin-project/lotus/pull/6178)) - - This is a 1:1 forward-port of PR#6183 from 1.9.x to master ([filecoin-project/lotus#6196](https://github.com/filecoin-project/lotus/pull/6196)) - - Allow creation of state tree v3s ([filecoin-project/lotus#6167](https://github.com/filecoin-project/lotus/pull/6167)) - - drand: fix beacon cache ([filecoin-project/lotus#6164](https://github.com/filecoin-project/lotus/pull/6164)) - - Update cli gen ([filecoin-project/lotus#6155](https://github.com/filecoin-project/lotus/pull/6155)) - - mpool: Cleanup pre-nv12 selection logic ([filecoin-project/lotus#6148](https://github.com/filecoin-project/lotus/pull/6148)) - - Update ffi to proofs v7 ([filecoin-project/lotus#6150](https://github.com/filecoin-project/lotus/pull/6150)) - - Generate CLI docs ([filecoin-project/lotus#6145](https://github.com/filecoin-project/lotus/pull/6145)) - - feat: allow checkpointing to forks ([filecoin-project/lotus#6107](https://github.com/filecoin-project/lotus/pull/6107)) - - attempt to do better padding on pieces being written into sectors ([filecoin-project/lotus#5988](https://github.com/filecoin-project/lotus/pull/5988)) - - remove duplicate ask and calculate ping before lock ([filecoin-project/lotus#5968](https://github.com/filecoin-project/lotus/pull/5968)) - - Add a command to get the fees of a deal ([filecoin-project/lotus#5307](https://github.com/filecoin-project/lotus/pull/5307)) - - flaky tests improvement: separate TestBatchDealInput from TestAPIDealFlow ([filecoin-project/lotus#6141](https://github.com/filecoin-project/lotus/pull/6141)) - - Testground checks on push ([filecoin-project/lotus#5887](https://github.com/filecoin-project/lotus/pull/5887)) - - Add a CLI tool for miner proving deadline ([filecoin-project/lotus#6132](https://github.com/filecoin-project/lotus/pull/6132)) - - Use EmptyTSK where appropriate ([filecoin-project/lotus#6134](https://github.com/filecoin-project/lotus/pull/6134)) - - fix: use a consistent tipset in commands ([filecoin-project/lotus#6142](https://github.com/filecoin-project/lotus/pull/6142)) - - go mod tidy for lotus-soup testplans ([filecoin-project/lotus#6124](https://github.com/filecoin-project/lotus/pull/6124)) - - fix testground payment channel tests: use 1 miner ([filecoin-project/lotus#6126](https://github.com/filecoin-project/lotus/pull/6126)) - - fix: use the parent state when listing actors ([filecoin-project/lotus#6143](https://github.com/filecoin-project/lotus/pull/6143)) - - Speed up StateListMessages in some cases ([filecoin-project/lotus#6007](https://github.com/filecoin-project/lotus/pull/6007)) - - Return total power when GetPowerRaw doesn't find miner claim ([filecoin-project/lotus#4938](https://github.com/filecoin-project/lotus/pull/4938)) - - fix(splitstore): fix a panic on revert-only head changes ([filecoin-project/lotus#6133](https://github.com/filecoin-project/lotus/pull/6133)) - - shed: command to list duplicate messages in tipsets (steb) ([filecoin-project/lotus#5847](https://github.com/filecoin-project/lotus/pull/5847)) - - upgrade `lotus-soup` testplans and reduce deals concurrency to a single miner ([filecoin-project/lotus#6122](https://github.com/filecoin-project/lotus/pull/6122)) - - Merge releases (1.8.0) into master ([filecoin-project/lotus#6118](https://github.com/filecoin-project/lotus/pull/6118)) -- github.com/filecoin-project/go-commp-utils (v0.1.0 -> v0.1.1-0.20210427191551-70bf140d31c7): - - add a padding helper function ([filecoin-project/go-commp-utils#3](https://github.com/filecoin-project/go-commp-utils/pull/3)) -- github.com/filecoin-project/go-data-transfer (v1.4.3 -> v1.6.0): - - release: v1.6.0 - - fix: option to disable accept and complete timeouts - - fix: disable restart ack timeout - - release: v1.5.0 - - Add isRestart param to validators (#197) ([filecoin-project/go-data-transfer#197](https://github.com/filecoin-project/go-data-transfer/pull/197)) - - fix: flaky TestChannelMonitorAutoRestart (#198) ([filecoin-project/go-data-transfer#198](https://github.com/filecoin-project/go-data-transfer/pull/198)) - - Channel monitor watches for errors instead of measuring data rate (#190) ([filecoin-project/go-data-transfer#190](https://github.com/filecoin-project/go-data-transfer/pull/190)) - - fix: prevent concurrent restarts for same channel (#195) ([filecoin-project/go-data-transfer#195](https://github.com/filecoin-project/go-data-transfer/pull/195)) - - fix: channel state machine event handling (#194) ([filecoin-project/go-data-transfer#194](https://github.com/filecoin-project/go-data-transfer/pull/194)) - - Dont double count data sent (#185) ([filecoin-project/go-data-transfer#185](https://github.com/filecoin-project/go-data-transfer/pull/185)) - - release: v1.4.3 (#189) ([filecoin-project/go-data-transfer#189](https://github.com/filecoin-project/go-data-transfer/pull/189)) -- github.com/filecoin-project/go-fil-markets (v1.2.5 -> v1.5.0): - - release: v1.5.0 - - Dynamic Retrieval Pricing (#542) ([filecoin-project/go-fil-markets#542](https://github.com/filecoin-project/go-fil-markets/pull/542)) - - release: v1.4.0 (#551) ([filecoin-project/go-fil-markets#551](https://github.com/filecoin-project/go-fil-markets/pull/551)) - - Update to go data transfer v1.6.0 (#550) ([filecoin-project/go-fil-markets#550](https://github.com/filecoin-project/go-fil-markets/pull/550)) - - fix first make error (#548) ([filecoin-project/go-fil-markets#548](https://github.com/filecoin-project/go-fil-markets/pull/548)) - - release: v1.3.0 (#544) ([filecoin-project/go-fil-markets#544](https://github.com/filecoin-project/go-fil-markets/pull/544)) - - fix restarts during data transfer for a retrieval deal (#540) ([filecoin-project/go-fil-markets#540](https://github.com/filecoin-project/go-fil-markets/pull/540)) - - Test Retrieval for offline deals (#541) ([filecoin-project/go-fil-markets#541](https://github.com/filecoin-project/go-fil-markets/pull/541)) - - Allow anonymous submodule checkout (#535) ([filecoin-project/go-fil-markets#535](https://github.com/filecoin-project/go-fil-markets/pull/535)) -- github.com/filecoin-project/specs-actors (v0.9.13 -> v0.9.14): - - Set ConsensusMinerMinPower to 10 TiB (#1427) ([filecoin-project/specs-actors#1427](https://github.com/filecoin-project/specs-actors/pull/1427)) -- github.com/filecoin-project/specs-actors/v2 (v2.3.5-0.20210114162132-5b58b773f4fb -> v2.3.5): - - Set ConsensusMinerMinPower to 10 TiB (#1428) ([filecoin-project/specs-actors#1428](https://github.com/filecoin-project/specs-actors/pull/1428)) - - v2 VM satisfies SimVM interface (#1355) ([filecoin-project/specs-actors#1355](https://github.com/filecoin-project/specs-actors/pull/1355)) -- github.com/filecoin-project/specs-actors/v3 (v3.1.0 -> v3.1.1): - - Set ConsensusMinerMinPower to 10 TiB for all PoStProofPolicies (#1429) ([filecoin-project/specs-actors#1429](https://github.com/filecoin-project/specs-actors/pull/1429)) -- github.com/filecoin-project/specs-actors/v4 (v4.0.0 -> v4.0.1): - - Set ConsensusMinerMinPower to 10 TiB for all PoStProofPolicies (#1430) ([filecoin-project/specs-actors#1430](https://github.com/filecoin-project/specs-actors/pull/1430)) -Contributors +## Bug Fixes +- Fix wallet error messages ([filecoin-project/lotus#6594](https://github.com/filecoin-project/lotus/pull/6594)) +- Fix CircleCI gen ([filecoin-project/lotus#6589](https://github.com/filecoin-project/lotus/pull/6589)) +- Make query-ask CLI more graceful ([filecoin-project/lotus#6590](https://github.com/filecoin-project/lotus/pull/6590)) +- scale up sector expiration to avoid sector expire in batch-pre-commit waitting ([filecoin-project/lotus#6566](https://github.com/filecoin-project/lotus/pull/6566)) +- Fix an error in msigLockCancel ([filecoin-project/lotus#6582](https://github.com/filecoin-project/lotus/pull/6582) +- fix circleci being out of sync. ([filecoin-project/lotus#6573](https://github.com/filecoin-project/lotus/pull/6573)) +- Fix helptext for ask price([filecoin-project/lotus#6560](https://github.com/filecoin-project/lotus/pull/6560)) +- fix commit finalize failed ([filecoin-project/lotus#6521](https://github.com/filecoin-project/lotus/pull/6521)) +- Fix soup ([filecoin-project/lotus#6501](https://github.com/filecoin-project/lotus/pull/6501)) +- fix: pick the correct partitions-per-post limit ([filecoin-project/lotus#6502](https://github.com/filecoin-project/lotus/pull/6502)) +- sealing: Fix restartSectors race ([filecoin-project/lotus#6495](https://github.com/filecoin-project/lotus/pull/6495)) +- Fix: correct the change of message size limit ([filecoin-project/lotus#6430](https://github.com/filecoin-project/lotus/pull/6430)) +- Fix logging of stringified CIDs double-encoded in hex ([filecoin-project/lotus#6413](https://github.com/filecoin-project/lotus/pull/6413)) +- Fix success handling in Retreival ([filecoin-project/lotus#5921](https://github.com/filecoin-project/lotus/pull/5921)) +- storagefsm: Fix batch deal packing behavior ([filecoin-project/lotus#6041](https://github.com/filecoin-project/lotus/pull/6041)) +- events: Fix handling of multiple matched events per epoch ([filecoin-project/lotus#6355](https://github.com/filecoin-project/lotus/pull/6355)) +- Fix logging around mineOne ([filecoin-project/lotus#6310](https://github.com/filecoin-project/lotus/pull/6310)) +- Fix shell completions ([filecoin-project/lotus#6316](https://github.com/filecoin-project/lotus/pull/6316)) +- Allow 8MB sectors in devnet ([filecoin-project/lotus#6312](https://github.com/filecoin-project/lotus/pull/6312)) +- fix ticket expired ([filecoin-project/lotus#6304](https://github.com/filecoin-project/lotus/pull/6304)) +- Revert "chore: update go-libp2p" ([filecoin-project/lotus#6306](https://github.com/filecoin-project/lotus/pull/6306)) +- fix: wait-api should use GetAPI to acquire binary specific API ([filecoin-project/lotus#6246](https://github.com/filecoin-project/lotus/pull/6246)) +- fix(ci): Updates to lotus CI build process ([filecoin-project/lotus#6256](https://github.com/filecoin-project/lotus/pull/6256)) +- fix: use a consistent tipset in commands ([filecoin-project/lotus#6142](https://github.com/filecoin-project/lotus/pull/6142)) +- go mod tidy for lotus-soup testplans ([filecoin-project/lotus#6124](https://github.com/filecoin-project/lotus/pull/6124)) +- fix testground payment channel tests: use 1 miner ([filecoin-project/lotus#6126](https://github.com/filecoin-project/lotus/pull/6126)) +- fix: use the parent state when listing actors ([filecoin-project/lotus#6143](https://github.com/filecoin-project/lotus/pull/6143)) +- Speed up StateListMessages in some cases ([filecoin-project/lotus#6007](https://github.com/filecoin-project/lotus/pull/6007)) +- fix(splitstore): fix a panic on revert-only head changes ([filecoin-project/lotus#6133](https://github.com/filecoin-project/lotus/pull/6133)) +- drand: fix beacon cache ([filecoin-project/lotus#6164](https://github.com/filecoin-project/lotus/pull/6164)) + +## Improvements +- gateway: Add support for Version method ([filecoin-project/lotus#6618](https://github.com/filecoin-project/lotus/pull/6618)) +- revamped integration test kit (aka. Operation Sparks Joy) ([filecoin-project/lotus#6329](https://github.com/filecoin-project/lotus/pull/6329)) +- move with changed name ([filecoin-project/lotus#6587](https://github.com/filecoin-project/lotus/pull/6587)) +- dynamic circleci config for streamlining test execution ([filecoin-project/lotus#6561](https://github.com/filecoin-project/lotus/pull/6561)) +- extern/storage: add ability to ignore worker resources when scheduling. ([filecoin-project/lotus#6542](https://github.com/filecoin-project/lotus/pull/6542)) +- Adjust various CLI display ratios to arbitrary precision ([filecoin-project/lotus#6309](https://github.com/filecoin-project/lotus/pull/6309)) +- Test multicore SDR support ([filecoin-project/lotus#6479](https://github.com/filecoin-project/lotus/pull/6479)) +- Unit tests for sector batchers ([filecoin-project/lotus#6432](https://github.com/filecoin-project/lotus/pull/6432)) +- Update chain list with correct help instructions ([filecoin-project/lotus#6465](https://github.com/filecoin-project/lotus/pull/6465)) +- clean failed sectors in batch commit ([filecoin-project/lotus#6451](https://github.com/filecoin-project/lotus/pull/6451)) +- itests/kit: add guard to ensure imports from tests only. ([filecoin-project/lotus#6445](https://github.com/filecoin-project/lotus/pull/6445)) +- consolidate integration tests into `itests` package; create test kit; cleanup ([filecoin-project/lotus#6311](https://github.com/filecoin-project/lotus/pull/6311)) +- Fee config for sector batching ([filecoin-project/lotus#6420](https://github.com/filecoin-project/lotus/pull/6420)) +- UX: lotus state power CLI should fail if called with a not-miner ([filecoin-project/lotus#6425](https://github.com/filecoin-project/lotus/pull/6425)) +- Increase message size limit ([filecoin-project/lotus#6419](https://github.com/filecoin-project/lotus/pull/6419)) +- polish(stmgr): define ExecMonitor for message application callback ([filecoin-project/lotus#6389](https://github.com/filecoin-project/lotus/pull/6389)) +- upgrade testground action version ([filecoin-project/lotus#6403](https://github.com/filecoin-project/lotus/pull/6403)) +- Bypass task scheduler for reading unsealed pieces ([filecoin-project/lotus#6280](https://github.com/filecoin-project/lotus/pull/6280)) +- testplans: lotus-soup: use default WPoStChallengeWindow ([filecoin-project/lotus#6400](https://github.com/filecoin-project/lotus/pull/6400)) +- Integration tests for offline deals ([filecoin-project/lotus#6081](https://github.com/filecoin-project/lotus/pull/6081)) +- Fix some flaky tests ([filecoin-project/lotus#6397](https://github.com/filecoin-project/lotus/pull/6397)) +- build appimage in CI ([filecoin-project/lotus#6384](https://github.com/filecoin-project/lotus/pull/6384)) +- Generate AppImage ([filecoin-project/lotus#6208](https://github.com/filecoin-project/lotus/pull/6208)) +- Add test for AddVerifiedClient ([filecoin-project/lotus#6317](https://github.com/filecoin-project/lotus/pull/6317)) +- Typo fix in error message: "pubusb" -> "pubsub" ([filecoin-project/lotus#6365](https://github.com/filecoin-project/lotus/pull/6365)) +- Improve the cli state call command ([filecoin-project/lotus#6226](https://github.com/filecoin-project/lotus/pull/6226)) +- Upscale mineOne message to a WARN on unexpected ineligibility ([filecoin-project/lotus#6358](https://github.com/filecoin-project/lotus/pull/6358)) +- Remove few useless variable assignments ([filecoin-project/lotus#6359](https://github.com/filecoin-project/lotus/pull/6359)) +- Reduce noise from 'peer has different genesis' messages ([filecoin-project/lotus#6357](https://github.com/filecoin-project/lotus/pull/6357)) +- Get current seal proof when necessary ([filecoin-project/lotus#6339](https://github.com/filecoin-project/lotus/pull/6339)) +- Remove log line when tracing is not configured ([filecoin-project/lotus#6334](https://github.com/filecoin-project/lotus/pull/6334)) +- separate tracing environment variables ([filecoin-project/lotus#6323](https://github.com/filecoin-project/lotus/pull/6323)) +- feat: log dispute rate ([filecoin-project/lotus#6322](https://github.com/filecoin-project/lotus/pull/6322)) +- Move verifreg shed utils to CLI ([filecoin-project/lotus#6135](https://github.com/filecoin-project/lotus/pull/6135)) +- consider storiface.PathStorage when calculating storage requirements ([filecoin-project/lotus#6233](https://github.com/filecoin-project/lotus/pull/6233)) +- `storage` module: add go docs and minor code quality refactors ([filecoin-project/lotus#6259](https://github.com/filecoin-project/lotus/pull/6259)) +- Increase data transfer timeouts ([filecoin-project/lotus#6300](https://github.com/filecoin-project/lotus/pull/6300)) +- gateway: spin off from cmd to package ([filecoin-project/lotus#6294](https://github.com/filecoin-project/lotus/pull/6294)) +- Return total power when GetPowerRaw doesn't find miner claim ([filecoin-project/lotus#4938](https://github.com/filecoin-project/lotus/pull/4938)) +- add flags to control gateway lookback parameters ([filecoin-project/lotus#6247](https://github.com/filecoin-project/lotus/pull/6247)) +- chore(ci): Enable build on RC tags ([filecoin-project/lotus#6238](https://github.com/filecoin-project/lotus/pull/6238)) +- cron-wc ([filecoin-project/lotus#6178](https://github.com/filecoin-project/lotus/pull/6178)) +- Allow creation of state tree v3s ([filecoin-project/lotus#6167](https://github.com/filecoin-project/lotus/pull/6167)) +- mpool: Cleanup pre-nv12 selection logic ([filecoin-project/lotus#6148](https://github.com/filecoin-project/lotus/pull/6148)) +- attempt to do better padding on pieces being written into sectors ([filecoin-project/lotus#5988](https://github.com/filecoin-project/lotus/pull/5988)) +- remove duplicate ask and calculate ping before lock ([filecoin-project/lotus#5968](https://github.com/filecoin-project/lotus/pull/5968)) +- flaky tests improvement: separate TestBatchDealInput from TestAPIDealFlow ([filecoin-project/lotus#6141](https://github.com/filecoin-project/lotus/pull/6141)) +- Testground checks on push ([filecoin-project/lotus#5887](https://github.com/filecoin-project/lotus/pull/5887)) +- Use EmptyTSK where appropriate ([filecoin-project/lotus#6134](https://github.com/filecoin-project/lotus/pull/6134)) +- upgrade `lotus-soup` testplans and reduce deals concurrency to a single miner ([filecoin-project/lotus#6122](https://github.com/filecoin-project/lotus/pull/6122) + +## Dependency Updates +- downgrade libp2p/go-libp2p-yamux to v0.5.1. ([filecoin-project/lotus#6605](https://github.com/filecoin-project/lotus/pull/6605)) +- Update libp2p to 0.14.2 ([filecoin-project/lotus#6404](https://github.com/filecoin-project/lotus/pull/6404)) +- update to markets-v1.4.0 ([filecoin-project/lotus#6369](https://github.com/filecoin-project/lotus/pull/6369)) +- Use new actor tags ([filecoin-project/lotus#6291](https://github.com/filecoin-project/lotus/pull/6291)) +- chore: update go-libp2p ([filecoin-project/lotus#6231](https://github.com/filecoin-project/lotus/pull/6231)) +- Update ffi to proofs v7 ([filecoin-project/lotus#6150](https://github.com/filecoin-project/lotus/pull/6150)) + +## Others +- Initial draft: basic build instructions on Readme ([filecoin-project/lotus#6498](https://github.com/filecoin-project/lotus/pull/6498)) +- Remove rc changelog, compile the new changelog for final release only ([filecoin-project/lotus#6444](https://github.com/filecoin-project/lotus/pull/6444)) +- updated configuration comments for docs ([filecoin-project/lotus#6440](https://github.com/filecoin-project/lotus/pull/6440)) +- Set ntwk v13 HyperDrive Calibration upgrade epoch ([filecoin-project/lotus#6441](https://github.com/filecoin-project/lotus/pull/6441)) +- build snapcraft ([filecoin-project/lotus#6388](https://github.com/filecoin-project/lotus/pull/6388)) +- Fix the doc errors of the sealing config funcs ([filecoin-project/lotus#6399](https://github.com/filecoin-project/lotus/pull/6399)) +- Add doc on gas balancing ([filecoin-project/lotus#6392](https://github.com/filecoin-project/lotus/pull/6392)) +- Add interop network ([filecoin-project/lotus#6387](https://github.com/filecoin-project/lotus/pull/6387)) +- Network version 13 (v1.11) ([filecoin-project/lotus#6342](https://github.com/filecoin-project/lotus/pull/6342)) +- Add a warning to the release issue template ([filecoin-project/lotus#6374](https://github.com/filecoin-project/lotus/pull/6374)) +- Update RELEASE_ISSUE_TEMPLATE.md ([filecoin-project/lotus#6236](https://github.com/filecoin-project/lotus/pull/6236)) +- Delete CODEOWNERS ([filecoin-project/lotus#6289](https://github.com/filecoin-project/lotus/pull/6289)) +- Feat/nerpa v4 ([filecoin-project/lotus#6248](https://github.com/filecoin-project/lotus/pull/6248)) +- Introduce a release issue template ([filecoin-project/lotus#5826](https://github.com/filecoin-project/lotus/pull/5826)) +- This is a 1:1 forward-port of PR#6183 from 1.9.x to master ([filecoin-project/lotus#6196](https://github.com/filecoin-project/lotus/pull/6196)) +- Update cli gen ([filecoin-project/lotus#6155](https://github.com/filecoin-project/lotus/pull/6155)) +- Generate CLI docs ([filecoin-project/lotus#6145](https://github.com/filecoin-project/lotus/pull/6145)) + +## Contributors | Contributor | Commits | Lines ± | Files Changed | |-------------|---------|---------|---------------| -| Raúl Kripalani | 118 | +11972/-10860 | 472 | -| Łukasz Magiera | 65 | +10824/-4158 | 353 | -| aarshkshah1992 | 59 | +8057/-3355 | 224 | -| Aayush Rajasekaran | 41 | +8786/-1691 | 331 | -| Steven Allen | 106 | +7653/-2718 | 273 | +| @raulk | 118 | +11972/-10860 | 472 | +| @magik6k | 65 | +10824/-4158 | 353 | +| @aarshkshah1992 | 59 | +8057/-3355 | 224 | +| @arajasek | 41 | +8786/-1691 | 331 | +| @Stebalien | 106 | +7653/-2718 | 273 | | dirkmc | 11 | +2580/-1371 | 77 | -| Dirk McCormick | 39 | +1865/-1194 | 79 | -| Jakub Sztandera | 19 | +1973/-485 | 81 | -| vyzo | 4 | +1748/-330 | 50 | -| Aarsh Shah | 5 | +1462/-213 | 27 | -| Cory Schwartz | 35 | +568/-206 | 59 | -| chadwick2143 | 3 | +739/-1 | 4 | -| Peter Rabbitson | 21 | +487/-164 | 36 | -| hannahhoward | 5 | +544/-5 | 19 | -| Jennifer Wang | 9 | +241/-174 | 19 | -| frrist | 1 | +137/-88 | 7 | -| Travis Person | 3 | +175/-6 | 7 | -| Alex Wade | 1 | +48/-129 | 1 | -| whyrusleeping | 8 | +161/-13 | 11 | +| @dirkmc | 39 | +1865/-1194 | 79 | +| @Kubuxu | 19 | +1973/-485 | 81 | +| @vyzo | 4 | +1748/-330 | 50 | +| @aarshkshah1992 | 5 | +1462/-213 | 27 | +| @coryschwartz | 35 | +568/-206 | 59 | +| @chadwick2143 | 3 | +739/-1 | 4 | +| @ribasushi | 21 | +487/-164 | 36 | +| @hannahhoward | 5 | +544/-5 | 19 | +| @jennijuju | 9 | +241/-174 | 19 | +| @frrist | 1 | +137/-88 | 7 | +| @travisperson | 3 | +175/-6 | 7 | +| @wadeAlexC | 1 | +48/-129 | 1 | +| @whyrusleeping | 8 | +161/-13 | 11 | | lotus | 1 | +114/-46 | 1 | -| Anton Evangelatov | 8 | +107/-53 | 20 | -| Rjan | 4 | +115/-33 | 4 | -| ZenGround0 | 3 | +114/-1 | 4 | -| Aloxaf | 1 | +43/-61 | 7 | -| yaohcn | 4 | +89/-9 | 5 | -| mitchellsoo | 1 | +51/-0 | 1 | -| Mike Greenberg | 3 | +28/-18 | 4 | -| Jennifer | 6 | +9/-14 | 6 | -| Frank | 2 | +11/-10 | 2 | -| wangchao | 3 | +5/-4 | 4 | -| Steve Loeppky | 1 | +7/-1 | 1 | -| Lion | 1 | +4/-2 | 1 | -| Mimir | 1 | +2/-2 | 1 | -| raulk | 1 | +1/-1 | 1 | -| Jack Yao | 1 | +1/-1 | 1 | -| IPFSUnion | 1 | +1/-1 | 1 | +| @nonsense | 8 | +107/-53 | 20 | +| @rjan90 | 4 | +115/-33 | 4 | +| @ZenGround0 | 3 | +114/-1 | 4 | +| @Aloxaf | 1 | +43/-61 | 7 | +| @yaohcn | 4 | +89/-9 | 5 | +| @mitchellsoo | 1 | +51/-0 | 1 | +| @placer14 | 3 | +28/-18 | 4 | +| @jennijuju | 6 | +9/-14 | 6 | +| @Frank | 2 | +11/-10 | 2 | +| @wangchao | 3 | +5/-4 | 4 | +| @Steve Loeppky | 1 | +7/-1 | 1 | +| @Lion | 1 | +4/-2 | 1 | +| @Mimir | 1 | +2/-2 | 1 | +| @raulk | 1 | +1/-1 | 1 | +| @Jack Yao | 1 | +1/-1 | 1 | +| @IPFSUnion | 1 | +1/-1 | 1 | -# 1.10.1-rc1 / 2021-07-02 +# 1.10.1 / 2021-07-05 -This is an optional, but **highly recommended** release of Lotus that have many bug fixes and improvements based on the feedbacks we got from the community since HyperDrive. +This is an optional but **highly recommended** release of Lotus for lotus miners that has many bug fixes and improvements based on the feedback we got from the community since HyperDrive. ## New Features - commit batch: AggregateAboveBaseFee config #6650 - - `AggregateAboveBaseFee` is added to miner sealing configuration for setting the network base fee to start aggregating proofs. When the network base fee is lower than this value, the prove commits will be submitted individually via `ProveCommitSector`. According to the [Batch Incentive Alignment](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0013. md#batch-incentive-alignment) introduced in FIP-0013, we recommend miners to set this value to 0.15 nanoFIL(which is also the default) to avoid unexpected aggregation fee in burn and enjoy the most benefits of aggregation! - + - `AggregateAboveBaseFee` is added to miner sealing configuration for setting the network base fee to start aggregating proofs. When the network base fee is lower than this value, the prove commits will be submitted individually via `ProveCommitSector`. According to the [Batch Incentive Alignment](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0013.md#batch-incentive-alignment) introduced in FIP-0013, we recommend miners to set this value to 0.15 nanoFIL(which is the default value) to avoid unexpected aggregation fee in burn and enjoy the most benefits of aggregation! + ## Bug Fixes - storage: Fix FinalizeSector with sectors in storage paths #6652 -- Fix tiny error in check-client-datacap #6664 +- Fix tiny error in check-client-datacap #6664 - Fix: precommit_batch method used the wrong cfg.PreCommitBatchWait #6658 - to optimize the batchwait #6636 - fix getTicket: sector precommitted but expired case #6635 @@ -247,13 +213,13 @@ Contributors | Contributor | Commits | Lines ± | Files Changed | |-------------|---------|---------|---------------| -| Łukasz Magiera | 7 | +151/-56 | 21 | -| llifezou | 4 | +59/-20 | 4 | -| johnli-helloworld | 2 | +45/-14 | 4 | -| wangchao | 1 | +1/-27 | 1 | +| @magik6k| 7 | +151/-56 | 21 | +| @llifezou | 4 | +59/-20 | 4 | +| @johnli-helloworld | 2 | +45/-14 | 4 | +| @wangchao | 1 | +1/-27 | 1 | | Jerry | 2 | +9/-4 | 2 | -| zhoutian527 | 1 | +2/-2 | 1 | -| Peter Rabbitson | 1 | +1/-1 | 1 | +| @zhoutian527 | 1 | +2/-2 | 1 | +| @ribasushi| 1 | +1/-1 | 1 | # 1.10.0 / 2021-06-23 diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index b46c9ba5b3689df5e203ff5d4b9217f036db7442..fe0c17662ad3ad0af07e497d156c2d06e58adb4f 100644 GIT binary patch delta 23373 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 delta 23377 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�BXMbXtZq+(c?L=v7?DiFI$j*^p zYGLY6kM~fRc`A}mEkX>0YCJqk+UNUjIQId2>|iJ!VX&@z1kh!<&LFa(qy4PXC@|4* z$L-GWny^+YWoe$bL#ZRWIr@2(rk**p1PsoM*PQYc#>x4u{6ZV?ekaU=M~;B^kmMJSJx0oo;8 z)}|N3Ygy7LIB3*Y4@bWN?_72&?0pje{=HML`y}$y^h1tSI8bgXXk_RJ$#uk3gYs+v z*YelxRWVbw0GFJzEt!ZjO%m;18Un!bI54}(FrJQq!HQb@U?Zm(eLQJ;D_&(C6_hDn zQ4W%gg<TjD)P(9U-rAtsKk0O&(g5d8(i-8?cYU(8K-C?(jD(sUe=8}Jcg1Iyn|N9RkgMD zU8>)mng%;+-|q?vrjjZoq}w642*gpOq%^a+PO^1ZDm9l3~WN}?ef=xiEcYUSfB&$k3^+j4P`KR97vj*NDE;4>%0Ic%A$szvk(a0THWlcn~K)-5Aos>R-VqkwjB~W-ev&pa+xcy=G=H< z`(w9`=t274>X#gJ?layxbnXh9dzlk=!kY`;Bp37F2@UHxIj!|Zrn~fy% zmT^rqJUe#_#EoW4E@WSIi9o)-dF*rBTR;FT)<%{q+us7*U98w*I81IAwvUjrlziIQQnnz;aZ>}IEuhr!lS~|qClX*TbaXrf*mCr z2^1mVAS7E7IG^w2o6GZJc{r-hIi{A{p`*Z6+U#p_nXNL(M_T;|?0C0bIvSD*=LqQ6 zwGmscHKnfh_HUS)`b$`$JMaq_Bao2zQZWhfMiV1eRRqx5EmuE6&dv5Uz}&FdcV|Ja zbr`WQk8-ows&^e-&SqZ6E&QJ$H-_1BxF~r&sSNgF1#aZe0p@~m_E3Sr#srKGxQ0n^4i4U9*d#fNX*4X1L`MUqx~q7YUcJxI8QYY91xiux z@#?<-aJjW369A_~s`%+6E+b2F*HZc)bMjnq)*j1$WZ-|5!D?!k$t%?PIj6mEM(k^P z14e;|<$@m=M&Dx&)#=o7OPnG^11l{zn^NPkn%WKleG5qmwxM%0-6t=CTl?u#l&_M~ zOHwydCaD#Jw!Jy3eS!(gPsScuV3F`Gvq7x@D`!+X!~B9cwjr~6aNS^atA$SMl~#82 z0g6mx>EXxep-?M)!U|rn4W^yo3|RTVbQHzmK18ClF>PrhZ5xQt0gN@S{*3cB_r%-* zQw42hXy6FSA%owN5x6FM+*nF~Wt8||B8IWi*8K&qGs`$SS24a(&ZR_U5Ng-XZU#X> zq9qG48VU9aEv$NSPbyCSx!xH@<|*C6B>}kJNiC$19`@V$moR|O>_jUQ-T;(Q?AP;) zn#3foMlE=z^JwkGu33q5W}2bnEkfIYhiDw~e2lC5 zUDtl6aC#(oYAo57G_ENFAyth_aqR{`(bQsDah`!&5m;-iqxY0!O|@`t?uD*Ow^I!F*I^z4G~ixRo0Db9V}RN8M!%N&jR<@)?yL zDBZBO?_(}U`hfS^J%hSX9E3Ek$1&XW#mR z>0LrG*ZT=dA15N@OqgFp|k@avrTAjCd8LK!kx(Xgc?2zUM zJ#i=$E0MPjDg{ruI}Hg}_YvGV`;?GPrzmnhlI`ThUD7@uFIU)Y%iJre84%mXswmKS zpl}bxi#AYI^rMET4C|*3w^S1t`P9~wI^CpAv9i%$FeuQwM&GI=3Z-j+h#b6ssZRt$ zILD)K2ncq(JLCt<__9L@BU4g#b&X0ePbM|~#(DH|zB6T&yTVEKVl9t3V**;K6*AvH zMV(?=l7l192DvdtT^TFr%s27QL6M6s*%OpueO~2*Q^v0J4un5I^J|Bq-xBKf>`kkm zz93`oweO>T;}8@Pj0OcD6NKmto(St4KeZ|tV>nVN084L=ackA<<_~#0)Mpk@;(%jV5I7-uVRI7* zhR%lOCjlPw6|+cXG}}2~a!?mMh=ruXX|wm=L;+W4agAU}ZQ18UPwcmsVtl!7DAmRM z)DgZF2ts;5pNaq{$)bc|UhZ536A&mO>HC7$hEpiRB4i|cSfd(giMD^9c}(`VFVsRf zeAA7dOw?{}6@d9SAp^-Yz>6B}gc z0bMK0+_k+OKShDw?x7WCUp9t@Zo)b`Pg9#455`y<)ABVdx90W%-c>EDAn0Qy*I^Pq zQj&*cPEC#3uwHROk4@lYOYgPdafc~>@A8w&?wQNSmtedg6E!Z7Kua-oESJ(212T|3 zEMj=^mev~m*cP&ZxbK`1Z+6p z;uP~CU9=QUeyB}}_3#2BVS(Nkn@#gs6isJv?aGKl_N~~Z6l2jpDrw@jR&RV%cm`kX zM-*wEh*>U3`$pN|yqN^?kPv==-y{rW=_@jYtiVLwS|I$V81t4aLc72)-3CY|kom#B zBqAhH3iE%U=f!y%_i(D#HEGELh*$U?#ZPUt%9Xi~SSVe)#-x&-2ZP+KycJo7mdEI? ze|u5i0@bx8lNl#tokc(HQU0(;oEgbkGbG`w(z&{7HY)4s}Id$the70*-Ei;Cw`SmjuYks+=I4J-ww$h zCgAq0b-Vd1+N`~LdXd3tQoDY7GIGpPZMr7o{h*8b7kB7=Ch5eP@yoI4#%~>bHqc-y z5Jf6r{BrUl;Vl~{E8<6M#aA6` z<=rTF76KkG-_;{ND(ubx*&Z^*{V=eE*f8=Iq7Zq5X&kZniW*1VVa%eUOpx?77{^ph zA_jUHmrYrb{0{b3A7&5Jydt0h1g?>RN_GW^vOtjn@!VHnOa`ARPz_{3z=%GHpr)Vg z747lBq8VI8(*umY-_gnU{$E73x1KyWyj*|1D3RkW3RA%et&RgER%7KJzj)9Uws!En zi^kru#4by5$`5EM!5%MpMr&y$R@rMt`9Rroqg}MUiJ+ZN;@H5t>Wb-IB?25!;{7TJ z&Bt7`a0gFIQaqbtoOpoU4N0BT8Gf)vM;Q$i+LxB@`Tp9!NFJZSeUnv3L7i~b7{u`7{@2q%;!Hz{{=R!#` zzu{tG7I_c8EX2`H${+n~!z5S2q?yUBvs3x@Sf3@rD~|F_eH&QbPsJ0Q5H+*twOjzS ziYp83Uhwp6U#di-OI+=y+Z%ah$S@fQZQXE@%gTO_-;4K=i+NI<;6gtN zRRs7u`9F*eB3aT`m>9mkw{D8*oF_6{!zU+WXIFnkj~0lQq37Kj+B23W;DU*56nR}O zXIlCoe(L@o;G?Fnqv-_lb4%pp(J%EWx&^1{)5pJpe(_pxgzr0J~CeC^{-+by;b-i*J+i4X~q+8jD=$ye4R( zVNvs6&4`k+NYbr@t~K*n+9JwY1h0e%izDDmE&!!YCK0Tw(}<6Rza3K@bf~1o{rni) zFKmDJpUN0Cx{(%qzJDiu9{;OI?L|Y6ch{bYTl77Keer6D4xT9y^hSv zgkFNE_|y&>SEK%RD!jJZA5OrsJWu8vpYPkx&_7k$T-g887$5=}+bg?2zZx%!*sCH9V$_1L&__4wi4LJIS6;SXX>a;f8?(QR(}I1N zJF8i~RQ_&d+0AEs@q%N6XM`m&x8(-ZTH_T3PKr*!*;w04saN9xZ}E51vGnI+g=rftiVljOVyc2>4VD)v&Yrbs zj+u#y#2G=k4xV!B!U1OS(-tlq_(?uwT!*ks3)B|mY=_efM^lYrrBoYDd^= z`wt?VhW{_qwP0rIS48ztrK_;XlJMuuNHn`{i5)iF-#g@vg5xNu#?zXY3q_v8`co#v zY8$f2jlxE2>i8UX$_OWJoE}jA5`#bT29K>~GE{LruYtFSw`EIMcG8lmzN)s$9lEIa z_Jt}TKLCS9w8Qgk7I0tCKeFyYV@JBTqNl1S8__+DiEvRm1o(tc5a47F@0+WAuam?e z2o>>O9zq`6+?Nx-m0=!V@t6~<)qDb~*5-H0Yszym+o-?OTUu?UtHyXGYw9q17DHmy zC$)$D;AIS5JE>cR6&Rk^D}Tvxls-#Zq-`djl>yeDXzMs5dkJsD@pJn*_Y=6yk%d~p zP#$^YM+Zd?q{@!LW5Qxr*C}5q%yo#w zFaWZBLU6Y11Yx9Cf8`S$TKBT;8&v$bAk*&UbUf|a8n;bmPJH`2Pwm{JpB?dcj63PJ z&N!ZZw)d}Oi=2y|V2ex{6~QtcDv?t$w;hE>AqlZv(nEAh^1Vi=@a4>k+pi~dbdy^< zX?FBN?7c+zD??M{O#XtF{S z$b^P=^9Tj=d5FAK;=s425Ovy*j|6qM$^87L<8rtvb=ZW=Bd;$nV4AN;(1WJEn z95{#&7(FzpUT;AuqlTLi6!dnE3`vIR`|3cIu|z?$%e;7SE~JA=<0i*=xC)yJz*L7I zwFx)r!kmEwAUm#ovSGq3v2zY=fKOA*Q!}olS}mH^U;&TW9Tqo(*gX?_R^9Bz2}$=gmI9+yHTfaj^nYLPD8$CzCUKhs)A?~^#YGgU+lNsZ4e@6jJKsk#;y>zgeV)#vAUHd}MMD()+mD^Y#_K0= zr03*{zr9nz-RF6H>za3Mb*;wPKM*9*E6#@?qjbZ}-3#BJT5e4U^=F*X7v`UeX8s=yZCdj)7l^<2tuRQ@3 z^scO2Sb}|YMddefP@vuMED2OOox3dB20M32VbixXur?IA1wDT%Ya@rRi;5^WSVTb4 z`GMF9;^>v>vB+}%G6{5m{)$fW6LGo2oC zz>t%RIK!nMqFKTw`Ec=1q{hUo6g%bj{;AcuS0q|-B6e!V?woD6F&j;=J&1Tp%!Q{ywNpP!ws*>502=5Qb#lr1rA)G?*4>!BUp7b9QDsugW$2x;3Z_A z>20GVHcVa3E~df)_pw5(T9@%8j*SUdyoxy#u3d23@w)~HK&kj2i7KC#F1?BZ?Mwlz zLMfINKbOzU1I@*BjVeGf_rb(jeqoF@1ZwV3#ITBXNSg$jLU%^6I?~$9$Ob?Co?U2P;A+$p$%v z7*oR_*;yV|JMv%)Rk8Dm-NXem7UHbxAx>?&^^^zf)y--B!h$=89Ds`5^5nX?V!v>w zrCH*Fn3QR^%$beo?yv<8m%Q335nIRf?< z6HFYS4ub)0<#-WayYMq0EU%gjII{t9N{F8SdEO8xD(w17!#T{)0_Z zk85#9BY{CYE->!5{aiwyaUYFocwSTSHHoZYIFxI2#4-)Vf&5)dlT<@Q2^A5&` zW44BlsvJ{md>RXc8z98Cgylo=#ie z;WAAjh<^$O@lQJ24U0D12cmEl!j4`#Db}UqLX#apSKO3d(K3&WXUdbE*of?HkSAc+ z5}w6OB)dZ}p&7MDoWeO!rxIhi&s=JO)>=5Ej|ooMK)IJuC*v%rHYmU^0o5oKB7`&m zAu9fk)b(Lzu2+i-9d5Lc)1zkhn32Y%Ii<|3@P=detDfX(3Ay{*vvF^I z#EYV*z-}C*vH5scL>jdRB`F(W_zKWsrA!`Lu@@vRO1Z+t%|D0prky%KQF*G~%R2-y z1Q8VW`;75O9}GJV)=&5>`koQxwlS6v+!>3I-VFZ z8?kq7B(tO+D~f8TI~hl{EX9~-<&E$r-j8!vyF3v)IBV>0*b4pMxDm6K1*g9&fyA8#V#7@Z13HSz%O5m$?GFW85!yN+Lm1b9(w%OBF>{unS{ow zBG1l#O0%54K==r5O^2ZJp5bhd)r-l~Km+19hZY`LF511VwvC-|Y9FqceCJ|!RK!%Y zyP9dt{n6bUHMej_`P1ot6$7A`^BMd2tAPe$d-u!fKjrq6o-W(aqs8Ae5=0*-(+ACg_L886K3jqtO625^navUw>;vz6V~65iL*Sp`SEq|8l@*?`T{UN?uVeWbF?Z ztcL_iwrU-wy+9N54sUG)gvq|RonOq!lV&{>X)mjR(x>PWP^Abcv;Y@3LtZlAET36e ztmUrx-vH9@^28!L2L{!-fz^))hoqU+Jd`mCr_bN)(<+MI|}-TXa^IgmHOyDs6!N0{MkF`ds9dZdmz)eR_bPb!Yb#Xz-3JeaR= z#hGq%DuFc5uhC6x2)BxJWfn&$zu^snV-f=sWPv2g{#Q;r4&_o<9;^q%O$>6CvePSH zB_nQd<)Y1~u70kuV&hZttVtNldcU?7fx*-_C4CGto>;QMFcAX|$hSAPRyWVE^)H|o zJLhYCAH8VrYys;bzJDTCA(6PysN*7|A6>OPY%2{OpJ32&44Ie2e49eQ%fQ84%EydC#yS)6cw7i{-hIDYPtH4vJOq7+@S)S)`?J0 z8Lj95=7$2MwwHEj9&SC{%To%r(#%Vilwbt!cZVqE^`f++W?1>Q-`S$O73?_zySwC6 zC-%$M-e$Bk`(LV84e%W>14OOtp?XH~q5`a0N1BS2KoFu-&+U4;(HeqI&xi}F!V%pX zi?@HW`)hdiOJcbVqoc>F0Z(5KW~&swdqXgQpf$a7es|%R72*zfpJ9Iv^6oc2=TKY| z;#X++qMV9r$TB~X6|yhP-zQ~ly{jqN?kh|8YLc()h7CrBUznAmqCT ze-vSJxzEU9_{TOZ;@sV8>l@Ui)rIOAKhmG4?^H2YlqEhAx$<6L#{(|4S|c1&g$hSa zB&*8;hz2ekR*;Ruw77-u+L+Gv!+^^{MTh(~!!t*wJd0U=dt?YY5Nn-`2Rz6@y6l`S zYbJDmVuP|OSs^|x&GE9E6eX$JBt!&bXzEt?&vDQx9yZN{)FAi8Ymwc-fGd& z2I%kYz9Sd*a3RN27lSXzZZE+uuTZRa;K7>n{li|wwdVJjJaBNPk znvP+C>+Y^FkQW!=*4ODehiZ?giOv+NeE8pG@Vr9Qi=A&U_5dCAzU)SHm!geiGQE(O zB(aW<2}-n6G)&GFv$%J(+j)K4#D||pC&Mj2cCH=Laz@(KV%$?sk=9^b^@ZPktGd4` z`A2yrow%q>PQm|qt`9#$u%3~o<45B-O<@!!*<}xNB_b!+WoqMp;sftvJm`ct7^?CtmQ5@jC(JKF5b(L23G{8gmH0GAO^TPy&Jm#Q>;1*w_j{gs}|!4 z7P?J3R&0@yNDn+a(o(W1?~uqH>lH7P^BUJ3S^<-6_axJ@vp=%?9!==#nKi(eo;)#< zQt`4nG9mxjXv5*Mnb5|y6rl2xb7>$^^(Xx@#x2M=2>$*eeX~rGgVy1(Uvh1xE;vFA zCl2}b881L|C^WF9BNteLg~*X8It(ry$Z^xaMjy&XIPW64Kq~jYll!l@qj`z}j{F)T zvah8E;o)C$(>_`x#eacQ$mnXU_rgQRc#ztGeQhf4OPinq&>sXh&V4hWy%Mk=w1pPp zLb!`*p}5#63)w~Hu>=iWwoaxIYy2XLljVRVWw|DQ+CMxN37%(M9#3Q|N9o!F>J?QU z^jF%#lo47)(Km&Y#j2-n%JrrbC-oh1h@MgPM>XIHh=Tu&yTmF~AxtnGqWD17tCNHs zEK+Wo^Sr9S1_e}LjTKB)>$zM`Q;4ivuYI;<-*)NKd#u$&IbQ+WCl|I(5ym3BRUM#! zsI#%b>^S-$N_m>* zP%%`55XqJP=b6K{r2D^*HO`&qo68=53P*~+bp`#OcokUA1r*=wa)aM4r?Rm*c_kXG z-u?0pdol@|;12!mlu9v?3x)jn900*3!xVeu-qA3e{IY0~0#ivl!AlKzmjTm8y-7A) zn}3b_$DWp#&gaxcasDYYd|i|qg}wT=wy!!aUNRqY9D{NM+uJc~&A)oYyA1@cbi5D}WtZB3(V-9{Jk!g#hhgUt1cD z8hPPvLlh9+(!hM4?3;d`CkhiyOFC& zQ=#$ZY!wb}r&gx>&~+CzsMwd`tqjhp#y#58`2o8A0g84bxTR{mT23)fB*Wm?JWT&& z_Vckbc%LzTvgtjTrMM;RQNTflryGO)8qrUf3VK*g6O_D?f1N=%l*U6CSaeo&(0P(S zqFwl76(d-5C2vg-#$j%oWt^nuQ-0$>;hc`_n?b4xus4532coe2SaHy@MAVI%qYRHU zs%Z#4QTG-cmk}CF4Y9}+CNM16qf2U7k&$HxxAU_7UBuff-LkEvJ;}4sG48G3Y_!}Q zg?3MeKxX2Sc1v^|w*~0(wyJqet z9kAv}clR=@qnQv|GwLQ=g(u*ox>bhN4#=nKj^|PN@E`ZcVbDhZY`?Uf5fxhorMvjhgS>&$|%Ff#eaWX zKx8m%=%;}qDEKF4x2x@dus+2`m!V>!bSvdW>kv;kGCDs<&C<%VS14-WThw(G_4g?v zTL@RC1>21w%Fy1#2Ky=+T9NH)od|1OuBp7nHZw9)*oCTFBZsdtLb#=$u?@b`7z_3xUGv4?0$o;{#3UO+^9|6!jOiKA@E9>Op{wx4U=`Ya(MB;P&L#T zeMWUdCC+frZEf&gu?FDU3VUX)(+H>2VoMH{ez}lC?a@>i!3OXpV0Ihw_&u~Lx&Bk( z)(ZVrt@CHIp0keh`BHMhmIgy6;m@9SDzk$!HL7qngG-2zok!u1S=wJqVcALrvz5`V zWIB}Qmzc&7dA{DPB?OlDpufyum<0bqk=kOT{944}P{sYvX#-#!A3h$O>D={}E$mxK zAA{_Qs7Bj`ljG|9PZ9hE{5FF)PJW8hx0E|GZe@{4`P-H;opjXEk`}$KU1e`$cln_D zgb48WTtJ3lP{hwsGPxQAsUZHhPu}qPaTrf*qpd6YO;}R0jn&sbFlPM;al%VW^{Tlx z&oz*U7B}DL0rcpsjBt5={Q;Yk+A%sIX@*KK0FY53d?J{ zzY$z{6lu}}h=2LWsG}s%*>5AA#T`nfvGmJcyERV>0jYp%vOVnasYr?mA7r!gbS zMAfS2Lq8s}$!?qR_A$VMF!r+wt686cGehg6*#;=!Vd?u7{vkH`9%RFo>3~$M=itZb z@mUR$(cGeOlEtg4Z-vcow?p!AuDoB%l*VR>DRHJx7|0WzJ?Un0mPBLjLQ`?Nulv7y_BVn5uy&M*m?W_I-D_1V^pxVJ8U1~vI>!!WmxodJNIP!3XId7Arz((*Uc=4@ zUX+3UkT98L|9D7j4VCQMPw^KlYOgszHHrBER~QEqr;WT+sS1Cjn%Mk~0KZwIe zERv~1blUQj6R6k_=s`JJDx*5Jj%EUn>ZF~kyyik#YIkW+j=XCN4q!=ZDV;&iLXNZ& zf19&?9p1i^VvhNiLkE0gde=crbN0L>j4gDmke{WkihM#!#{#`Yah?;ARX{A!$mE)3 zqCX)PAwSgjtKopH{r8&KE5j0mA`BaBbMUMN<6RF-M%J@Ggiv^N5-D=1X8SSipgRGq zQa#z@cnBI}oH4x~4WNr^IZo%jbKeHu&^nehp=RIdNtZ!HT>3r@VBWuQhO4O_+)HM2 zAh!@)@GPmyv!YWU*Y@PCWN*;aEt_<@{Fg{cmz&yfXoWiJdcj`z-G)Y5V3y%lA$f$S zVsXG`%SGT&>|N(a>@9;d&u>Gq>&z;+T8j=nr-1gf<0DJ$9l#g=_%pGdQNgiihGR0t z&rD;K+fQChDjYp>4t5q$DlGvO_v(Gng3D<*MtwD-xtw75dlDUG>6@0*zoERW_4YRI z+9<7x_(UrhFEC=RvyR2yW1ao93BS|Ts;o#-A}(xxVrpc8V`}l@vtvUEoh^9>4&w+i z#pf1eUH`~KKmg!o4<(f#x8?n&F*vFzp+j|FX-YgejP9S z>r9U*FxQhkw_JuP$!Ed8w#tyxKf%tXxNYy~%`=f*lNnrgmbXoFr59N@>%qi7(sfO% z&4Wzl6kgbP%pY5j{#i%TUJ)!+VJVi+XJ*ph3_3#tg$-a|W6!2_Ay3mCF|a=vBRa6y z^9^B~p7XP*+R;*q4M%)s1fN`vI7Ojz-zkC%?#L-(i!OfMrUBX~=mIWWQ)(kz`7k3b zR`)QYflPgP`X`NgO$6#uq2gSb`=;@OIOsNdMO0gdRG#fr zY0b;BxG|v6z2O^#U+8@hL ztR(g;yO5i-A6aIo)tC-<87{(~XBghhdc!5Fk?qQE`PjeQTijX> zoL@Uz%&4X?2S$+hN7bCy@Xz6=DFE@pm0D- z#c4>B0SW_ExG~>r!rOb~$sB&uRgu!L^wbEZRG+;mc)qfMeFGn#wgZT4as@^8xlh=G zzcMEiY77YEe%@I=57z!l6piPr1=_sN)jpuo3kxm5F3C1_3u#NWZC2S^O_$yXESU>u zQ0jn&9~-__OH|ey;%pcO-AklpTl*t{o?AjdsVpV z`l5FmxLO^I77TtF2-ED~51gJgMA@I9)cdnx#(V;Cfh5_qRk4MLr$+_yrV9nDDRdbr_kTRvFp+f*QAODTV%4^N! zO-7CzEXF>AHv~`yc!-Ges&c%27H`k)^_q!HUb@U*B_h}8yd=-+A%cE@N!Kf&`8MX2 ze_G;(?1@^oYg=lT)G6g7HZlkBlM->(q>Pl}h?XN-GX;`(k5vdDnOAo!a2#SDMnbY} z1ym1IendNE9_8XZ8cZ-(nXnvsED_e%js6XiOdP=|=6hd*wV%>2f(c;VKJYt`Wtt2 zy?#k4*_%ek1bG}Q6>0W#Oje(difN5q(wIFBGhN$KFj>4xW1V+Ba3so+C@a6P{H`s# zgO%RfcpZGcA$jZmH_EQ^Pd=fW@{zTes7?8|@ed*5z9>>r(Pe&Fxu`-@xl@#OlC{}IDp zzo%kL$nBl>g^5pZPU*Q&fb>Gm^qa&|scg+#+gq>RzTSGXweu!d0WzW1EVi?$5OxQY za71{-74~=+z)-M$7u?RF4VQY8lV0sg*+9T%G+nRE4s+IbwBJCN;NFf9Pvz?TNyk z+6`dIv@^!SH${Wq+k$a$G46x1$un4V=Sxh=njdFPrl!Oh3Iph&0~kUNi)lPx=CK}m zqQFu-IQJ?c#ue|94{phs@68V0)`DD`tFi}J?aZ}kzrFppZb@tn)h+GXnSHiortk&C z4|Hj5ob~R3;L^tWOc#aZe{j#EXighx1BxO{#LjjN0{Z?VY1AG7<;Kwl^Q0AX7QHZi z9LIZ3U`=e{d!m3wFW#NqcG+IUT^C1r=QBa3jK6Gy%)Yw^uSb-T&D)91dqL2-uF~X8 zJ6AuMXWVDVqt{5{mX1xVz72I_eWr7Y3OG6sXOs2k%xjZ2)Pj?le|~KZ4?3`F-lsp)cXMW zM@-Bk`PnTs2D$oGLV5m!TC`jmaBIGhn}qrErst>l@qWpQX}UKyX8H#udc;Gd==Kqv zpWW3oxqQ0rhLJ8>f7vZ}hw2LWx-X~Xc1mui_(ZuO&nb zQ~#1=Gn{2Bzho#-dWN`hObK^4@Er-9sc%TnLRsICduNqEe>Y+b5m9tUlzUf&GfAEu z6Cd4b6!tkpDZo1jC`ak9F$@AkM(Go!89s;v9S)Oc-;^_$>Lk4rr<(p|+{EM&(gpIB zlJ>PzSiMxMnp+E-8o9}}u23-%cDMM| z4zMYzcZk*Xf2ZtLvvLZoS?Tt5<1J)ev$SLFYvy-4s4^5OQE#JT} z4`?yN^vD)~NQ`eckEBb8cpbPU-R@KU!S@_b{>@tQ{bZ?6sGqrMRCVhG(FpM!G zCYhK~hPHAfR2qa>X~kXkJx8NvXWz^0?{f0J{7V}h)Cs;ewm48I!Y+Pm%p$ym6b&-5QJLcUS>m@)AG1?*iU*|FEL>!XpbNb)ynfyk=j-h3{wa{cH#S5Wx;;VR2_AW(a zS>~zAxsG_X@R3XRYgu2AduOAcjB`?$oO{$q3%plha+I~rvX_jhb-p|^{FdTMb1F5x zHY`jv$N?nndb|uoXt|f9)6xzf7f7$`|C1pM)*VH>x2f&gvo6fB0vMdXj`iG|p z#1Q9jg!%w-9!)SA0W81`K03hW+X)q50);nL#pPqg49(}sXC4d! z#K4V8j4miZgh$Nek3qN46T#GUfAx2SxVj6U`4DuAyhtElPx};n{BnMw{Wf$9730Dj zpuZy+$j*}74|1OzV1MnBe8Xa_b>f(tmIhRe3uBNIOBo(v0)u2g6F8Mif*=EsUlJa9 z9^!l$1;I2KXfn}#a5KiLqvSFFZZgq9n7qhe;CV(csN8% zQqP0qL%H-*DTKd=Tql0zYByYxv>3-D0wrMSgFz%rGeH2T7$c_F2?@lwUO?IXGfpGs zq2GPP1tv-p*1sf#s`U99<@5m(-r92~CEYR5Xhdg*BF`3kD*0``EqP=lsX!db6AA%G z!SJOnGmx9YGi?|ED+zAWf7%*27Mez~3G%^U3Lr>Cdk7@^_rNoK5MqR_wssT$xGvDoE}a^6^?;DqGC*ch&t=Lck0iDr3O>ORK;Pij*x5_yUJ$re_~=bcE2p9+!Ob`5LizTwt9b zKl4K06hj0m2ZHp`1&$~G3=Ja^x2&Q^=&#U`H{L1sgekdTPy>0lCG5AvJBjPciPjIJ z*jlu+p8Tgb(0>@RQ5uW=JQ_$CWPZ17uF$uTn$M6iR%Xx+!bj*Sv zc~|Q^|C)`pt`_smZksFRMlJSJ%D60-_ltF!i@OxayZ1WSjis$vFuwbD*z zU{r@=6VFuJQ;=Z8cG}H6lxy8>g8EwL_Nc&??W136klD6g29M4k8qE=7M~oLqjE$t- z@)WN&5r1DbbIRK$xAJoYnKzbXrISS^soue;qP)oA0Iw-0QWcD$55jFQpfpfHYWe7d z(yJ)6GPh($l64)IO*U9wl4?p(&A|YAS0D<3pdgS`OoyCFf~{*if(}5FT4yqmXRyi^ z>LDEJ3qP`wF<;z_5ks*BC)Sx?l1uXG^ToSepnq&MHdYv|zAsy0E(rw5oFxGP%PqcC z&y$jC9}8BIjJo}j92_44F^0q#QZgn5Gb6uw*#Au{$orW_&&(XCM&-tUy8I>43dGon z4#lE&{Gc@6wL3GYOd>9_29@%Z)Y?bgPZ$LB#zb)Q|4fYxva+HEYoKg^ z(SN%~*(VAOToTnZ1&ZD{Lya@kI75vy)GXq1OrGc7ode_c*+W42(?S`{yg&^Kl^IxfX#6sETdei+GeSc>ub0w>zY?g234kFm(ZUd%0Sqf~W;aOh! zE!IqgFC88f3WI936P<~`pac;l>pa!`ST4BDLvybCbIYzimu1XSTh1zNJGsDBo!|SO5Z6i=y;staZiZHH3hAhD`dsb>ZC8(oG=Sd0aHl! zl8t;3v)Xe0mu$2GO&nf~@;M@k0;b?t7piLtrd1mDuN*~s;1t2nN*+FWJUk+nG!__&cW)Ia$+oZyG zw_L&oj2+?NtMYRaO$>CY4DU1eWqI!+&+A&%HJI)B7`5V1HMMN1%( zcHNeQ7f02he*Bdks+#HRP_sO19U6&O^J(*+?Iy>+m|Y(P7!e^KMIDoURJAl`Xi_DB z8#5KXLClT|Rgc3WCSFy|e1dN%An;&%)k(9I_-ign;edRO01?5a@fD_| zApr*gikrJ6X-iL1;eX=TU<*BX@ofTs53tZd)j5cWz(FpQIb;l9Bc6%J0f`SrNJpel z1Tjsh;ZZWgJ|Z3hJ_^Nn&Bgn0@jhIY>;NT*O@2y#jmr^9g=YRU4nm@BqvgA@W ztXTfw%{O(1`S_TH6q9m>8*37ws#}|vbUL+JBqDCpf`3S;qKY8!m_%?%7`)^q^7~+d zAW0IqNjgEvZvvoe#N_$80`LY-!I04jz`{9PJ%k4JQxuea5zWI4aZN;kAb8~G@@<_- zcuKsFkagzUrtVC(J@X`{4K*J_Q?B9+D(2j9^afLtSbpu2eBnm_zh42A#(Z)gSe8j%_buTK}o-vqt%?rbC@= zz^7cGNxM^AsW7RZq}(eTg^3Eyrj2VqaV{HH<)L&fe&B6p&QnU{U`uYx+ zN`EGlP4Revy(@jHzMdVKt7v5fuB0XbQt9ZD>uTRHIiL~ISs-Ur-bc`*BK1&i_>!Jh7GARidMe3=1s#3Y;phOd~Y;j zXk=39Unsh>+3y`f0c+Of0#6VZa1!d9uzzY>o#T;h^&`q;aRLLS+BKmn5D_LpSDcG< zKj7*2ngp513$OAITk_RhqqVnH9}5(3r}!`Or1XHdnZUw^X>&_h?TN0bqSS+K%(y^E zy1}WrMt??4KD0$(iR^)U4AWm?0xbrevWSiYPZ>_P!565N4MgpLig|l8o?*(ZZ+}MT zNo}|46%4N3;42t#mj=3qI7k4)6XyUaj=R4jS#`)Vh{ER3FwH8Dt2nZlg+Ko28-PnGJ))BF9^Dt2eJ)RDh+1}+=UkErR{7% z5Jqf-lu5wI)E@N4s1GLaO73|qKz~R%$Adt{KTxVeLA9qa2O&e(m_|I9=1u=|YZaf| z-r8!gI_dSAZ(}XQ@|10=S)r4Z1QDsTKUHq9feOcgeHc3+YeN)(BZ!^N$=RG%=D=^) z-7B0D@2fch7b;p!r&FJA!v2==fYQLmCRJ*`nI7beXLj<<7%5Nu-0cUGz<(BVO$z{J zfKcJwKOVsS!+2spgnRbVp4=L1@i!O*NbJJ^60g0*I9J>97VvZM%vdGx=$MFE=eF2I z{gKU;%-NL(=9w`l=dSj~p|)b%^B6%t3DPxQDF0r%8@p9!C%ZN^L@0UbuACN+*{d3Z zr{0@~Xb7V~)P*;&J8k(!s()QIT87=IX}IZ_4E88O<LD-3;HQ12oy=c84vjMZ@njCZrz_9!yEFu}t2~nQG3$irf`B0p zsh~3uB>XkjL3=^utA95chG?#Os>&Rw#4;wL$)XRCV<;{d;KPxDw~ac96U@630a>+L z|M2}srxR})Y&z?*2naA2Tt&pm=o`>n{I6;UmcF7iPgNym??Ne3{piOY9p9~dm@<1Y z!>6=^#G~Gx+v|-~ZkjDff1v4wGCOu-PrChCynpEvx-stmTwe#M7QoW< zm>Se^Jd$HuyCi$p5CPDj`-21Ie(m<*Z8t^cVc8(XhV~Xe#6vE z%^b2hsxnfN}8D_ckwR_Ezu_qm%6KPn38j zlj>I$220G=+}qW+cGVJ8g^H}qFgqB8 zJ{n!KEq}c2QI2lJc*;kwZm({`zlUV=X6XI1Gr8UzPw17n8ThwX@OGQ`eznbTroOuE z4W!I>cc^OS&oUBYGNEmIis#;@AG6q&>Ehv}>pdF1>DqpY*?+C8#hd-^cua#~GDkP- zPH(YL%iyk0;5hetDaf(BqW*ByB(pS*200qkk$(ndZxCkp{?Y>TRSl)PU6(>xgVy+J z!F;Zug;weyyI!8IdhT*3vvg>M8p++L)O!KOYHl4X)kM$nkw<;)F$%#A3WAsBf{_{b z!qED?hjVpG={r1Wb;)AQW<(4R+owOwR&KAJQ|W$6nwD11K}pxy6hDopPE`N`Ugex! z`%D04^NFb2iFAUr9?!TyRC*UBm69t>Dg$}y-|bVxRX(6GypFFyJ{1q7<=GJgZ dKj&4pC~~W^&;I!J{{jF2|Nnidmiteo1OSlMb3Xt8 diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index fd98bad0d831c578aaee8647650fc35b33430b48..b653c2e7f7795f541bfd2b3aeccecc93b9f77a89 100644 GIT binary patch delta 8034 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 diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index c6d1eb204fede74e7b3e5a0c3907fac345db636f..4b2eb6a5a4f3c66cb107472c37695e8eda692360 100644 GIT binary patch delta 2408 zcmV-u377WK6V4Nme}C}Gzz(Q6w!=@fH(Hn_=`^LpRh-)Q0Q=OrR?2X$(CT9wsRAU(YYaq9cq~e0ipm7bR;^GRX z268*-`z@K!##iPN%YtBlYx)xmW1Cj-C+Yu&vA%Y-~rxD5Ug2GBX1Zs zuuBASf-Ufb-p0w|+~tz`TNYkUY_r==?Q3dh5_9Vx<{TWN&lsMFa&g7h!A8^ zewE$S%q7=YWgW47X}3DP+l-Z!Tt+WfwX~rqrd9cxq8TW}(XH+zJzMFqL*BMcR3@ie z9g5h1z-Bya2edNd*4yCEdB$JSA6&^wgu=WmB)U7TgF~K1!GP_)fgQ?XzrxOejIWH? z+Ka&emGffACy>tP1mn{H)fHLPL zkKd;$hZ8sEF=*HGYZ%}I#m&VrQS-357i)fR`rH1ATTlTmM(h^DiZv*Fg`hA`JP(JM z_5hdCs4uNZg`^HkAU0()9Aio<;kWDu!===?7+(&5fXYnOFs_Dirv~HN{Twe&8L{b4 z2!GF_q&rU#m(Bk~?N@}&DtYJa*&{byyXT`&p<{5*TT)gnS5snZzf7kRRI$DF6Dt)r zrefx&_H4ChJ2lVN>1BJi5u5Uo{!Ei(rzW=V1L&T+{8KpELGlz?{5+$$iB3h7_n%y< z^;8-8h@7f6FB4fLQ<31c+l$@y5ahfxa%KRAVEB6 zInoWo@mCrA?}Pt8ZGcxLHGaeJG7|U@^RF^^UiXPoG^?!@l$bf-zKGU-2z##WQi{=S zJCfMQB2y&xwje=pGPNn`UUWOzrsNZUfa?H9l(Z-@%KfChD&XWK4>d?WDsOxYAbbGvaYxCv5TgOq`A zmC}m@akheZ9<>@@zwX9Usll?+xz3OT-m6g};BWv8JF7dc7$E3kn`_{t=Z z@--M+)PHx{K0SRMk{lJlI);#>&fC{#8mVFQayU% z^F96(1i{TR_hM^`A+=-${C}8S%64g{o~Oo zq^aCYUhX{O+fasbpD3t~_v(1>C4<^`Irq6XcrNX}i-Out`Qi%Q8p6mgp86#m+NpDx z$EG~TfIZVv_VVyp?TBhebaIX;=MJ+r=wkuZ6D%9zz2sQ7!kvmPD#27dTT*+fqtLEn z@Kh(CC8;w9wU4iT{C_L*@xSL(&Lliym3VVQTrK3>xZ~0~r1+{@DoXVc2e>Aj+dHbd5`#Qb*|qM593t)|Qh#%Z2*A4WU zE2QQ`|3xK|pcG}Z8|IJ&Qsf>GK~s1{5=_o4i4;fLh>{smpnoVL?~xW%%d_`bNA~x; zuC6ZB`q=Gv^6qH`2<*LO`A`0o75OA}exM;Jo9&YP)L8lAzqeq)Pi7Q*e^~tG0{eVl z*Xt9-oUHbrM1S621_rC77{(}bMG%Ost(f$u37$`XRveRK9$pkv{1tz#UGt&UH2v_Y z*{MbIS46X$lZ?@468PH+k{J;0RWR2>)^hnOMC!Som$cepz>cuLb_J~ndeSJ;zErI`EC>Svdo_2iUBlBkX1v07C7*eZ3 z#yq)(`gwsmbzbOII4QY3;5RUOt?s*hdihl%qdLHzd=xEyv#~_v^KuWL>U60m4Bc(TB%7p_Knk*1O{|>$*Wgvov+yWE5 zd7M*ojwrLJUZS4E@oYs+ef8WW<~>;JS(FdH39}GEpLDM|k@H4UaQ5>sK>fb&`bJZI zqbb0G{hZ8XsLLgBU`Ul6*R0LM^EhlX#z9^um0`EAP5Xg-Ubo%tysPZ>j#YeevWeda zRsZrRsFDJ-rppweXEQT#(rn3D_dpYyoA(lVOi>%DIS4>R0Aj(t7Kwz%n16@n7lrNB arAprR@oIIu`fmUL0RR8Kc1!k#asU8O9K=2V delta 2411 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 diff --git a/build/version.go b/build/version.go index 92f011424..9262af171 100644 --- a/build/version.go +++ b/build/version.go @@ -34,7 +34,7 @@ func buildType() string { } // BuildVersion is the local build version, set by build system -const BuildVersion = "1.11.0-rc2" +const BuildVersion = "1.11.0" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 42f964715..b3dcebaae 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -7,7 +7,7 @@ USAGE: lotus-miner [global options] command [command options] [arguments...] VERSION: - 1.11.0-rc2 + 1.11.0 COMMANDS: init Initialize a lotus miner repo @@ -42,7 +42,7 @@ COMMANDS: GLOBAL OPTIONS: --actor value, -a value specify other actor to check state for (read only) --color (default: false) - --miner-repo value, --storagerepo value Specify miner repo path. flag(storagerepo) and env(LOTUS_STORAGE_PATH) are DEPRECATION, will REMOVE SOON (default: "~/.lotusminer") [$LOTUS_MINER_PATH, $LOTUS_STORAGE_PATH] + --miner-repo value, --storagerepo value Specify miner repo path. flag(storagerepo) and env(LOTUS_STORAGE_PATH) are DEPRECATION, will REMOVE SOON (default: "/Users/jennijuju/.lotusminer") [$LOTUS_MINER_PATH, $LOTUS_STORAGE_PATH] --help, -h show help (default: false) --version, -v print the version (default: false) ``` diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index b7e04e5f1..a983a596c 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -7,7 +7,7 @@ USAGE: lotus-worker [global options] command [command options] [arguments...] VERSION: - 1.11.0-rc2 + 1.11.0 COMMANDS: run Start lotus worker @@ -20,7 +20,7 @@ COMMANDS: GLOBAL OPTIONS: --worker-repo value, --workerrepo value Specify worker repo path. flag workerrepo and env WORKER_PATH are DEPRECATION, will REMOVE SOON (default: "~/.lotusworker") [$LOTUS_WORKER_PATH, $WORKER_PATH] - --miner-repo value, --storagerepo value Specify miner repo path. flag storagerepo and env LOTUS_STORAGE_PATH are DEPRECATION, will REMOVE SOON (default: "~/.lotusminer") [$LOTUS_MINER_PATH, $LOTUS_STORAGE_PATH] + --miner-repo value, --storagerepo value Specify miner repo path. flag storagerepo and env LOTUS_STORAGE_PATH are DEPRECATION, will REMOVE SOON (default: "/Users/jennijuju/.lotusminer") [$LOTUS_MINER_PATH, $LOTUS_STORAGE_PATH] --enable-gpu-proving enable use of GPU for mining operations (default: true) --help, -h show help (default: false) --version, -v print the version (default: false) diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 1326c93f6..aeefd8dfa 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -7,7 +7,7 @@ USAGE: lotus [global options] command [command options] [arguments...] VERSION: - 1.11.0-rc2 + 1.11.0 COMMANDS: daemon Start a lotus daemon process From d6783736dcb119711c120033e37d4c107dcc2931 Mon Sep 17 00:00:00 2001 From: Liviu Damian Date: Thu, 22 Jul 2021 16:31:28 +0300 Subject: [PATCH 21/51] Nerpa v13 upgrade --- build/params_nerpanet.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/params_nerpanet.go b/build/params_nerpanet.go index 6663a9162..3cba64ae2 100644 --- a/build/params_nerpanet.go +++ b/build/params_nerpanet.go @@ -42,7 +42,7 @@ const UpgradeOrangeHeight = 300 const UpgradeTrustHeight = 600 const UpgradeNorwegianHeight = 201000 const UpgradeTurboHeight = 203000 -const UpgradeHyperdriveHeight = 999999999 +const UpgradeHyperdriveHeight = 379178 func init() { // Minimum block production power is set to 4 TiB From f4fa4c8cce4d4dc1ec973919bb828a3435d90274 Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Tue, 27 Jul 2021 17:09:44 -0700 Subject: [PATCH 22/51] fix(marketevents): use ReceivedCidsLen improve data transfer logger by not reading in entire cid lists --- markets/loggers/loggers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markets/loggers/loggers.go b/markets/loggers/loggers.go index e5f669f2f..2acf987cb 100644 --- a/markets/loggers/loggers.go +++ b/markets/loggers/loggers.go @@ -40,7 +40,7 @@ func DataTransferLogger(event datatransfer.Event, state datatransfer.ChannelStat "sent", state.Sent(), "received", state.Received(), "queued", state.Queued(), - "received count", len(state.ReceivedCids()), + "received count", state.ReceivedCidsLen(), "total size", state.TotalSize(), "remote peer", state.OtherPeer(), "event message", event.Message, From 8a54273f8b03a62348b54723e5aa479cac605156 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Tue, 27 Jul 2021 22:37:24 -0400 Subject: [PATCH 23/51] add v1.11.1-rc1 changelog and bump the version --- CHANGELOG.md | 179 +++++++++++++++++++++++++++++++++++++++++++++++ build/version.go | 2 +- 2 files changed, 180 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c90c80fef..c00105f5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,184 @@ # Lotus changelog +# 1.11.1-rc1 / 2021-07-27 + +This is the first release candidate for the **highly-recommended** but optional Lotus v1.11.1 release that introduces many deal making and datastore improvements and new features along with other bug fixes. A more organized and detailed release note will be shared in the next few days with future RCs, highlights are: +- [lotus-miner market subsystem](https://docs.filecoin.io/mine/lotus/split-markets-miners/#frontmatter-title) +- [splistore](https://github.com/filecoin-project/lotus/blob/master/blockstore/splitstore/README.md) + +- github.com/filecoin-project/lotus: + - Merge branch 'releases' into release/v1.11.1 + - Update to proof v8.0.3 ([filecoin-project/lotus#6890](https://github.com/filecoin-project/lotus/pull/6890)) + - lotus-shed: initial export cmd for markets related metadata ([filecoin-project/lotus#6840](https://github.com/filecoin-project/lotus/pull/6840)) + - add a very verbose -vv flag to lotus and lotus-miner. ([filecoin-project/lotus#6888](https://github.com/filecoin-project/lotus/pull/6888)) + - Update RELEASE_ISSUE_TEMPLATE.md ([filecoin-project/lotus#6880](https://github.com/filecoin-project/lotus/pull/6880)) + - Moving GC for badger ([filecoin-project/lotus#6854](https://github.com/filecoin-project/lotus/pull/6854)) + - Add github actions for staled pr ([filecoin-project/lotus#6879](https://github.com/filecoin-project/lotus/pull/6879)) + - Add allocated sectorid vis ([filecoin-project/lotus#4638](https://github.com/filecoin-project/lotus/pull/4638)) + - rename `cmd/lotus{-storage=>}-miner` to match binary. ([filecoin-project/lotus#6886](https://github.com/filecoin-project/lotus/pull/6886)) + - update to go-fil-market v1.6.0 ([filecoin-project/lotus#6885](https://github.com/filecoin-project/lotus/pull/6885)) + - Bump go-multihash, adjust test for supported version ([filecoin-project/lotus#6674](https://github.com/filecoin-project/lotus/pull/6674)) + - Fix padding of deals, which only partially shipped in #5988 ([filecoin-project/lotus#6683](https://github.com/filecoin-project/lotus/pull/6683)) + - fix racy TestSimultanenousTransferLimit. ([filecoin-project/lotus#6862](https://github.com/filecoin-project/lotus/pull/6862)) + - Improve splitstore warmup ([filecoin-project/lotus#6867](https://github.com/filecoin-project/lotus/pull/6867)) + - ValidateBlock: Assert that block header height's are greater than parents ([filecoin-project/lotus#6872](https://github.com/filecoin-project/lotus/pull/6872)) + - feat: Don't panic when api impl is nil ([filecoin-project/lotus#6857](https://github.com/filecoin-project/lotus/pull/6857)) + - splitstore shed utils ([filecoin-project/lotus#6811](https://github.com/filecoin-project/lotus/pull/6811)) + - Fix links in issue templates + - Update issue templates and add templates for M1 ([filecoin-project/lotus#6856](https://github.com/filecoin-project/lotus/pull/6856)) + - Splitstore: support on-disk marksets using badger ([filecoin-project/lotus#6833](https://github.com/filecoin-project/lotus/pull/6833)) + - Config UX improvements ([filecoin-project/lotus#6848](https://github.com/filecoin-project/lotus/pull/6848)) + - fix deal concurrency test failures by upgrading graphsync and others ([filecoin-project/lotus#6724](https://github.com/filecoin-project/lotus/pull/6724)) + - Update issue templates to forms ([filecoin-project/lotus#6798](https://github.com/filecoin-project/lotus/pull/6798)) + - Nerpa v13 upgrade ([filecoin-project/lotus#6837](https://github.com/filecoin-project/lotus/pull/6837)) + - add docker-compose file ([filecoin-project/lotus#6544](https://github.com/filecoin-project/lotus/pull/6544)) + - fix warmup by decoupling state from message receipt walk ([filecoin-project/lotus#6841](https://github.com/filecoin-project/lotus/pull/6841)) + - add a command for compacting sector numbers bitfield ([filecoin-project/lotus#4640](https://github.com/filecoin-project/lotus/pull/4640)) + - PriceListByVersion ([filecoin-project/lotus#6766](https://github.com/filecoin-project/lotus/pull/6766)) + - easy way to make install app ([filecoin-project/lotus#5183](https://github.com/filecoin-project/lotus/pull/5183)) + - api: Separate the Net interface from Common ([filecoin-project/lotus#6627](https://github.com/filecoin-project/lotus/pull/6627)) + - cache loaded block messages ([filecoin-project/lotus#6760](https://github.com/filecoin-project/lotus/pull/6760)) + - fix: on randomness change, use new rand ([filecoin-project/lotus#6805](https://github.com/filecoin-project/lotus/pull/6805)) + - Splitstore: add retention policy option for keeping messages in the hotstore ([filecoin-project/lotus#6775](https://github.com/filecoin-project/lotus/pull/6775)) + - Introduce the LOTUS_CHAIN_BADGERSTORE_DISABLE_FSYNC envvar ([filecoin-project/lotus#6817](https://github.com/filecoin-project/lotus/pull/6817)) + - add StateReadState to gateway api ([filecoin-project/lotus#6818](https://github.com/filecoin-project/lotus/pull/6818)) + - add SealProof in SectorBuilder ([filecoin-project/lotus#6815](https://github.com/filecoin-project/lotus/pull/6815)) + - release -> master ([filecoin-project/lotus#6828](https://github.com/filecoin-project/lotus/pull/6828)) + - sealing: Handle preCommitParams errors more correctly ([filecoin-project/lotus#6763](https://github.com/filecoin-project/lotus/pull/6763)) + - fix: always check if StateSearchMessage returns nil ([filecoin-project/lotus#6802](https://github.com/filecoin-project/lotus/pull/6802)) + - ClientFindData: always fetch peer id from chain ([filecoin-project/lotus#6807](https://github.com/filecoin-project/lotus/pull/6807)) + - test: fix flaky window post tests ([filecoin-project/lotus#6804](https://github.com/filecoin-project/lotus/pull/6804)) + - ([filecoin-project/lotus#6800](https://github.com/filecoin-project/lotus/pull/6800)) + - fixes #6786 segfault ([filecoin-project/lotus#6787](https://github.com/filecoin-project/lotus/pull/6787)) + - Splitstore: add support for protecting out of chain references in the blockstore ([filecoin-project/lotus#6777](https://github.com/filecoin-project/lotus/pull/6777)) + - Resurrect CODEOWNERS, but for maintainers group ([filecoin-project/lotus#6773](https://github.com/filecoin-project/lotus/pull/6773)) + - update go-libp2p-pubsub to v0.5.0 ([filecoin-project/lotus#6764](https://github.com/filecoin-project/lotus/pull/6764)) + - Implement exposed splitstore ([filecoin-project/lotus#6762](https://github.com/filecoin-project/lotus/pull/6762)) + - Add ChainGetMessagesInTipset API ([filecoin-project/lotus#6642](https://github.com/filecoin-project/lotus/pull/6642)) + - test: handle null blocks in TestForkRefuseCall ([filecoin-project/lotus#6758](https://github.com/filecoin-project/lotus/pull/6758)) + - Master disclaimer ([filecoin-project/lotus#6757](https://github.com/filecoin-project/lotus/pull/6757)) + - Splitstore code reorg ([filecoin-project/lotus#6756](https://github.com/filecoin-project/lotus/pull/6756)) + - Create stale.yml ([filecoin-project/lotus#6747](https://github.com/filecoin-project/lotus/pull/6747)) + - Splitstore: Some small fixes ([filecoin-project/lotus#6754](https://github.com/filecoin-project/lotus/pull/6754)) + - ([filecoin-project/lotus#6746](https://github.com/filecoin-project/lotus/pull/6746)) + - Handle the --color flag via proper global state ([filecoin-project/lotus#6743](https://github.com/filecoin-project/lotus/pull/6743)) + - Config for collateral from miner available balance ([filecoin-project/lotus#6629](https://github.com/filecoin-project/lotus/pull/6629)) + - Support standalone miner-market process ([filecoin-project/lotus#6356](https://github.com/filecoin-project/lotus/pull/6356)) + - Splitstore Enhanchements ([filecoin-project/lotus#6474](https://github.com/filecoin-project/lotus/pull/6474)) + - ([filecoin-project/lotus#6739](https://github.com/filecoin-project/lotus/pull/6739)) + - Add more deal details to lotus-miner info ([filecoin-project/lotus#6708](https://github.com/filecoin-project/lotus/pull/6708)) + - Release template: Update all testnet infra at once ([filecoin-project/lotus#6710](https://github.com/filecoin-project/lotus/pull/6710)) + - Fix Lotus shed + - Fix bugs in sectors extend --v1-sectors ([filecoin-project/lotus#6066](https://github.com/filecoin-project/lotus/pull/6066)) + - add election backtest ([filecoin-project/lotus#5950](https://github.com/filecoin-project/lotus/pull/5950)) + - Envvar to disable slash filter ([filecoin-project/lotus#6620](https://github.com/filecoin-project/lotus/pull/6620)) + - Release Template: remove binary validation step ([filecoin-project/lotus#6709](https://github.com/filecoin-project/lotus/pull/6709)) + - Config for deal publishing control addresses ([filecoin-project/lotus#6697](https://github.com/filecoin-project/lotus/pull/6697)) + - Reset of the interop network ([filecoin-project/lotus#6689](https://github.com/filecoin-project/lotus/pull/6689)) + - Enable color by default only if os.Stdout is a TTY ([filecoin-project/lotus#6696](https://github.com/filecoin-project/lotus/pull/6696)) + - Stop outputing ANSI color on non-TTY ([filecoin-project/lotus#6694](https://github.com/filecoin-project/lotus/pull/6694)) + - add dollar sign ([filecoin-project/lotus#6690](https://github.com/filecoin-project/lotus/pull/6690)) + - get-actor cli spelling fix ([filecoin-project/lotus#6681](https://github.com/filecoin-project/lotus/pull/6681)) + - fix "lotus-seed genesis car" error "merkledag: not found" ([filecoin-project/lotus#6688](https://github.com/filecoin-project/lotus/pull/6688)) + - polish(statetree): accept a context in statetree diff for timeouts ([filecoin-project/lotus#6639](https://github.com/filecoin-project/lotus/pull/6639)) + - Add helptext to lotus chain export ([filecoin-project/lotus#6672](https://github.com/filecoin-project/lotus/pull/6672)) + - Get retrieval pricing input should not error out on a deal state fetch ([filecoin-project/lotus#6679](https://github.com/filecoin-project/lotus/pull/6679)) + - Fix more CID double-encoding as hex ([filecoin-project/lotus#6680](https://github.com/filecoin-project/lotus/pull/6680)) + - add an incremental nonce itest. ([filecoin-project/lotus#6663](https://github.com/filecoin-project/lotus/pull/6663)) + - storage: Fix FinalizeSector with sectors in stoage paths ([filecoin-project/lotus#6653](https://github.com/filecoin-project/lotus/pull/6653)) + - Fix tiny error in check-client-datacap ([filecoin-project/lotus#6664](https://github.com/filecoin-project/lotus/pull/6664)) + - Fix: precommit_batch method used the wrong cfg.CommitBatchWait ([filecoin-project/lotus#6658](https://github.com/filecoin-project/lotus/pull/6658)) + - fix ticket expiration check ([filecoin-project/lotus#6635](https://github.com/filecoin-project/lotus/pull/6635)) + - commit batch: AggregateAboveBaseFee config ([filecoin-project/lotus#6650](https://github.com/filecoin-project/lotus/pull/6650)) + - commit batch: Initialize the FailedSectors map ([filecoin-project/lotus#6647](https://github.com/filecoin-project/lotus/pull/6647)) + - Fast-path retry submitting commit aggregate if commit is still valid ([filecoin-project/lotus#6638](https://github.com/filecoin-project/lotus/pull/6638)) + - remove precommit check in handleCommitFailed ([filecoin-project/lotus#6634](https://github.com/filecoin-project/lotus/pull/6634)) + - Reuse timers in sealing batch logic ([filecoin-project/lotus#6636](https://github.com/filecoin-project/lotus/pull/6636)) + - shed tool to estimate aggregate network fees ([filecoin-project/lotus#6631](https://github.com/filecoin-project/lotus/pull/6631)) + - fix prove commit aggregate send token amount ([filecoin-project/lotus#6625](https://github.com/filecoin-project/lotus/pull/6625)) + - Update version.go to 1.11.1 ([filecoin-project/lotus#6621](https://github.com/filecoin-project/lotus/pull/6621)) +- github.com/filecoin-project/go-data-transfer (v1.6.0 -> v1.7.0): + - release: v1.7.0 + - Fire a transfer queued event when a transfer is queued in Graphsync (#221) ([filecoin-project/go-data-transfer#221](https://github.com/filecoin-project/go-data-transfer/pull/221)) + - feat: pass ChannelID to ValidatePush & ValidatePull (#220) ([filecoin-project/go-data-transfer#220](https://github.com/filecoin-project/go-data-transfer/pull/220)) + - release: v1.6.1 ([filecoin-project/go-data-transfer#218](https://github.com/filecoin-project/go-data-transfer/pull/218)) + - Remove CID lists (#217) ([filecoin-project/go-data-transfer#217](https://github.com/filecoin-project/go-data-transfer/pull/217)) + - Merge v1.6.0 ([filecoin-project/go-data-transfer#214](https://github.com/filecoin-project/go-data-transfer/pull/214)) + - Remove restart ack timeout (#211) ([filecoin-project/go-data-transfer#211](https://github.com/filecoin-project/go-data-transfer/pull/211)) + - feat: use different extension names to fit multiple hooks data in same graphsync message (#204) ([filecoin-project/go-data-transfer#204](https://github.com/filecoin-project/go-data-transfer/pull/204)) + - fix: map race in GS transport (#208) ([filecoin-project/go-data-transfer#208](https://github.com/filecoin-project/go-data-transfer/pull/208)) + - refactor: simplify graphsync transport (#203) ([filecoin-project/go-data-transfer#203](https://github.com/filecoin-project/go-data-transfer/pull/203)) + - release: v1.5.0 (#200) ([filecoin-project/go-data-transfer#200](https://github.com/filecoin-project/go-data-transfer/pull/200)) +- github.com/filecoin-project/go-fil-markets (v1.5.0 -> v1.6.0): + - release: v1.6.0 + - support padding out smaller files (#536) ([filecoin-project/go-fil-markets#536](https://github.com/filecoin-project/go-fil-markets/pull/536)) + - On overloaded CI 10 seconds just isn't enough (#587) ([filecoin-project/go-fil-markets#587](https://github.com/filecoin-project/go-fil-markets/pull/587)) + - Do not hex-encode CIDs in logs (#561) ([filecoin-project/go-fil-markets#561](https://github.com/filecoin-project/go-fil-markets/pull/561)) + - remove wrong peer check in push deal validation (#585) ([filecoin-project/go-fil-markets#585](https://github.com/filecoin-project/go-fil-markets/pull/585)) + - fix: circleci docs-gen task (#574) ([filecoin-project/go-fil-markets#574](https://github.com/filecoin-project/go-fil-markets/pull/574)) + - Storage market request queued event and validation interface changes (#555) ([filecoin-project/go-fil-markets#555](https://github.com/filecoin-project/go-fil-markets/pull/555)) + - build(deps): bump ws from 6.2.1 to 6.2.2 (#554) ([filecoin-project/go-fil-markets#554](https://github.com/filecoin-project/go-fil-markets/pull/554)) + - release: v1.5.0 ([filecoin-project/go-fil-markets#553](https://github.com/filecoin-project/go-fil-markets/pull/553)) +- github.com/filecoin-project/go-padreader (v0.0.0-20200903213702-ed5fae088b20 -> v0.0.0-20210723183308-812a16dc01b1): + - New method to pad harder (#6) ([filecoin-project/go-padreader#6](https://github.com/filecoin-project/go-padreader/pull/6)) + - Create SECURITY.md (#5) ([filecoin-project/go-padreader#5](https://github.com/filecoin-project/go-padreader/pull/5)) +- github.com/filecoin-project/go-state-types (v0.1.1-0.20210506134452-99b279731c48 -> v0.1.1-0.20210722133031-ad9bfe54c124): + - Add version 6.5 (#30) ([filecoin-project/go-state-types#30](https://github.com/filecoin-project/go-state-types/pull/30)) + - rename file +- github.com/filecoin-project/specs-actors/v5 (v5.0.1 -> v5.0.3): + - Adjust code for subtle change in go-multihash 0.0.15 (#1463) ([filecoin-project/specs-actors#1463](https://github.com/filecoin-project/specs-actors/pull/1463)) + - Bump go state types (#1464) ([filecoin-project/specs-actors#1464](https://github.com/filecoin-project/specs-actors/pull/1464)) + - Create CODEOWNERS (#1465) ([filecoin-project/specs-actors#1465](https://github.com/filecoin-project/specs-actors/pull/1465)) + - Test deterministic offset (#1462) ([filecoin-project/specs-actors#1462](https://github.com/filecoin-project/specs-actors/pull/1462)) + +Contributors + +| Contributor | Commits | Lines ± | Files Changed | +|-------------|---------|---------|---------------| +| vyzo | 295 | +8700/-5936 | 397 | +| Anton Evangelatov | 94 | +4680/-2965 | 277 | +| Łukasz Magiera | 37 | +3851/-1611 | 146 | +| Mike Greenberg | 1 | +2310/-578 | 8 | +| dirkmc | 7 | +1154/-726 | 29 | +| Jennifer Wang | 9 | +485/-341 | 26 | +| Peter Rabbitson | 18 | +469/-273 | 64 | +| Cory Schwartz | 5 | +576/-135 | 14 | +| hunjixin | 7 | +404/-82 | 19 | +| ZenGround0 | 17 | +284/-135 | 44 | +| Dirk McCormick | 17 | +348/-47 | 17 | +| Raúl Kripalani | 18 | +254/-97 | 62 | +| tchardin | 1 | +261/-33 | 4 | +| Jakub Sztandera | 4 | +254/-16 | 4 | +| Aarsh Shah | 2 | +196/-40 | 28 | +| whyrusleeping | 3 | +150/-9 | 8 | +| Whyrusleeping | 2 | +87/-66 | 10 | +| Aayush Rajasekaran | 10 | +81/-53 | 13 | +| zgfzgf | 2 | +104/-4 | 2 | +| aarshkshah1992 | 4 | +73/-7 | 6 | +| llifezou | 4 | +59/-20 | 4 | +| Steven Allen | 7 | +47/-17 | 9 | +| johnli-helloworld | 3 | +46/-15 | 5 | +| frrist | 1 | +28/-23 | 2 | +| Jennifer | 4 | +31/-2 | 4 | +| wangchao | 1 | +1/-27 | 1 | +| Jiaying Wang | 2 | +7/-21 | 2 | +| hannahhoward | 3 | +21/-2 | 3 | +| chadwick2143 | 1 | +15/-1 | 1 | +| Jerry | 2 | +9/-4 | 2 | +| Steve Loeppky | 2 | +12/-0 | 2 | +| David Dias | 1 | +9/-0 | 1 | +| dependabot[bot] | 1 | +3/-3 | 1 | +| zhoutian527 | 1 | +2/-2 | 1 | +| xloem | 1 | +4/-0 | 1 | +| Travis Person | 2 | +2/-2 | 3 | +| Liviu Damian | 2 | +2/-2 | 2 | +| Jim Pick | 2 | +2/-2 | 2 | +| Frank | 1 | +3/-0 | 1 | +| turuslan | 1 | +1/-1 | 1 | +| Kirk Baird | 1 | +0/-0 | 1 | + + + # 1.11.0 / 2021-07-22 This is a **highly recommended** release of Lotus that have many bug fixes, improvements and new features. diff --git a/build/version.go b/build/version.go index c6a1be3e2..64d1049b5 100644 --- a/build/version.go +++ b/build/version.go @@ -34,7 +34,7 @@ func buildType() string { } // BuildVersion is the local build version, set by build system -const BuildVersion = "1.11.1-dev" +const BuildVersion = "1.11.1-rc1" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { From 2e98f8b5d2094e76ad83a9fb6db90b5c98cd61b7 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Tue, 27 Jul 2021 22:52:39 -0400 Subject: [PATCH 24/51] make gen --- build/openrpc/full.json.gz | Bin 25240 -> 25240 bytes build/openrpc/miner.json.gz | Bin 9479 -> 9479 bytes build/openrpc/worker.json.gz | Bin 2710 -> 2710 bytes documentation/en/cli-lotus-miner.md | 2 +- documentation/en/cli-lotus-worker.md | 2 +- documentation/en/cli-lotus.md | 2 +- 6 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index c940d921b0af50de4f243bc595a80f87b709ce86..ddcf0611767ea9b47c66180b6063a2252ebf40ab 100644 GIT binary patch delta 25057 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 BZjb-~ delta 25103 zcma%?Q*dT&^yOpQw#|-hCmnWd+kRvB8{1aLwvCQ$+vfB)^PigAsdKaI)VX--seP*U zUhB8ghCtJXK;xnSa@d;>{!c#agQW{*U7rp@-VoE`i_a@!NJFOQC?eqr$Pqo{{8|rh z0@$q7y@HyEpRdQc=-v{;q)xr;Q2L$70@v(rvyjN5;X=@>XMaEJc9i>P8Mk?Vem@2F zfbYOK5Gs&TUHhKN=LTCazw}GVdoWc#fx>~|@k0w$k7AAhOnRFYVWdC<^?{N%H2}~c z0ri_G=!kGoRHe5aJrv)P53&b8Jja75FrlIEQ?_IU!TT1-?7uamf9daza{*6p0$9`L zELsmwK5bj-ItVwkVC1iGB(KKu;IEEB4k(}|0(~Hnqz-|Jx0t97>Z`P-0m?{N5y7aU z5HFx^V$f{>zts?M0p!WLd`2{Jfb-i&q>&D3XZiJRR

6o%-h-Z!lb-L#nw&h? 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 diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 41e51a13ec002908072c639cd2136778bea75f3e..5a65b3a33921ffe18ee4fe002bdec37d7b59b576 100644 GIT binary patch delta 22 dcmZqoYWJGZ&Sc8Iv9nBt<4W=INty>4831D42wwmI delta 22 dcmZqoYWJGZ&g4|Sv9nBt!^8GVj^;r|1^{F>2q6Ff diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 075b54c3277e2bc961f796975999dbcd64e8d26b..09e5b1a87e567fbadc0a81ca94a0e97e5021fc73 100644 GIT binary patch delta 22 ecmbOxI!$y!6I0^$jV)YU9Q&+p-iWMXU;qGOdI(Se delta 22 dcmbOxI!$y!6BE1K#uhFv4&_7bA0w+67ywd72N3`O diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 29593fbd4..863ca8dc9 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -7,7 +7,7 @@ USAGE: lotus-miner [global options] command [command options] [arguments...] VERSION: - 1.11.1-dev + 1.11.1-rc1 COMMANDS: init Initialize a lotus miner repo diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index dbfc8da29..0319649fb 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -7,7 +7,7 @@ USAGE: lotus-worker [global options] command [command options] [arguments...] VERSION: - 1.11.1-dev + 1.11.1-rc1 COMMANDS: run Start lotus worker diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 5faf5c58b..c7504246f 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -7,7 +7,7 @@ USAGE: lotus [global options] command [command options] [arguments...] VERSION: - 1.11.1-dev + 1.11.1-rc1 COMMANDS: daemon Start a lotus daemon process From 5073c7e6cf7eea3403eb74b826aec2ad71a66fec Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Wed, 28 Jul 2021 14:46:13 -0700 Subject: [PATCH 25/51] feat(deps): update to branches with improved logging update sub repos with improved logging around data transfer processing --- go.mod | 8 ++++---- go.sum | 14 ++++++++------ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 5f968f6e0..89db6a3ae 100644 --- a/go.mod +++ b/go.mod @@ -33,16 +33,16 @@ require ( github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 github.com/filecoin-project/go-commp-utils v0.1.1-0.20210427191551-70bf140d31c7 github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 - github.com/filecoin-project/go-data-transfer v1.7.0 + github.com/filecoin-project/go-data-transfer v1.7.1 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.6.0 + github.com/filecoin-project/go-fil-markets v1.6.1 github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1 github.com/filecoin-project/go-paramfetch v0.0.2-0.20210614165157-25a6c7769498 github.com/filecoin-project/go-state-types v0.1.1-0.20210722133031-ad9bfe54c124 - github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe + github.com/filecoin-project/go-statemachine v1.0.0 github.com/filecoin-project/go-statestore v0.1.1 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b github.com/filecoin-project/specs-actors v0.9.14 @@ -78,7 +78,7 @@ require ( github.com/ipfs/go-ds-pebble v0.0.2-0.20200921225637-ce220f8ac459 github.com/ipfs/go-filestore v1.0.0 github.com/ipfs/go-fs-lock v0.0.6 - github.com/ipfs/go-graphsync v0.6.5 + github.com/ipfs/go-graphsync v0.6.6 github.com/ipfs/go-ipfs-blockstore v1.0.3 github.com/ipfs/go-ipfs-chunker v0.0.5 github.com/ipfs/go-ipfs-ds-help v1.0.0 diff --git a/go.sum b/go.sum index b22f3dc15..e39d883d9 100644 --- a/go.sum +++ b/go.sum @@ -274,8 +274,9 @@ github.com/filecoin-project/go-commp-utils v0.1.1-0.20210427191551-70bf140d31c7/ github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-data-transfer v1.0.1/go.mod h1:UxvfUAY9v3ub0a21BSK9u3pB2aq30Y0KMsG+w9/ysyo= -github.com/filecoin-project/go-data-transfer v1.7.0 h1:mFRn+UuTdPROmhplLSekzd4rAs9ug8ubtSY4nw9wYkU= github.com/filecoin-project/go-data-transfer v1.7.0/go.mod h1:GLRr5BmLEqsLwXfiRDG7uJvph22KGL2M4iOuF8EINaU= +github.com/filecoin-project/go-data-transfer v1.7.1 h1:Co4bTenvCc3WnOhQWyXRt59FLZvxwH8UeF0ZCOc1ik0= +github.com/filecoin-project/go-data-transfer v1.7.1/go.mod h1:GLRr5BmLEqsLwXfiRDG7uJvph22KGL2M4iOuF8EINaU= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= @@ -285,8 +286,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+ github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= github.com/filecoin-project/go-fil-markets v1.0.5-0.20201113164554-c5eba40d5335/go.mod h1:AJySOJC00JRWEZzRG2KsfUnqEf5ITXxeX09BE9N4f9c= -github.com/filecoin-project/go-fil-markets v1.6.0 h1:+1usyX7rXz6Ey6hbHd/Fhx616ZvGCI94rW7wneMcptU= -github.com/filecoin-project/go-fil-markets v1.6.0/go.mod h1:ZuFDagROUV6GfvBU//KReTQDw+EZci4rH7jMYTD10vs= +github.com/filecoin-project/go-fil-markets v1.6.1 h1:8xdFyWrELfOzwcGa229bLu/olD+1l4sEWFIsZR7oz5U= +github.com/filecoin-project/go-fil-markets v1.6.1/go.mod h1:ZuFDagROUV6GfvBU//KReTQDw+EZci4rH7jMYTD10vs= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -311,8 +312,9 @@ github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psS github.com/filecoin-project/go-state-types v0.1.1-0.20210506134452-99b279731c48/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.1-0.20210722133031-ad9bfe54c124 h1:veGrNABg/9I7prngrowkhwbvW5d5JN55MNKmbsr5FqA= github.com/filecoin-project/go-state-types v0.1.1-0.20210722133031-ad9bfe54c124/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= -github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= +github.com/filecoin-project/go-statemachine v1.0.0 h1:b8FpFewPSklyAIUqH0oHt4nvKf03bU7asop1bJpjAtQ= +github.com/filecoin-project/go-statemachine v1.0.0/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= github.com/filecoin-project/go-statestore v0.1.1 h1:ufMFq00VqnT2CAuDpcGnwLnCX1I/c3OROw/kXVNSTZk= github.com/filecoin-project/go-statestore v0.1.1/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= @@ -631,8 +633,8 @@ github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CE github.com/ipfs/go-graphsync v0.4.2/go.mod h1:/VmbZTUdUMTbNkgzAiCEucIIAU3BkLE2cZrDCVUhyi0= github.com/ipfs/go-graphsync v0.4.3/go.mod h1:mPOwDYv128gf8gxPFgXnz4fNrSYPsWyqisJ7ych+XDY= github.com/ipfs/go-graphsync v0.6.4/go.mod h1:5WyaeigpNdpiYQuW2vwpuecOoEfB4h747ZGEOKmAGTg= -github.com/ipfs/go-graphsync v0.6.5 h1:YAJl6Yit23PQcaawzb1rPK9PSnbbq2jjMRPpRpJ0Y5U= -github.com/ipfs/go-graphsync v0.6.5/go.mod h1:GdHT8JeuIZ0R4lSjFR16Oe4zPi5dXwKi9zR9ADVlcdk= +github.com/ipfs/go-graphsync v0.6.6 h1:In7jjzvSXlrAUz4OjN41lxYf/dzkf1bVeVxLpwKMRo8= +github.com/ipfs/go-graphsync v0.6.6/go.mod h1:GdHT8JeuIZ0R4lSjFR16Oe4zPi5dXwKi9zR9ADVlcdk= github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= From 9b7a7713a78ec32316665abf8c99562f7ea55c01 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 28 Jul 2021 12:10:17 +0300 Subject: [PATCH 26/51] add RuntimeSubsystems API method; use it in `lotus-miner info` --- api/api_storage.go | 2 + api/api_subsystems.go | 63 +++ api/docgen/docgen.go | 11 +- api/proxy_gen.go | 13 + cmd/lotus-miner/info.go | 562 ++++++++++++----------- documentation/en/api-v0-methods-miner.md | 14 + node/builder_miner.go | 2 + node/impl/storminer.go | 6 + node/modules/storageminer.go | 17 + v1.11.1 | 170 +++++++ 10 files changed, 580 insertions(+), 280 deletions(-) create mode 100644 api/api_subsystems.go create mode 100644 v1.11.1 diff --git a/api/api_storage.go b/api/api_storage.go index 154abcea7..d52032650 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -166,6 +166,8 @@ type StorageMiner interface { MarketPendingDeals(ctx context.Context) (PendingDealInfo, error) //perm:write MarketPublishPendingDeals(ctx context.Context) error //perm:admin + RuntimeSubsystems(ctx context.Context) (MinerSubsystems, error) //perm:read + DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error //perm:admin DealsList(ctx context.Context) ([]MarketDeal, error) //perm:admin DealsConsiderOnlineStorageDeals(context.Context) (bool, error) //perm:admin diff --git a/api/api_subsystems.go b/api/api_subsystems.go new file mode 100644 index 000000000..1894bbdd8 --- /dev/null +++ b/api/api_subsystems.go @@ -0,0 +1,63 @@ +package api + +import ( + "bytes" + "encoding/json" +) + +type MinerSubsystems []MinerSubsystem + +func (ms MinerSubsystems) Has(entry MinerSubsystem) bool { + for _, v := range ms { + if v == entry { + return true + } + + } + return false +} + +type MinerSubsystem int + +const ( + MarketsSubsystem MinerSubsystem = iota + MiningSubsystem + SealingSubsystem + SectorStorageSubsystem +) + +func (ms MinerSubsystem) String() string { + return MinerSubsystemToString[ms] +} + +var MinerSubsystemToString = map[MinerSubsystem]string{ + MarketsSubsystem: "Markets", + MiningSubsystem: "Mining", + SealingSubsystem: "Sealing", + SectorStorageSubsystem: "SectorStorage", +} + +var MinerSubsystemToID = map[string]MinerSubsystem{ + "Markets": MarketsSubsystem, + "Mining": MiningSubsystem, + "Sealing": SealingSubsystem, + "SectorStorage": SectorStorageSubsystem, +} + +func (ms MinerSubsystem) MarshalJSON() ([]byte, error) { + buffer := bytes.NewBufferString(`"`) + buffer.WriteString(MinerSubsystemToString[ms]) + buffer.WriteString(`"`) + return buffer.Bytes(), nil +} + +func (ms *MinerSubsystem) UnmarshalJSON(b []byte) error { + var j string + err := json.Unmarshal(b, &j) + if err != nil { + return err + } + // TODO: handle zero value + *ms = MinerSubsystemToID[j] + return nil +} diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 39980023f..1e712a0ae 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -46,11 +46,12 @@ import ( ) var ExampleValues = map[reflect.Type]interface{}{ - reflect.TypeOf(auth.Permission("")): auth.Permission("write"), - reflect.TypeOf(""): "string value", - reflect.TypeOf(uint64(42)): uint64(42), - reflect.TypeOf(byte(7)): byte(7), - reflect.TypeOf([]byte{}): []byte("byte array"), + reflect.TypeOf(api.MinerSubsystem(0)): api.MinerSubsystem(1), + reflect.TypeOf(auth.Permission("")): auth.Permission("write"), + reflect.TypeOf(""): "string value", + reflect.TypeOf(uint64(42)): uint64(42), + reflect.TypeOf(byte(7)): byte(7), + reflect.TypeOf([]byte{}): []byte("byte array"), } func addExample(v interface{}) { diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 7d96425ff..a4feb7be1 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -699,6 +699,8 @@ type StorageMinerStruct struct { ReturnUnsealPiece func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + RuntimeSubsystems func(p0 context.Context) (MinerSubsystems, error) `perm:"read"` + SealingAbort func(p0 context.Context, p1 storiface.CallID) error `perm:"admin"` SealingSchedDiag func(p0 context.Context, p1 bool) (interface{}, error) `perm:"admin"` @@ -4095,6 +4097,17 @@ func (s *StorageMinerStub) ReturnUnsealPiece(p0 context.Context, p1 storiface.Ca return ErrNotSupported } +func (s *StorageMinerStruct) RuntimeSubsystems(p0 context.Context) (MinerSubsystems, error) { + if s.Internal.RuntimeSubsystems == nil { + return *new(MinerSubsystems), ErrNotSupported + } + return s.Internal.RuntimeSubsystems(p0) +} + +func (s *StorageMinerStub) RuntimeSubsystems(p0 context.Context) (MinerSubsystems, error) { + return *new(MinerSubsystems), ErrNotSupported +} + func (s *StorageMinerStruct) SealingAbort(p0 context.Context, p1 storiface.CallID) error { if s.Internal.SealingAbort == nil { return ErrNotSupported diff --git a/cmd/lotus-miner/info.go b/cmd/lotus-miner/info.go index 3941ce563..4c409788f 100644 --- a/cmd/lotus-miner/info.go +++ b/cmd/lotus-miner/info.go @@ -55,7 +55,7 @@ func infoCmdAct(cctx *cli.Context) error { } defer closer() - api, acloser, err := lcli.GetFullNodeAPI(cctx) + fullapi, acloser, err := lcli.GetFullNodeAPI(cctx) if err != nil { return err } @@ -63,9 +63,16 @@ func infoCmdAct(cctx *cli.Context) error { ctx := lcli.ReqContext(cctx) + subsystems, err := nodeApi.RuntimeSubsystems(ctx) + if err != nil { + return err + } + + fmt.Println("Enabled subsystems:", subsystems) + fmt.Print("Chain: ") - head, err := api.ChainHead(ctx) + head, err := fullapi.ChainHead(ctx) if err != nil { return err } @@ -95,284 +102,289 @@ func infoCmdAct(cctx *cli.Context) error { fmt.Println() - maddr, err := getActorAddress(ctx, cctx) - if err != nil { - return err - } - - mact, err := api.StateGetActor(ctx, maddr, types.EmptyTSK) - if err != nil { - return err - } - - tbs := blockstore.NewTieredBstore(blockstore.NewAPIBlockstore(api), blockstore.NewMemory()) - mas, err := miner.Load(adt.WrapStore(ctx, cbor.NewCborStore(tbs)), mact) - if err != nil { - return err - } - - // Sector size - mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK) - if err != nil { - return err - } - - ssize := types.SizeStr(types.NewInt(uint64(mi.SectorSize))) - fmt.Printf("Miner: %s (%s sectors)\n", color.BlueString("%s", maddr), ssize) - - pow, err := api.StateMinerPower(ctx, maddr, types.EmptyTSK) - if err != nil { - return err - } - - fmt.Printf("Power: %s / %s (%0.4f%%)\n", - color.GreenString(types.DeciStr(pow.MinerPower.QualityAdjPower)), - types.DeciStr(pow.TotalPower.QualityAdjPower), - types.BigDivFloat( - types.BigMul(pow.MinerPower.QualityAdjPower, big.NewInt(100)), - pow.TotalPower.QualityAdjPower, - ), - ) - - fmt.Printf("\tRaw: %s / %s (%0.4f%%)\n", - color.BlueString(types.SizeStr(pow.MinerPower.RawBytePower)), - types.SizeStr(pow.TotalPower.RawBytePower), - types.BigDivFloat( - types.BigMul(pow.MinerPower.RawBytePower, big.NewInt(100)), - pow.TotalPower.RawBytePower, - ), - ) - secCounts, err := api.StateMinerSectorCount(ctx, maddr, types.EmptyTSK) - if err != nil { - return err - } - - proving := secCounts.Active + secCounts.Faulty - nfaults := secCounts.Faulty - fmt.Printf("\tCommitted: %s\n", types.SizeStr(types.BigMul(types.NewInt(secCounts.Live), types.NewInt(uint64(mi.SectorSize))))) - if nfaults == 0 { - fmt.Printf("\tProving: %s\n", types.SizeStr(types.BigMul(types.NewInt(proving), types.NewInt(uint64(mi.SectorSize))))) - } else { - var faultyPercentage float64 - if secCounts.Live != 0 { - faultyPercentage = float64(100*nfaults) / float64(secCounts.Live) - } - fmt.Printf("\tProving: %s (%s Faulty, %.2f%%)\n", - types.SizeStr(types.BigMul(types.NewInt(proving), types.NewInt(uint64(mi.SectorSize)))), - types.SizeStr(types.BigMul(types.NewInt(nfaults), types.NewInt(uint64(mi.SectorSize)))), - faultyPercentage) - } - - if !pow.HasMinPower { - fmt.Print("Below minimum power threshold, no blocks will be won") - } else { - - winRatio := new(corebig.Rat).SetFrac( - types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(build.BlocksPerEpoch)).Int, - pow.TotalPower.QualityAdjPower.Int, - ) - - if winRatioFloat, _ := winRatio.Float64(); winRatioFloat > 0 { - - // if the corresponding poisson distribution isn't infinitely small then - // throw it into the mix as well, accounting for multi-wins - winRationWithPoissonFloat := -math.Expm1(-winRatioFloat) - winRationWithPoisson := new(corebig.Rat).SetFloat64(winRationWithPoissonFloat) - if winRationWithPoisson != nil { - winRatio = winRationWithPoisson - winRatioFloat = winRationWithPoissonFloat - } - - weekly, _ := new(corebig.Rat).Mul( - winRatio, - new(corebig.Rat).SetInt64(7*builtin.EpochsInDay), - ).Float64() - - avgDuration, _ := new(corebig.Rat).Mul( - new(corebig.Rat).SetInt64(builtin.EpochDurationSeconds), - new(corebig.Rat).Inv(winRatio), - ).Float64() - - fmt.Print("Projected average block win rate: ") - color.Blue( - "%.02f/week (every %s)", - weekly, - (time.Second * time.Duration(avgDuration)).Truncate(time.Second).String(), - ) - - // Geometric distribution of P(Y < k) calculated as described in https://en.wikipedia.org/wiki/Geometric_distribution#Probability_Outcomes_Examples - // https://www.wolframalpha.com/input/?i=t+%3E+0%3B+p+%3E+0%3B+p+%3C+1%3B+c+%3E+0%3B+c+%3C1%3B+1-%281-p%29%5E%28t%29%3Dc%3B+solve+t - // t == how many dice-rolls (epochs) before win - // p == winRate == ( minerPower / netPower ) - // c == target probability of win ( 99.9% in this case ) - fmt.Print("Projected block win with ") - color.Green( - "99.9%% probability every %s", - (time.Second * time.Duration( - builtin.EpochDurationSeconds*math.Log(1-0.999)/ - math.Log(1-winRatioFloat), - )).Truncate(time.Second).String(), - ) - fmt.Println("(projections DO NOT account for future network and miner growth)") - } - } - - fmt.Println() - - deals, err := nodeApi.MarketListIncompleteDeals(ctx) - if err != nil { - return err - } - - type dealStat struct { - count, verifCount int - bytes, verifBytes uint64 - } - dsAdd := func(ds *dealStat, deal storagemarket.MinerDeal) { - ds.count++ - ds.bytes += uint64(deal.Proposal.PieceSize) - if deal.Proposal.VerifiedDeal { - ds.verifCount++ - ds.verifBytes += uint64(deal.Proposal.PieceSize) - } - } - - showDealStates := map[storagemarket.StorageDealStatus]struct{}{ - storagemarket.StorageDealActive: {}, - storagemarket.StorageDealTransferring: {}, - storagemarket.StorageDealStaged: {}, - storagemarket.StorageDealAwaitingPreCommit: {}, - storagemarket.StorageDealSealing: {}, - storagemarket.StorageDealPublish: {}, - storagemarket.StorageDealCheckForAcceptance: {}, - storagemarket.StorageDealPublishing: {}, - } - - var total dealStat - perState := map[storagemarket.StorageDealStatus]*dealStat{} - for _, deal := range deals { - if _, ok := showDealStates[deal.State]; !ok { - continue - } - if perState[deal.State] == nil { - perState[deal.State] = new(dealStat) - } - - dsAdd(&total, deal) - dsAdd(perState[deal.State], deal) - } - - type wstr struct { - str string - status storagemarket.StorageDealStatus - } - sorted := make([]wstr, 0, len(perState)) - for status, stat := range perState { - st := strings.TrimPrefix(storagemarket.DealStates[status], "StorageDeal") - sorted = append(sorted, wstr{ - str: fmt.Sprintf(" %s:\t%d\t\t%s\t(Verified: %d\t%s)\n", st, stat.count, types.SizeStr(types.NewInt(stat.bytes)), stat.verifCount, types.SizeStr(types.NewInt(stat.verifBytes))), - status: status, - }, - ) - } - sort.Slice(sorted, func(i, j int) bool { - if sorted[i].status == storagemarket.StorageDealActive || sorted[j].status == storagemarket.StorageDealActive { - return sorted[i].status == storagemarket.StorageDealActive - } - return sorted[i].status > sorted[j].status - }) - - fmt.Printf("Storage Deals: %d, %s\n", total.count, types.SizeStr(types.NewInt(total.bytes))) - - tw := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0) - for _, e := range sorted { - _, _ = tw.Write([]byte(e.str)) - } - - _ = tw.Flush() - fmt.Println() - - retrievals, err := nodeApi.MarketListRetrievalDeals(ctx) - if err != nil { - return xerrors.Errorf("getting retrieval deal list: %w", err) - } - - var retrComplete dealStat - for _, retrieval := range retrievals { - if retrieval.Status == retrievalmarket.DealStatusCompleted { - retrComplete.count++ - retrComplete.bytes += retrieval.TotalSent - } - } - - fmt.Printf("Retrieval Deals (complete): %d, %s\n", retrComplete.count, types.SizeStr(types.NewInt(retrComplete.bytes))) - - fmt.Println() - - spendable := big.Zero() - - // NOTE: there's no need to unlock anything here. Funds only - // vest on deadline boundaries, and they're unlocked by cron. - lockedFunds, err := mas.LockedFunds() - if err != nil { - return xerrors.Errorf("getting locked funds: %w", err) - } - availBalance, err := mas.AvailableBalance(mact.Balance) - if err != nil { - return xerrors.Errorf("getting available balance: %w", err) - } - spendable = big.Add(spendable, availBalance) - - fmt.Printf("Miner Balance: %s\n", color.YellowString("%s", types.FIL(mact.Balance).Short())) - fmt.Printf(" PreCommit: %s\n", types.FIL(lockedFunds.PreCommitDeposits).Short()) - fmt.Printf(" Pledge: %s\n", types.FIL(lockedFunds.InitialPledgeRequirement).Short()) - fmt.Printf(" Vesting: %s\n", types.FIL(lockedFunds.VestingFunds).Short()) - colorTokenAmount(" Available: %s\n", availBalance) - - mb, err := api.StateMarketBalance(ctx, maddr, types.EmptyTSK) - if err != nil { - return xerrors.Errorf("getting market balance: %w", err) - } - spendable = big.Add(spendable, big.Sub(mb.Escrow, mb.Locked)) - - fmt.Printf("Market Balance: %s\n", types.FIL(mb.Escrow).Short()) - fmt.Printf(" Locked: %s\n", types.FIL(mb.Locked).Short()) - colorTokenAmount(" Available: %s\n", big.Sub(mb.Escrow, mb.Locked)) - - wb, err := api.WalletBalance(ctx, mi.Worker) - if err != nil { - return xerrors.Errorf("getting worker balance: %w", err) - } - spendable = big.Add(spendable, wb) - color.Cyan("Worker Balance: %s", types.FIL(wb).Short()) - if len(mi.ControlAddresses) > 0 { - cbsum := big.Zero() - for _, ca := range mi.ControlAddresses { - b, err := api.WalletBalance(ctx, ca) - if err != nil { - return xerrors.Errorf("getting control address balance: %w", err) - } - cbsum = big.Add(cbsum, b) - } - spendable = big.Add(spendable, cbsum) - - fmt.Printf(" Control: %s\n", types.FIL(cbsum).Short()) - } - colorTokenAmount("Total Spendable: %s\n", spendable) - - fmt.Println() - - if !cctx.Bool("hide-sectors-info") { - fmt.Println("Sectors:") - err = sectorsInfo(ctx, nodeApi) + if subsystems.Has(api.SectorStorageSubsystem) { + maddr, err := getActorAddress(ctx, cctx) if err != nil { return err } + + mact, err := fullapi.StateGetActor(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + + tbs := blockstore.NewTieredBstore(blockstore.NewAPIBlockstore(fullapi), blockstore.NewMemory()) + mas, err := miner.Load(adt.WrapStore(ctx, cbor.NewCborStore(tbs)), mact) + if err != nil { + return err + } + + // Sector size + mi, err := fullapi.StateMinerInfo(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + + ssize := types.SizeStr(types.NewInt(uint64(mi.SectorSize))) + fmt.Printf("Miner: %s (%s sectors)\n", color.BlueString("%s", maddr), ssize) + + pow, err := fullapi.StateMinerPower(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + + fmt.Printf("Power: %s / %s (%0.4f%%)\n", + color.GreenString(types.DeciStr(pow.MinerPower.QualityAdjPower)), + types.DeciStr(pow.TotalPower.QualityAdjPower), + types.BigDivFloat( + types.BigMul(pow.MinerPower.QualityAdjPower, big.NewInt(100)), + pow.TotalPower.QualityAdjPower, + ), + ) + + fmt.Printf("\tRaw: %s / %s (%0.4f%%)\n", + color.BlueString(types.SizeStr(pow.MinerPower.RawBytePower)), + types.SizeStr(pow.TotalPower.RawBytePower), + types.BigDivFloat( + types.BigMul(pow.MinerPower.RawBytePower, big.NewInt(100)), + pow.TotalPower.RawBytePower, + ), + ) + secCounts, err := fullapi.StateMinerSectorCount(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + + proving := secCounts.Active + secCounts.Faulty + nfaults := secCounts.Faulty + fmt.Printf("\tCommitted: %s\n", types.SizeStr(types.BigMul(types.NewInt(secCounts.Live), types.NewInt(uint64(mi.SectorSize))))) + if nfaults == 0 { + fmt.Printf("\tProving: %s\n", types.SizeStr(types.BigMul(types.NewInt(proving), types.NewInt(uint64(mi.SectorSize))))) + } else { + var faultyPercentage float64 + if secCounts.Live != 0 { + faultyPercentage = float64(100*nfaults) / float64(secCounts.Live) + } + fmt.Printf("\tProving: %s (%s Faulty, %.2f%%)\n", + types.SizeStr(types.BigMul(types.NewInt(proving), types.NewInt(uint64(mi.SectorSize)))), + types.SizeStr(types.BigMul(types.NewInt(nfaults), types.NewInt(uint64(mi.SectorSize)))), + faultyPercentage) + } + + if !pow.HasMinPower { + fmt.Print("Below minimum power threshold, no blocks will be won") + } else { + + winRatio := new(corebig.Rat).SetFrac( + types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(build.BlocksPerEpoch)).Int, + pow.TotalPower.QualityAdjPower.Int, + ) + + if winRatioFloat, _ := winRatio.Float64(); winRatioFloat > 0 { + + // if the corresponding poisson distribution isn't infinitely small then + // throw it into the mix as well, accounting for multi-wins + winRationWithPoissonFloat := -math.Expm1(-winRatioFloat) + winRationWithPoisson := new(corebig.Rat).SetFloat64(winRationWithPoissonFloat) + if winRationWithPoisson != nil { + winRatio = winRationWithPoisson + winRatioFloat = winRationWithPoissonFloat + } + + weekly, _ := new(corebig.Rat).Mul( + winRatio, + new(corebig.Rat).SetInt64(7*builtin.EpochsInDay), + ).Float64() + + avgDuration, _ := new(corebig.Rat).Mul( + new(corebig.Rat).SetInt64(builtin.EpochDurationSeconds), + new(corebig.Rat).Inv(winRatio), + ).Float64() + + fmt.Print("Projected average block win rate: ") + color.Blue( + "%.02f/week (every %s)", + weekly, + (time.Second * time.Duration(avgDuration)).Truncate(time.Second).String(), + ) + + // Geometric distribution of P(Y < k) calculated as described in https://en.wikipedia.org/wiki/Geometric_distribution#Probability_Outcomes_Examples + // https://www.wolframalpha.com/input/?i=t+%3E+0%3B+p+%3E+0%3B+p+%3C+1%3B+c+%3E+0%3B+c+%3C1%3B+1-%281-p%29%5E%28t%29%3Dc%3B+solve+t + // t == how many dice-rolls (epochs) before win + // p == winRate == ( minerPower / netPower ) + // c == target probability of win ( 99.9% in this case ) + fmt.Print("Projected block win with ") + color.Green( + "99.9%% probability every %s", + (time.Second * time.Duration( + builtin.EpochDurationSeconds*math.Log(1-0.999)/ + math.Log(1-winRatioFloat), + )).Truncate(time.Second).String(), + ) + fmt.Println("(projections DO NOT account for future network and miner growth)") + } + } + + fmt.Println() + + spendable := big.Zero() + + // NOTE: there's no need to unlock anything here. Funds only + // vest on deadline boundaries, and they're unlocked by cron. + lockedFunds, err := mas.LockedFunds() + if err != nil { + return xerrors.Errorf("getting locked funds: %w", err) + } + availBalance, err := mas.AvailableBalance(mact.Balance) + if err != nil { + return xerrors.Errorf("getting available balance: %w", err) + } + spendable = big.Add(spendable, availBalance) + + fmt.Printf("Miner Balance: %s\n", color.YellowString("%s", types.FIL(mact.Balance).Short())) + fmt.Printf(" PreCommit: %s\n", types.FIL(lockedFunds.PreCommitDeposits).Short()) + fmt.Printf(" Pledge: %s\n", types.FIL(lockedFunds.InitialPledgeRequirement).Short()) + fmt.Printf(" Vesting: %s\n", types.FIL(lockedFunds.VestingFunds).Short()) + colorTokenAmount(" Available: %s\n", availBalance) + + mb, err := fullapi.StateMarketBalance(ctx, maddr, types.EmptyTSK) + if err != nil { + return xerrors.Errorf("getting market balance: %w", err) + } + spendable = big.Add(spendable, big.Sub(mb.Escrow, mb.Locked)) + + fmt.Printf("Market Balance: %s\n", types.FIL(mb.Escrow).Short()) + fmt.Printf(" Locked: %s\n", types.FIL(mb.Locked).Short()) + colorTokenAmount(" Available: %s\n", big.Sub(mb.Escrow, mb.Locked)) + + wb, err := fullapi.WalletBalance(ctx, mi.Worker) + if err != nil { + return xerrors.Errorf("getting worker balance: %w", err) + } + spendable = big.Add(spendable, wb) + color.Cyan("Worker Balance: %s", types.FIL(wb).Short()) + if len(mi.ControlAddresses) > 0 { + cbsum := big.Zero() + for _, ca := range mi.ControlAddresses { + b, err := fullapi.WalletBalance(ctx, ca) + if err != nil { + return xerrors.Errorf("getting control address balance: %w", err) + } + cbsum = big.Add(cbsum, b) + } + spendable = big.Add(spendable, cbsum) + + fmt.Printf(" Control: %s\n", types.FIL(cbsum).Short()) + } + colorTokenAmount("Total Spendable: %s\n", spendable) + + fmt.Println() + + if !cctx.Bool("hide-sectors-info") { + fmt.Println("Sectors:") + err = sectorsInfo(ctx, nodeApi) + if err != nil { + return err + } + } + + // TODO: grab actr state / info + // * Sealed sectors (count / bytes) + // * Power + } + + if subsystems.Has(api.MarketsSubsystem) { + deals, err := nodeApi.MarketListIncompleteDeals(ctx) + if err != nil { + return err + } + + type dealStat struct { + count, verifCount int + bytes, verifBytes uint64 + } + dsAdd := func(ds *dealStat, deal storagemarket.MinerDeal) { + ds.count++ + ds.bytes += uint64(deal.Proposal.PieceSize) + if deal.Proposal.VerifiedDeal { + ds.verifCount++ + ds.verifBytes += uint64(deal.Proposal.PieceSize) + } + } + + showDealStates := map[storagemarket.StorageDealStatus]struct{}{ + storagemarket.StorageDealActive: {}, + storagemarket.StorageDealTransferring: {}, + storagemarket.StorageDealStaged: {}, + storagemarket.StorageDealAwaitingPreCommit: {}, + storagemarket.StorageDealSealing: {}, + storagemarket.StorageDealPublish: {}, + storagemarket.StorageDealCheckForAcceptance: {}, + storagemarket.StorageDealPublishing: {}, + } + + var total dealStat + perState := map[storagemarket.StorageDealStatus]*dealStat{} + for _, deal := range deals { + if _, ok := showDealStates[deal.State]; !ok { + continue + } + if perState[deal.State] == nil { + perState[deal.State] = new(dealStat) + } + + dsAdd(&total, deal) + dsAdd(perState[deal.State], deal) + } + + type wstr struct { + str string + status storagemarket.StorageDealStatus + } + sorted := make([]wstr, 0, len(perState)) + for status, stat := range perState { + st := strings.TrimPrefix(storagemarket.DealStates[status], "StorageDeal") + sorted = append(sorted, wstr{ + str: fmt.Sprintf(" %s:\t%d\t\t%s\t(Verified: %d\t%s)\n", st, stat.count, types.SizeStr(types.NewInt(stat.bytes)), stat.verifCount, types.SizeStr(types.NewInt(stat.verifBytes))), + status: status, + }, + ) + } + sort.Slice(sorted, func(i, j int) bool { + if sorted[i].status == storagemarket.StorageDealActive || sorted[j].status == storagemarket.StorageDealActive { + return sorted[i].status == storagemarket.StorageDealActive + } + return sorted[i].status > sorted[j].status + }) + + fmt.Printf("Storage Deals: %d, %s\n", total.count, types.SizeStr(types.NewInt(total.bytes))) + + tw := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0) + for _, e := range sorted { + _, _ = tw.Write([]byte(e.str)) + } + + _ = tw.Flush() + fmt.Println() + + retrievals, err := nodeApi.MarketListRetrievalDeals(ctx) + if err != nil { + return xerrors.Errorf("getting retrieval deal list: %w", err) + } + + var retrComplete dealStat + for _, retrieval := range retrievals { + if retrieval.Status == retrievalmarket.DealStatusCompleted { + retrComplete.count++ + retrComplete.bytes += retrieval.TotalSent + } + } + + fmt.Printf("Retrieval Deals (complete): %d, %s\n", retrComplete.count, types.SizeStr(types.NewInt(retrComplete.bytes))) + + fmt.Println() } - // TODO: grab actr state / info - // * Sealed sectors (count / bytes) - // * Power return nil } diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index e8598ff0c..dcd3abd4d 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -94,6 +94,8 @@ * [ReturnSealPreCommit1](#ReturnSealPreCommit1) * [ReturnSealPreCommit2](#ReturnSealPreCommit2) * [ReturnUnsealPiece](#ReturnUnsealPiece) +* [Runtime](#Runtime) + * [RuntimeSubsystems](#RuntimeSubsystems) * [Sealing](#Sealing) * [SealingAbort](#SealingAbort) * [SealingSchedDiag](#SealingSchedDiag) @@ -1522,6 +1524,18 @@ Inputs: Response: `{}` +## Runtime + + +### RuntimeSubsystems + + +Perms: read + +Inputs: `null` + +Response: `null` + ## Sealing diff --git a/node/builder_miner.go b/node/builder_miner.go index 0c0f9d15a..d62cbcad9 100644 --- a/node/builder_miner.go +++ b/node/builder_miner.go @@ -72,6 +72,7 @@ func ConfigStorageMiner(c interface{}) Option { return Options( ConfigCommon(&cfg.Common, enableLibp2pNode), + Override(new([]api.MinerSubsystem), modules.AddMinerSubsystems(cfg.Subsystems)), Override(new(stores.LocalStorage), From(new(repo.LockedRepo))), Override(new(*stores.Local), modules.LocalStorage), Override(new(*stores.Remote), modules.RemoteStorage), @@ -215,6 +216,7 @@ func StorageMiner(out *api.StorageMiner, subsystemsCfg config.MinerSubsystemConf func(s *Settings) error { resAPI := &impl.StorageMinerAPI{} + s.invokes[ExtractApiKey] = fx.Populate(resAPI) *out = resAPI return nil diff --git a/node/impl/storminer.go b/node/impl/storminer.go index 9db6a3775..86c84fee7 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -48,6 +48,8 @@ import ( type StorageMinerAPI struct { fx.In + Subsystems api.MinerSubsystems + api.Common api.Net @@ -703,4 +705,8 @@ func (sm *StorageMinerAPI) ComputeProof(ctx context.Context, ssi []builtin.Secto return sm.Epp.ComputeProof(ctx, ssi, rand) } +func (sm *StorageMinerAPI) RuntimeSubsystems(context.Context) (res api.MinerSubsystems, err error) { + return sm.Subsystems, nil +} + var _ api.StorageMiner = &StorageMinerAPI{} diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 3a3914e0c..06ef78ca0 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -1007,3 +1007,20 @@ func mutateCfg(r repo.LockedRepo, mutator func(*config.StorageMiner)) error { return multierr.Combine(typeErr, setConfigErr) } + +func AddMinerSubsystems(cfg config.MinerSubsystemConfig) (res api.MinerSubsystems) { + if cfg.EnableMining { + res = append(res, api.MiningSubsystem) + } + if cfg.EnableSealing { + res = append(res, api.SealingSubsystem) + } + if cfg.EnableSectorStorage { + res = append(res, api.SectorStorageSubsystem) + } + if cfg.EnableMarkets { + res = append(res, api.MarketsSubsystem) + } + + return +} diff --git a/v1.11.1 b/v1.11.1 new file mode 100644 index 000000000..225a346de --- /dev/null +++ b/v1.11.1 @@ -0,0 +1,170 @@ +- github.com/filecoin-project/lotus: + - Merge branch 'releases' into release/v1.11.1 + - Update to proof v8.0.3 ([filecoin-project/lotus#6890](https://github.com/filecoin-project/lotus/pull/6890)) + - lotus-shed: initial export cmd for markets related metadata ([filecoin-project/lotus#6840](https://github.com/filecoin-project/lotus/pull/6840)) + - add a very verbose -vv flag to lotus and lotus-miner. ([filecoin-project/lotus#6888](https://github.com/filecoin-project/lotus/pull/6888)) + - Update RELEASE_ISSUE_TEMPLATE.md ([filecoin-project/lotus#6880](https://github.com/filecoin-project/lotus/pull/6880)) + - Moving GC for badger ([filecoin-project/lotus#6854](https://github.com/filecoin-project/lotus/pull/6854)) + - Add github actions for staled pr ([filecoin-project/lotus#6879](https://github.com/filecoin-project/lotus/pull/6879)) + - Add allocated sectorid vis ([filecoin-project/lotus#4638](https://github.com/filecoin-project/lotus/pull/4638)) + - rename `cmd/lotus{-storage=>}-miner` to match binary. ([filecoin-project/lotus#6886](https://github.com/filecoin-project/lotus/pull/6886)) + - update to go-fil-market v1.6.0 ([filecoin-project/lotus#6885](https://github.com/filecoin-project/lotus/pull/6885)) + - Bump go-multihash, adjust test for supported version ([filecoin-project/lotus#6674](https://github.com/filecoin-project/lotus/pull/6674)) + - Fix padding of deals, which only partially shipped in #5988 ([filecoin-project/lotus#6683](https://github.com/filecoin-project/lotus/pull/6683)) + - fix racy TestSimultanenousTransferLimit. ([filecoin-project/lotus#6862](https://github.com/filecoin-project/lotus/pull/6862)) + - Improve splitstore warmup ([filecoin-project/lotus#6867](https://github.com/filecoin-project/lotus/pull/6867)) + - ValidateBlock: Assert that block header height's are greater than parents ([filecoin-project/lotus#6872](https://github.com/filecoin-project/lotus/pull/6872)) + - feat: Don't panic when api impl is nil ([filecoin-project/lotus#6857](https://github.com/filecoin-project/lotus/pull/6857)) + - splitstore shed utils ([filecoin-project/lotus#6811](https://github.com/filecoin-project/lotus/pull/6811)) + - Fix links in issue templates + - Update issue templates and add templates for M1 ([filecoin-project/lotus#6856](https://github.com/filecoin-project/lotus/pull/6856)) + - Splitstore: support on-disk marksets using badger ([filecoin-project/lotus#6833](https://github.com/filecoin-project/lotus/pull/6833)) + - Config UX improvements ([filecoin-project/lotus#6848](https://github.com/filecoin-project/lotus/pull/6848)) + - fix deal concurrency test failures by upgrading graphsync and others ([filecoin-project/lotus#6724](https://github.com/filecoin-project/lotus/pull/6724)) + - Update issue templates to forms ([filecoin-project/lotus#6798](https://github.com/filecoin-project/lotus/pull/6798)) + - Nerpa v13 upgrade ([filecoin-project/lotus#6837](https://github.com/filecoin-project/lotus/pull/6837)) + - add docker-compose file ([filecoin-project/lotus#6544](https://github.com/filecoin-project/lotus/pull/6544)) + - fix warmup by decoupling state from message receipt walk ([filecoin-project/lotus#6841](https://github.com/filecoin-project/lotus/pull/6841)) + - add a command for compacting sector numbers bitfield ([filecoin-project/lotus#4640](https://github.com/filecoin-project/lotus/pull/4640)) + - PriceListByVersion ([filecoin-project/lotus#6766](https://github.com/filecoin-project/lotus/pull/6766)) + - easy way to make install app ([filecoin-project/lotus#5183](https://github.com/filecoin-project/lotus/pull/5183)) + - api: Separate the Net interface from Common ([filecoin-project/lotus#6627](https://github.com/filecoin-project/lotus/pull/6627)) + - cache loaded block messages ([filecoin-project/lotus#6760](https://github.com/filecoin-project/lotus/pull/6760)) + - fix: on randomness change, use new rand ([filecoin-project/lotus#6805](https://github.com/filecoin-project/lotus/pull/6805)) + - Splitstore: add retention policy option for keeping messages in the hotstore ([filecoin-project/lotus#6775](https://github.com/filecoin-project/lotus/pull/6775)) + - Introduce the LOTUS_CHAIN_BADGERSTORE_DISABLE_FSYNC envvar ([filecoin-project/lotus#6817](https://github.com/filecoin-project/lotus/pull/6817)) + - add StateReadState to gateway api ([filecoin-project/lotus#6818](https://github.com/filecoin-project/lotus/pull/6818)) + - add SealProof in SectorBuilder ([filecoin-project/lotus#6815](https://github.com/filecoin-project/lotus/pull/6815)) + - release -> master ([filecoin-project/lotus#6828](https://github.com/filecoin-project/lotus/pull/6828)) + - sealing: Handle preCommitParams errors more correctly ([filecoin-project/lotus#6763](https://github.com/filecoin-project/lotus/pull/6763)) + - fix: always check if StateSearchMessage returns nil ([filecoin-project/lotus#6802](https://github.com/filecoin-project/lotus/pull/6802)) + - ClientFindData: always fetch peer id from chain ([filecoin-project/lotus#6807](https://github.com/filecoin-project/lotus/pull/6807)) + - test: fix flaky window post tests ([filecoin-project/lotus#6804](https://github.com/filecoin-project/lotus/pull/6804)) + - ([filecoin-project/lotus#6800](https://github.com/filecoin-project/lotus/pull/6800)) + - fixes #6786 segfault ([filecoin-project/lotus#6787](https://github.com/filecoin-project/lotus/pull/6787)) + - Splitstore: add support for protecting out of chain references in the blockstore ([filecoin-project/lotus#6777](https://github.com/filecoin-project/lotus/pull/6777)) + - Resurrect CODEOWNERS, but for maintainers group ([filecoin-project/lotus#6773](https://github.com/filecoin-project/lotus/pull/6773)) + - update go-libp2p-pubsub to v0.5.0 ([filecoin-project/lotus#6764](https://github.com/filecoin-project/lotus/pull/6764)) + - Implement exposed splitstore ([filecoin-project/lotus#6762](https://github.com/filecoin-project/lotus/pull/6762)) + - Add ChainGetMessagesInTipset API ([filecoin-project/lotus#6642](https://github.com/filecoin-project/lotus/pull/6642)) + - test: handle null blocks in TestForkRefuseCall ([filecoin-project/lotus#6758](https://github.com/filecoin-project/lotus/pull/6758)) + - Master disclaimer ([filecoin-project/lotus#6757](https://github.com/filecoin-project/lotus/pull/6757)) + - Splitstore code reorg ([filecoin-project/lotus#6756](https://github.com/filecoin-project/lotus/pull/6756)) + - Create stale.yml ([filecoin-project/lotus#6747](https://github.com/filecoin-project/lotus/pull/6747)) + - Splitstore: Some small fixes ([filecoin-project/lotus#6754](https://github.com/filecoin-project/lotus/pull/6754)) + - ([filecoin-project/lotus#6746](https://github.com/filecoin-project/lotus/pull/6746)) + - Handle the --color flag via proper global state ([filecoin-project/lotus#6743](https://github.com/filecoin-project/lotus/pull/6743)) + - Config for collateral from miner available balance ([filecoin-project/lotus#6629](https://github.com/filecoin-project/lotus/pull/6629)) + - Support standalone miner-market process ([filecoin-project/lotus#6356](https://github.com/filecoin-project/lotus/pull/6356)) + - Splitstore Enhanchements ([filecoin-project/lotus#6474](https://github.com/filecoin-project/lotus/pull/6474)) + - ([filecoin-project/lotus#6739](https://github.com/filecoin-project/lotus/pull/6739)) + - Add more deal details to lotus-miner info ([filecoin-project/lotus#6708](https://github.com/filecoin-project/lotus/pull/6708)) + - Release template: Update all testnet infra at once ([filecoin-project/lotus#6710](https://github.com/filecoin-project/lotus/pull/6710)) + - Fix Lotus shed + - Fix bugs in sectors extend --v1-sectors ([filecoin-project/lotus#6066](https://github.com/filecoin-project/lotus/pull/6066)) + - add election backtest ([filecoin-project/lotus#5950](https://github.com/filecoin-project/lotus/pull/5950)) + - Envvar to disable slash filter ([filecoin-project/lotus#6620](https://github.com/filecoin-project/lotus/pull/6620)) + - Release Template: remove binary validation step ([filecoin-project/lotus#6709](https://github.com/filecoin-project/lotus/pull/6709)) + - Config for deal publishing control addresses ([filecoin-project/lotus#6697](https://github.com/filecoin-project/lotus/pull/6697)) + - Reset of the interop network ([filecoin-project/lotus#6689](https://github.com/filecoin-project/lotus/pull/6689)) + - Enable color by default only if os.Stdout is a TTY ([filecoin-project/lotus#6696](https://github.com/filecoin-project/lotus/pull/6696)) + - Stop outputing ANSI color on non-TTY ([filecoin-project/lotus#6694](https://github.com/filecoin-project/lotus/pull/6694)) + - add dollar sign ([filecoin-project/lotus#6690](https://github.com/filecoin-project/lotus/pull/6690)) + - get-actor cli spelling fix ([filecoin-project/lotus#6681](https://github.com/filecoin-project/lotus/pull/6681)) + - fix "lotus-seed genesis car" error "merkledag: not found" ([filecoin-project/lotus#6688](https://github.com/filecoin-project/lotus/pull/6688)) + - polish(statetree): accept a context in statetree diff for timeouts ([filecoin-project/lotus#6639](https://github.com/filecoin-project/lotus/pull/6639)) + - Add helptext to lotus chain export ([filecoin-project/lotus#6672](https://github.com/filecoin-project/lotus/pull/6672)) + - Get retrieval pricing input should not error out on a deal state fetch ([filecoin-project/lotus#6679](https://github.com/filecoin-project/lotus/pull/6679)) + - Fix more CID double-encoding as hex ([filecoin-project/lotus#6680](https://github.com/filecoin-project/lotus/pull/6680)) + - add an incremental nonce itest. ([filecoin-project/lotus#6663](https://github.com/filecoin-project/lotus/pull/6663)) + - storage: Fix FinalizeSector with sectors in stoage paths ([filecoin-project/lotus#6653](https://github.com/filecoin-project/lotus/pull/6653)) + - Fix tiny error in check-client-datacap ([filecoin-project/lotus#6664](https://github.com/filecoin-project/lotus/pull/6664)) + - Fix: precommit_batch method used the wrong cfg.CommitBatchWait ([filecoin-project/lotus#6658](https://github.com/filecoin-project/lotus/pull/6658)) + - fix ticket expiration check ([filecoin-project/lotus#6635](https://github.com/filecoin-project/lotus/pull/6635)) + - commit batch: AggregateAboveBaseFee config ([filecoin-project/lotus#6650](https://github.com/filecoin-project/lotus/pull/6650)) + - commit batch: Initialize the FailedSectors map ([filecoin-project/lotus#6647](https://github.com/filecoin-project/lotus/pull/6647)) + - Fast-path retry submitting commit aggregate if commit is still valid ([filecoin-project/lotus#6638](https://github.com/filecoin-project/lotus/pull/6638)) + - remove precommit check in handleCommitFailed ([filecoin-project/lotus#6634](https://github.com/filecoin-project/lotus/pull/6634)) + - Reuse timers in sealing batch logic ([filecoin-project/lotus#6636](https://github.com/filecoin-project/lotus/pull/6636)) + - shed tool to estimate aggregate network fees ([filecoin-project/lotus#6631](https://github.com/filecoin-project/lotus/pull/6631)) + - fix prove commit aggregate send token amount ([filecoin-project/lotus#6625](https://github.com/filecoin-project/lotus/pull/6625)) + - Update version.go to 1.11.1 ([filecoin-project/lotus#6621](https://github.com/filecoin-project/lotus/pull/6621)) +- github.com/filecoin-project/go-data-transfer (v1.6.0 -> v1.7.0): + - release: v1.7.0 + - Fire a transfer queued event when a transfer is queued in Graphsync (#221) ([filecoin-project/go-data-transfer#221](https://github.com/filecoin-project/go-data-transfer/pull/221)) + - feat: pass ChannelID to ValidatePush & ValidatePull (#220) ([filecoin-project/go-data-transfer#220](https://github.com/filecoin-project/go-data-transfer/pull/220)) + - release: v1.6.1 ([filecoin-project/go-data-transfer#218](https://github.com/filecoin-project/go-data-transfer/pull/218)) + - Remove CID lists (#217) ([filecoin-project/go-data-transfer#217](https://github.com/filecoin-project/go-data-transfer/pull/217)) + - Merge v1.6.0 ([filecoin-project/go-data-transfer#214](https://github.com/filecoin-project/go-data-transfer/pull/214)) + - Remove restart ack timeout (#211) ([filecoin-project/go-data-transfer#211](https://github.com/filecoin-project/go-data-transfer/pull/211)) + - feat: use different extension names to fit multiple hooks data in same graphsync message (#204) ([filecoin-project/go-data-transfer#204](https://github.com/filecoin-project/go-data-transfer/pull/204)) + - fix: map race in GS transport (#208) ([filecoin-project/go-data-transfer#208](https://github.com/filecoin-project/go-data-transfer/pull/208)) + - refactor: simplify graphsync transport (#203) ([filecoin-project/go-data-transfer#203](https://github.com/filecoin-project/go-data-transfer/pull/203)) + - release: v1.5.0 (#200) ([filecoin-project/go-data-transfer#200](https://github.com/filecoin-project/go-data-transfer/pull/200)) +- github.com/filecoin-project/go-fil-markets (v1.5.0 -> v1.6.0): + - release: v1.6.0 + - support padding out smaller files (#536) ([filecoin-project/go-fil-markets#536](https://github.com/filecoin-project/go-fil-markets/pull/536)) + - On overloaded CI 10 seconds just isn't enough (#587) ([filecoin-project/go-fil-markets#587](https://github.com/filecoin-project/go-fil-markets/pull/587)) + - Do not hex-encode CIDs in logs (#561) ([filecoin-project/go-fil-markets#561](https://github.com/filecoin-project/go-fil-markets/pull/561)) + - remove wrong peer check in push deal validation (#585) ([filecoin-project/go-fil-markets#585](https://github.com/filecoin-project/go-fil-markets/pull/585)) + - fix: circleci docs-gen task (#574) ([filecoin-project/go-fil-markets#574](https://github.com/filecoin-project/go-fil-markets/pull/574)) + - Storage market request queued event and validation interface changes (#555) ([filecoin-project/go-fil-markets#555](https://github.com/filecoin-project/go-fil-markets/pull/555)) + - build(deps): bump ws from 6.2.1 to 6.2.2 (#554) ([filecoin-project/go-fil-markets#554](https://github.com/filecoin-project/go-fil-markets/pull/554)) + - release: v1.5.0 ([filecoin-project/go-fil-markets#553](https://github.com/filecoin-project/go-fil-markets/pull/553)) +- github.com/filecoin-project/go-padreader (v0.0.0-20200903213702-ed5fae088b20 -> v0.0.0-20210723183308-812a16dc01b1): + - New method to pad harder (#6) ([filecoin-project/go-padreader#6](https://github.com/filecoin-project/go-padreader/pull/6)) + - Create SECURITY.md (#5) ([filecoin-project/go-padreader#5](https://github.com/filecoin-project/go-padreader/pull/5)) +- github.com/filecoin-project/go-state-types (v0.1.1-0.20210506134452-99b279731c48 -> v0.1.1-0.20210722133031-ad9bfe54c124): + - Add version 6.5 (#30) ([filecoin-project/go-state-types#30](https://github.com/filecoin-project/go-state-types/pull/30)) + - rename file +- github.com/filecoin-project/specs-actors/v5 (v5.0.1 -> v5.0.3): + - Adjust code for subtle change in go-multihash 0.0.15 (#1463) ([filecoin-project/specs-actors#1463](https://github.com/filecoin-project/specs-actors/pull/1463)) + - Bump go state types (#1464) ([filecoin-project/specs-actors#1464](https://github.com/filecoin-project/specs-actors/pull/1464)) + - Create CODEOWNERS (#1465) ([filecoin-project/specs-actors#1465](https://github.com/filecoin-project/specs-actors/pull/1465)) + - Test deterministic offset (#1462) ([filecoin-project/specs-actors#1462](https://github.com/filecoin-project/specs-actors/pull/1462)) + +Contributors + +| Contributor | Commits | Lines ± | Files Changed | +|-------------|---------|---------|---------------| +| vyzo | 295 | +8700/-5936 | 397 | +| Anton Evangelatov | 94 | +4680/-2965 | 277 | +| Łukasz Magiera | 37 | +3851/-1611 | 146 | +| Mike Greenberg | 1 | +2310/-578 | 8 | +| dirkmc | 7 | +1154/-726 | 29 | +| Jennifer Wang | 9 | +485/-341 | 26 | +| Peter Rabbitson | 18 | +469/-273 | 64 | +| Cory Schwartz | 5 | +576/-135 | 14 | +| hunjixin | 7 | +404/-82 | 19 | +| ZenGround0 | 17 | +284/-135 | 44 | +| Dirk McCormick | 17 | +348/-47 | 17 | +| Raúl Kripalani | 18 | +254/-97 | 62 | +| tchardin | 1 | +261/-33 | 4 | +| Jakub Sztandera | 4 | +254/-16 | 4 | +| Aarsh Shah | 2 | +196/-40 | 28 | +| whyrusleeping | 3 | +150/-9 | 8 | +| Whyrusleeping | 2 | +87/-66 | 10 | +| Aayush Rajasekaran | 10 | +81/-53 | 13 | +| zgfzgf | 2 | +104/-4 | 2 | +| aarshkshah1992 | 4 | +73/-7 | 6 | +| llifezou | 4 | +59/-20 | 4 | +| Steven Allen | 7 | +47/-17 | 9 | +| johnli-helloworld | 3 | +46/-15 | 5 | +| frrist | 1 | +28/-23 | 2 | +| Jennifer | 4 | +31/-2 | 4 | +| wangchao | 1 | +1/-27 | 1 | +| Jiaying Wang | 2 | +7/-21 | 2 | +| hannahhoward | 3 | +21/-2 | 3 | +| chadwick2143 | 1 | +15/-1 | 1 | +| Jerry | 2 | +9/-4 | 2 | +| Steve Loeppky | 2 | +12/-0 | 2 | +| David Dias | 1 | +9/-0 | 1 | +| dependabot[bot] | 1 | +3/-3 | 1 | +| zhoutian527 | 1 | +2/-2 | 1 | +| xloem | 1 | +4/-0 | 1 | +| Travis Person | 2 | +2/-2 | 3 | +| Liviu Damian | 2 | +2/-2 | 2 | +| Jim Pick | 2 | +2/-2 | 2 | +| Frank | 1 | +3/-0 | 1 | +| turuslan | 1 | +1/-1 | 1 | +| Kirk Baird | 1 | +0/-0 | 1 | From 0dd83c675557f36d4295dc1b30cb53e70769e6cc Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 28 Jul 2021 16:23:04 +0300 Subject: [PATCH 27/51] fixup --- node/builder_miner.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/node/builder_miner.go b/node/builder_miner.go index d62cbcad9..830e6d075 100644 --- a/node/builder_miner.go +++ b/node/builder_miner.go @@ -72,7 +72,7 @@ func ConfigStorageMiner(c interface{}) Option { return Options( ConfigCommon(&cfg.Common, enableLibp2pNode), - Override(new([]api.MinerSubsystem), modules.AddMinerSubsystems(cfg.Subsystems)), + Override(new(api.MinerSubsystems), modules.AddMinerSubsystems(cfg.Subsystems)), Override(new(stores.LocalStorage), From(new(repo.LockedRepo))), Override(new(*stores.Local), modules.LocalStorage), Override(new(*stores.Remote), modules.RemoteStorage), @@ -216,7 +216,6 @@ func StorageMiner(out *api.StorageMiner, subsystemsCfg config.MinerSubsystemConf func(s *Settings) error { resAPI := &impl.StorageMinerAPI{} - s.invokes[ExtractApiKey] = fx.Populate(resAPI) *out = resAPI return nil From cea26348c44a56ecd46f6443c503cdb3ddab3cf7 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 28 Jul 2021 17:30:59 +0300 Subject: [PATCH 28/51] extract outputs for mining node and markets node in separate functions --- cmd/lotus-miner/info.go | 561 +++++++++++++++++++++------------------- 1 file changed, 290 insertions(+), 271 deletions(-) diff --git a/cmd/lotus-miner/info.go b/cmd/lotus-miner/info.go index 4c409788f..2a3627959 100644 --- a/cmd/lotus-miner/info.go +++ b/cmd/lotus-miner/info.go @@ -21,6 +21,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/v0api" sealing "github.com/filecoin-project/lotus/extern/storage-sealing" "github.com/filecoin-project/lotus/api" @@ -103,291 +104,309 @@ func infoCmdAct(cctx *cli.Context) error { fmt.Println() if subsystems.Has(api.SectorStorageSubsystem) { - maddr, err := getActorAddress(ctx, cctx) + err := handleMiningInfo(cctx, ctx, fullapi, nodeApi) if err != nil { return err } - - mact, err := fullapi.StateGetActor(ctx, maddr, types.EmptyTSK) - if err != nil { - return err - } - - tbs := blockstore.NewTieredBstore(blockstore.NewAPIBlockstore(fullapi), blockstore.NewMemory()) - mas, err := miner.Load(adt.WrapStore(ctx, cbor.NewCborStore(tbs)), mact) - if err != nil { - return err - } - - // Sector size - mi, err := fullapi.StateMinerInfo(ctx, maddr, types.EmptyTSK) - if err != nil { - return err - } - - ssize := types.SizeStr(types.NewInt(uint64(mi.SectorSize))) - fmt.Printf("Miner: %s (%s sectors)\n", color.BlueString("%s", maddr), ssize) - - pow, err := fullapi.StateMinerPower(ctx, maddr, types.EmptyTSK) - if err != nil { - return err - } - - fmt.Printf("Power: %s / %s (%0.4f%%)\n", - color.GreenString(types.DeciStr(pow.MinerPower.QualityAdjPower)), - types.DeciStr(pow.TotalPower.QualityAdjPower), - types.BigDivFloat( - types.BigMul(pow.MinerPower.QualityAdjPower, big.NewInt(100)), - pow.TotalPower.QualityAdjPower, - ), - ) - - fmt.Printf("\tRaw: %s / %s (%0.4f%%)\n", - color.BlueString(types.SizeStr(pow.MinerPower.RawBytePower)), - types.SizeStr(pow.TotalPower.RawBytePower), - types.BigDivFloat( - types.BigMul(pow.MinerPower.RawBytePower, big.NewInt(100)), - pow.TotalPower.RawBytePower, - ), - ) - secCounts, err := fullapi.StateMinerSectorCount(ctx, maddr, types.EmptyTSK) - if err != nil { - return err - } - - proving := secCounts.Active + secCounts.Faulty - nfaults := secCounts.Faulty - fmt.Printf("\tCommitted: %s\n", types.SizeStr(types.BigMul(types.NewInt(secCounts.Live), types.NewInt(uint64(mi.SectorSize))))) - if nfaults == 0 { - fmt.Printf("\tProving: %s\n", types.SizeStr(types.BigMul(types.NewInt(proving), types.NewInt(uint64(mi.SectorSize))))) - } else { - var faultyPercentage float64 - if secCounts.Live != 0 { - faultyPercentage = float64(100*nfaults) / float64(secCounts.Live) - } - fmt.Printf("\tProving: %s (%s Faulty, %.2f%%)\n", - types.SizeStr(types.BigMul(types.NewInt(proving), types.NewInt(uint64(mi.SectorSize)))), - types.SizeStr(types.BigMul(types.NewInt(nfaults), types.NewInt(uint64(mi.SectorSize)))), - faultyPercentage) - } - - if !pow.HasMinPower { - fmt.Print("Below minimum power threshold, no blocks will be won") - } else { - - winRatio := new(corebig.Rat).SetFrac( - types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(build.BlocksPerEpoch)).Int, - pow.TotalPower.QualityAdjPower.Int, - ) - - if winRatioFloat, _ := winRatio.Float64(); winRatioFloat > 0 { - - // if the corresponding poisson distribution isn't infinitely small then - // throw it into the mix as well, accounting for multi-wins - winRationWithPoissonFloat := -math.Expm1(-winRatioFloat) - winRationWithPoisson := new(corebig.Rat).SetFloat64(winRationWithPoissonFloat) - if winRationWithPoisson != nil { - winRatio = winRationWithPoisson - winRatioFloat = winRationWithPoissonFloat - } - - weekly, _ := new(corebig.Rat).Mul( - winRatio, - new(corebig.Rat).SetInt64(7*builtin.EpochsInDay), - ).Float64() - - avgDuration, _ := new(corebig.Rat).Mul( - new(corebig.Rat).SetInt64(builtin.EpochDurationSeconds), - new(corebig.Rat).Inv(winRatio), - ).Float64() - - fmt.Print("Projected average block win rate: ") - color.Blue( - "%.02f/week (every %s)", - weekly, - (time.Second * time.Duration(avgDuration)).Truncate(time.Second).String(), - ) - - // Geometric distribution of P(Y < k) calculated as described in https://en.wikipedia.org/wiki/Geometric_distribution#Probability_Outcomes_Examples - // https://www.wolframalpha.com/input/?i=t+%3E+0%3B+p+%3E+0%3B+p+%3C+1%3B+c+%3E+0%3B+c+%3C1%3B+1-%281-p%29%5E%28t%29%3Dc%3B+solve+t - // t == how many dice-rolls (epochs) before win - // p == winRate == ( minerPower / netPower ) - // c == target probability of win ( 99.9% in this case ) - fmt.Print("Projected block win with ") - color.Green( - "99.9%% probability every %s", - (time.Second * time.Duration( - builtin.EpochDurationSeconds*math.Log(1-0.999)/ - math.Log(1-winRatioFloat), - )).Truncate(time.Second).String(), - ) - fmt.Println("(projections DO NOT account for future network and miner growth)") - } - } - - fmt.Println() - - spendable := big.Zero() - - // NOTE: there's no need to unlock anything here. Funds only - // vest on deadline boundaries, and they're unlocked by cron. - lockedFunds, err := mas.LockedFunds() - if err != nil { - return xerrors.Errorf("getting locked funds: %w", err) - } - availBalance, err := mas.AvailableBalance(mact.Balance) - if err != nil { - return xerrors.Errorf("getting available balance: %w", err) - } - spendable = big.Add(spendable, availBalance) - - fmt.Printf("Miner Balance: %s\n", color.YellowString("%s", types.FIL(mact.Balance).Short())) - fmt.Printf(" PreCommit: %s\n", types.FIL(lockedFunds.PreCommitDeposits).Short()) - fmt.Printf(" Pledge: %s\n", types.FIL(lockedFunds.InitialPledgeRequirement).Short()) - fmt.Printf(" Vesting: %s\n", types.FIL(lockedFunds.VestingFunds).Short()) - colorTokenAmount(" Available: %s\n", availBalance) - - mb, err := fullapi.StateMarketBalance(ctx, maddr, types.EmptyTSK) - if err != nil { - return xerrors.Errorf("getting market balance: %w", err) - } - spendable = big.Add(spendable, big.Sub(mb.Escrow, mb.Locked)) - - fmt.Printf("Market Balance: %s\n", types.FIL(mb.Escrow).Short()) - fmt.Printf(" Locked: %s\n", types.FIL(mb.Locked).Short()) - colorTokenAmount(" Available: %s\n", big.Sub(mb.Escrow, mb.Locked)) - - wb, err := fullapi.WalletBalance(ctx, mi.Worker) - if err != nil { - return xerrors.Errorf("getting worker balance: %w", err) - } - spendable = big.Add(spendable, wb) - color.Cyan("Worker Balance: %s", types.FIL(wb).Short()) - if len(mi.ControlAddresses) > 0 { - cbsum := big.Zero() - for _, ca := range mi.ControlAddresses { - b, err := fullapi.WalletBalance(ctx, ca) - if err != nil { - return xerrors.Errorf("getting control address balance: %w", err) - } - cbsum = big.Add(cbsum, b) - } - spendable = big.Add(spendable, cbsum) - - fmt.Printf(" Control: %s\n", types.FIL(cbsum).Short()) - } - colorTokenAmount("Total Spendable: %s\n", spendable) - - fmt.Println() - - if !cctx.Bool("hide-sectors-info") { - fmt.Println("Sectors:") - err = sectorsInfo(ctx, nodeApi) - if err != nil { - return err - } - } - - // TODO: grab actr state / info - // * Sealed sectors (count / bytes) - // * Power } if subsystems.Has(api.MarketsSubsystem) { - deals, err := nodeApi.MarketListIncompleteDeals(ctx) + err := handleMarketsInfo(ctx, nodeApi) if err != nil { return err } - - type dealStat struct { - count, verifCount int - bytes, verifBytes uint64 - } - dsAdd := func(ds *dealStat, deal storagemarket.MinerDeal) { - ds.count++ - ds.bytes += uint64(deal.Proposal.PieceSize) - if deal.Proposal.VerifiedDeal { - ds.verifCount++ - ds.verifBytes += uint64(deal.Proposal.PieceSize) - } - } - - showDealStates := map[storagemarket.StorageDealStatus]struct{}{ - storagemarket.StorageDealActive: {}, - storagemarket.StorageDealTransferring: {}, - storagemarket.StorageDealStaged: {}, - storagemarket.StorageDealAwaitingPreCommit: {}, - storagemarket.StorageDealSealing: {}, - storagemarket.StorageDealPublish: {}, - storagemarket.StorageDealCheckForAcceptance: {}, - storagemarket.StorageDealPublishing: {}, - } - - var total dealStat - perState := map[storagemarket.StorageDealStatus]*dealStat{} - for _, deal := range deals { - if _, ok := showDealStates[deal.State]; !ok { - continue - } - if perState[deal.State] == nil { - perState[deal.State] = new(dealStat) - } - - dsAdd(&total, deal) - dsAdd(perState[deal.State], deal) - } - - type wstr struct { - str string - status storagemarket.StorageDealStatus - } - sorted := make([]wstr, 0, len(perState)) - for status, stat := range perState { - st := strings.TrimPrefix(storagemarket.DealStates[status], "StorageDeal") - sorted = append(sorted, wstr{ - str: fmt.Sprintf(" %s:\t%d\t\t%s\t(Verified: %d\t%s)\n", st, stat.count, types.SizeStr(types.NewInt(stat.bytes)), stat.verifCount, types.SizeStr(types.NewInt(stat.verifBytes))), - status: status, - }, - ) - } - sort.Slice(sorted, func(i, j int) bool { - if sorted[i].status == storagemarket.StorageDealActive || sorted[j].status == storagemarket.StorageDealActive { - return sorted[i].status == storagemarket.StorageDealActive - } - return sorted[i].status > sorted[j].status - }) - - fmt.Printf("Storage Deals: %d, %s\n", total.count, types.SizeStr(types.NewInt(total.bytes))) - - tw := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0) - for _, e := range sorted { - _, _ = tw.Write([]byte(e.str)) - } - - _ = tw.Flush() - fmt.Println() - - retrievals, err := nodeApi.MarketListRetrievalDeals(ctx) - if err != nil { - return xerrors.Errorf("getting retrieval deal list: %w", err) - } - - var retrComplete dealStat - for _, retrieval := range retrievals { - if retrieval.Status == retrievalmarket.DealStatusCompleted { - retrComplete.count++ - retrComplete.bytes += retrieval.TotalSent - } - } - - fmt.Printf("Retrieval Deals (complete): %d, %s\n", retrComplete.count, types.SizeStr(types.NewInt(retrComplete.bytes))) - - fmt.Println() } return nil } +func handleMiningInfo(cctx *cli.Context, ctx context.Context, fullapi v0api.FullNode, nodeApi api.StorageMiner) error { + maddr, err := getActorAddress(ctx, cctx) + if err != nil { + return err + } + + mact, err := fullapi.StateGetActor(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + + tbs := blockstore.NewTieredBstore(blockstore.NewAPIBlockstore(fullapi), blockstore.NewMemory()) + mas, err := miner.Load(adt.WrapStore(ctx, cbor.NewCborStore(tbs)), mact) + if err != nil { + return err + } + + // Sector size + mi, err := fullapi.StateMinerInfo(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + + ssize := types.SizeStr(types.NewInt(uint64(mi.SectorSize))) + fmt.Printf("Miner: %s (%s sectors)\n", color.BlueString("%s", maddr), ssize) + + pow, err := fullapi.StateMinerPower(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + + fmt.Printf("Power: %s / %s (%0.4f%%)\n", + color.GreenString(types.DeciStr(pow.MinerPower.QualityAdjPower)), + types.DeciStr(pow.TotalPower.QualityAdjPower), + types.BigDivFloat( + types.BigMul(pow.MinerPower.QualityAdjPower, big.NewInt(100)), + pow.TotalPower.QualityAdjPower, + ), + ) + + fmt.Printf("\tRaw: %s / %s (%0.4f%%)\n", + color.BlueString(types.SizeStr(pow.MinerPower.RawBytePower)), + types.SizeStr(pow.TotalPower.RawBytePower), + types.BigDivFloat( + types.BigMul(pow.MinerPower.RawBytePower, big.NewInt(100)), + pow.TotalPower.RawBytePower, + ), + ) + secCounts, err := fullapi.StateMinerSectorCount(ctx, maddr, types.EmptyTSK) + if err != nil { + return err + } + + proving := secCounts.Active + secCounts.Faulty + nfaults := secCounts.Faulty + fmt.Printf("\tCommitted: %s\n", types.SizeStr(types.BigMul(types.NewInt(secCounts.Live), types.NewInt(uint64(mi.SectorSize))))) + if nfaults == 0 { + fmt.Printf("\tProving: %s\n", types.SizeStr(types.BigMul(types.NewInt(proving), types.NewInt(uint64(mi.SectorSize))))) + } else { + var faultyPercentage float64 + if secCounts.Live != 0 { + faultyPercentage = float64(100*nfaults) / float64(secCounts.Live) + } + fmt.Printf("\tProving: %s (%s Faulty, %.2f%%)\n", + types.SizeStr(types.BigMul(types.NewInt(proving), types.NewInt(uint64(mi.SectorSize)))), + types.SizeStr(types.BigMul(types.NewInt(nfaults), types.NewInt(uint64(mi.SectorSize)))), + faultyPercentage) + } + + if !pow.HasMinPower { + fmt.Print("Below minimum power threshold, no blocks will be won") + } else { + + winRatio := new(corebig.Rat).SetFrac( + types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(build.BlocksPerEpoch)).Int, + pow.TotalPower.QualityAdjPower.Int, + ) + + if winRatioFloat, _ := winRatio.Float64(); winRatioFloat > 0 { + + // if the corresponding poisson distribution isn't infinitely small then + // throw it into the mix as well, accounting for multi-wins + winRationWithPoissonFloat := -math.Expm1(-winRatioFloat) + winRationWithPoisson := new(corebig.Rat).SetFloat64(winRationWithPoissonFloat) + if winRationWithPoisson != nil { + winRatio = winRationWithPoisson + winRatioFloat = winRationWithPoissonFloat + } + + weekly, _ := new(corebig.Rat).Mul( + winRatio, + new(corebig.Rat).SetInt64(7*builtin.EpochsInDay), + ).Float64() + + avgDuration, _ := new(corebig.Rat).Mul( + new(corebig.Rat).SetInt64(builtin.EpochDurationSeconds), + new(corebig.Rat).Inv(winRatio), + ).Float64() + + fmt.Print("Projected average block win rate: ") + color.Blue( + "%.02f/week (every %s)", + weekly, + (time.Second * time.Duration(avgDuration)).Truncate(time.Second).String(), + ) + + // Geometric distribution of P(Y < k) calculated as described in https://en.wikipedia.org/wiki/Geometric_distribution#Probability_Outcomes_Examples + // https://www.wolframalpha.com/input/?i=t+%3E+0%3B+p+%3E+0%3B+p+%3C+1%3B+c+%3E+0%3B+c+%3C1%3B+1-%281-p%29%5E%28t%29%3Dc%3B+solve+t + // t == how many dice-rolls (epochs) before win + // p == winRate == ( minerPower / netPower ) + // c == target probability of win ( 99.9% in this case ) + fmt.Print("Projected block win with ") + color.Green( + "99.9%% probability every %s", + (time.Second * time.Duration( + builtin.EpochDurationSeconds*math.Log(1-0.999)/ + math.Log(1-winRatioFloat), + )).Truncate(time.Second).String(), + ) + fmt.Println("(projections DO NOT account for future network and miner growth)") + } + } + + fmt.Println() + + spendable := big.Zero() + + // NOTE: there's no need to unlock anything here. Funds only + // vest on deadline boundaries, and they're unlocked by cron. + lockedFunds, err := mas.LockedFunds() + if err != nil { + return xerrors.Errorf("getting locked funds: %w", err) + } + availBalance, err := mas.AvailableBalance(mact.Balance) + if err != nil { + return xerrors.Errorf("getting available balance: %w", err) + } + spendable = big.Add(spendable, availBalance) + + fmt.Printf("Miner Balance: %s\n", color.YellowString("%s", types.FIL(mact.Balance).Short())) + fmt.Printf(" PreCommit: %s\n", types.FIL(lockedFunds.PreCommitDeposits).Short()) + fmt.Printf(" Pledge: %s\n", types.FIL(lockedFunds.InitialPledgeRequirement).Short()) + fmt.Printf(" Vesting: %s\n", types.FIL(lockedFunds.VestingFunds).Short()) + colorTokenAmount(" Available: %s\n", availBalance) + + mb, err := fullapi.StateMarketBalance(ctx, maddr, types.EmptyTSK) + if err != nil { + return xerrors.Errorf("getting market balance: %w", err) + } + spendable = big.Add(spendable, big.Sub(mb.Escrow, mb.Locked)) + + fmt.Printf("Market Balance: %s\n", types.FIL(mb.Escrow).Short()) + fmt.Printf(" Locked: %s\n", types.FIL(mb.Locked).Short()) + colorTokenAmount(" Available: %s\n", big.Sub(mb.Escrow, mb.Locked)) + + wb, err := fullapi.WalletBalance(ctx, mi.Worker) + if err != nil { + return xerrors.Errorf("getting worker balance: %w", err) + } + spendable = big.Add(spendable, wb) + color.Cyan("Worker Balance: %s", types.FIL(wb).Short()) + if len(mi.ControlAddresses) > 0 { + cbsum := big.Zero() + for _, ca := range mi.ControlAddresses { + b, err := fullapi.WalletBalance(ctx, ca) + if err != nil { + return xerrors.Errorf("getting control address balance: %w", err) + } + cbsum = big.Add(cbsum, b) + } + spendable = big.Add(spendable, cbsum) + + fmt.Printf(" Control: %s\n", types.FIL(cbsum).Short()) + } + colorTokenAmount("Total Spendable: %s\n", spendable) + + fmt.Println() + + if !cctx.Bool("hide-sectors-info") { + fmt.Println("Sectors:") + err = sectorsInfo(ctx, nodeApi) + if err != nil { + return err + } + } + + // TODO: grab actr state / info + // * Sealed sectors (count / bytes) + // * Power + + return nil +} + +func handleMarketsInfo(ctx context.Context, nodeApi api.StorageMiner) error { + deals, err := nodeApi.MarketListIncompleteDeals(ctx) + if err != nil { + return err + } + + type dealStat struct { + count, verifCount int + bytes, verifBytes uint64 + } + dsAdd := func(ds *dealStat, deal storagemarket.MinerDeal) { + ds.count++ + ds.bytes += uint64(deal.Proposal.PieceSize) + if deal.Proposal.VerifiedDeal { + ds.verifCount++ + ds.verifBytes += uint64(deal.Proposal.PieceSize) + } + } + + showDealStates := map[storagemarket.StorageDealStatus]struct{}{ + storagemarket.StorageDealActive: {}, + storagemarket.StorageDealTransferring: {}, + storagemarket.StorageDealStaged: {}, + storagemarket.StorageDealAwaitingPreCommit: {}, + storagemarket.StorageDealSealing: {}, + storagemarket.StorageDealPublish: {}, + storagemarket.StorageDealCheckForAcceptance: {}, + storagemarket.StorageDealPublishing: {}, + } + + var total dealStat + perState := map[storagemarket.StorageDealStatus]*dealStat{} + for _, deal := range deals { + if _, ok := showDealStates[deal.State]; !ok { + continue + } + if perState[deal.State] == nil { + perState[deal.State] = new(dealStat) + } + + dsAdd(&total, deal) + dsAdd(perState[deal.State], deal) + } + + type wstr struct { + str string + status storagemarket.StorageDealStatus + } + sorted := make([]wstr, 0, len(perState)) + for status, stat := range perState { + st := strings.TrimPrefix(storagemarket.DealStates[status], "StorageDeal") + sorted = append(sorted, wstr{ + str: fmt.Sprintf(" %s:\t%d\t\t%s\t(Verified: %d\t%s)\n", st, stat.count, types.SizeStr(types.NewInt(stat.bytes)), stat.verifCount, types.SizeStr(types.NewInt(stat.verifBytes))), + status: status, + }, + ) + } + sort.Slice(sorted, func(i, j int) bool { + if sorted[i].status == storagemarket.StorageDealActive || sorted[j].status == storagemarket.StorageDealActive { + return sorted[i].status == storagemarket.StorageDealActive + } + return sorted[i].status > sorted[j].status + }) + + fmt.Printf("Storage Deals: %d, %s\n", total.count, types.SizeStr(types.NewInt(total.bytes))) + + tw := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0) + for _, e := range sorted { + _, _ = tw.Write([]byte(e.str)) + } + + _ = tw.Flush() + fmt.Println() + + retrievals, err := nodeApi.MarketListRetrievalDeals(ctx) + if err != nil { + return xerrors.Errorf("getting retrieval deal list: %w", err) + } + + var retrComplete dealStat + for _, retrieval := range retrievals { + if retrieval.Status == retrievalmarket.DealStatusCompleted { + retrComplete.count++ + retrComplete.bytes += retrieval.TotalSent + } + } + + fmt.Printf("Retrieval Deals (complete): %d, %s\n", retrComplete.count, types.SizeStr(types.NewInt(retrComplete.bytes))) + + fmt.Println() + + return nil +} + type stateMeta struct { i int col color.Attribute From 0c036b1157cf8142d0fc440a38935bddafc2d585 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 28 Jul 2021 17:47:01 +0300 Subject: [PATCH 29/51] make linter happy --- cmd/lotus-miner/info.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-miner/info.go b/cmd/lotus-miner/info.go index 2a3627959..92f25667c 100644 --- a/cmd/lotus-miner/info.go +++ b/cmd/lotus-miner/info.go @@ -104,7 +104,7 @@ func infoCmdAct(cctx *cli.Context) error { fmt.Println() if subsystems.Has(api.SectorStorageSubsystem) { - err := handleMiningInfo(cctx, ctx, fullapi, nodeApi) + err := handleMiningInfo(ctx, cctx, fullapi, nodeApi) if err != nil { return err } @@ -120,7 +120,7 @@ func infoCmdAct(cctx *cli.Context) error { return nil } -func handleMiningInfo(cctx *cli.Context, ctx context.Context, fullapi v0api.FullNode, nodeApi api.StorageMiner) error { +func handleMiningInfo(ctx context.Context, cctx *cli.Context, fullapi v0api.FullNode, nodeApi api.StorageMiner) error { maddr, err := getActorAddress(ctx, cctx) if err != nil { return err From c119ab6ed970483521ed8793451ed2933cfba6b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Wed, 28 Jul 2021 19:51:45 +0100 Subject: [PATCH 30/51] fix docs and nits. --- api/api_storage.go | 2 + api/api_subsystems.go | 63 ------------------- api/docgen/docgen.go | 10 ++- api/miner_subsystems.go | 79 ++++++++++++++++++++++++ cmd/lotus-miner/info.go | 4 +- documentation/en/api-v0-methods-miner.md | 12 +++- node/builder_miner.go | 2 +- node/impl/storminer.go | 10 +-- node/modules/storageminer.go | 11 ++-- 9 files changed, 113 insertions(+), 80 deletions(-) delete mode 100644 api/api_subsystems.go create mode 100644 api/miner_subsystems.go diff --git a/api/api_storage.go b/api/api_storage.go index d52032650..c39114929 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -166,6 +166,8 @@ type StorageMiner interface { MarketPendingDeals(ctx context.Context) (PendingDealInfo, error) //perm:write MarketPublishPendingDeals(ctx context.Context) error //perm:admin + // RuntimeSubsystems returns the subsystems that are enabled + // in this instance. RuntimeSubsystems(ctx context.Context) (MinerSubsystems, error) //perm:read DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error //perm:admin diff --git a/api/api_subsystems.go b/api/api_subsystems.go deleted file mode 100644 index 1894bbdd8..000000000 --- a/api/api_subsystems.go +++ /dev/null @@ -1,63 +0,0 @@ -package api - -import ( - "bytes" - "encoding/json" -) - -type MinerSubsystems []MinerSubsystem - -func (ms MinerSubsystems) Has(entry MinerSubsystem) bool { - for _, v := range ms { - if v == entry { - return true - } - - } - return false -} - -type MinerSubsystem int - -const ( - MarketsSubsystem MinerSubsystem = iota - MiningSubsystem - SealingSubsystem - SectorStorageSubsystem -) - -func (ms MinerSubsystem) String() string { - return MinerSubsystemToString[ms] -} - -var MinerSubsystemToString = map[MinerSubsystem]string{ - MarketsSubsystem: "Markets", - MiningSubsystem: "Mining", - SealingSubsystem: "Sealing", - SectorStorageSubsystem: "SectorStorage", -} - -var MinerSubsystemToID = map[string]MinerSubsystem{ - "Markets": MarketsSubsystem, - "Mining": MiningSubsystem, - "Sealing": SealingSubsystem, - "SectorStorage": SectorStorageSubsystem, -} - -func (ms MinerSubsystem) MarshalJSON() ([]byte, error) { - buffer := bytes.NewBufferString(`"`) - buffer.WriteString(MinerSubsystemToString[ms]) - buffer.WriteString(`"`) - return buffer.Bytes(), nil -} - -func (ms *MinerSubsystem) UnmarshalJSON(b []byte) error { - var j string - err := json.Unmarshal(b, &j) - if err != nil { - return err - } - // TODO: handle zero value - *ms = MinerSubsystemToID[j] - return nil -} diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 1e712a0ae..f9addc940 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -16,10 +16,10 @@ import ( "github.com/google/uuid" "github.com/ipfs/go-cid" "github.com/ipfs/go-filestore" - metrics "github.com/libp2p/go-libp2p-core/metrics" + "github.com/libp2p/go-libp2p-core/metrics" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" - protocol "github.com/libp2p/go-libp2p-core/protocol" + "github.com/libp2p/go-libp2p-core/protocol" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/multiformats/go-multiaddr" @@ -265,6 +265,12 @@ func init() { addExample(api.CheckStatusCode(0)) addExample(map[string]interface{}{"abc": 123}) + addExample(api.MinerSubsystems{ + api.SubsystemMining, + api.SubsystemSealing, + api.SubsystemSectorStorage, + api.SubsystemMarkets, + }) } func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) { diff --git a/api/miner_subsystems.go b/api/miner_subsystems.go new file mode 100644 index 000000000..a77de7e3c --- /dev/null +++ b/api/miner_subsystems.go @@ -0,0 +1,79 @@ +package api + +import ( + "encoding/json" +) + +// MinerSubsystem represents a miner subsystem. Int and string values are not +// guaranteed to be stable over time is not +// guaranteed to be stable over time. +type MinerSubsystem int + +const ( + // SubsystemUnknown is a placeholder for the zero value. It should never + // be used. + SubsystemUnknown MinerSubsystem = iota + // SubsystemMarkets signifies the storage and retrieval + // deal-making subsystem. + SubsystemMarkets + // SubsystemMining signifies the mining subsystem. + SubsystemMining + // SubsystemSealing signifies the sealing subsystem. + SubsystemSealing + // SubsystemSectorStorage signifies the sector storage subsystem. + SubsystemSectorStorage +) + +var MinerSubsystemToString = map[MinerSubsystem]string{ + SubsystemUnknown: "Unknown", + SubsystemMarkets: "Markets", + SubsystemMining: "Mining", + SubsystemSealing: "Sealing", + SubsystemSectorStorage: "SectorStorage", +} + +var MinerSubsystemToID = map[string]MinerSubsystem{ + "Unknown": SubsystemUnknown, + "Markets": SubsystemMarkets, + "Mining": SubsystemMining, + "Sealing": SubsystemSealing, + "SectorStorage": SubsystemSectorStorage, +} + +func (ms MinerSubsystem) MarshalJSON() ([]byte, error) { + return json.Marshal(MinerSubsystemToString[ms]) +} + +func (ms *MinerSubsystem) UnmarshalJSON(b []byte) error { + var j string + err := json.Unmarshal(b, &j) + if err != nil { + return err + } + s, ok := MinerSubsystemToID[j] + if !ok { + *ms = SubsystemUnknown + } else { + *ms = s + } + return nil +} + +type MinerSubsystems []MinerSubsystem + +func (ms MinerSubsystems) Has(entry MinerSubsystem) bool { + for _, v := range ms { + if v == entry { + return true + } + } + return false +} + +func (ms MinerSubsystem) String() string { + s, ok := MinerSubsystemToString[ms] + if !ok { + return MinerSubsystemToString[SubsystemUnknown] + } + return s +} diff --git a/cmd/lotus-miner/info.go b/cmd/lotus-miner/info.go index 92f25667c..878361dac 100644 --- a/cmd/lotus-miner/info.go +++ b/cmd/lotus-miner/info.go @@ -103,14 +103,14 @@ func infoCmdAct(cctx *cli.Context) error { fmt.Println() - if subsystems.Has(api.SectorStorageSubsystem) { + if subsystems.Has(api.SubsystemSectorStorage) { err := handleMiningInfo(ctx, cctx, fullapi, nodeApi) if err != nil { return err } } - if subsystems.Has(api.MarketsSubsystem) { + if subsystems.Has(api.SubsystemMarkets) { err := handleMarketsInfo(ctx, nodeApi) if err != nil { return err diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index dcd3abd4d..3b6d5ac51 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -1528,13 +1528,23 @@ Response: `{}` ### RuntimeSubsystems +RuntimeSubsystems returns the subsystems that are enabled +in this instance. Perms: read Inputs: `null` -Response: `null` +Response: +```json +[ + "Mining", + "Sealing", + "SectorStorage", + "Markets" +] +``` ## Sealing diff --git a/node/builder_miner.go b/node/builder_miner.go index 830e6d075..acb9d3d43 100644 --- a/node/builder_miner.go +++ b/node/builder_miner.go @@ -72,7 +72,7 @@ func ConfigStorageMiner(c interface{}) Option { return Options( ConfigCommon(&cfg.Common, enableLibp2pNode), - Override(new(api.MinerSubsystems), modules.AddMinerSubsystems(cfg.Subsystems)), + Override(new(api.MinerSubsystems), modules.PopulateEnabledMinerSubsystems(cfg.Subsystems)), Override(new(stores.LocalStorage), From(new(repo.LockedRepo))), Override(new(*stores.Local), modules.LocalStorage), Override(new(*stores.Remote), modules.RemoteStorage), diff --git a/node/impl/storminer.go b/node/impl/storminer.go index 86c84fee7..0fbd12111 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -23,8 +23,8 @@ import ( "github.com/filecoin-project/go-address" datatransfer "github.com/filecoin-project/go-data-transfer" "github.com/filecoin-project/go-fil-markets/piecestore" - retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket" - storagemarket "github.com/filecoin-project/go-fil-markets/storagemarket" + "github.com/filecoin-project/go-fil-markets/retrievalmarket" + "github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-state-types/abi" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" @@ -48,11 +48,11 @@ import ( type StorageMinerAPI struct { fx.In - Subsystems api.MinerSubsystems - api.Common api.Net + EnabledSubsystems api.MinerSubsystems + Full api.FullNode LocalStore *stores.Local RemoteStore *stores.Remote @@ -706,7 +706,7 @@ func (sm *StorageMinerAPI) ComputeProof(ctx context.Context, ssi []builtin.Secto } func (sm *StorageMinerAPI) RuntimeSubsystems(context.Context) (res api.MinerSubsystems, err error) { - return sm.Subsystems, nil + return sm.EnabledSubsystems, nil } var _ api.StorageMiner = &StorageMinerAPI{} diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 06ef78ca0..26792ca19 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -1008,19 +1008,18 @@ func mutateCfg(r repo.LockedRepo, mutator func(*config.StorageMiner)) error { return multierr.Combine(typeErr, setConfigErr) } -func AddMinerSubsystems(cfg config.MinerSubsystemConfig) (res api.MinerSubsystems) { +func PopulateEnabledMinerSubsystems(cfg config.MinerSubsystemConfig) (res api.MinerSubsystems) { if cfg.EnableMining { - res = append(res, api.MiningSubsystem) + res = append(res, api.SubsystemMining) } if cfg.EnableSealing { - res = append(res, api.SealingSubsystem) + res = append(res, api.SubsystemSealing) } if cfg.EnableSectorStorage { - res = append(res, api.SectorStorageSubsystem) + res = append(res, api.SubsystemSectorStorage) } if cfg.EnableMarkets { - res = append(res, api.MarketsSubsystem) + res = append(res, api.SubsystemMarkets) } - return } From d8c90b91be22983e23fced4a8facac74c0872c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Wed, 28 Jul 2021 23:46:21 +0100 Subject: [PATCH 31/51] address nits. --- node/builder_miner.go | 2 +- node/modules/storageminer.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/node/builder_miner.go b/node/builder_miner.go index acb9d3d43..3be055de7 100644 --- a/node/builder_miner.go +++ b/node/builder_miner.go @@ -72,7 +72,7 @@ func ConfigStorageMiner(c interface{}) Option { return Options( ConfigCommon(&cfg.Common, enableLibp2pNode), - Override(new(api.MinerSubsystems), modules.PopulateEnabledMinerSubsystems(cfg.Subsystems)), + Override(new(api.MinerSubsystems), modules.ExtractEnabledMinerSubsystems(cfg.Subsystems)), Override(new(stores.LocalStorage), From(new(repo.LockedRepo))), Override(new(*stores.Local), modules.LocalStorage), Override(new(*stores.Remote), modules.RemoteStorage), diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 26792ca19..5497eab58 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -1008,7 +1008,7 @@ func mutateCfg(r repo.LockedRepo, mutator func(*config.StorageMiner)) error { return multierr.Combine(typeErr, setConfigErr) } -func PopulateEnabledMinerSubsystems(cfg config.MinerSubsystemConfig) (res api.MinerSubsystems) { +func ExtractEnabledMinerSubsystems(cfg config.MinerSubsystemConfig) (res api.MinerSubsystems) { if cfg.EnableMining { res = append(res, api.SubsystemMining) } @@ -1021,5 +1021,5 @@ func PopulateEnabledMinerSubsystems(cfg config.MinerSubsystemConfig) (res api.Mi if cfg.EnableMarkets { res = append(res, api.SubsystemMarkets) } - return + return res } From d039764a343102dcd856eb26c2842eb212e0120f Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 28 Jul 2021 11:49:42 +0300 Subject: [PATCH 32/51] code cosmetics: rename variables for better readability and some comments --- blockstore/badger/blockstore.go | 69 +++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/blockstore/badger/blockstore.go b/blockstore/badger/blockstore.go index 8e1a3a1ff..49951db6e 100644 --- a/blockstore/badger/blockstore.go +++ b/blockstore/badger/blockstore.go @@ -258,16 +258,16 @@ func (b *Blockstore) movingGC() error { b.moveCond.Broadcast() b.moveMx.Unlock() - var path string + var newPath string defer func() { b.lockMove() - db2 := b.dbNext + dbNext := b.dbNext b.dbNext = nil var state bsMoveState - if db2 != nil { + if dbNext != nil { state = moveStateCleanup } else { state = moveStateNone @@ -275,12 +275,13 @@ func (b *Blockstore) movingGC() error { b.unlockMove(state) - if db2 != nil { - err := db2.Close() + if dbNext != nil { + // the move failed and we have a left-over db; delete it. + err := dbNext.Close() if err != nil { log.Warnf("error closing badger db: %s", err) } - b.deleteDB(path) + b.deleteDB(newPath) b.lockMove() b.unlockMove(moveStateNone) @@ -296,63 +297,71 @@ func (b *Blockstore) movingGC() error { } if basePath == linkPath { - path = basePath + newPath = basePath } else { + // we do this dance to create a name adjacent to the current one, while avoiding clown + // shoes with multiple moves (i.e. we can't just take the basename of the linkPath, as it + // could have been created in a previous move and have the timestamp suffix, which would then + // perpetuate itself. name := filepath.Base(basePath) dir := filepath.Dir(linkPath) - path = filepath.Join(dir, name) + newPath = filepath.Join(dir, name) } - path = fmt.Sprintf("%s.%d", path, time.Now().UnixNano()) + newPath = fmt.Sprintf("%s.%d", newPath, time.Now().UnixNano()) - log.Infof("moving blockstore from %s to %s", b.opts.Dir, path) + log.Infof("moving blockstore from %s to %s", b.opts.Dir, newPath) opts := b.opts - opts.Dir = path - opts.ValueDir = path + opts.Dir = newPath + opts.ValueDir = newPath - db2, err := badger.Open(opts.Options) + dbNew, err := badger.Open(opts.Options) if err != nil { - return fmt.Errorf("failed to open badger blockstore in %s: %w", path, err) + return fmt.Errorf("failed to open badger blockstore in %s: %w", newPath, err) } b.lockMove() - b.dbNext = db2 + b.dbNext = dbNew b.unlockMove(moveStateMoving) log.Info("copying blockstore") err = b.doCopy(b.db, b.dbNext) if err != nil { - return fmt.Errorf("error moving badger blockstore to %s: %w", path, err) + return fmt.Errorf("error moving badger blockstore to %s: %w", newPath, err) } b.lockMove() - db1 := b.db + dbOld := b.db b.db = b.dbNext b.dbNext = nil b.unlockMove(moveStateCleanup) - err = db1.Close() + err = dbOld.Close() if err != nil { log.Warnf("error closing old badger db: %s", err) } - dbpath := b.opts.Dir - oldpath := fmt.Sprintf("%s.old.%d", dbpath, time.Now().Unix()) + // this is the canonical db path; this is where our db lives. + dbPath := b.opts.Dir - if err = os.Rename(dbpath, oldpath); err != nil { + // we first move the existing db out of the way, and only delete it after we have symlinked the + // new db to the canonical path + backupPath := fmt.Sprintf("%s.old.%d", dbPath, time.Now().Unix()) + if err = os.Rename(dbPath, backupPath); err != nil { // this is not catastrophic in the sense that we have not lost any data. // but it is pretty bad, as the db path points to the old db, while we are now using to the new // db; we can't continue and leave a ticking bomb for the next restart. // so a panic is appropriate and user can fix. - panic(fmt.Errorf("error renaming old badger db dir from %s to %s: %w; USER ACTION REQUIRED", dbpath, oldpath, err)) //nolint + panic(fmt.Errorf("error renaming old badger db dir from %s to %s: %w; USER ACTION REQUIRED", dbPath, backupPath, err)) //nolint } - if err = os.Symlink(path, dbpath); err != nil { + if err = os.Symlink(newPath, dbPath); err != nil { // same here; the db path is pointing to the void. panic and let the user fix. - panic(fmt.Errorf("error symlinking new badger db dir from %s to %s: %w; USER ACTION REQUIRED", path, dbpath, err)) //nolint + panic(fmt.Errorf("error symlinking new badger db dir from %s to %s: %w; USER ACTION REQUIRED", newPath, dbPath, err)) //nolint } - b.deleteDB(oldpath) + // the delete follows symlinks + b.deleteDB(backupPath) log.Info("moving blockstore done") return nil @@ -390,19 +399,19 @@ func (b *Blockstore) doCopy(from, to *badger.DB) error { func (b *Blockstore) deleteDB(path string) { // follow symbolic links, otherwise the data wil be left behind - lpath, err := filepath.EvalSymlinks(path) + linkPath, err := filepath.EvalSymlinks(path) if err != nil { log.Warnf("error resolving symlinks in %s", path) return } - log.Infof("removing data directory %s", lpath) - if err := os.RemoveAll(lpath); err != nil { - log.Warnf("error deleting db at %s: %s", lpath, err) + log.Infof("removing data directory %s", linkPath) + if err := os.RemoveAll(linkPath); err != nil { + log.Warnf("error deleting db at %s: %s", linkPath, err) return } - if path != lpath { + if path != linkPath { log.Infof("removing link %s", path) if err := os.Remove(path); err != nil { log.Warnf("error removing symbolic link %s", err) From 7a3193a75bf132818e2b617cd8740d6f1b352438 Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 28 Jul 2021 11:56:23 +0300 Subject: [PATCH 33/51] make relative links when the canonical and new db paths are in the same directory --- blockstore/badger/blockstore.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/blockstore/badger/blockstore.go b/blockstore/badger/blockstore.go index 49951db6e..3d1862283 100644 --- a/blockstore/badger/blockstore.go +++ b/blockstore/badger/blockstore.go @@ -355,7 +355,7 @@ func (b *Blockstore) movingGC() error { panic(fmt.Errorf("error renaming old badger db dir from %s to %s: %w; USER ACTION REQUIRED", dbPath, backupPath, err)) //nolint } - if err = os.Symlink(newPath, dbPath); err != nil { + if err = b.symlink(newPath, dbPath); err != nil { // same here; the db path is pointing to the void. panic and let the user fix. panic(fmt.Errorf("error symlinking new badger db dir from %s to %s: %w; USER ACTION REQUIRED", newPath, dbPath, err)) //nolint } @@ -367,6 +367,18 @@ func (b *Blockstore) movingGC() error { return nil } +// symlink creates a symlink from path to linkPath; the link is relative if the two are +// in the same directory +func (b *Blockstore) symlink(path, linkTo string) error { + pathDir := filepath.Dir(path) + linkDir := filepath.Dir(linkTo) + if pathDir == linkDir { + path = filepath.Base(path) + } + + return os.Symlink(path, linkTo) +} + // doCopy copies a badger blockstore to another, with an optional filter; if the filter // is not nil, then only cids that satisfy the filter will be copied. func (b *Blockstore) doCopy(from, to *badger.DB) error { From a24b2436b0d9ded5d3ca91929d3944fe98073fcc Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 28 Jul 2021 11:56:35 +0300 Subject: [PATCH 34/51] extend test to check the validity of relative links --- blockstore/badger/blockstore_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/blockstore/badger/blockstore_test.go b/blockstore/badger/blockstore_test.go index ddfa6f28d..d8ef5241b 100644 --- a/blockstore/badger/blockstore_test.go +++ b/blockstore/badger/blockstore_test.go @@ -245,6 +245,21 @@ func testMove(t *testing.T, optsF func(string) Options) { checkBlocks() checkPath() + + // reopen the db to make sure our relative link works: + err = db.Close() + if err != nil { + t.Fatal(err) + } + + db, err = Open(optsF(dbPath)) + if err != nil { + t.Fatal(err) + } + + // db.Close() is already deferred + + checkBlocks() } func TestMoveNoPrefix(t *testing.T) { From 0caabf1328d3db16aeda222dc080b701d17c92f1 Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 28 Jul 2021 16:15:39 +0300 Subject: [PATCH 35/51] improve detection of relative links --- blockstore/badger/blockstore.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/blockstore/badger/blockstore.go b/blockstore/badger/blockstore.go index 3d1862283..094b8eb6c 100644 --- a/blockstore/badger/blockstore.go +++ b/blockstore/badger/blockstore.go @@ -370,9 +370,17 @@ func (b *Blockstore) movingGC() error { // symlink creates a symlink from path to linkPath; the link is relative if the two are // in the same directory func (b *Blockstore) symlink(path, linkTo string) error { - pathDir := filepath.Dir(path) - linkDir := filepath.Dir(linkTo) - if pathDir == linkDir { + resolvedPathDir, err := filepath.EvalSymlinks(filepath.Dir(path)) + if err != nil { + return fmt.Errorf("error resolving links in %s: %w", path, err) + } + + resolvedLinkDir, err := filepath.EvalSymlinks(filepath.Dir(linkTo)) + if err != nil { + return fmt.Errorf("error resolving links in %s: %W", linkTo, err) + } + + if resolvedPathDir == resolvedLinkDir { path = filepath.Base(path) } From ec78d3d7b1b7c00e381e74ac41d20fab1bbc3a6f Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 28 Jul 2021 16:20:25 +0300 Subject: [PATCH 36/51] fix format specifier --- blockstore/badger/blockstore.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockstore/badger/blockstore.go b/blockstore/badger/blockstore.go index 094b8eb6c..dad37a6b1 100644 --- a/blockstore/badger/blockstore.go +++ b/blockstore/badger/blockstore.go @@ -377,7 +377,7 @@ func (b *Blockstore) symlink(path, linkTo string) error { resolvedLinkDir, err := filepath.EvalSymlinks(filepath.Dir(linkTo)) if err != nil { - return fmt.Errorf("error resolving links in %s: %W", linkTo, err) + return fmt.Errorf("error resolving links in %s: %w", linkTo, err) } if resolvedPathDir == resolvedLinkDir { From 4417be81ad647a85cafcf592390e1c59635196d0 Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 28 Jul 2021 17:11:04 +0300 Subject: [PATCH 37/51] fix typo Co-authored-by: Jakub Sztandera --- blockstore/badger/blockstore.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockstore/badger/blockstore.go b/blockstore/badger/blockstore.go index dad37a6b1..05e9048c9 100644 --- a/blockstore/badger/blockstore.go +++ b/blockstore/badger/blockstore.go @@ -367,7 +367,7 @@ func (b *Blockstore) movingGC() error { return nil } -// symlink creates a symlink from path to linkPath; the link is relative if the two are +// symlink creates a symlink from path to linkTo; the link is relative if the two are // in the same directory func (b *Blockstore) symlink(path, linkTo string) error { resolvedPathDir, err := filepath.EvalSymlinks(filepath.Dir(path)) From fd33b96e08d241140e402945bafa0405ae74a772 Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 29 Jul 2021 08:35:53 +0300 Subject: [PATCH 38/51] make symlink helper freestanding --- blockstore/badger/blockstore.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blockstore/badger/blockstore.go b/blockstore/badger/blockstore.go index 05e9048c9..a0b51d8df 100644 --- a/blockstore/badger/blockstore.go +++ b/blockstore/badger/blockstore.go @@ -355,7 +355,7 @@ func (b *Blockstore) movingGC() error { panic(fmt.Errorf("error renaming old badger db dir from %s to %s: %w; USER ACTION REQUIRED", dbPath, backupPath, err)) //nolint } - if err = b.symlink(newPath, dbPath); err != nil { + if err = symlink(newPath, dbPath); err != nil { // same here; the db path is pointing to the void. panic and let the user fix. panic(fmt.Errorf("error symlinking new badger db dir from %s to %s: %w; USER ACTION REQUIRED", newPath, dbPath, err)) //nolint } @@ -369,7 +369,7 @@ func (b *Blockstore) movingGC() error { // symlink creates a symlink from path to linkTo; the link is relative if the two are // in the same directory -func (b *Blockstore) symlink(path, linkTo string) error { +func symlink(path, linkTo string) error { resolvedPathDir, err := filepath.EvalSymlinks(filepath.Dir(path)) if err != nil { return fmt.Errorf("error resolving links in %s: %w", path, err) From 786d3e79eb9264b528e2f2588c6787aa30b834f4 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Thu, 29 Jul 2021 04:51:28 -0400 Subject: [PATCH 39/51] make gen --- build/openrpc/full.json.gz | Bin 25240 -> 25241 bytes build/openrpc/miner.json.gz | Bin 9479 -> 9596 bytes build/openrpc/worker.json.gz | Bin 2710 -> 2710 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index ddcf0611767ea9b47c66180b6063a2252ebf40ab..6100677034b49cd1397ebfb057a848753b073d4e 100644 GIT binary patch delta 20851 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 KEvu8%>jVI~YL15h delta 20863 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 a*%kMGwJTJzpZ_la0RR6#+m49T>jVIiN@(f; diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 5a65b3a33921ffe18ee4fe002bdec37d7b59b576..963ce6f50c0fa7b5bf03d02e4b213c273755e78f 100644 GIT binary patch delta 9102 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 Z$*9v7o=)$k{|f*B|NkYIA0}CP000Z*f5!j- delta 1731 zcmV;!20Zze6_ypS`vL>BkF}Hj0zZGwNwF&Z3d$ZEDpE*ehGr8-8sz#bM(%d(s**z_R2b2+)eusE23~@q+*ff9rH7ma+ zY-AkvGd*uD{x8Zm0|GSw*a;)u1pu(1$Ll4m42Jgi;ZTCAHnw4QY0ZIIGyPS^&N_DP zTkPze701p?Hspp8Q?m|Nl$GL@=0hJSIX z=3Qyvj~>uZG?=^xn6acG@bAX;(yzrC~G+X^O#jw1@}Uh(m#{x-2k-O)UvYMeP}d zr5UeVf!{^kmE<*YmA0GQI4A4|Vziipxca7MsrYW>6>^yL6Ss*Q@?LcJPoSf5rDVzm zQzW};YiI2eTNB&{DQ}ZG1!gygnSJOKo7pwEKqP!+5{UWUp9Sh4`7CCk>us&n@)Fjo zwVlGAyRcfTpT^Wn!g@)#&r8D7R=1Pa1yz4)_lk{6ugcH4=TVi{p5+#nqBH}gkx~-( zI$S?7kaB)BF0>h9EBXkz8ol^nU3k1EdWh;DFLZHE9cc)1Q(|lj;ATf^anG?9qXxP= z5m9#m=;p0s50A=~+WDK7HNVk$!DDTG)e`n}9%oGBK?xl)Q|QtGrs$BSH91L`{vUtV zFsYF{Ug5N~U$5x3=4qDx3vOzMNrsco;5)H_bf2U%KACh$_e2f4@&P>mFaG?uA56IC z|26Q2Fd24xL)r}{CqV$c&SNiH18lNALsyw}ZZ@CkVKAZGB*>~4r1gUIEo0_R$sx`J z&*j5+Rm|Km-*=-+V;K2+pw@=Do$Y_a+)kat-8I|X1!$XB;Nr=&xqXXs-I5dL z+M!R7lF_PYzQaPQMRb?T!=5jBc&D~zPX;od#zGC=Cu_#REBRAtar=5o89uKCnblP zZ$Pd0lFWp#3?>dZcbDw;OB#6Xj=u~mOLqMw9ePAONTkLvvkD>+ME9CA>u8`aTp=|k z`iDv+K`F{cx6C6Gq{ssxf`)(age2IUIT9(3w0kEbqCj6LA|H@ecPDT+xX19vyq&Y& z#P_LpdRB61GTuJ=(Q(34ai)for7mA&3Cc#x>?hmKtBokfR=Fi@Y(*62gsQzDG5!9L zO}>!u-D&lQlH-Yg5czNs`94F9PEnR>GZ0rhL>YDyy~3hYvs3N8R;z!rtZiSTb7EG1 z{b%#B)wIK29W}QJ^`0|UYxld*?smz!o!Ok2 zzRqDzSG)xFi2p4=@pm$$ewi*?7|&Z?vNT@NywQR=ElIH<%xa*c+o09z0*YQ-@al!| z3Mq0kvbuhigxk!nw3dI)OsoGAZh7^I(t~o9$u~8ATA85Q@6^#*r{q{pw0(D-Z&sx! z*L}6u>_ayHoG7?t4m_{;bXDPYjbmg}r*Tdl!zV5&{ z-*@V@x@VjC#M9n>scO&m&*Trl#NKoD%oJ{N$+mS)9VB%35}1F|qDXLuM^T*tWuquc zFolTY2#^vSMCYwF(52D?Fyz7m2Ms2Op#MbQV6+fH=iC7s9XySxJw}u{REwzl@B&v+ zTi-qMiTwc1ycZR&MhJ5dL7#Q4F_Gg&R&h3S*rxtaME#Vqeo7fZ&2GtQme`gJVP;HK zyhNM3hjN$~S6Ooc@!}dr$S&b(EAQ7U8>*yyOHs7j?sh(`9Y=RmA$uj;&i^D-{X3wb z3{`SYSE!Vw$*(!tYja=e{)^Qw>1yC|`$3|BDe59M1_6i&KrDJnCy@vk3!m-1Qe)p; ZGV1sgPp5a&{{;X5|Np)^+1Ocn000qYVg>*J From 0daee83735ab53db2087b0f78230a9ab059e9e9d Mon Sep 17 00:00:00 2001 From: aarshkshah1992 Date: Thu, 29 Jul 2021 15:28:08 +0530 Subject: [PATCH 40/51] more logging in data transfer and markets --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 89db6a3ae..4b2665743 100644 --- a/go.mod +++ b/go.mod @@ -33,10 +33,10 @@ require ( github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 github.com/filecoin-project/go-commp-utils v0.1.1-0.20210427191551-70bf140d31c7 github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 - github.com/filecoin-project/go-data-transfer v1.7.1 + github.com/filecoin-project/go-data-transfer v1.7.2 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.6.1 + github.com/filecoin-project/go-fil-markets v1.6.2 github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1 diff --git a/go.sum b/go.sum index e39d883d9..8c8a4396b 100644 --- a/go.sum +++ b/go.sum @@ -275,8 +275,8 @@ github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMX github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-data-transfer v1.0.1/go.mod h1:UxvfUAY9v3ub0a21BSK9u3pB2aq30Y0KMsG+w9/ysyo= github.com/filecoin-project/go-data-transfer v1.7.0/go.mod h1:GLRr5BmLEqsLwXfiRDG7uJvph22KGL2M4iOuF8EINaU= -github.com/filecoin-project/go-data-transfer v1.7.1 h1:Co4bTenvCc3WnOhQWyXRt59FLZvxwH8UeF0ZCOc1ik0= -github.com/filecoin-project/go-data-transfer v1.7.1/go.mod h1:GLRr5BmLEqsLwXfiRDG7uJvph22KGL2M4iOuF8EINaU= +github.com/filecoin-project/go-data-transfer v1.7.2 h1:iL3q5pxSloA7V2QucFofoVN3lquULz+Ml0KrNqMT5ZU= +github.com/filecoin-project/go-data-transfer v1.7.2/go.mod h1:GLRr5BmLEqsLwXfiRDG7uJvph22KGL2M4iOuF8EINaU= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= @@ -286,8 +286,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+ github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= github.com/filecoin-project/go-fil-markets v1.0.5-0.20201113164554-c5eba40d5335/go.mod h1:AJySOJC00JRWEZzRG2KsfUnqEf5ITXxeX09BE9N4f9c= -github.com/filecoin-project/go-fil-markets v1.6.1 h1:8xdFyWrELfOzwcGa229bLu/olD+1l4sEWFIsZR7oz5U= -github.com/filecoin-project/go-fil-markets v1.6.1/go.mod h1:ZuFDagROUV6GfvBU//KReTQDw+EZci4rH7jMYTD10vs= +github.com/filecoin-project/go-fil-markets v1.6.2 h1:ib1sGUOF+hf50YwP7+p9yoK+9g84YcXzvuenxd6MYoE= +github.com/filecoin-project/go-fil-markets v1.6.2/go.mod h1:ZuFDagROUV6GfvBU//KReTQDw+EZci4rH7jMYTD10vs= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= From 029ba39fd961dc216e913d27d1fb6da35594ef1a Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Thu, 29 Jul 2021 20:04:50 +0530 Subject: [PATCH 41/51] update deps for logging --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4b2665743..522a0d568 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,7 @@ require ( github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1 github.com/filecoin-project/go-paramfetch v0.0.2-0.20210614165157-25a6c7769498 github.com/filecoin-project/go-state-types v0.1.1-0.20210722133031-ad9bfe54c124 - github.com/filecoin-project/go-statemachine v1.0.0 + github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.1.1 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b github.com/filecoin-project/specs-actors v0.9.14 diff --git a/go.sum b/go.sum index 8c8a4396b..90c52baab 100644 --- a/go.sum +++ b/go.sum @@ -313,8 +313,8 @@ github.com/filecoin-project/go-state-types v0.1.1-0.20210506134452-99b279731c48/ github.com/filecoin-project/go-state-types v0.1.1-0.20210722133031-ad9bfe54c124 h1:veGrNABg/9I7prngrowkhwbvW5d5JN55MNKmbsr5FqA= github.com/filecoin-project/go-state-types v0.1.1-0.20210722133031-ad9bfe54c124/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= -github.com/filecoin-project/go-statemachine v1.0.0 h1:b8FpFewPSklyAIUqH0oHt4nvKf03bU7asop1bJpjAtQ= -github.com/filecoin-project/go-statemachine v1.0.0/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= +github.com/filecoin-project/go-statemachine v1.0.1 h1:LQ60+JDVjMdLxXmVFM2jjontzOYnfVE7u02CXV3WKSw= +github.com/filecoin-project/go-statemachine v1.0.1/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= github.com/filecoin-project/go-statestore v0.1.1 h1:ufMFq00VqnT2CAuDpcGnwLnCX1I/c3OROw/kXVNSTZk= github.com/filecoin-project/go-statestore v0.1.1/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= From 8442bac5b2fb25f39c9415eeb5a2ade66b36bfbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 29 Jul 2021 10:55:37 +0100 Subject: [PATCH 42/51] support MARKETS_API_INFO env var; support markets-repo, markets-api-url flags. --- cli/auth.go | 3 +- cli/util/api.go | 148 +++++++++++++++++++++++++------------------- node/repo/fsrepo.go | 5 +- 3 files changed, 91 insertions(+), 65 deletions(-) diff --git a/cli/auth.go b/cli/auth.go index 20b9bb394..ccf5dcc8b 100644 --- a/cli/auth.go +++ b/cli/auth.go @@ -128,7 +128,8 @@ var AuthApiInfoToken = &cli.Command{ // TODO: Log in audit log when it is implemented - fmt.Printf("%s=%s:%s\n", cliutil.EnvForRepo(t), string(token), ainfo.Addr) + currentEnv, _ := cliutil.EnvsForRepo(t) + fmt.Printf("%s=%s:%s\n", currentEnv, string(token), ainfo.Addr) return nil }, } diff --git a/cli/util/api.go b/cli/util/api.go index 730b75d9d..fca667b5a 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -27,112 +27,134 @@ const ( metadataTraceContext = "traceContext" ) -// The flag passed on the command line with the listen address of the API -// server (only used by the tests) -func flagForAPI(t repo.RepoType) string { +// The flags passed on the command line with the listen address of the API +// server (only used by the tests), in the order of precedence they should be +// applied for the requested kind of node. +func flagsForAPI(t repo.RepoType) []string { switch t { case repo.FullNode: - return "api-url" + return []string{"api-url"} case repo.StorageMiner: - return "miner-api-url" + return []string{"miner-api-url"} case repo.Worker: - return "worker-api-url" + return []string{"worker-api-url"} + case repo.Markets: + // support split markets-miner and monolith deployments. + return []string{"markets-api-url", "miner-api-url"} default: panic(fmt.Sprintf("Unknown repo type: %v", t)) } } -func flagForRepo(t repo.RepoType) string { +func flagsForRepo(t repo.RepoType) []string { switch t { case repo.FullNode: - return "repo" + return []string{"repo"} case repo.StorageMiner: - return "miner-repo" + return []string{"miner-repo"} case repo.Worker: - return "worker-repo" + return []string{"worker-repo"} + case repo.Markets: + // support split markets-miner and monolith deployments. + return []string{"markets-repo", "miner-repo"} default: panic(fmt.Sprintf("Unknown repo type: %v", t)) } } -func EnvForRepo(t repo.RepoType) string { +// EnvsForRepo returns the environment variables to use in order of precedence +// to determine the API endpoint of the specified node type. +// +// It returns the current variables and deprecated ones separately, so that +// the user can log a warning when deprecated ones are found to be in use. +func EnvsForRepo(t repo.RepoType) (current []string, deprecated []string) { switch t { case repo.FullNode: - return "FULLNODE_API_INFO" + return []string{"FULLNODE_API_INFO"}, nil case repo.StorageMiner: - return "MINER_API_INFO" + // TODO remove deprecated deprecation period + return []string{"MINER_API_INFO"}, []string{"STORAGE_API_INFO"} case repo.Worker: - return "WORKER_API_INFO" - default: - panic(fmt.Sprintf("Unknown repo type: %v", t)) - } -} - -// TODO remove after deprecation period -func envForRepoDeprecation(t repo.RepoType) string { - switch t { - case repo.FullNode: - return "FULLNODE_API_INFO" - case repo.StorageMiner: - return "STORAGE_API_INFO" - case repo.Worker: - return "WORKER_API_INFO" + return []string{"WORKER_API_INFO"}, nil + case repo.Markets: + // support split markets-miner and monolith deployments. + return []string{"MARKETS_API_INFO, MINER_API_INFO"}, nil default: panic(fmt.Sprintf("Unknown repo type: %v", t)) } } +// GetAPIInfo returns the API endpoint to use for the specified kind of repo. +// +// The order of precedence is as follows: +// +// 1. *-api-url command line flags. +// 2. *_API_INFO environment variables +// 3. deprecated *_API_INFO environment variables +// 4. *-repo command line flags. func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { // Check if there was a flag passed with the listen address of the API // server (only used by the tests) - apiFlag := flagForAPI(t) - if ctx.IsSet(apiFlag) { - strma := ctx.String(apiFlag) + apiFlags := flagsForAPI(t) + for _, f := range apiFlags { + if !ctx.IsSet(f) { + continue + } + strma := ctx.String(f) strma = strings.TrimSpace(strma) return APIInfo{Addr: strma}, nil } - envKey := EnvForRepo(t) - env, ok := os.LookupEnv(envKey) - if !ok { - // TODO remove after deprecation period - envKey = envForRepoDeprecation(t) - env, ok = os.LookupEnv(envKey) + currentEnv, deprecatedEnv := EnvsForRepo(t) + for _, env := range currentEnv { + env, ok := os.LookupEnv(env) if ok { - log.Warnf("Use deprecation env(%s) value, please use env(%s) instead.", envKey, EnvForRepo(t)) + return ParseApiInfo(env), nil } } - if ok { - return ParseApiInfo(env), nil + + for _, env := range deprecatedEnv { + env, ok := os.LookupEnv(env) + if ok { + log.Warnf("Use deprecation env(%s) value, please use env(%s) instead.", env, currentEnv) + return ParseApiInfo(env), nil + } } - repoFlag := flagForRepo(t) + repoFlags := flagsForRepo(t) + for _, f := range repoFlags { + if !ctx.IsSet(f) { + continue + } - p, err := homedir.Expand(ctx.String(repoFlag)) - if err != nil { - return APIInfo{}, xerrors.Errorf("could not expand home dir (%s): %w", repoFlag, err) + p, err := homedir.Expand(ctx.String(f)) + if err != nil { + return APIInfo{}, xerrors.Errorf("could not expand home dir (%s): %w", f, err) + } + + r, err := repo.NewFS(p) + if err != nil { + return APIInfo{}, xerrors.Errorf("could not open repo at path: %s; %w", p, err) + } + + ma, err := r.APIEndpoint() + if err != nil { + return APIInfo{}, xerrors.Errorf("could not get api endpoint: %w", err) + } + + token, err := r.APIToken() + if err != nil { + log.Warnf("Couldn't load CLI token, capabilities may be limited: %v", err) + } + + return APIInfo{ + Addr: ma.String(), + Token: token, + }, nil } - r, err := repo.NewFS(p) - if err != nil { - return APIInfo{}, xerrors.Errorf("could not open repo at path: %s; %w", p, err) - } - - ma, err := r.APIEndpoint() - if err != nil { - return APIInfo{}, xerrors.Errorf("could not get api endpoint: %w", err) - } - - token, err := r.APIToken() - if err != nil { - log.Warnf("Couldn't load CLI token, capabilities may be limited: %v", err) - } - - return APIInfo{ - Addr: ma.String(), - Token: token, - }, nil + return APIInfo{}, fmt.Errorf("could not determine API endpoint for node type: %s", t) } func GetRawAPI(ctx *cli.Context, t repo.RepoType, version string) (string, http.Header, error) { diff --git a/node/repo/fsrepo.go b/node/repo/fsrepo.go index 9323410dd..d3e6f4f2f 100644 --- a/node/repo/fsrepo.go +++ b/node/repo/fsrepo.go @@ -49,13 +49,16 @@ const ( StorageMiner Worker Wallet + Markets ) func defConfForType(t RepoType) interface{} { switch t { case FullNode: return config.DefaultFullNode() - case StorageMiner: + case StorageMiner, Markets: + // markets is a specialised miner service + // this taxonomy needs to be cleaned up return config.DefaultStorageMiner() case Worker: return &struct{}{} From 92056423c3b540f6ff7ac0ee4d1e4cd1693b143d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 29 Jul 2021 12:37:29 +0100 Subject: [PATCH 43/51] target markets API for markets commands. --- cli/auth.go | 3 ++- cli/cmd.go | 3 ++- cli/util/api.go | 20 +++++++++++++-- cmd/lotus-miner/dagstore.go | 30 ++++++++++++++++++++++ cmd/lotus-miner/main.go | 24 ++++++++++++------ cmd/lotus-miner/market.go | 40 +++++++++++++++++------------- cmd/lotus-miner/retrieval-deals.go | 18 +++++++------- 7 files changed, 101 insertions(+), 37 deletions(-) create mode 100644 cmd/lotus-miner/dagstore.go diff --git a/cli/auth.go b/cli/auth.go index ccf5dcc8b..88cbdbb66 100644 --- a/cli/auth.go +++ b/cli/auth.go @@ -113,7 +113,7 @@ var AuthApiInfoToken = &cli.Command{ ti, ok := cctx.App.Metadata["repoType"] if !ok { - log.Errorf("unknown repo type, are you sure you want to use GetAPI?") + log.Errorf("unknown repo type, are you sure you want to use GetCommonAPI?") ti = repo.FullNode } t, ok := ti.(repo.RepoType) @@ -128,6 +128,7 @@ var AuthApiInfoToken = &cli.Command{ // TODO: Log in audit log when it is implemented + // WARN: this is unable to tell currentEnv, _ := cliutil.EnvsForRepo(t) fmt.Printf("%s=%s:%s\n", currentEnv, string(token), ainfo.Addr) return nil diff --git a/cli/cmd.go b/cli/cmd.go index 630aae1bc..7e4a7636c 100644 --- a/cli/cmd.go +++ b/cli/cmd.go @@ -44,7 +44,7 @@ func GetFullNodeServices(ctx *cli.Context) (ServicesAPI, error) { var GetAPIInfo = cliutil.GetAPIInfo var GetRawAPI = cliutil.GetRawAPI -var GetAPI = cliutil.GetAPI +var GetAPI = cliutil.GetCommonAPI var DaemonContext = cliutil.DaemonContext var ReqContext = cliutil.ReqContext @@ -54,6 +54,7 @@ var GetFullNodeAPIV1 = cliutil.GetFullNodeAPIV1 var GetGatewayAPI = cliutil.GetGatewayAPI var GetStorageMinerAPI = cliutil.GetStorageMinerAPI +var GetMarketsAPI = cliutil.GetMarketsAPI var GetWorkerAPI = cliutil.GetWorkerAPI var CommonCommands = []*cli.Command{ diff --git a/cli/util/api.go b/cli/util/api.go index fca667b5a..76289ec7c 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -175,10 +175,10 @@ func GetRawAPI(ctx *cli.Context, t repo.RepoType, version string) (string, http. return addr, ainfo.AuthHeader(), nil } -func GetAPI(ctx *cli.Context) (api.CommonNet, jsonrpc.ClientCloser, error) { +func GetCommonAPI(ctx *cli.Context) (api.CommonNet, jsonrpc.ClientCloser, error) { ti, ok := ctx.App.Metadata["repoType"] if !ok { - log.Errorf("unknown repo type, are you sure you want to use GetAPI?") + log.Errorf("unknown repo type, are you sure you want to use GetCommonAPI?") ti = repo.FullNode } t, ok := ti.(repo.RepoType) @@ -296,6 +296,22 @@ func GetWorkerAPI(ctx *cli.Context) (api.Worker, jsonrpc.ClientCloser, error) { return client.NewWorkerRPCV0(ctx.Context, addr, headers) } +func GetMarketsAPI(ctx *cli.Context) (api.StorageMiner, jsonrpc.ClientCloser, error) { + addr, headers, err := GetRawAPI(ctx, repo.Markets, "v0") + if err != nil { + return nil, nil, err + } + + if IsVeryVerbose { + _, _ = fmt.Fprintln(ctx.App.Writer, "using markets API v0 endpoint:", addr) + } + + // the markets node is a specialised miner's node, supporting only the + // markets API, which is a subset of the miner API. All non-markets + // operations will error out with "unsupported". + return client.NewStorageMinerRPCV0(ctx.Context, addr, headers) +} + func GetGatewayAPI(ctx *cli.Context) (api.Gateway, jsonrpc.ClientCloser, error) { addr, headers, err := GetRawAPI(ctx, repo.FullNode, "v1") if err != nil { diff --git a/cmd/lotus-miner/dagstore.go b/cmd/lotus-miner/dagstore.go new file mode 100644 index 000000000..a50d99d99 --- /dev/null +++ b/cmd/lotus-miner/dagstore.go @@ -0,0 +1,30 @@ +package main + +import ( + "github.com/urfave/cli/v2" +) + +var dagstoreCmd = &cli.Command{ + Name: "dagstore", + Usage: "Manage the DAG store", + Subcommands: []*cli.Command{ + dagstoreListShardsCmd, + dagstoreGarbageCollectCmd, + }, +} + +var dagstoreListShardsCmd = &cli.Command{ + Name: "list-shards", + Usage: "List shards known to the DAG store", + Action: func(cctx *cli.Context) error { + return nil + }, +} + +var dagstoreGarbageCollectCmd = &cli.Command{ + Name: "gc", + Usage: "Garbage collect the DAG store", + Action: func(cctx *cli.Context) error { + return nil + }, +} diff --git a/cmd/lotus-miner/main.go b/cmd/lotus-miner/main.go index c697de0c9..fb8ac35b9 100644 --- a/cmd/lotus-miner/main.go +++ b/cmd/lotus-miner/main.go @@ -76,10 +76,10 @@ func main() { } app := &cli.App{ - Name: "lotus-miner", - Usage: "Filecoin decentralized storage network miner", - Version: build.UserVersion(), - EnableBashCompletion: true, + Name: "lotus-miner", + Usage: "Filecoin decentralized storage network miner", + Version: build.UserVersion(), + Commands: append(local, lcli.CommonCommands...), Flags: []cli.Flag{ &cli.StringFlag{ Name: "actor", @@ -106,14 +106,24 @@ func main() { Value: "~/.lotusminer", // TODO: Consider XDG_DATA_HOME Usage: fmt.Sprintf("Specify miner repo path. flag(%s) and env(LOTUS_STORAGE_PATH) are DEPRECATION, will REMOVE SOON", FlagMinerRepoDeprecation), }, + &cli.BoolFlag{ + Name: "call-on-markets", + Usage: "(experimental; may be removed) call this command against a markets node; use only with common commands like net, auth, pprof, etc. whose target may be ambiguous", + }, cliutil.FlagVeryVerbose, }, - - Commands: append(local, lcli.CommonCommands...), + EnableBashCompletion: true, + Before: func(c *cli.Context) error { + // this command is explicitly called on markets, inform + // common commands by overriding the repoType. + if c.Bool("call-on-markets") { + c.App.Metadata["repoType"] = repo.Markets + } + return nil + }, } app.Setup() app.Metadata["repoType"] = repo.StorageMiner - lcli.RunApp(app) } diff --git a/cmd/lotus-miner/market.go b/cmd/lotus-miner/market.go index b216d24fc..a9d1f2f46 100644 --- a/cmd/lotus-miner/market.go +++ b/cmd/lotus-miner/market.go @@ -73,7 +73,7 @@ var storageDealSelectionShowCmd = &cli.Command{ Name: "list", Usage: "List storage deal proposal selection criteria", Action: func(cctx *cli.Context) error { - smapi, closer, err := lcli.GetStorageMinerAPI(cctx) + smapi, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -100,7 +100,7 @@ var storageDealSelectionResetCmd = &cli.Command{ Name: "reset", Usage: "Reset storage deal proposal selection criteria to default values", Action: func(cctx *cli.Context) error { - smapi, closer, err := lcli.GetStorageMinerAPI(cctx) + smapi, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -148,7 +148,7 @@ var storageDealSelectionRejectCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { - smapi, closer, err := lcli.GetStorageMinerAPI(cctx) + smapi, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -215,7 +215,13 @@ var setAskCmd = &cli.Command{ Action: func(cctx *cli.Context) error { ctx := lcli.DaemonContext(cctx) - api, closer, err := lcli.GetStorageMinerAPI(cctx) + minerApi, closer, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer closer() + + marketsApi, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -252,12 +258,12 @@ var setAskCmd = &cli.Command{ return xerrors.Errorf("cannot parse max-piece-size to quantity of bytes: %w", err) } - maddr, err := api.ActorAddress(ctx) + maddr, err := minerApi.ActorAddress(ctx) if err != nil { return err } - ssize, err := api.ActorSectorSize(ctx, maddr) + ssize, err := minerApi.ActorSectorSize(ctx, maddr) if err != nil { return err } @@ -272,7 +278,7 @@ var setAskCmd = &cli.Command{ return xerrors.Errorf("max piece size (w/bit-padding) %s cannot exceed miner sector size %s", types.SizeStr(types.NewInt(uint64(max))), types.SizeStr(types.NewInt(uint64(smax)))) } - return api.MarketSetAsk(ctx, types.BigInt(pri), types.BigInt(vpri), abi.ChainEpoch(qty), abi.PaddedPieceSize(min), abi.PaddedPieceSize(max)) + return marketsApi.MarketSetAsk(ctx, types.BigInt(pri), types.BigInt(vpri), abi.ChainEpoch(qty), abi.PaddedPieceSize(min), abi.PaddedPieceSize(max)) }, } @@ -289,7 +295,7 @@ var getAskCmd = &cli.Command{ } defer closer() - smapi, closer, err := lcli.GetStorageMinerAPI(cctx) + smapi, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -352,7 +358,7 @@ var dealsImportDataCmd = &cli.Command{ Usage: "Manually import data for a deal", ArgsUsage: " ", Action: func(cctx *cli.Context) error { - api, closer, err := lcli.GetStorageMinerAPI(cctx) + api, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -390,7 +396,7 @@ var dealsListCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { - api, closer, err := lcli.GetStorageMinerAPI(cctx) + api, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -494,7 +500,7 @@ var getBlocklistCmd = &cli.Command{ &CidBaseFlag, }, Action: func(cctx *cli.Context) error { - api, closer, err := lcli.GetStorageMinerAPI(cctx) + api, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -524,7 +530,7 @@ var setBlocklistCmd = &cli.Command{ ArgsUsage: "[ (optional, will read from stdin if omitted)]", Flags: []cli.Flag{}, Action: func(cctx *cli.Context) error { - api, closer, err := lcli.GetStorageMinerAPI(cctx) + api, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -570,7 +576,7 @@ var resetBlocklistCmd = &cli.Command{ Usage: "Remove all entries from the miner's piece CID blocklist", Flags: []cli.Flag{}, Action: func(cctx *cli.Context) error { - api, closer, err := lcli.GetStorageMinerAPI(cctx) + api, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -634,7 +640,7 @@ var marketRestartTransfer = &cli.Command{ if !cctx.Args().Present() { return cli.ShowCommandHelp(cctx, cctx.Command.Name) } - nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) + nodeApi, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -699,7 +705,7 @@ var marketCancelTransfer = &cli.Command{ if !cctx.Args().Present() { return cli.ShowCommandHelp(cctx, cctx.Command.Name) } - nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) + nodeApi, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -775,7 +781,7 @@ var transfersListCmd = &cli.Command{ color.NoColor = !cctx.Bool("color") } - api, closer, err := lcli.GetStorageMinerAPI(cctx) + api, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -842,7 +848,7 @@ var dealsPendingPublish = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { - api, closer, err := lcli.GetStorageMinerAPI(cctx) + api, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } diff --git a/cmd/lotus-miner/retrieval-deals.go b/cmd/lotus-miner/retrieval-deals.go index 0411f7f13..1ce1f6593 100644 --- a/cmd/lotus-miner/retrieval-deals.go +++ b/cmd/lotus-miner/retrieval-deals.go @@ -39,7 +39,7 @@ var retrievalDealSelectionShowCmd = &cli.Command{ Name: "list", Usage: "List retrieval deal proposal selection criteria", Action: func(cctx *cli.Context) error { - smapi, closer, err := lcli.GetStorageMinerAPI(cctx) + smapi, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -66,7 +66,7 @@ var retrievalDealSelectionResetCmd = &cli.Command{ Name: "reset", Usage: "Reset retrieval deal proposal selection criteria to default values", Action: func(cctx *cli.Context) error { - smapi, closer, err := lcli.GetStorageMinerAPI(cctx) + smapi, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -98,7 +98,7 @@ var retrievalDealSelectionRejectCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { - smapi, closer, err := lcli.GetStorageMinerAPI(cctx) + smapi, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -126,7 +126,7 @@ var retrievalDealsListCmd = &cli.Command{ Name: "list", Usage: "List all active retrieval deals for this miner", Action: func(cctx *cli.Context) error { - api, closer, err := lcli.GetStorageMinerAPI(cctx) + api, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -186,7 +186,7 @@ var retrievalSetAskCmd = &cli.Command{ Action: func(cctx *cli.Context) error { ctx := lcli.DaemonContext(cctx) - api, closer, err := lcli.GetStorageMinerAPI(cctx) + api, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -240,7 +240,7 @@ var retrievalGetAskCmd = &cli.Command{ Action: func(cctx *cli.Context) error { ctx := lcli.DaemonContext(cctx) - api, closer, err := lcli.GetStorageMinerAPI(cctx) + api, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -252,13 +252,13 @@ var retrievalGetAskCmd = &cli.Command{ } w := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0) - fmt.Fprintf(w, "Price per Byte\tUnseal Price\tPayment Interval\tPayment Interval Increase\n") + _, _ = fmt.Fprintf(w, "Price per Byte\tUnseal Price\tPayment Interval\tPayment Interval Increase\n") if ask == nil { - fmt.Fprintf(w, "\n") + _, _ = fmt.Fprintf(w, "\n") return w.Flush() } - fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", + _, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", types.FIL(ask.PricePerByte), types.FIL(ask.UnsealPrice), units.BytesSize(float64(ask.PaymentInterval)), From d37ae957e02259e33b4774695ebeb25616cfff6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 29 Jul 2021 12:51:26 +0100 Subject: [PATCH 44/51] refactor miner info command. --- cli/auth.go | 1 - cmd/lotus-miner/dagstore.go | 30 ------------------------------ cmd/lotus-miner/info.go | 35 ++++++++++++++++++++++------------- 3 files changed, 22 insertions(+), 44 deletions(-) delete mode 100644 cmd/lotus-miner/dagstore.go diff --git a/cli/auth.go b/cli/auth.go index 88cbdbb66..33b0d25c8 100644 --- a/cli/auth.go +++ b/cli/auth.go @@ -128,7 +128,6 @@ var AuthApiInfoToken = &cli.Command{ // TODO: Log in audit log when it is implemented - // WARN: this is unable to tell currentEnv, _ := cliutil.EnvsForRepo(t) fmt.Printf("%s=%s:%s\n", currentEnv, string(token), ainfo.Addr) return nil diff --git a/cmd/lotus-miner/dagstore.go b/cmd/lotus-miner/dagstore.go deleted file mode 100644 index a50d99d99..000000000 --- a/cmd/lotus-miner/dagstore.go +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "github.com/urfave/cli/v2" -) - -var dagstoreCmd = &cli.Command{ - Name: "dagstore", - Usage: "Manage the DAG store", - Subcommands: []*cli.Command{ - dagstoreListShardsCmd, - dagstoreGarbageCollectCmd, - }, -} - -var dagstoreListShardsCmd = &cli.Command{ - Name: "list-shards", - Usage: "List shards known to the DAG store", - Action: func(cctx *cli.Context) error { - return nil - }, -} - -var dagstoreGarbageCollectCmd = &cli.Command{ - Name: "gc", - Usage: "Garbage collect the DAG store", - Action: func(cctx *cli.Context) error { - return nil - }, -} diff --git a/cmd/lotus-miner/info.go b/cmd/lotus-miner/info.go index 878361dac..67f8180b7 100644 --- a/cmd/lotus-miner/info.go +++ b/cmd/lotus-miner/info.go @@ -50,7 +50,13 @@ var infoCmd = &cli.Command{ } func infoCmdAct(cctx *cli.Context) error { - nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) + minerApi, closer, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer closer() + + marketsApi, closer, err := lcli.GetMarketsAPI(cctx) if err != nil { return err } @@ -64,12 +70,19 @@ func infoCmdAct(cctx *cli.Context) error { ctx := lcli.ReqContext(cctx) - subsystems, err := nodeApi.RuntimeSubsystems(ctx) + subsystems, err := minerApi.RuntimeSubsystems(ctx) if err != nil { return err } - fmt.Println("Enabled subsystems:", subsystems) + fmt.Println("Enabled subsystems (from miner API):", subsystems) + + subsystems, err = marketsApi.RuntimeSubsystems(ctx) + if err != nil { + return err + } + + fmt.Println("Enabled subsystems (from markets API):", subsystems) fmt.Print("Chain: ") @@ -103,18 +116,14 @@ func infoCmdAct(cctx *cli.Context) error { fmt.Println() - if subsystems.Has(api.SubsystemSectorStorage) { - err := handleMiningInfo(ctx, cctx, fullapi, nodeApi) - if err != nil { - return err - } + err = handleMiningInfo(ctx, cctx, fullapi, minerApi) + if err != nil { + return err } - if subsystems.Has(api.SubsystemMarkets) { - err := handleMarketsInfo(ctx, nodeApi) - if err != nil { - return err - } + err = handleMarketsInfo(ctx, marketsApi) + if err != nil { + return err } return nil From 107777fdacb8f914d0dc627b9d5b70a86ddde181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 29 Jul 2021 12:54:23 +0100 Subject: [PATCH 45/51] polish. --- cli/util/api.go | 6 +++--- cmd/lotus-miner/main.go | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cli/util/api.go b/cli/util/api.go index 76289ec7c..4ddaac88a 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -27,9 +27,9 @@ const ( metadataTraceContext = "traceContext" ) -// The flags passed on the command line with the listen address of the API -// server (only used by the tests), in the order of precedence they should be -// applied for the requested kind of node. +// flagsForAPI returns flags passed on the command line with the listen address +// of the API server (only used by the tests), in the order of precedence they +// should be applied for the requested kind of node. func flagsForAPI(t repo.RepoType) []string { switch t { case repo.FullNode: diff --git a/cmd/lotus-miner/main.go b/cmd/lotus-miner/main.go index fb8ac35b9..ea6fca0a1 100644 --- a/cmd/lotus-miner/main.go +++ b/cmd/lotus-miner/main.go @@ -76,10 +76,10 @@ func main() { } app := &cli.App{ - Name: "lotus-miner", - Usage: "Filecoin decentralized storage network miner", - Version: build.UserVersion(), - Commands: append(local, lcli.CommonCommands...), + Name: "lotus-miner", + Usage: "Filecoin decentralized storage network miner", + Version: build.UserVersion(), + EnableBashCompletion: true, Flags: []cli.Flag{ &cli.StringFlag{ Name: "actor", @@ -112,7 +112,7 @@ func main() { }, cliutil.FlagVeryVerbose, }, - EnableBashCompletion: true, + Commands: append(local, lcli.CommonCommands...), Before: func(c *cli.Context) error { // this command is explicitly called on markets, inform // common commands by overriding the repoType. From 1b5a2dd79a20e484fdb222a43b68c5480801592a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 29 Jul 2021 13:21:55 +0100 Subject: [PATCH 46/51] fix tests. --- cli/util/api.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cli/util/api.go b/cli/util/api.go index 4ddaac88a..4413fd3bb 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -117,7 +117,7 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { for _, env := range deprecatedEnv { env, ok := os.LookupEnv(env) if ok { - log.Warnf("Use deprecation env(%s) value, please use env(%s) instead.", env, currentEnv) + log.Warnf("Using deprecated env(%s) value, please use env(%s) instead.", env, currentEnv) return ParseApiInfo(env), nil } } @@ -125,6 +125,7 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { repoFlags := flagsForRepo(t) for _, f := range repoFlags { if !ctx.IsSet(f) { + fmt.Println("not set", f) continue } @@ -154,7 +155,7 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { }, nil } - return APIInfo{}, fmt.Errorf("could not determine API endpoint for node type: %s", t) + return APIInfo{}, fmt.Errorf("could not determine API endpoint for node type: %v", t) } func GetRawAPI(ctx *cli.Context, t repo.RepoType, version string) (string, http.Header, error) { @@ -297,6 +298,11 @@ func GetWorkerAPI(ctx *cli.Context) (api.Worker, jsonrpc.ClientCloser, error) { } func GetMarketsAPI(ctx *cli.Context) (api.StorageMiner, jsonrpc.ClientCloser, error) { + // to support lotus-miner cli tests. + if tn, ok := ctx.App.Metadata["testnode-storage"]; ok { + return tn.(api.StorageMiner), func() {}, nil + } + addr, headers, err := GetRawAPI(ctx, repo.Markets, "v0") if err != nil { return nil, nil, err From 299b106f38beb76d94669f42dc4b90b97781059b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 29 Jul 2021 13:38:08 +0100 Subject: [PATCH 47/51] fix docs, add flag. --- cli/util/api.go | 1 - cmd/lotus-miner/main.go | 6 ++++++ documentation/en/cli-lotus-miner.md | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cli/util/api.go b/cli/util/api.go index 4413fd3bb..c6e3ae9be 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -125,7 +125,6 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { repoFlags := flagsForRepo(t) for _, f := range repoFlags { if !ctx.IsSet(f) { - fmt.Println("not set", f) continue } diff --git a/cmd/lotus-miner/main.go b/cmd/lotus-miner/main.go index ea6fca0a1..d1c203b57 100644 --- a/cmd/lotus-miner/main.go +++ b/cmd/lotus-miner/main.go @@ -23,6 +23,7 @@ import ( var log = logging.Logger("main") const FlagMinerRepo = "miner-repo" +const FlagMarketsRepo = "markets-repo" // TODO remove after deprecation period const FlagMinerRepoDeprecation = "storagerepo" @@ -106,6 +107,11 @@ func main() { Value: "~/.lotusminer", // TODO: Consider XDG_DATA_HOME Usage: fmt.Sprintf("Specify miner repo path. flag(%s) and env(LOTUS_STORAGE_PATH) are DEPRECATION, will REMOVE SOON", FlagMinerRepoDeprecation), }, + &cli.StringFlag{ + Name: FlagMarketsRepo, + EnvVars: []string{"LOTUS_MARKETS_PATH"}, + Usage: fmt.Sprintf("Markets repo path"), + }, &cli.BoolFlag{ Name: "call-on-markets", Usage: "(experimental; may be removed) call this command against a markets node; use only with common commands like net, auth, pprof, etc. whose target may be ambiguous", diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 863ca8dc9..775f4e9a7 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -43,6 +43,7 @@ GLOBAL OPTIONS: --actor value, -a value specify other actor to check state for (read only) --color use color in display output (default: depends on output being a TTY) --miner-repo value, --storagerepo value Specify miner repo path. flag(storagerepo) and env(LOTUS_STORAGE_PATH) are DEPRECATION, will REMOVE SOON (default: "~/.lotusminer") [$LOTUS_MINER_PATH, $LOTUS_STORAGE_PATH] + --call-on-markets (experimental; may be removed) call this command against a markets node; use only with common commands like net, auth, pprof, etc. whose target may be ambiguous (default: false) --vv enables very verbose mode, useful for debugging the CLI (default: false) --help, -h show help (default: false) --version, -v print the version (default: false) From b3c951c924071936c3ad2013f551753781c77413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 29 Jul 2021 13:49:47 +0100 Subject: [PATCH 48/51] add RepoType#String; adjust repo parsing logic. --- cli/util/api.go | 4 +++- node/repo/fsrepo.go | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/cli/util/api.go b/cli/util/api.go index c6e3ae9be..bf34f4421 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -124,7 +124,9 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { repoFlags := flagsForRepo(t) for _, f := range repoFlags { - if !ctx.IsSet(f) { + // cannot use ctx.IsSet because it ignores default values + f := ctx.String(f) + if f == "" { continue } diff --git a/node/repo/fsrepo.go b/node/repo/fsrepo.go index d3e6f4f2f..5c1c91bc5 100644 --- a/node/repo/fsrepo.go +++ b/node/repo/fsrepo.go @@ -52,6 +52,21 @@ const ( Markets ) +func (t RepoType) String() string { + s := [...]string{ + "__invalid__", + "FullNode", + "StorageMiner", + "Worker", + "Wallet", + "Markets", + } + if t < 0 || int(t) > len(s) { + return "__invalid__" + } + return s[t] +} + func defConfForType(t RepoType) interface{} { switch t { case FullNode: From 4b6fa79ea205a2847f583d8ca0c9d005f1c7aa8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 29 Jul 2021 14:36:04 +0100 Subject: [PATCH 49/51] bugfix. --- cli/util/api.go | 8 ++++---- cmd/lotus-miner/info.go | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cli/util/api.go b/cli/util/api.go index bf34f4421..766969dfa 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -78,7 +78,7 @@ func EnvsForRepo(t repo.RepoType) (current []string, deprecated []string) { return []string{"WORKER_API_INFO"}, nil case repo.Markets: // support split markets-miner and monolith deployments. - return []string{"MARKETS_API_INFO, MINER_API_INFO"}, nil + return []string{"MARKETS_API_INFO", "MINER_API_INFO"}, nil default: panic(fmt.Sprintf("Unknown repo type: %v", t)) } @@ -125,12 +125,12 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { repoFlags := flagsForRepo(t) for _, f := range repoFlags { // cannot use ctx.IsSet because it ignores default values - f := ctx.String(f) - if f == "" { + path := ctx.String(f) + if path == "" { continue } - p, err := homedir.Expand(ctx.String(f)) + p, err := homedir.Expand(path) if err != nil { return APIInfo{}, xerrors.Errorf("could not expand home dir (%s): %w", f, err) } diff --git a/cmd/lotus-miner/info.go b/cmd/lotus-miner/info.go index 67f8180b7..f37952057 100644 --- a/cmd/lotus-miner/info.go +++ b/cmd/lotus-miner/info.go @@ -386,6 +386,7 @@ func handleMarketsInfo(ctx context.Context, nodeApi api.StorageMiner) error { return sorted[i].status > sorted[j].status }) + fmt.Println() fmt.Printf("Storage Deals: %d, %s\n", total.count, types.SizeStr(types.NewInt(total.bytes))) tw := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0) From 00c3432e5a646640398f1ba316b56e7578ac877b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 29 Jul 2021 16:10:04 +0100 Subject: [PATCH 50/51] use fallback api infos last; init service with markets-path. --- cli/auth.go | 2 +- cli/util/api.go | 37 ++++++++++++++++++----------- cmd/lotus-miner/init_restore.go | 11 +++++---- cmd/lotus-miner/init_service.go | 7 +++++- cmd/lotus-miner/main.go | 6 +++-- documentation/en/cli-lotus-miner.md | 1 + 6 files changed, 41 insertions(+), 23 deletions(-) diff --git a/cli/auth.go b/cli/auth.go index 33b0d25c8..342d5e3aa 100644 --- a/cli/auth.go +++ b/cli/auth.go @@ -128,7 +128,7 @@ var AuthApiInfoToken = &cli.Command{ // TODO: Log in audit log when it is implemented - currentEnv, _ := cliutil.EnvsForRepo(t) + currentEnv, _ := cliutil.EnvsForAPIInfos(t) fmt.Printf("%s=%s:%s\n", currentEnv, string(token), ainfo.Addr) return nil }, diff --git a/cli/util/api.go b/cli/util/api.go index 766969dfa..37df41a87 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -62,23 +62,23 @@ func flagsForRepo(t repo.RepoType) []string { } } -// EnvsForRepo returns the environment variables to use in order of precedence +// EnvsForAPIInfos returns the environment variables to use in order of precedence // to determine the API endpoint of the specified node type. // // It returns the current variables and deprecated ones separately, so that // the user can log a warning when deprecated ones are found to be in use. -func EnvsForRepo(t repo.RepoType) (current []string, deprecated []string) { +func EnvsForAPIInfos(t repo.RepoType) (primary string, fallbacks []string, deprecated []string) { switch t { case repo.FullNode: - return []string{"FULLNODE_API_INFO"}, nil + return "FULLNODE_API_INFO", nil, nil case repo.StorageMiner: // TODO remove deprecated deprecation period - return []string{"MINER_API_INFO"}, []string{"STORAGE_API_INFO"} + return "MINER_API_INFO", nil, []string{"STORAGE_API_INFO"} case repo.Worker: - return []string{"WORKER_API_INFO"}, nil + return "WORKER_API_INFO", nil, nil case repo.Markets: // support split markets-miner and monolith deployments. - return []string{"MARKETS_API_INFO", "MINER_API_INFO"}, nil + return "MARKETS_API_INFO", []string{"MINER_API_INFO"}, nil default: panic(fmt.Sprintf("Unknown repo type: %v", t)) } @@ -106,18 +106,20 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { return APIInfo{Addr: strma}, nil } - currentEnv, deprecatedEnv := EnvsForRepo(t) - for _, env := range currentEnv { - env, ok := os.LookupEnv(env) - if ok { - return ParseApiInfo(env), nil - } + // + // Note: it is not correct/intuitive to prefer environment variables over + // CLI flags (repo flags below). + // + primaryEnv, fallbacksEnvs, deprecatedEnvs := EnvsForAPIInfos(t) + env, ok := os.LookupEnv(primaryEnv) + if ok { + return ParseApiInfo(env), nil } - for _, env := range deprecatedEnv { + for _, env := range deprecatedEnvs { env, ok := os.LookupEnv(env) if ok { - log.Warnf("Using deprecated env(%s) value, please use env(%s) instead.", env, currentEnv) + log.Warnf("Using deprecated env(%s) value, please use env(%s) instead.", env, primaryEnv) return ParseApiInfo(env), nil } } @@ -156,6 +158,13 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { }, nil } + for _, env := range fallbacksEnvs { + env, ok := os.LookupEnv(env) + if ok { + return ParseApiInfo(env), nil + } + } + return APIInfo{}, fmt.Errorf("could not determine API endpoint for node type: %v", t) } diff --git a/cmd/lotus-miner/init_restore.go b/cmd/lotus-miner/init_restore.go index 3b4e2b26d..393b44dd2 100644 --- a/cmd/lotus-miner/init_restore.go +++ b/cmd/lotus-miner/init_restore.go @@ -17,7 +17,7 @@ import ( "gopkg.in/cheggaaa/pb.v1" "github.com/filecoin-project/go-address" - paramfetch "github.com/filecoin-project/go-paramfetch" + "github.com/filecoin-project/go-paramfetch" "github.com/filecoin-project/go-state-types/big" lapi "github.com/filecoin-project/lotus/api" @@ -72,7 +72,9 @@ var restoreCmd = &cli.Command{ } } - if err := restore(ctx, cctx, storageCfg, nil, func(api lapi.FullNode, maddr address.Address, peerid peer.ID, mi miner.MinerInfo) error { + repoPath := cctx.String(FlagMinerRepo) + + if err := restore(ctx, cctx, repoPath, storageCfg, nil, func(api lapi.FullNode, maddr address.Address, peerid peer.ID, mi miner.MinerInfo) error { log.Info("Checking proof parameters") if err := paramfetch.GetParams(ctx, build.ParametersJSON(), build.SrsJSON(), uint64(mi.SectorSize)); err != nil { @@ -94,7 +96,7 @@ var restoreCmd = &cli.Command{ }, } -func restore(ctx context.Context, cctx *cli.Context, strConfig *stores.StorageConfig, manageConfig func(*config.StorageMiner) error, after func(api lapi.FullNode, addr address.Address, peerid peer.ID, mi miner.MinerInfo) error) error { +func restore(ctx context.Context, cctx *cli.Context, targetPath string, strConfig *stores.StorageConfig, manageConfig func(*config.StorageMiner) error, after func(api lapi.FullNode, addr address.Address, peerid peer.ID, mi miner.MinerInfo) error) error { if cctx.Args().Len() != 1 { return xerrors.Errorf("expected 1 argument") } @@ -142,8 +144,7 @@ func restore(ctx context.Context, cctx *cli.Context, strConfig *stores.StorageCo log.Info("Checking if repo exists") - repoPath := cctx.String(FlagMinerRepo) - r, err := repo.NewFS(repoPath) + r, err := repo.NewFS(targetPath) if err != nil { return err } diff --git a/cmd/lotus-miner/init_service.go b/cmd/lotus-miner/init_service.go index ad803a830..6e874023e 100644 --- a/cmd/lotus-miner/init_service.go +++ b/cmd/lotus-miner/init_service.go @@ -71,7 +71,12 @@ var serviceCmd = &cli.Command{ return xerrors.Errorf("--api-sector-index is required without the sector storage module enabled") } - if err := restore(ctx, cctx, &stores.StorageConfig{}, func(cfg *config.StorageMiner) error { + repoPath := cctx.String(FlagMarketsRepo) + if repoPath == "" { + return xerrors.Errorf("please provide Lotus markets repo path via flag %s", FlagMarketsRepo) + } + + if err := restore(ctx, cctx, repoPath, &stores.StorageConfig{}, func(cfg *config.StorageMiner) error { cfg.Subsystems.EnableMarkets = es.Contains(MarketsService) cfg.Subsystems.EnableMining = false cfg.Subsystems.EnableSealing = false diff --git a/cmd/lotus-miner/main.go b/cmd/lotus-miner/main.go index d1c203b57..2916fce1f 100644 --- a/cmd/lotus-miner/main.go +++ b/cmd/lotus-miner/main.go @@ -22,8 +22,10 @@ import ( var log = logging.Logger("main") -const FlagMinerRepo = "miner-repo" -const FlagMarketsRepo = "markets-repo" +const ( + FlagMinerRepo = "miner-repo" + FlagMarketsRepo = "markets-repo" +) // TODO remove after deprecation period const FlagMinerRepoDeprecation = "storagerepo" diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 775f4e9a7..bd87774bc 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -43,6 +43,7 @@ GLOBAL OPTIONS: --actor value, -a value specify other actor to check state for (read only) --color use color in display output (default: depends on output being a TTY) --miner-repo value, --storagerepo value Specify miner repo path. flag(storagerepo) and env(LOTUS_STORAGE_PATH) are DEPRECATION, will REMOVE SOON (default: "~/.lotusminer") [$LOTUS_MINER_PATH, $LOTUS_STORAGE_PATH] + --markets-repo value Markets repo path [$LOTUS_MARKETS_PATH] --call-on-markets (experimental; may be removed) call this command against a markets node; use only with common commands like net, auth, pprof, etc. whose target may be ambiguous (default: false) --vv enables very verbose mode, useful for debugging the CLI (default: false) --help, -h show help (default: false) From bb040abb2c929630e980bbcc418330832285ca64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 29 Jul 2021 16:18:43 +0100 Subject: [PATCH 51/51] fix compilation error. --- cli/auth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/auth.go b/cli/auth.go index 342d5e3aa..286eb978b 100644 --- a/cli/auth.go +++ b/cli/auth.go @@ -128,7 +128,7 @@ var AuthApiInfoToken = &cli.Command{ // TODO: Log in audit log when it is implemented - currentEnv, _ := cliutil.EnvsForAPIInfos(t) + currentEnv, _, _ := cliutil.EnvsForAPIInfos(t) fmt.Printf("%s=%s:%s\n", currentEnv, string(token), ainfo.Addr) return nil },