From 6fd9d5f28bd2f81565702db90cc1f345ae9f628e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 30 Sep 2021 16:53:12 +0200 Subject: [PATCH 1/5] Precommit batch balancer support/config --- .../mocks/mock_precommit_batcher.go | 15 +++ extern/storage-sealing/precommit_batch.go | 102 +++++++++++++++++- .../storage-sealing/precommit_batch_test.go | 37 ++++++- extern/storage-sealing/sealiface/config.go | 3 +- node/config/def.go | 3 +- node/config/doc_gen.go | 7 ++ node/config/types.go | 4 + node/modules/storageminer.go | 13 +-- 8 files changed, 171 insertions(+), 13 deletions(-) diff --git a/extern/storage-sealing/mocks/mock_precommit_batcher.go b/extern/storage-sealing/mocks/mock_precommit_batcher.go index ed97229b4..02e84fee8 100644 --- a/extern/storage-sealing/mocks/mock_precommit_batcher.go +++ b/extern/storage-sealing/mocks/mock_precommit_batcher.go @@ -40,6 +40,21 @@ func (m *MockPreCommitBatcherApi) EXPECT() *MockPreCommitBatcherApiMockRecorder return m.recorder } +// ChainBaseFee mocks base method. +func (m *MockPreCommitBatcherApi) ChainBaseFee(arg0 context.Context, arg1 sealing.TipSetToken) (big.Int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ChainBaseFee", arg0, arg1) + ret0, _ := ret[0].(big.Int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ChainBaseFee indicates an expected call of ChainBaseFee. +func (mr *MockPreCommitBatcherApiMockRecorder) ChainBaseFee(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainBaseFee", reflect.TypeOf((*MockPreCommitBatcherApi)(nil).ChainBaseFee), arg0, arg1) +} + // ChainHead mocks base method. func (m *MockPreCommitBatcherApi) ChainHead(arg0 context.Context) (sealing.TipSetToken, abi.ChainEpoch, error) { m.ctrl.T.Helper() diff --git a/extern/storage-sealing/precommit_batch.go b/extern/storage-sealing/precommit_batch.go index 719455b90..519216851 100644 --- a/extern/storage-sealing/precommit_batch.go +++ b/extern/storage-sealing/precommit_batch.go @@ -20,6 +20,7 @@ import ( "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/policy" + "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/extern/storage-sealing/sealiface" "github.com/filecoin-project/lotus/node/config" ) @@ -31,6 +32,7 @@ type PreCommitBatcherApi interface { StateMinerInfo(context.Context, address.Address, TipSetToken) (miner.MinerInfo, error) StateMinerAvailableBalance(context.Context, address.Address, TipSetToken) (big.Int, error) ChainHead(ctx context.Context) (TipSetToken, abi.ChainEpoch, error) + ChainBaseFee(context.Context, TipSetToken) (abi.TokenAmount, error) } type preCommitEntry struct { @@ -185,8 +187,30 @@ func (b *PreCommitBatcher) maybeStartBatch(notif bool) ([]sealiface.PreCommitBat return nil, nil } + individual := false + if !cfg.BatchPreCommitAboveBaseFee.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.BatchPreCommitAboveBaseFee) { // todo: only enable after nv14? + individual = true + } + } + // todo support multiple batches - res, err := b.processBatch(cfg) + var res []sealiface.PreCommitBatchRes + if !individual { + res, err = b.processBatch(cfg) + } else { + res, err = b.processIndividually(cfg) + } if err != nil && len(res) == 0 { return nil, err } @@ -210,6 +234,82 @@ func (b *PreCommitBatcher) maybeStartBatch(notif bool) ([]sealiface.PreCommitBat return res, nil } +func (b *PreCommitBatcher) processIndividually(cfg sealiface.Config) ([]sealiface.PreCommitBatchRes, error) { + mi, err := b.api.StateMinerInfo(b.mctx, b.maddr, nil) + if err != nil { + return nil, xerrors.Errorf("couldn't get miner info: %w", err) + } + + avail := types.TotalFilecoinInt + + if cfg.CollateralFromMinerBalance && !cfg.DisableCollateralFallback { + avail, err = b.api.StateMinerAvailableBalance(b.mctx, b.maddr, nil) + if err != nil { + return nil, xerrors.Errorf("getting available miner balance: %w", err) + } + + avail = big.Sub(avail, cfg.AvailableBalanceBuffer) + if avail.LessThan(big.Zero()) { + avail = big.Zero() + } + } + + var res []sealiface.PreCommitBatchRes + + for sn, info := range b.todo { + r := sealiface.PreCommitBatchRes{ + Sectors: []abi.SectorNumber{sn}, + } + + mcid, err := b.processSingle(cfg, mi, &avail, info) + if err != nil { + r.Error = err.Error() + } else { + r.Msg = &mcid + } + + res = append(res, r) + } + + return res, nil +} + +func (b *PreCommitBatcher) processSingle(cfg sealiface.Config, mi miner.MinerInfo, avail *abi.TokenAmount, params *preCommitEntry) (cid.Cid, error) { + enc := new(bytes.Buffer) + + if err := params.pci.MarshalCBOR(enc); err != nil { + return cid.Undef, xerrors.Errorf("marshaling commit params: %w", err) + } + + deposit := params.deposit + if cfg.CollateralFromMinerBalance { + c := big.Sub(deposit, *avail) + *avail = big.Sub(*avail, deposit) + deposit = c + + if deposit.LessThan(big.Zero()) { + deposit = big.Zero() + } + if (*avail).LessThan(big.Zero()) { + *avail = big.Zero() + } + } + + goodFunds := big.Add(deposit, big.Int(b.feeCfg.MaxPreCommitGasFee)) + + from, _, err := b.addrSel(b.mctx, mi, api.PreCommitAddr, goodFunds, deposit) + if err != nil { + return cid.Undef, xerrors.Errorf("no good address to send commit message from: %w", err) + } + + mcid, err := b.api.SendMsg(b.mctx, from, b.maddr, miner.Methods.PreCommitSector, deposit, big.Int(b.feeCfg.MaxPreCommitGasFee), enc.Bytes()) + if err != nil { + return cid.Undef, xerrors.Errorf("pushing message to mpool: %w", err) + } + + return mcid, nil +} + func (b *PreCommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.PreCommitBatchRes, error) { params := miner5.PreCommitSectorBatchParams{} deposit := big.Zero() diff --git a/extern/storage-sealing/precommit_batch_test.go b/extern/storage-sealing/precommit_batch_test.go index b6c35362e..67694e37e 100644 --- a/extern/storage-sealing/precommit_batch_test.go +++ b/extern/storage-sealing/precommit_batch_test.go @@ -54,10 +54,11 @@ func TestPrecommitBatcher(t *testing.T) { WaitDealsDelay: time.Hour * 6, AlwaysKeepUnsealedCopy: true, - BatchPreCommits: true, - MaxPreCommitBatch: maxBatch, - PreCommitBatchWait: 24 * time.Hour, - PreCommitBatchSlack: 3 * time.Hour, + BatchPreCommits: true, + MaxPreCommitBatch: maxBatch, + PreCommitBatchWait: 24 * time.Hour, + PreCommitBatchSlack: 3 * time.Hour, + BatchPreCommitAboveBaseFee: big.NewInt(10000), AggregateCommits: true, MinCommitBatch: miner5.MinAggregatedSectors, @@ -149,6 +150,9 @@ func TestPrecommitBatcher(t *testing.T) { expectSend := func(expect []abi.SectorNumber) action { return func(t *testing.T, s *mocks.MockPreCommitBatcherApi, pcb *sealing.PreCommitBatcher) promise { + s.EXPECT().ChainHead(gomock.Any()).Return(nil, abi.ChainEpoch(1), nil) + s.EXPECT().ChainBaseFee(gomock.Any(), gomock.Any()).Return(big.NewInt(10001), nil) + s.EXPECT().StateMinerInfo(gomock.Any(), gomock.Any(), gomock.Any()).Return(miner.MinerInfo{Owner: t0123, Worker: t0123}, nil) s.EXPECT().SendMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), funMatcher(func(i interface{}) bool { b := i.([]byte) @@ -163,6 +167,25 @@ func TestPrecommitBatcher(t *testing.T) { } } + expectSendsSingle := func(expect []abi.SectorNumber) action { + return func(t *testing.T, s *mocks.MockPreCommitBatcherApi, pcb *sealing.PreCommitBatcher) promise { + s.EXPECT().ChainHead(gomock.Any()).Return(nil, abi.ChainEpoch(1), nil) + s.EXPECT().ChainBaseFee(gomock.Any(), gomock.Any()).Return(big.NewInt(9999), nil) + + s.EXPECT().StateMinerInfo(gomock.Any(), gomock.Any(), gomock.Any()).Return(miner.MinerInfo{Owner: t0123, Worker: t0123}, nil) + for _, number := range expect { + s.EXPECT().SendMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), funMatcher(func(i interface{}) bool { + b := i.([]byte) + var params miner5.PreCommitSectorParams + require.NoError(t, params.UnmarshalCBOR(bytes.NewReader(b))) + require.Equal(t, number, params.SectorNumber) + return true + })) + } + return nil + } + } + flush := func(expect []abi.SectorNumber) action { return func(t *testing.T, s *mocks.MockPreCommitBatcherApi, pcb *sealing.PreCommitBatcher) promise { _ = expectSend(expect)(t, s, pcb) @@ -211,6 +234,12 @@ func TestPrecommitBatcher(t *testing.T) { addSectors(getSectors(maxBatch)), }, }, + "addMax-belowBaseFee": { + actions: []action{ + expectSendsSingle(getSectors(maxBatch)), + addSectors(getSectors(maxBatch)), + }, + }, } for name, tc := range tcs { diff --git a/extern/storage-sealing/sealiface/config.go b/extern/storage-sealing/sealiface/config.go index 95b851609..2a886e6c4 100644 --- a/extern/storage-sealing/sealiface/config.go +++ b/extern/storage-sealing/sealiface/config.go @@ -41,7 +41,8 @@ type Config struct { CommitBatchWait time.Duration CommitBatchSlack time.Duration - AggregateAboveBaseFee abi.TokenAmount + AggregateAboveBaseFee abi.TokenAmount + BatchPreCommitAboveBaseFee abi.TokenAmount TerminateBatchMax uint64 TerminateBatchMin uint64 diff --git a/node/config/def.go b/node/config/def.go index a1a4856a9..c23f888ac 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -109,7 +109,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 + BatchPreCommitAboveBaseFee: types.FIL(types.BigMul(types.PicoFil, types.NewInt(320))), // 0.32 nFIL + AggregateAboveBaseFee: types.FIL(types.BigMul(types.PicoFil, types.NewInt(320))), // 0.32 nFIL TerminateBatchMin: 1, TerminateBatchMax: 100, diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index adb3b9485..3536a3879 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -711,6 +711,13 @@ avoid the relatively high cost of unsealing the data later, at the cost of more Comment: `time buffer for forceful batch submission before sectors/deals in batch would start expiring`, }, + { + Name: "BatchPreCommitAboveBaseFee", + Type: "types.FIL", + + Comment: `network BaseFee below which to stop doing precommit batching, instead +sending precommit messages to the chain individually`, + }, { Name: "AggregateAboveBaseFee", Type: "types.FIL", diff --git a/node/config/types.go b/node/config/types.go index 845566537..fe86739fc 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -219,6 +219,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 precommit batching, instead + // sending precommit messages to the chain individually + BatchPreCommitAboveBaseFee types.FIL + // network BaseFee below which to stop doing commit aggregation, instead // submitting proofs to the chain individually AggregateAboveBaseFee types.FIL diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index a461ee5ec..710d1f38f 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -918,12 +918,13 @@ func ToSealingConfig(cfg *config.StorageMiner) sealiface.Config { 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), + 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), + BatchPreCommitAboveBaseFee: types.BigInt(cfg.Sealing.BatchPreCommitAboveBaseFee), TerminateBatchMax: cfg.Sealing.TerminateBatchMax, TerminateBatchMin: cfg.Sealing.TerminateBatchMin, From d6dd86b4198d317052c132c46b5193a8945bea30 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Thu, 30 Sep 2021 12:45:50 -0400 Subject: [PATCH 2/5] Fix lint --- extern/storage-sealing/precommit_batch_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extern/storage-sealing/precommit_batch_test.go b/extern/storage-sealing/precommit_batch_test.go index 67694e37e..6013ee17d 100644 --- a/extern/storage-sealing/precommit_batch_test.go +++ b/extern/storage-sealing/precommit_batch_test.go @@ -174,11 +174,12 @@ func TestPrecommitBatcher(t *testing.T) { s.EXPECT().StateMinerInfo(gomock.Any(), gomock.Any(), gomock.Any()).Return(miner.MinerInfo{Owner: t0123, Worker: t0123}, nil) for _, number := range expect { + numClone := number s.EXPECT().SendMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), funMatcher(func(i interface{}) bool { b := i.([]byte) var params miner5.PreCommitSectorParams require.NoError(t, params.UnmarshalCBOR(bytes.NewReader(b))) - require.Equal(t, number, params.SectorNumber) + require.Equal(t, numClone, params.SectorNumber) return true })) } From f8a89cafd818b9cdb50af98156d9a0948b8f10a3 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Thu, 30 Sep 2021 12:46:25 -0400 Subject: [PATCH 3/5] Fix logs --- 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 519216851..f3225c160 100644 --- a/extern/storage-sealing/precommit_batch.go +++ b/extern/storage-sealing/precommit_batch.go @@ -278,7 +278,7 @@ func (b *PreCommitBatcher) processSingle(cfg sealiface.Config, mi miner.MinerInf enc := new(bytes.Buffer) if err := params.pci.MarshalCBOR(enc); err != nil { - return cid.Undef, xerrors.Errorf("marshaling commit params: %w", err) + return cid.Undef, xerrors.Errorf("marshaling precommit params: %w", err) } deposit := params.deposit @@ -299,7 +299,7 @@ func (b *PreCommitBatcher) processSingle(cfg sealiface.Config, mi miner.MinerInf from, _, err := b.addrSel(b.mctx, mi, api.PreCommitAddr, goodFunds, deposit) if err != nil { - return cid.Undef, xerrors.Errorf("no good address to send commit message from: %w", err) + return cid.Undef, xerrors.Errorf("no good address to send precommit message from: %w", err) } mcid, err := b.api.SendMsg(b.mctx, from, b.maddr, miner.Methods.PreCommitSector, deposit, big.Int(b.feeCfg.MaxPreCommitGasFee), enc.Bytes()) From f004d036dc31d469a731a3e92dbb619094d26394 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Thu, 30 Sep 2021 21:23:39 -0400 Subject: [PATCH 4/5] Set BatchPreCommitAboveBaseFee correctly --- extern/storage-sealing/commit_batch_test.go | 3 ++- itests/sector_miner_collateral_test.go | 1 + node/modules/storageminer.go | 13 +++++++------ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/extern/storage-sealing/commit_batch_test.go b/extern/storage-sealing/commit_batch_test.go index aea6d455e..e03c34693 100644 --- a/extern/storage-sealing/commit_batch_test.go +++ b/extern/storage-sealing/commit_batch_test.go @@ -59,7 +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 + AggregateAboveBaseFee: types.BigMul(types.PicoFil, types.NewInt(150)), // 0.15 nFIL + BatchPreCommitAboveBaseFee: types.BigMul(types.PicoFil, types.NewInt(150)), // 0.15 nFIL TerminateBatchMin: 1, TerminateBatchMax: 100, diff --git a/itests/sector_miner_collateral_test.go b/itests/sector_miner_collateral_test.go index 891356ef1..de3da21f6 100644 --- a/itests/sector_miner_collateral_test.go +++ b/itests/sector_miner_collateral_test.go @@ -53,6 +53,7 @@ func TestMinerBalanceCollateral(t *testing.T) { AvailableBalanceBuffer: big.Zero(), DisableCollateralFallback: false, AggregateAboveBaseFee: big.Zero(), + BatchPreCommitAboveBaseFee: big.Zero(), }, nil }, nil })), diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 710d1f38f..5e6113072 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -883,12 +883,13 @@ 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), - AggregateAboveBaseFee: types.FIL(cfg.AggregateAboveBaseFee), + AggregateCommits: cfg.AggregateCommits, + MinCommitBatch: cfg.MinCommitBatch, + MaxCommitBatch: cfg.MaxCommitBatch, + CommitBatchWait: config.Duration(cfg.CommitBatchWait), + CommitBatchSlack: config.Duration(cfg.CommitBatchSlack), + AggregateAboveBaseFee: types.FIL(cfg.AggregateAboveBaseFee), + BatchPreCommitAboveBaseFee: types.FIL(cfg.BatchPreCommitAboveBaseFee), TerminateBatchMax: cfg.TerminateBatchMax, TerminateBatchMin: cfg.TerminateBatchMin, From a335cb3767f04e7518cbb7910fdc97c791be2770 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Fri, 1 Oct 2021 10:23:21 -0400 Subject: [PATCH 5/5] Update to latest actors --- chain/actors/policy/policy.go | 40 +++++++++++- chain/actors/policy/policy.go.template | 29 +++++++-- chain/gen/genesis/miners.go | 1 - cmd/lotus-shed/math.go | 49 +++++++++++++-- extern/storage-sealing/commit_batch.go | 7 ++- .../mocks/mock_precommit_batcher.go | 16 +++++ extern/storage-sealing/precommit_batch.go | 63 ++++++++++++------- .../storage-sealing/precommit_batch_test.go | 17 +++-- go.mod | 2 +- go.sum | 4 +- testplans/lotus-soup/go.sum | 4 +- 11 files changed, 183 insertions(+), 49 deletions(-) diff --git a/chain/actors/policy/policy.go b/chain/actors/policy/policy.go index 29be33ddf..e00a6ae10 100644 --- a/chain/actors/policy/policy.go +++ b/chain/actors/policy/policy.go @@ -474,7 +474,7 @@ func GetDeclarationsMax(nwVer network.Version) (int, error) { } } -func AggregateNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.TokenAmount) (abi.TokenAmount, error) { +func AggregateProveCommitNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.TokenAmount) (abi.TokenAmount, error) { v, err := actors.VersionForNetwork(nwVer) if err != nil { return big.Zero(), err @@ -503,7 +503,43 @@ func AggregateNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.T case actors.Version6: - return miner6.AggregateNetworkFee(aggregateSize, baseFee), nil + return miner6.AggregateProveCommitNetworkFee(aggregateSize, baseFee), nil + + default: + return big.Zero(), xerrors.Errorf("unsupported network version") + } +} + +func AggregatePreCommitNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.TokenAmount) (abi.TokenAmount, error) { + v, err := actors.VersionForNetwork(nwVer) + if err != nil { + return big.Zero(), err + } + switch v { + + case actors.Version0: + + return big.Zero(), nil + + case actors.Version2: + + return big.Zero(), nil + + case actors.Version3: + + return big.Zero(), nil + + case actors.Version4: + + return big.Zero(), nil + + case actors.Version5: + + return big.Zero(), nil + + case actors.Version6: + + return miner6.AggregatePreCommitNetworkFee(aggregateSize, baseFee), nil default: return big.Zero(), xerrors.Errorf("unsupported network version") diff --git a/chain/actors/policy/policy.go.template b/chain/actors/policy/policy.go.template index 4c13560d0..64c1b7083 100644 --- a/chain/actors/policy/policy.go.template +++ b/chain/actors/policy/policy.go.template @@ -294,7 +294,7 @@ func GetDeclarationsMax(nwVer network.Version) (int, error) { } } -func AggregateNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.TokenAmount) (abi.TokenAmount, error) { +func AggregateProveCommitNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.TokenAmount) (abi.TokenAmount, error) { v, err := actors.VersionForNetwork(nwVer) if err != nil { return big.Zero(), err @@ -302,10 +302,31 @@ func AggregateNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.T switch v { {{range .versions}} case actors.Version{{.}}: - {{if (le . 4)}} - return big.Zero(), nil - {{else}} + {{if (ge . 6)}} + return miner{{.}}.AggregateProveCommitNetworkFee(aggregateSize, baseFee), nil + {{else if (eq . 5)}} return miner{{.}}.AggregateNetworkFee(aggregateSize, baseFee), nil + {{else}} + return big.Zero(), nil + {{end}} + {{end}} + default: + return big.Zero(), xerrors.Errorf("unsupported network version") + } +} + +func AggregatePreCommitNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.TokenAmount) (abi.TokenAmount, error) { + v, err := actors.VersionForNetwork(nwVer) + if err != nil { + return big.Zero(), err + } + switch v { + {{range .versions}} + case actors.Version{{.}}: + {{if (ge . 6)}} + return miner{{.}}.AggregatePreCommitNetworkFee(aggregateSize, baseFee), nil + {{else}} + return big.Zero(), nil {{end}} {{end}} default: diff --git a/chain/gen/genesis/miners.go b/chain/gen/genesis/miners.go index bcc13aa5d..edacfe304 100644 --- a/chain/gen/genesis/miners.go +++ b/chain/gen/genesis/miners.go @@ -195,7 +195,6 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sys vm.Syscal if err != nil { return xerrors.Errorf("failed to create genesis miner (publish deals): %w", err) } - retval, err := market.DecodePublishStorageDealsReturn(ret, nv) if err != nil { return xerrors.Errorf("failed to create genesis miner (decoding published deals): %w", err) diff --git a/cmd/lotus-shed/math.go b/cmd/lotus-shed/math.go index c6d4ed0c9..4b53495f0 100644 --- a/cmd/lotus-shed/math.go +++ b/cmd/lotus-shed/math.go @@ -7,11 +7,12 @@ import ( "os" "strings" + miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner" + "github.com/urfave/cli/v2" "golang.org/x/xerrors" "github.com/filecoin-project/lotus/chain/types" - miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner" ) var mathCmd = &cli.Command{ @@ -19,7 +20,8 @@ var mathCmd = &cli.Command{ Usage: "utility commands around doing math on a list of numbers", Subcommands: []*cli.Command{ mathSumCmd, - mathAggFeesCmd, + mathPreCommitAggFeesCmd, + mathProveCommitAggFeesCmd, }, } @@ -105,8 +107,8 @@ var mathSumCmd = &cli.Command{ }, } -var mathAggFeesCmd = &cli.Command{ - Name: "agg-fees", +var mathProveCommitAggFeesCmd = &cli.Command{ + Name: "agg-fees-commit", Flags: []cli.Flag{ &cli.IntFlag{ Name: "size", @@ -117,6 +119,11 @@ var mathAggFeesCmd = &cli.Command{ Usage: "baseFee aFIL", Required: true, }, + &cli.StringFlag{ + Name: "base-fee", + Usage: "baseFee aFIL", + Required: true, + }, }, Action: func(cctx *cli.Context) error { as := cctx.Int("size") @@ -126,7 +133,39 @@ var mathAggFeesCmd = &cli.Command{ return xerrors.Errorf("parsing basefee: %w", err) } - fmt.Println(types.FIL(miner5.AggregateNetworkFee(as, bf))) + fmt.Println(types.FIL(miner6.AggregateProveCommitNetworkFee(as, bf))) + + return nil + }, +} + +var mathPreCommitAggFeesCmd = &cli.Command{ + Name: "agg-fees-precommit", + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "size", + Required: true, + }, + &cli.StringFlag{ + Name: "base-fee", + Usage: "baseFee aFIL", + Required: true, + }, + &cli.StringFlag{ + Name: "base-fee", + Usage: "baseFee aFIL", + Required: true, + }, + }, + Action: func(cctx *cli.Context) error { + as := cctx.Int("size") + + bf, err := types.BigFromString(cctx.String("base-fee")) + if err != nil { + return xerrors.Errorf("parsing basefee: %w", err) + } + + fmt.Println(types.FIL(miner6.AggregatePreCommitNetworkFee(as, bf))) return nil }, diff --git a/extern/storage-sealing/commit_batch.go b/extern/storage-sealing/commit_batch.go index 3a97f7d68..1c55b6700 100644 --- a/extern/storage-sealing/commit_batch.go +++ b/extern/storage-sealing/commit_batch.go @@ -347,11 +347,12 @@ func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBa return []sealiface.CommitBatchRes{res}, xerrors.Errorf("getting network version: %s", err) } - aggFeeRaw, err := policy.AggregateNetworkFee(nv, len(infos), bf) + aggFeeRaw, err := policy.AggregateProveCommitNetworkFee(nv, len(infos), bf) if err != nil { - log.Errorf("getting aggregate network fee: %s", err) - return []sealiface.CommitBatchRes{res}, xerrors.Errorf("getting aggregate network fee: %s", err) + log.Errorf("getting aggregate commit network fee: %s", err) + return []sealiface.CommitBatchRes{res}, xerrors.Errorf("getting aggregate commit network fee: %s", err) } + aggFee := big.Div(big.Mul(aggFeeRaw, aggFeeNum), aggFeeDen) needFunds := big.Add(collateral, aggFee) diff --git a/extern/storage-sealing/mocks/mock_precommit_batcher.go b/extern/storage-sealing/mocks/mock_precommit_batcher.go index 02e84fee8..fe7424d35 100644 --- a/extern/storage-sealing/mocks/mock_precommit_batcher.go +++ b/extern/storage-sealing/mocks/mock_precommit_batcher.go @@ -11,6 +11,7 @@ import ( address "github.com/filecoin-project/go-address" abi "github.com/filecoin-project/go-state-types/abi" big "github.com/filecoin-project/go-state-types/big" + network "github.com/filecoin-project/go-state-types/network" miner "github.com/filecoin-project/lotus/chain/actors/builtin/miner" sealing "github.com/filecoin-project/lotus/extern/storage-sealing" gomock "github.com/golang/mock/gomock" @@ -115,3 +116,18 @@ func (mr *MockPreCommitBatcherApiMockRecorder) StateMinerInfo(arg0, arg1, arg2 i mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateMinerInfo", reflect.TypeOf((*MockPreCommitBatcherApi)(nil).StateMinerInfo), arg0, arg1, arg2) } + +// StateNetworkVersion mocks base method. +func (m *MockPreCommitBatcherApi) StateNetworkVersion(arg0 context.Context, arg1 sealing.TipSetToken) (network.Version, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StateNetworkVersion", arg0, arg1) + ret0, _ := ret[0].(network.Version) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// StateNetworkVersion indicates an expected call of StateNetworkVersion. +func (mr *MockPreCommitBatcherApiMockRecorder) StateNetworkVersion(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateNetworkVersion", reflect.TypeOf((*MockPreCommitBatcherApi)(nil).StateNetworkVersion), arg0, arg1) +} diff --git a/extern/storage-sealing/precommit_batch.go b/extern/storage-sealing/precommit_batch.go index f3225c160..07d2e796e 100644 --- a/extern/storage-sealing/precommit_batch.go +++ b/extern/storage-sealing/precommit_batch.go @@ -7,6 +7,8 @@ import ( "sync" "time" + "github.com/filecoin-project/go-state-types/network" + "github.com/ipfs/go-cid" "golang.org/x/xerrors" @@ -33,6 +35,7 @@ type PreCommitBatcherApi interface { StateMinerAvailableBalance(context.Context, address.Address, TipSetToken) (big.Int, error) ChainHead(ctx context.Context) (TipSetToken, abi.ChainEpoch, error) ChainBaseFee(context.Context, TipSetToken) (abi.TokenAmount, error) + StateNetworkVersion(ctx context.Context, tok TipSetToken) (network.Version, error) } type preCommitEntry struct { @@ -187,27 +190,31 @@ func (b *PreCommitBatcher) maybeStartBatch(notif bool) ([]sealiface.PreCommitBat return nil, nil } + 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) + } + + // TODO: Drop this once nv14 has come and gone + nv, err := b.api.StateNetworkVersion(b.mctx, tok) + if err != nil { + return nil, xerrors.Errorf("couldn't get network version: %w", err) + } + individual := false - if !cfg.BatchPreCommitAboveBaseFee.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.BatchPreCommitAboveBaseFee) { // todo: only enable after nv14? - individual = true - } + if !cfg.BatchPreCommitAboveBaseFee.Equals(big.Zero()) && bf.LessThan(cfg.BatchPreCommitAboveBaseFee) && nv >= network.Version14 { + individual = true } // todo support multiple batches var res []sealiface.PreCommitBatchRes if !individual { - res, err = b.processBatch(cfg) + res, err = b.processBatch(cfg, tok, bf, nv) } else { res, err = b.processIndividually(cfg) } @@ -310,7 +317,7 @@ func (b *PreCommitBatcher) processSingle(cfg sealiface.Config, mi miner.MinerInf return mcid, nil } -func (b *PreCommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.PreCommitBatchRes, error) { +func (b *PreCommitBatcher) processBatch(cfg sealiface.Config, tok TipSetToken, bf abi.TokenAmount, nv network.Version) ([]sealiface.PreCommitBatchRes, error) { params := miner5.PreCommitSectorBatchParams{} deposit := big.Zero() var res sealiface.PreCommitBatchRes @@ -326,11 +333,6 @@ func (b *PreCommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.PreCo deposit = big.Add(deposit, p.deposit) } - deposit, err := collateralSendAmount(b.mctx, b.api, b.maddr, cfg, deposit) - if err != nil { - return []sealiface.PreCommitBatchRes{res}, err - } - enc := new(bytes.Buffer) if err := params.MarshalCBOR(enc); err != nil { return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("couldn't serialize PreCommitSectorBatchParams: %w", err) @@ -342,14 +344,29 @@ func (b *PreCommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.PreCo } maxFee := b.feeCfg.MaxPreCommitBatchGasFee.FeeForSectors(len(params.Sectors)) - goodFunds := big.Add(deposit, maxFee) + + aggFeeRaw, err := policy.AggregatePreCommitNetworkFee(nv, len(params.Sectors), bf) + if err != nil { + log.Errorf("getting aggregate precommit network fee: %s", err) + return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("getting aggregate precommit network fee: %s", err) + } + + aggFee := big.Div(big.Mul(aggFeeRaw, aggFeeNum), aggFeeDen) + + needFunds := big.Add(deposit, aggFee) + needFunds, err = collateralSendAmount(b.mctx, b.api, b.maddr, cfg, needFunds) + if err != nil { + return []sealiface.PreCommitBatchRes{res}, err + } + + goodFunds := big.Add(maxFee, needFunds) from, _, err := b.addrSel(b.mctx, mi, api.PreCommitAddr, goodFunds, deposit) if err != nil { return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("no good address found: %w", err) } - mcid, err := b.api.SendMsg(b.mctx, from, b.maddr, miner.Methods.PreCommitSectorBatch, deposit, maxFee, enc.Bytes()) + mcid, err := b.api.SendMsg(b.mctx, from, b.maddr, miner.Methods.PreCommitSectorBatch, needFunds, maxFee, enc.Bytes()) if err != nil { return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("sending message failed: %w", err) } diff --git a/extern/storage-sealing/precommit_batch_test.go b/extern/storage-sealing/precommit_batch_test.go index 6013ee17d..f6440996e 100644 --- a/extern/storage-sealing/precommit_batch_test.go +++ b/extern/storage-sealing/precommit_batch_test.go @@ -8,13 +8,16 @@ import ( "testing" "time" + miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner" + + "github.com/filecoin-project/go-state-types/network" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" @@ -44,7 +47,7 @@ func TestPrecommitBatcher(t *testing.T) { return t0123, big.Zero(), nil } - maxBatch := miner5.PreCommitSectorBatchMaxSize + maxBatch := miner6.PreCommitSectorBatchMaxSize cfg := func() (sealiface.Config, error) { return sealiface.Config{ @@ -61,8 +64,8 @@ func TestPrecommitBatcher(t *testing.T) { BatchPreCommitAboveBaseFee: big.NewInt(10000), AggregateCommits: true, - MinCommitBatch: miner5.MinAggregatedSectors, - MaxCommitBatch: miner5.MaxAggregatedSectors, + MinCommitBatch: miner6.MinAggregatedSectors, + MaxCommitBatch: miner6.MaxAggregatedSectors, CommitBatchWait: 24 * time.Hour, CommitBatchSlack: 1 * time.Hour, @@ -152,11 +155,12 @@ func TestPrecommitBatcher(t *testing.T) { return func(t *testing.T, s *mocks.MockPreCommitBatcherApi, pcb *sealing.PreCommitBatcher) promise { s.EXPECT().ChainHead(gomock.Any()).Return(nil, abi.ChainEpoch(1), nil) s.EXPECT().ChainBaseFee(gomock.Any(), gomock.Any()).Return(big.NewInt(10001), nil) + s.EXPECT().StateNetworkVersion(gomock.Any(), gomock.Any()).Return(network.Version14, nil) s.EXPECT().StateMinerInfo(gomock.Any(), gomock.Any(), gomock.Any()).Return(miner.MinerInfo{Owner: t0123, Worker: t0123}, nil) s.EXPECT().SendMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), funMatcher(func(i interface{}) bool { b := i.([]byte) - var params miner5.PreCommitSectorBatchParams + var params miner6.PreCommitSectorBatchParams require.NoError(t, params.UnmarshalCBOR(bytes.NewReader(b))) for s, number := range expect { require.Equal(t, number, params.Sectors[s].SectorNumber) @@ -171,13 +175,14 @@ func TestPrecommitBatcher(t *testing.T) { return func(t *testing.T, s *mocks.MockPreCommitBatcherApi, pcb *sealing.PreCommitBatcher) promise { s.EXPECT().ChainHead(gomock.Any()).Return(nil, abi.ChainEpoch(1), nil) s.EXPECT().ChainBaseFee(gomock.Any(), gomock.Any()).Return(big.NewInt(9999), nil) + s.EXPECT().StateNetworkVersion(gomock.Any(), gomock.Any()).Return(network.Version14, nil) s.EXPECT().StateMinerInfo(gomock.Any(), gomock.Any(), gomock.Any()).Return(miner.MinerInfo{Owner: t0123, Worker: t0123}, nil) for _, number := range expect { numClone := number s.EXPECT().SendMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), funMatcher(func(i interface{}) bool { b := i.([]byte) - var params miner5.PreCommitSectorParams + var params miner6.PreCommitSectorParams require.NoError(t, params.UnmarshalCBOR(bytes.NewReader(b))) require.Equal(t, numClone, params.SectorNumber) return true diff --git a/go.mod b/go.mod index f646eb634..7b4bd85b7 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/filecoin-project/specs-actors/v3 v3.1.1 github.com/filecoin-project/specs-actors/v4 v4.0.1 github.com/filecoin-project/specs-actors/v5 v5.0.4 - github.com/filecoin-project/specs-actors/v6 v6.0.0-20210929155130-9dcf49dee05b + github.com/filecoin-project/specs-actors/v6 v6.0.0-20211001164657-a2369c587d17 github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 github.com/filecoin-project/test-vectors/schema v0.0.5 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 diff --git a/go.sum b/go.sum index 17d8764a6..c303adec2 100644 --- a/go.sum +++ b/go.sum @@ -344,8 +344,8 @@ github.com/filecoin-project/specs-actors/v4 v4.0.1/go.mod h1:TkHXf/l7Wyw4ZejyXIP github.com/filecoin-project/specs-actors/v5 v5.0.0-20210512015452-4fe3889fff57/go.mod h1:283yBMMUSDB2abcjP/hhrwTkhb9h3sfM6KGrep/ZlBI= github.com/filecoin-project/specs-actors/v5 v5.0.4 h1:OY7BdxJWlUfUFXWV/kpNBYGXNPasDIedf42T3sGx08s= github.com/filecoin-project/specs-actors/v5 v5.0.4/go.mod h1:5BAKRAMsOOlD8+qCw4UvT/lTLInCJ3JwOWZbX8Ipwq4= -github.com/filecoin-project/specs-actors/v6 v6.0.0-20210929155130-9dcf49dee05b h1:q/ez+gqSlqmzWUb/1bs5ynUqH5G5L1jcFCiOAPfkE8k= -github.com/filecoin-project/specs-actors/v6 v6.0.0-20210929155130-9dcf49dee05b/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= +github.com/filecoin-project/specs-actors/v6 v6.0.0-20211001164657-a2369c587d17 h1:AtIN4w99era1Do9JP4OmibJ8vnYBDrHEbTDWBlBeJTM= +github.com/filecoin-project/specs-actors/v6 v6.0.0-20211001164657-a2369c587d17/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 h1:Ur/l2+6qN+lQiqjozWWc5p9UDaAMDZKTlDS98oRnlIw= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= diff --git a/testplans/lotus-soup/go.sum b/testplans/lotus-soup/go.sum index 14f3e7988..9fb304cd1 100644 --- a/testplans/lotus-soup/go.sum +++ b/testplans/lotus-soup/go.sum @@ -439,8 +439,8 @@ github.com/filecoin-project/specs-actors/v4 v4.0.1/go.mod h1:TkHXf/l7Wyw4ZejyXIP github.com/filecoin-project/specs-actors/v5 v5.0.0-20210512015452-4fe3889fff57/go.mod h1:283yBMMUSDB2abcjP/hhrwTkhb9h3sfM6KGrep/ZlBI= github.com/filecoin-project/specs-actors/v5 v5.0.4 h1:OY7BdxJWlUfUFXWV/kpNBYGXNPasDIedf42T3sGx08s= github.com/filecoin-project/specs-actors/v5 v5.0.4/go.mod h1:5BAKRAMsOOlD8+qCw4UvT/lTLInCJ3JwOWZbX8Ipwq4= -github.com/filecoin-project/specs-actors/v6 v6.0.0-20210929155130-9dcf49dee05b h1:q/ez+gqSlqmzWUb/1bs5ynUqH5G5L1jcFCiOAPfkE8k= -github.com/filecoin-project/specs-actors/v6 v6.0.0-20210929155130-9dcf49dee05b/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= +github.com/filecoin-project/specs-actors/v6 v6.0.0-20211001164657-a2369c587d17 h1:AtIN4w99era1Do9JP4OmibJ8vnYBDrHEbTDWBlBeJTM= +github.com/filecoin-project/specs-actors/v6 v6.0.0-20211001164657-a2369c587d17/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 h1:Ur/l2+6qN+lQiqjozWWc5p9UDaAMDZKTlDS98oRnlIw= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E=