Compare commits

...
507 Commits
Author SHA1 Message Date
Aarsh Shah 48e8f54c6a Merge pull request #6835 from filecoin-project/feat/dag-store-ds
Create DAG store datastore under DAG store dir
2021-07-22 17:34:44 +05:30
Dirk McCormick 776c216072 feat: create DAG store datastore under DAG store dir 2021-07-22 13:58:25 +02:00
Anton Evangelatov c60959ea9f fetch peer id from chain 2021-07-22 10:50:55 +02:00
Aarsh Shah 62044c34b1 Merge pull request #6826 from filecoin-project/fix/dagstore-wrapper-bugs
Fix bugs in the DAGStore wrapper
2021-07-22 11:30:38 +05:30
aarshkshah1992 c8d328d386 fix bugs in the dagstore wrapper 2021-07-22 09:44:14 +05:30
aarshkshah1992 fd879e0426 update ds 2021-07-22 00:21:39 +05:30
aarshkshah1992 27f3170022 update dagstore 2021-07-21 23:38:22 +05:30
aarshkshah1992 5b1241d213 fix dagstore errors 2021-07-21 23:15:39 +05:30
aarshkshah1992 eaee1578dd log more 2021-07-21 22:47:31 +05:30
aarshkshah1992 9e5c5b624b update dagstore logs 2021-07-21 22:22:26 +05:30
aarshkshah1992 640d69f5cb update dagstire 2021-07-21 21:54:28 +05:30
aarshkshah1992 36876c2601 update deps 2021-07-21 20:50:47 +05:30
Dirk McCormick 39c1594505 feat: add logs to wrapper load shard 2021-07-21 17:18:23 +02:00
Aarsh Shah 86e1c854fa Merge pull request #6814 from filecoin-project/nonsense/add-sealproof-in-sectorbuilder
add SealProof in sector builder
2021-07-21 20:44:01 +05:30
Anton Evangelatov 1af89236da add SealProof in sector builder 2021-07-21 15:49:45 +02:00
aarshkshah1992 9741867426 remove dev.gen 2021-07-21 17:55:53 +05:30
Aarsh Shah b7b98f94a6 Delete localnet.json 2021-07-21 17:50:52 +05:30
Aarsh Shah fb50d68c32 Merge pull request #6812 from filecoin-project/fix/ensure-mount-started
Ensure piece store starts before calling lotus accessor methods
2021-07-21 17:49:35 +05:30
aarshkshah1992 692961e019 fix error handling 2021-07-21 17:49:09 +05:30
aarshkshah1992 312cc94e6d Merge branch 'feat/replace-multistore-carv2' of github.com:filecoin-project/lotus into feat/replace-multistore-carv2 2021-07-21 17:42:52 +05:30
aarshkshah1992 ea71e4de60 update dagstore fix 2021-07-21 17:42:19 +05:30
aarshkshah1992 4ed9cd152c fix lotus accessor startup 2021-07-21 17:34:07 +05:30
Dirk McCormick 0dbb1940f0 fix: ensure piece store starts before calling lotus accessor methods 2021-07-21 13:31:20 +02:00
dirkmc 1452a361a9 Merge pull request #6809 from filecoin-project/fix/dagstore-tests
fix dagstore tests
2021-07-21 12:24:53 +02:00
Dirk McCormick 503c08f999 fix: dagstore tests 2021-07-21 12:23:55 +02:00
aarshkshah1992 6bee14d6fa update dagstore and markets 2021-07-21 15:34:38 +05:30
dirkmc 839abdf910 Merge pull request #6808 from filecoin-project/fix/wait-piece-store-start
Wait for piece store to start before starting DAG store wrapper
2021-07-21 11:57:31 +02:00
Dirk McCormick 6057f2e6d9 fix: wait for piece store to start before starting DAG store wrapper 2021-07-21 11:56:48 +02:00
aarshkshah1992 213dbc6bc8 update dagstore 2021-07-21 14:54:33 +05:30
Aarsh Shah fc77705229 Merge pull request #6806 from filecoin-project/fix/lotus-mount-caps
capitalize lotus mount fields for deserialization
2021-07-21 14:24:11 +05:30
Dirk McCormick 12d7db4efb fix: capitalize lotus mount fields for deserialization 2021-07-21 10:45:14 +02:00
aarshkshah1992 d7827da5bb update deps 2021-07-21 09:30:33 +05:30
Aarsh Shah b2ff2edd0c Merge branch 'master' into feat/replace-multistore-carv2 2021-07-20 22:03:18 +05:30
aarshkshah1992 13e845ae51 fix import test 2021-07-20 21:47:55 +05:30
aarshkshah1992 0c90868929 get it compiling 2021-07-20 21:44:25 +05:30
Aarsh Shah 44496afc66 Merge pull request #6793 from filecoin-project/refactor/mv-lotus-mount
move lotus mount, dag store etc from markets to lotus
2021-07-20 20:33:46 +05:30
Dirk McCormick 8becd922cf test: for dag store wrapper 2021-07-20 15:05:08 +02:00
Dirk McCormick 16be5b5478 fix: add comment about car path 2021-07-20 12:52:45 +02:00
Dirk McCormick 1e7095995b refactor: use concrete type in DI for dag store wrapper 2021-07-20 12:45:20 +02:00
Dirk McCormick ffb995035f feat: log trace events 2021-07-20 12:37:52 +02:00
Dirk McCormick ffe7185443 fix: simplify recover shard processing 2021-07-20 11:50:40 +02:00
Dirk McCormick 44036d9a4a fix: address review comments 2021-07-20 11:04:47 +02:00
Dirk McCormick b6a7a8c987 refactor: move lotus mount, dag store etc from markets to lotus 2021-07-19 15:53:34 +02:00
aarshkshah1992 905592a3dc integrate unsealing changes with Lotus 2021-07-19 16:12:58 +05:30
Aayush Rajasekaran 1c30d07d68 Merge pull request #6773 from filecoin-project/biglep/codeowners
Resurrect CODEOWNERS, but for maintainers group
2021-07-18 10:27:17 -04:00
Steve Loeppky d8431da9b9 Resurrect CODEOWNERS, but for maintainers group
Per updated CR policies for this repo, we want non-draft PRs to be assigned to the filecoin-project/lotus-maintainers team.
2021-07-16 22:53:26 -07:00
aarshkshah1992 9724248a49 update lotus soup go mod 2021-07-15 18:33:15 +05:30
Łukasz Magiera fd9f5dc83c Merge pull request #6764 from filecoin-project/deps/update-pubsub
update go-libp2p-pubsub to v0.5.0
2021-07-15 14:58:52 +02:00
aarshkshah1992 ed058ae193 update go mod 2021-07-15 18:21:35 +05:30
aarshkshah1992 ca5a2eaa74 update lotus soup and address nit 2021-07-15 18:08:41 +05:30
aarshkshah1992 35b39063ac add tests and merge master 2021-07-15 17:50:35 +05:30
vyzo 1d9dcef878 update go-libp2p-pubsub to v0.5.0 2021-07-15 15:07:14 +03:00
Łukasz Magiera 25cd577d06 Merge pull request #6762 from filecoin-project/feat/splitstore-exposed
Implement exposed splitstore
2021-07-15 13:11:45 +02:00
vyzo e003203bea implement exposed splitstore 2021-07-15 13:12:10 +03:00
aarshkshah1992 33c347956c rebased and fixed tests 2021-07-15 14:47:10 +05:30
Łukasz Magiera f07a370711 Merge pull request #6642 from hunjixin/feat/add_getmessagesints_api
Add ChainGetMessagesInTipset API
2021-07-15 11:12:51 +02:00
Łukasz Magiera a03c5ac3d2 Merge pull request #6758 from filecoin-project/test/deflake-fork-refuse-call
test: handle null blocks in TestForkRefuseCall
2021-07-15 11:01:15 +02:00
aarshkshah1992 a259ee307f resolve conflicts 2021-07-15 14:27:48 +05:30
aarshkshah1992 46b78406b1 replace badger in storage client 2021-07-15 14:26:02 +05:30
Łukasz Magiera ab2f159d54 Merge pull request #6757 from filecoin-project/jennijuju-patch-1
Master disclaimer
2021-07-15 10:37:55 +02:00
hunjixin d023026cb0 fix confilct 2021-07-15 14:55:03 +08:00
hunjixin b2f8b4011a fix imports 2021-07-15 14:52:12 +08:00
hunjixin 3e9ec01d04 rm fmt 2021-07-15 14:52:12 +08:00
hunjixin a48a6a168a add test for new api 2021-07-15 14:52:12 +08:00
hunjixin ac03c01e4a test for messages in tipset 2021-07-15 14:52:12 +08:00
hunjixin bdaa73a413 add ChainGetMessagesInTipset api 2021-07-15 14:52:09 +08:00
Steven Allen cf81c897df test: handle null blocks in TestForkRefuseCall
Otherwise, this fails on rare occasions.
2021-07-14 17:41:24 -07:00
Steven Allen 81d614a607 Merge pull request #6756 from filecoin-project/feat/splitstore-reorg
Splitstore code reorg
2021-07-14 16:57:11 -07:00
Jennifer 5e5b4b7191 Update README.md 2021-07-14 19:07:02 -04:00
Jennifer dd0f4dea81 Update README.md 2021-07-14 18:32:17 -04:00
Steven Allen c738d1f7ef Merge pull request #6747 from filecoin-project/action/stale
Create stale.yml
2021-07-14 13:50:38 -07:00
vyzo 5a23f64b3b code reorg: break splitstore.go into smaller logical units 2021-07-14 13:11:15 -07:00
Steven Allen 44d01712c8 Merge pull request #6754 from filecoin-project/feat/splitstore-refactor
Splitstore: Some small fixes
2021-07-14 13:09:59 -07:00
vyzo 3f3a12b75c remove BlockstoreMover interface
we decided it's premature
2021-07-14 22:59:53 +03:00
vyzo 023146803d use Broadcast for view barrier 2021-07-14 22:59:53 +03:00
vyzo 3d77ae1f4d make trackTxnRefMany consistent with trackTxnRef 2021-07-14 22:59:53 +03:00
vyzo 6f126c80bf remove redundant log, more descriptive error message for closing condition 2021-07-14 22:59:53 +03:00
vyzo ff093fae00 use a missing compactionIndex as an indicator for warmup
so that splitstore v0 nodes upgrading will get a fresh warmup.
2021-07-14 22:59:53 +03:00
vyzo 669b47cfc9 do moving gc for hotstore every 20 compactions
that's about once a week
2021-07-14 22:59:53 +03:00
vyzo 818b8de182 keep track of the compaction serial (index)
it is useful so that:
- we only do slow (but very effective) moving gc every 10 compactions
- we can detect a splitstore v0 upgrade and re-warm up
2021-07-14 22:59:53 +03:00
vyzo c93328b036 use the new traits for hotstore gc 2021-07-14 22:59:52 +03:00
vyzo 35180b4761 merge Compact and CollectGarbage in badger 2021-07-14 22:59:52 +03:00
vyzo dc81c0e6a2 add blockstore traits related to gc 2021-07-14 22:59:52 +03:00
Łukasz Magiera f0c9e4e8f2 Merge pull request #6746 from filecoin-project/chore/add_power_to_shed_storage-stats 2021-07-14 11:54:43 +02:00
Jennifer 71ddbdaf10 Update stale.yml 2021-07-14 02:52:39 -04:00
Jennifer 856cbb2ca0 Create stale.yml
Mark any issue thats labeled with `hint/needs-author-input` and has no activity more than 5 days as stale and give a 24 hours notice before closing.
2021-07-14 02:50:18 -04:00
Peter Rabbitson a37ababc20 Minor rearrange 2021-07-14 08:32:07 +02:00
Peter Rabbitson 677c193e6c Add current power to the stats 2021-07-14 08:11:23 +02:00
Łukasz Magiera dd09666399 Merge pull request #6743 from filecoin-project/chore/centralize_all_cli_color_handling
Handle the --color flag via proper global state
2021-07-13 17:34:25 +02:00
Łukasz Magiera 583a8a13d9 Merge pull request #6629 from filecoin-project/feat/pledge-from-miner-balance
Config for collateral from miner available balance
2021-07-13 17:22:00 +02:00
Łukasz Magiera 837322ea59 Merge pull request #6356 from filecoin-project/nonsense/split-market-miner-processes
Support standalone miner-market process
2021-07-13 17:16:07 +02:00
Łukasz Magiera 0678b3fa05 sealing: Cleanup DisableCollateralFallback handling 2021-07-13 17:06:41 +02:00
Łukasz Magiera 7526a074d9 sealing: collateral buffer / falback config 2021-07-13 17:04:58 +02:00
Anton Evangelatov 2af02af1c1 rename --name to --type; provide empty stores.StorageConfig when init new service 2021-07-13 12:57:43 +02:00
Łukasz Magiera c37401a1a3 Merge pull request #6474 from filecoin-project/feat/splitstore-redux
Splitstore Enhanchements
2021-07-13 12:43:57 +02:00
Peter Rabbitson 6efd2e7335 Handle the --color flag via proper global state
Use `color.NoColor` as a global progressively modified as one descends
down command flags. Allows non-surprising operation when --color is
accepted at multiple layers, and even makes this behave predictably:

    lotus-miner --color actor control list --color=false
2021-07-13 12:22:29 +02:00
vyzo af399529ec finetune view waiting 2021-07-13 09:06:40 +03:00
vyzo 257423e917 fix view waiting issues with the WaitGroup
We can add after Wait is called, which is problematic with WaitGroups.
This instead uses a mx/cond combo and waits while the count is > 0.
The only downside is that we might needlessly wait for (a bunch) of views
that started while the txn is active, but we can live with that.
2021-07-13 09:01:50 +03:00
Steven Allen 04abd190ab nit: remove useless goto
Because stebalien has allergies.
2021-07-12 21:46:50 -07:00
vyzo 60212c86cb put a mutex around HeadChange 2021-07-13 03:14:13 +03:00
vyzo 759594d01c always return the waitgroup in protectView
so that we preclude the following scenario:
    Start compaction.
    Start view.
    Finish compaction.
    Start compaction.

which would not wait for the view to complete.
2021-07-13 03:11:40 +03:00
raulk 5c3e79e8d0 Merge pull request #6739 from filecoin-project/fix/cancel-stops-retrieval 2021-07-12 23:22:35 +01:00
hannahhoward 92ec239202 fix(node): ClientRetrieve stops on cancel
When a deal is cancelled, any in progress calls to ClientRetrieve or ClientRetrieveWithEvents should
return
2021-07-12 14:46:18 -07:00
Łukasz Magiera 4433c3cd7c Merge pull request #6708 from filecoin-project/feat/miner-info-deals
Add more deal details to lotus-miner info
2021-07-12 22:18:56 +02:00
Anton Evangelatov 7728d6bfc3 remove --enable-markets flag; add --name string slice flag 2021-07-12 14:38:29 +02:00
Łukasz Magiera 83f2368507 Add CollateralFromMinerBalance config 2021-07-12 14:11:58 +02:00
Anton Evangelatov 4bc9fa04ba rename cfg.Subsystems.EnableStorageMarket to EnableMarkets 2021-07-12 12:12:29 +02:00
Anton Evangelatov 056136ef5a rename argument from url to apiInfo 2021-07-12 11:36:22 +02:00
Anton Evangelatov a423c46f2a rename mock.go to net.go 2021-07-12 11:35:03 +02:00
Anton Evangelatov d89ddb9315 resolve conflicts 2021-07-12 11:34:37 +02:00
Anton Evangelatov 16784aa2cc remove pieceProvider from DI; small refactors 2021-07-12 11:30:26 +02:00
Aayush Rajasekaran 88ac2ebc0c Merge pull request #6710 from filecoin-project/arajasek-patch-1
Release template: Update all testnet infra at once
2021-07-11 17:26:43 -04:00
Aayush Rajasekaran 13dcfec8fe Release template: Update all testnet infra at once 2021-07-11 17:26:21 -04:00
Aayush Rajasekaran 20582037c5 Fix Lotus shed 2021-07-11 14:03:22 -04:00
Aayush Rajasekaran e983d90a28 Merge pull request #6066 from chadwick2143/extend-v1-sectors
Fix bugs in sectors extend --v1-sectors
2021-07-11 13:19:35 -04:00
Aayush Rajasekaran ea9ad8c5a8 Update cmd/lotus-storage-miner/sectors.go 2021-07-11 13:01:19 -04:00
Aayush Rajasekaran 93d929a10a Merge pull request #5950 from zgfzgf/feat-shed-election-backtest
add election backtest
2021-07-11 12:08:21 -04:00
vyzo df9670c58d fix lint 2021-07-10 16:38:40 +03:00
vyzo 0c5e336ff1 address review comments 2021-07-10 16:30:27 +03:00
Aayush Rajasekaran f7f5fd4809 Merge pull request #6620 from filecoin-project/asr/no-filter
Envvar to disable slash filter
2021-07-09 17:12:16 -04:00
Aayush RajasekaranandPeter Rabbitson dff097a992 Update miner/miner.go
Co-authored-by: Peter Rabbitson <ribasushi@protocol.ai>
2021-07-09 17:07:23 -04:00
vyzo 870a47f55d handle id cids in internal versions of view/get 2021-07-09 20:07:17 +03:00
vyzo f5ae10e3d1 refactor debug log code to eliminate duplication 2021-07-09 19:53:51 +03:00
vyzo 41290383e2 fix test 2021-07-09 19:24:44 +03:00
vyzo b9a5ea8f7b update wording around discard store 2021-07-09 19:23:55 +03:00
vyzo c0a1cfffa1 rename noopstore to discardstore 2021-07-09 19:19:37 +03:00
vyzo 18161fee38 remove unused lookback constructs 2021-07-09 19:12:58 +03:00
vyzo 095d7427ba make view protection optimistic again, as there is a race window 2021-07-09 15:41:10 +03:00
vyzo da0feb3fa4 dont mark references inline; instad rely on the main compaction thread to do concurrent marking
The problem is that it is possible that an inline marking might take minutes for some objects
(infrequent, but still possible for state roots and prohibitive if that's a block validation).
So we simply track references continuously and rely on the main compaction thread to trigger
concurrent marking for all references at opportune moments.

Assumption: we can mark references faster than they are created during purge or else we'll
never purge anything.
2021-07-09 15:10:02 +03:00
vyzo acc4c374ef properly handle protecting long-running views 2021-07-09 13:20:18 +03:00
Dirk McCormick 872843e491 feat: integrate dag store into lotus 2021-07-09 10:59:10 +02:00
vyzo 565faff754 fix test 2021-07-09 11:38:09 +03:00
vyzo 4f89d260b0 kill isOldBlockHeader; it's dangerous. 2021-07-09 11:35:10 +03:00
vyzo de5e21bf1a correctly handle identity cids 2021-07-09 11:31:04 +03:00
vyzo 909f7039d4 make badger Close-safe 2021-07-09 09:54:12 +03:00
vyzo abdf4a161a explicitly switch marksets for concurrent marking
this has very noticeable impact in initial marking time; it also allows us
to get rid of the confusing ts monikers.
2021-07-09 04:26:36 +03:00
Łukasz Magiera 77a1a8a23f Merge pull request #6709 from filecoin-project/arajasek-patch-1
Release Template: remove binary validation step
2021-07-08 20:45:49 +02:00
Aayush Rajasekaran dbc721af3a Release Template: remove binary validation step 2021-07-08 14:45:24 -04:00
vyzo b6611125b6 add environment variables to turn on the debug log without recompiling 2021-07-08 21:30:39 +03:00
vyzo 60dd97c7fc fix potential deadlock in View
As pointed out by magik, it is possible to deadlock if the view callback performs
a blockstore operation while a Lock is pending.
This fixes the issue by optimistically tracking the reference before actually calling
the underlying View and limiting the scope of the lock.
2021-07-08 21:18:59 +03:00
Łukasz Magiera 44e81424f2 Print completed deal stats in miner info 2021-07-08 19:40:05 +02:00
Łukasz Magiera ed0cc0b56d Handle bad peerIDs in MarketListRetrievalDeals 2021-07-08 19:27:03 +02:00
Łukasz Magiera 10825e3a95 Add more info about deals to miner info 2021-07-08 19:02:18 +02:00
Łukasz Magiera 8f7bf1df86 Merge pull request #6697 from filecoin-project/feat/dealpublish-ctl-config
Config for deal publishing control addresses
2021-07-08 19:00:29 +02:00
Łukasz Magiera 79b0bfb272 policy: Add a docstring to SetProviderCollateralSupplyTarget 2021-07-08 18:56:03 +02:00
vyzoandŁukasz Magiera c0537848b3 fix typo
Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com>
2021-07-08 17:54:16 +03:00
vyzoandŁukasz Magiera fa30ac8c5d fix typo
Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com>
2021-07-08 17:53:59 +03:00
Łukasz Magiera 616fcb974c Merge pull request #6689 from filecoin-project/reset/interopnet
Reset of the interop network
2021-07-08 15:53:24 +02:00
vyzo 00d7772f57 move check for closure in walkChain
so that we don't do it too often and also cover warmup.
2021-07-08 13:12:19 +03:00
Łukasz Magiera e258e7c353 Merge pull request #6696 from filecoin-project/chore/even-less-color-on-cli
Enable color by default only if os.Stdout is a TTY
2021-07-08 12:05:10 +02:00
vyzo 5cf1e09e81 README: add instructions for how to enable 2021-07-08 13:00:31 +03:00
vyzo 9aa4f3b3b2 add README for documentation 2021-07-08 12:32:41 +03:00
Peter Rabbitson 4dd59b566c Respect GOLOG_LOG_FMT=color 2021-07-08 10:44:37 +02:00
Peter Rabbitson 140a2e0200 Stabilize default text and make gen docsgen-cli 2021-07-08 10:44:13 +02:00
vyzo e6eacbdd56 use RW mutexes in marksets 2021-07-08 10:20:29 +03:00
vyzo 48f13a43b7 intelligently close marksets and signal errors in concurrent operations 2021-07-08 10:18:43 +03:00
vyzo f5c45bd517 check the closing state variable often
so that we have a reasonably quick graceful shutdown
2021-07-08 10:13:44 +03:00
Łukasz Magiera 9bdea91a70 itests: Some kit cleanup 2021-07-07 21:40:44 +02:00
vyzo 4f808367f8 fix lint 2021-07-07 21:32:58 +03:00
vyzo fee50b13a2 check the closing state on each batch during the purge. 2021-07-07 21:32:05 +03:00
vyzo c6421f8a75 don't nil the mark sets on close, it's dangerous.
a concurrent marking can panic.
2021-07-07 21:27:36 +03:00
Łukasz Magiera d0e87a7487 dealpublisher: Fix provider address checks 2021-07-07 20:06:49 +02:00
Łukasz Magiera 2dc27d6ab4 itests: Fix deal provider collateral flakiness 2021-07-07 19:41:46 +02:00
Łukasz Magiera ee97aa0a8a dealpublisher: Use address selector 2021-07-07 19:12:03 +02:00
Peter Rabbitson c7bb326c78 Enable color by default only if os.Stdout is a TTY 2021-07-07 18:12:24 +02:00
Łukasz Magiera 8f5c0c60f5 Config for deal publishing control addresses 2021-07-07 18:00:54 +02:00
Anton Evangelatov 82efe01c70 fixup 2021-07-07 18:00:28 +02:00
Anton Evangelatov bb466ede66 fix cast on role_miner in testground lotus-soup plan 2021-07-07 16:04:01 +02:00
vyzo aec2ba2c82 nil map/bf on markset close 2021-07-07 16:46:14 +03:00
vyzo ec586a852a remove bbolt dependency from go.mod 2021-07-07 16:41:11 +03:00
vyzo 451ddf50ab RIP bbolt-backed markset 2021-07-07 16:39:37 +03:00
vyzo 9dbb2e0abd don't leak tracking errors through the API 2021-07-07 16:34:02 +03:00
Łukasz Magiera 49896afe9f Merge pull request #6694 from filecoin-project/chore/no-unexpected-color
Stop outputing ANSI color on non-TTY
2021-07-07 15:04:44 +02:00
Anton Evangelatov 1fe08f5973 refactor testkit in lotus-soup to include Subsystems when instantiating miner 2021-07-07 14:21:28 +02:00
Anton Evangelatov 6b014f57e5 pass Subsystems to StorageMiner option; add enableLibp2p bool in Settings 2021-07-07 13:56:37 +02:00
Anton Evangelatov caa366bc6a variadic WithSubsystems 2021-07-07 13:35:40 +02:00
Anton Evangelatov 42ae876711 remove ApplyIfEnableLibP2P 2021-07-07 13:31:56 +02:00
aarshkshah1992 a5ba556fff fix lint 2021-07-07 14:47:00 +05:30
aarshkshah1992 44d088be1e use filestore to create the Unixfs dag 2021-07-07 14:43:12 +05:30
Peter Rabbitson dcfbb1998f Stop outputing ANSI color on non-TTY
No more stuff like: https://circleci.com/gh/filecoin-project/lotus/189136
2021-07-07 11:06:20 +02:00
aarshkshah1992 b40985a57c Merge remote-tracking branch 'origin/nonsense/split-market-miner-processes' into feat/replace-multistore-carv2 2021-07-07 14:11:55 +05:30
aarshkshah1992 f8d32f5328 changes as per review 2021-07-07 14:10:59 +05:30
vyzo 83c30dc4c0 protect assignment of warmup epoch with the mutex 2021-07-07 11:31:27 +03:00
vyzo 6cc2112749 remove the curTs state variable; we don't need it 2021-07-07 09:55:25 +03:00
vyzo 05dbbe9681 rename som Txn methods for better readability 2021-07-07 09:52:31 +03:00
aarshkshah1992 ba236fe258 have a typed importID 2021-07-07 12:02:48 +05:30
aarshkshah1992 2b5164c956 Merge remote-tracking branch 'origin/feat/replace-multistore-carv2-rtrvl-pr' into feat/replace-multistore-carv2 2021-07-07 11:11:53 +05:30
aarshkshah1992 ca2d441b6d integrate dagstore 2021-07-07 11:11:29 +05:30
vyzo 90da6227b3 transactional protect incoming tipsets 2021-07-07 02:11:37 +03:00
vyzo 0e2af11f6a prepare the transaction before launching the compaction goroutine 2021-07-07 01:39:58 +03:00
Łukasz Magiera 88c578bc54 Merge pull request #6690 from filecoin-project/fix-gate-dollar
add dollar sign
2021-07-06 22:56:42 +02:00
Cory Schwartz f268068457 add dollar sign 2021-07-06 13:29:49 -07:00
Łukasz Magiera 251214dfd9 Merge pull request #6681 from jimpick/patch-1
get-actor cli spelling fix
2021-07-06 21:05:40 +02:00
Jim Pick a8ca7baa93 Run make docsgen-cli 2021-07-06 18:16:06 +00:00
Travis Person 9977a6d1d7 Add genesis for interop network 2021-07-06 17:06:55 +00:00
Travis Person 9d6d1f5715 Reset interop network 2021-07-06 17:06:55 +00:00
Anton Evangelatov 566a9d5541 fix signature 2021-07-06 18:12:30 +02:00
Łukasz Magiera 9f83da836d Merge pull request #6688 from turuslan/fix/seed-car
fix "lotus-seed genesis car" error "merkledag: not found"
2021-07-06 17:59:54 +02:00
Anton Evangelatov 2a7af38538 fix testServ to Start with correct listener 2021-07-06 17:57:08 +02:00
Anton Evangelatov 7a78527fde remove not used sa; cleanup 2021-07-06 17:46:21 +02:00
Anton Evangelatov b572c2b7bc fix IsUnsealed 2021-07-06 17:40:03 +02:00
Anton Evangelatov 10dc90f7fe addressing comments 2021-07-06 17:33:47 +02:00
Anton EvangelatovandŁukasz Magiera 898687ea2e Update node/modules/storageminer.go
Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com>
2021-07-06 17:28:52 +02:00
Anton EvangelatovandŁukasz Magiera 8cf3accc53 Update itests/kit/ensemble.go
Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com>
2021-07-06 17:25:33 +02:00
Anton EvangelatovandŁukasz Magiera 604be5fc82 Update extern/sector-storage/stores/remote.go
Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com>
2021-07-06 17:24:56 +02:00
Anton Evangelatov 51696bb35d fix SectorsStatus to query full node for on-chain data 2021-07-06 16:34:07 +02:00
vyzo f2f4af669d clean up: simplify debug log, get rid of ugly debug log 2021-07-06 17:13:38 +03:00
Anton Evangelatov ff2772a58c resolved conflicts 2021-07-06 16:00:41 +02:00
Anton Evangelatov 9839d5701b fix SectorsStatus to query full node for on-chain data 2021-07-06 15:41:14 +02:00
vyzo c1c25868cc improve comments 2021-07-06 15:09:04 +03:00
vyzo fdff1bebc9 move map markset implementation to its own file 2021-07-06 14:44:40 +03:00
vyzo 5c514504f7 remove unused GetGenesis method from ChainAccessor interface 2021-07-06 14:41:41 +03:00
vyzo dc8139a1d2 add some comments for debug only code 2021-07-06 13:23:12 +03:00
turuslan 8697edc8b7 fix "lotus-seed car" error "merkledag: not found" 2021-07-06 12:54:09 +03:00
Dirk McCormick bed4c03a50 feat: integrate go-fil-markets#560 2021-07-06 11:09:05 +02:00
aarshkshah1992 e041fe130b tests for storage client import impls 2021-07-06 12:40:57 +05:30
vyzo c4ae3e0c3d minor tweak 2021-07-06 09:17:35 +03:00
vyzo 169ab262f5 really optimize computing object weights
sort is still taking a long time, this should be as fast as it gets.
2021-07-06 09:02:44 +03:00
vyzo 55a9e0ccd1 short-circuit block headers on sort weight computation 2021-07-06 08:22:43 +03:00
vyzo bf7aeb3167 optimize sort a tad
it's taking a long time to compute weights...
2021-07-06 08:10:57 +03:00
vyzo 0659235e21 cache cid strings in sort
so as to avoid making a gazillion of strings
2021-07-06 07:26:13 +03:00
aarshkshah1992 a07a0935fe fix bug in CAR generation 2021-07-06 09:31:52 +05:30
vyzo 525a2c71dd use hashes as keys in weight map to avoid duplicate work
otherwise the root object will be raw, but internal references will be dag; duplicate work.
2021-07-06 01:27:56 +03:00
vyzo c6ad8fdaed use walkObjectRaw for computing object weights
cids that come out of the hotstore with ForEach are raw.
2021-07-06 01:08:44 +03:00
vyzo 2cbd3faf5a make sure to nil everything in txnEndProtect 2021-07-05 23:56:31 +03:00
vyzo 51ab891d5c quiet linter
it's a false positive, function doesn't escape.
2021-07-05 23:53:45 +03:00
vyzo bd436ab9de make endTxnProtect idempotent 2021-07-05 23:51:10 +03:00
vyzo e859942fa4 code cleanup: refactor txn state code into their own functions 2021-07-05 23:31:37 +03:00
vyzo 3477d265c6 unify the two marksets
really, it's concurrent marking and there is no reason to have two different marksets
2021-07-05 20:10:47 +03:00
Łukasz Magiera 97207df705 Merge pull request #6639 from filecoin-project/frrist/context-in-statetree-diff
polish(statetree): accept a context in statetree diff for timeouts
2021-07-05 17:30:31 +02:00
vyzo 73d07999bf dont needlessly wait 1 min in first retry for missing refs 2021-07-05 18:24:48 +03:00
vyzo af8cf712be handle all missing refs together
so that we wait 6min at most, not 12.
2021-07-05 18:16:54 +03:00
Jim Pick 17c0b9be44 Spelling fix
Change 'actorr' to 'actor'
2021-07-05 07:44:06 -07:00
Łukasz Magiera d76cbf805a Merge pull request #6672 from filecoin-project/asr/nit
Add helptext to lotus chain export
2021-07-05 16:22:16 +02:00
Łukasz Magiera 5e5de9b41b Merge pull request #6679 from filecoin-project/fix/get-retrieval-pricing-input-error
Get retrieval pricing input should not error out on a deal state fetch
2021-07-05 16:18:48 +02:00
Łukasz Magiera a56b6fea99 Merge pull request #6680 from filecoin-project/chore/double-encoded-cid
Fix more CID double-encoding as hex
2021-07-05 16:14:52 +02:00
vyzo 5a099b7d05 more commentary on the missing refs situation 2021-07-05 16:12:17 +03:00
vyzo 59639a0788 reinstate some better code for handling missing references. 2021-07-05 16:08:08 +03:00
Anton Evangelatov 5a87f04e71 fix finalize sectors early test 2021-07-05 13:36:23 +02:00
vyzo fa195bede2 get rid of ugly missing reference handling code
those missing objects don't seem to ever get there, are they from an abandoned fork?
2021-07-05 14:29:55 +03:00
Anton Evangelatov 4be0a7a215 resolve conflicts with master 2021-07-05 13:13:32 +02:00
Peter Rabbitson a544fa0f97 Fix more CID doucle-encoding as hex 2021-07-05 12:51:15 +02:00
aarshkshah1992 add113f585 use multierror 2021-07-05 16:08:51 +05:30
vyzo 59936ef468 fix log 2021-07-05 13:30:31 +03:00
aarshkshah1992 44985722d2 changes as per review 2021-07-05 15:53:41 +05:30
vyzo 0b7153be86 use internal version of has for occurs checks 2021-07-05 12:41:11 +03:00
vyzo d8b8d75e0f readd minute delay before trying for missing objects 2021-07-05 12:38:09 +03:00
vyzo d7709deb2b reduce memory pressure from marksets when the size is decreased 2021-07-05 11:51:22 +03:00
vyzo 3ec834b2e3 improve logs and error messages 2021-07-05 11:41:09 +03:00
vyzo 918a7ec749 a bit more fil commitment short-circuiting 2021-07-05 11:38:53 +03:00
vyzo 2ea2abc07d short-circuit fil commitments
they don't make it to the blockstore anyway
2021-07-05 11:32:52 +03:00
vyzo 839f7bd2b5 only occur check for DAGs 2021-07-05 11:11:08 +03:00
vyzo c81ae5fc20 add some comments about the missing business and anothre log 2021-07-05 10:42:14 +03:00
vyzo 4c41f52828 add warning for missing objects for marking for debug purposes 2021-07-05 10:35:04 +03:00
vyzo 3597192d58 remove the sleeps and busy loop more times when waiting for missing objects 2021-07-05 10:31:47 +03:00
vyzo 1726eb993c deal with incomplete objects that need to be marked and protected
seems that something is writing DAGs before its consituents, which causes problems.
2021-07-05 10:22:52 +03:00
aarshkshah1992 8ecdc929b4 get retrieval pricing input should not error out on a deal state fetch 2021-07-05 09:34:56 +05:30
vyzo db53859e7a reduce CompactionThreshold to 5 finalities
so that we run compaction every finality, once we've first compacted
2021-07-04 22:12:51 +03:00
vyzo b08e0b7102 fix lint 2021-07-04 21:24:15 +03:00
vyzo 94efae419e reduce length of critical section
Just the purge; the rest is not critical -- e.g. it's ok if we do some duplicate copies
to the coldstore, we'll have gc soon.
2021-07-04 21:21:53 +03:00
vyzo f33d4e79aa simplify transactional protection logic
Now that we delete objects heaviest first, we don't have to do deep walk and rescan gymnastics.
2021-07-04 20:49:39 +03:00
vyzo 40c271cda1 sort cold objects before deleting
so that we can't shoot ourselves in the foot by deleting the constituents of a DAG while it is
still in the hotstore.
2021-07-04 20:17:07 +03:00
vyzo 13d612f72f smarter trackTxnRefMany 2021-07-04 19:33:49 +03:00
vyzo f124389b66 recursively protect all references 2021-07-04 19:21:00 +03:00
vyzo 4d286da593 fix error message 2021-07-04 18:58:39 +03:00
vyzo 680af8eb09 use deep object walking for more robust handling of transactional references 2021-07-04 18:38:28 +03:00
vyzo 1f02428225 fix lint 2021-07-04 18:38:28 +03:00
vyzo 2c7a89a1db short-circuit rescanning on block headers 2021-07-04 18:38:28 +03:00
vyzo 028a5c4942 make test do something useful again 2021-07-04 18:38:28 +03:00
vyzo 8e56fffb33 walkChain should visit the genesis state root 2021-07-04 18:38:28 +03:00
vyzo 95c3aaec9a fix test 2021-07-04 18:38:28 +03:00
vyzo 190cb18ab0 housekeeping
- remove defunct tracking store implementations
- update splitstore node config
- use mark set type config option (defaulting to mapts); a memory constrained node
  may want to use an on-disk one
2021-07-04 18:38:28 +03:00
vyzo 19d1b1f532 deal with partially written objects 2021-07-04 18:38:28 +03:00
vyzo 0a1d7b3732 fix log 2021-07-04 18:38:28 +03:00
vyzo 08cad30be2 reuse key buffer in badger ForEachKey
cid copies the bytes so it's safe
2021-07-04 18:38:28 +03:00
vyzo eafffc1634 more efficient trackTxnRefMany 2021-07-04 18:38:28 +03:00
vyzo 36f93649ef fix panic from concurrent map writes in txnRefs 2021-07-04 18:38:28 +03:00
vyzo 6fa2cd232d simplify compaction model 2021-07-04 18:38:28 +03:00
vyzo 5f7ae1f489 update splistore DI constructor 2021-07-04 18:38:28 +03:00
vyzo 1f2b604c07 RIP tracking store 2021-07-04 18:38:28 +03:00
vyzo d476a3db2c BlockstoreIterator trait with implementation for badger 2021-07-04 18:38:28 +03:00
vyzo 68a83500bc fix bug that turned candidate filtering to dead code 2021-07-04 18:38:28 +03:00
vyzo 00fcf6dd72 add staging cache to bolt tracking store 2021-07-04 18:38:28 +03:00
vyzo 642f0e4740 deal with memory pressure, don't walk under the boundary 2021-07-04 18:38:28 +03:00
vyzo c5cf8e226b remove unnecessary code 2021-07-04 18:38:28 +03:00
vyzo d79e4da7aa more accurate stats about mark set updates 2021-07-04 18:38:28 +03:00
vyzo 6f58fdcb22 remove vm copy context detection hack
stack tracing is slow.
2021-07-04 18:38:28 +03:00
vyzo 2b03316cd9 fix log message 2021-07-04 18:38:28 +03:00
vyzo 184d3802b6 remove dead code 2021-07-04 18:38:28 +03:00
vyzo 228a435ba7 rework tracking logic; do it lazily and far more efficiently 2021-07-04 18:38:28 +03:00
vyzo 9d6cabd18a if it's not a dag, it's not a block 2021-07-04 18:38:28 +03:00
vyzo 8157f889ce short-circuit marking walks when encountering a block and more efficient walking 2021-07-04 18:38:28 +03:00
vyzo 736d6a3c19 only treat Has as an implicit write within vm.Copy context 2021-07-04 18:38:28 +03:00
vyzo 39723bbe60 use a single map for tracking pending writes, properly track implicits 2021-07-04 18:38:28 +03:00
vyzo 5834231e58 create the transactional protect filter before walking 2021-07-04 18:38:28 +03:00
vyzo e4bb4be855 fix some residual purge races 2021-07-04 18:38:28 +03:00
vyzo 68bc5d2291 skip moving cold blocks when running with a noop coldstore
it is a noop but it still takes (a lot of) time because it has to read all the cold blocks.
2021-07-04 18:38:28 +03:00
vyzo b87295db93 bubble up dependent txn ref errors
This cause Has to return false if it fails to traverse/protect all links, which would cause
the vm to recompute.
2021-07-04 18:38:28 +03:00
vyzo 637fbf6c5b fix faulty if/else logic for implicit txn protection 2021-07-04 18:38:28 +03:00
vyzo 9d6bcd7705 avoid clown shoes: only walk links for tracking in implicit writes/refs 2021-07-04 18:38:28 +03:00
vyzo 484dfaebce reused cidset across all walks when flushing pending writes 2021-07-04 18:38:28 +03:00
vyzo 1d41e1544a optimize transitive write tracking a bit 2021-07-04 18:38:28 +03:00
vyzo da00fc66ee downgrade a couple of logs to warnings 2021-07-04 18:38:28 +03:00
vyzo 4071488ef2 first write, then track 2021-07-04 18:38:28 +03:00
vyzo bd92c230da refactor txn reference tracking, do deep marking of DAGs 2021-07-04 18:38:28 +03:00
vyzo a98a062347 do the dag walk for deep write tracking during flush
avoid crawling everything to a halt
2021-07-04 18:38:28 +03:00
vyzo 13a674330f add pending write check before tracking the object in Has 2021-07-04 18:38:28 +03:00
vyzo 982867317e transitively track dags from implicit writes in Has 2021-07-04 18:38:28 +03:00
vyzo 4de0cd9fcb move write log back to flush so that we don't crawl to a halt 2021-07-04 18:38:28 +03:00
vyzo b3ddaa5f02 fix panic at startup
genesis is written (!) before starting the splitstore, so curTs is nil
2021-07-04 18:38:28 +03:00
vyzo 2faa4aa993 debug log writes at track so that we get correct stack traces 2021-07-04 18:38:28 +03:00
vyzo aeaa59d4b5 move comments about tracking perf issues into a more pertinent place 2021-07-04 18:38:28 +03:00
vyzo 3e8e9273ca track all writes using async batching, not just implicit ones 2021-07-04 18:38:28 +03:00
vyzo d0bfe421b5 flush implicit writes at the right time before starting compaction to avoid races 2021-07-04 18:38:28 +03:00
vyzo 7f473f56eb flush implicit writes before starting compaction 2021-07-04 18:38:28 +03:00
vyzo a29947d47c flush implicit writes in all paths in updateWriteEpoch 2021-07-04 18:38:28 +03:00
vyzo be6cc2c3e6 batch implicit write tracking
bolt performance leaves something to be desired; doing a single Put takes 10ms, about the same time
as batching thousands of them.
2021-07-04 18:38:28 +03:00
vyzo e472cacb3e add missing return 2021-07-04 18:38:28 +03:00
vyzo 6a3cbea790 treat Has as an implicit Write
Rationale: the VM uses the Has check to avoid issuing a duplicate Write in the blockstore.
This means that live objects that would be otherwise written are not actually written, resulting
in the first write epoch being considered the write epoch.
2021-07-04 18:38:28 +03:00
vyzo f97535d87e store the hash in map markset 2021-07-04 18:38:28 +03:00
vyzo 90dc274113 better logging for chain walk 2021-07-04 18:38:28 +03:00
vyzo 40f42db7fa walk tweaks 2021-07-04 18:38:28 +03:00
vyzo 09efed50fd check for lookback references to block headers in walk 2021-07-04 18:38:28 +03:00
vyzo 7de0771883 count txn live objects explicitly for logging 2021-07-04 18:38:28 +03:00
vyzo e29b64c5de check both markset and txn liveset before declaring an object cold 2021-07-04 18:38:28 +03:00
vyzo 4bed3161f0 fix broken purge count log 2021-07-04 18:38:28 +03:00
vyzo 7307eb54dc cache stack repr computation 2021-07-04 18:38:28 +03:00
vyzo 57e25ae1cd use succint timetamp in debug logs 2021-07-04 18:38:28 +03:00
vyzo b2b13bbe89 fix debug panic 2021-07-04 18:38:28 +03:00
vyzo 0b315e97c8 fix index out of range 2021-07-04 18:38:28 +03:00
vyzo dec61fa333 deduplicate stack logs and optionally trace write stacks 2021-07-04 18:38:28 +03:00
vyzo 7ebef6d838 better log message 2021-07-04 18:38:28 +03:00
vyzo 40ff5bf164 log put errors in splitstore log 2021-07-04 18:38:28 +03:00
vyzo 9fda61abec fix error check for unreachable cids 2021-07-04 18:38:28 +03:00
vyzo 4a71c68e06 move code around for better readability 2021-07-04 18:38:28 +03:00
vyzo 31497f4bd3 use internal get during walk to avoid blowing the compaction txn
otherwise the walk itself precludes purge... duh!
2021-07-04 18:38:28 +03:00
vyzo 6af3a23dd4 use a map for txn protection mark set 2021-07-04 18:38:28 +03:00
vyzo 65ccc99e79 minor tweaks in purge
- allocate once
- log purge count
2021-07-04 18:38:28 +03:00
vyzo cb665d07e0 fix transactional race during compaction
It is possible for an object to be written or recreated (and checked with Has)
after the mark completes and during the purge; if this happens we will purge
a live block.
2021-07-04 18:38:28 +03:00
vyzo 649b7dd162 add config option for hot headers 2021-07-04 18:38:28 +03:00
vyzo 50ebaf25aa don't log read misses before warmup 2021-07-04 18:38:28 +03:00
vyzo 375a1790e7 reset counters after flush 2021-07-04 18:38:28 +03:00
vyzo b187b5c301 fix lint 2021-07-04 18:38:28 +03:00
vyzo a53c4e1597 implement debug log 2021-07-04 18:38:28 +03:00
vyzo fce7b8dc9b flush move log when cold collection is done 2021-07-04 18:38:28 +03:00
vyzo fc247e4223 add debug log skeleton 2021-07-04 18:38:28 +03:00
vyzo 0390285c4e always do full walks, not only when there is a sync gap 2021-07-04 18:38:28 +03:00
vyzo 30dbe4978b adjust compaction range 2021-07-04 18:38:28 +03:00
vyzo a21f55919b CompactionThreshold should be 4 finalities
otherwise we'll wear clown shoes with the slack and end up in continuous compaction.
2021-07-04 18:38:28 +03:00
vyzo 79d21489df fix test 2021-07-04 18:38:28 +03:00
vyzo a25ac80777 reintroduce compaction slack 2021-07-04 18:38:28 +03:00
vyzo a178c1fb93 fix test 2021-07-04 18:38:28 +03:00
vyzo c4d95de987 coalesce back-to-back compactions
get rid of the CompactionCold construct, run a single compaction on catch up
2021-07-04 18:38:28 +03:00
vyzo b7897595eb augment current epoch by +1
to account for off by one conditions
2021-07-04 18:38:28 +03:00
vyzo 933c786421 update write epoch in the background every second 2021-07-04 18:38:28 +03:00
vyzo 66f1630f14 fix lint issue 2021-07-04 18:38:28 +03:00
vyzo bb17608ae0 track writeEpoch relative to current wall clock time
The issue: head change notifications are not emitted until after catching up,
which results in all writes during a catch up period being tracked at the base epoch.
2021-07-04 18:38:28 +03:00
vyzo 421f05eab9 save the warm up epoch only if successful in warming up 2021-07-04 18:38:28 +03:00
vyzo 9b6448518c refactor warmup to trigger at startup and not wait for sync 2021-07-04 18:38:28 +03:00
vyzo 3fe4261f12 don't attempt compaction while still syncing 2021-07-04 18:38:28 +03:00
vyzo 7b02673620 don't try to visit genesis parent blocks 2021-07-04 18:38:28 +03:00
vyzo 997f2c098b keep headers hot when running with a noop splitstore 2021-07-04 18:38:28 +03:00
vyzo 7c814cd2e3 refactor genesis state loading code into its own method 2021-07-04 18:38:28 +03:00
vyzo 41573f1fb2 also walk parent message receipts when including messages in the walk 2021-07-04 18:38:28 +03:00
vyzo fa6481401d reduce SyncGapTime to 1 minute
for maximal safety.
2021-07-04 18:38:28 +03:00
vyzo fda291b876 fix test 2021-07-04 18:38:28 +03:00
vyzo d33a44e67f first visit the cid, then short-circuit non dagcbor objects 2021-07-04 18:38:28 +03:00
vyzo bdb97d6186 more robust handling of sync gap walks 2021-07-04 18:38:28 +03:00
vyzo 7cf75e667d keep genesis-linked state hot 2021-07-04 18:38:28 +03:00
vyzo e9f531b4aa don't open bolt tracking store with NoSync, it might get corrupted 2021-07-04 18:38:28 +03:00
Raúl Kripalani b2b7eb2ded metrics: increment misses in View(). 2021-07-04 18:38:28 +03:00
vyzo 3a9b7c592d mark from current epoch to boundary epoch when necessary
this is necessary to avoid wearing clown shoes when the node stays
offline for an extended period of time (more than 1 finality).

Basically it gets quite slow if we do the full 2 finality walk, so we
try to avoid it unless necessary.
The conditions under which a full walk is necessary is if there is a
sync gap (most likely because the node was offline) during which the
tracking of writes is inaccurate because we have not yet delivered the
HeadChange notification.  In this case, it is possible to have
actually hot blocks to be tracked before the boundary and fail to mark
them accordingly.  So when we detect a sync gap, we do the full walk;
if there is no sync gap, we can just use the much faster boundary
epoch walk.
2021-07-04 18:38:28 +03:00
vyzo d7ceef104e decrease CompactionThreshold to 3 finalities 2021-07-04 18:38:28 +03:00
vyzo e3cbeec6ee implement chain walking 2021-07-04 18:38:28 +03:00
vyzo 04f2e102a1 kill full splitstore compaction, simplify splitstore configuration 2021-07-04 18:38:28 +03:00
vyzo 5cca29d1db hook noop blockstore for splitstore in DI 2021-07-04 18:38:28 +03:00
vyzo 4d3c73f4ca noop blockstore 2021-07-04 18:38:28 +03:00
Łukasz Magiera a577bf340e Merge pull request #6675 from filecoin-project/chore/remove_vestigial_replace
Remove leftover from the great de-submoduling
2021-07-04 12:11:54 +02:00
Peter Rabbitson 5c643d6141 Remove leftover from the great de-submoduling
This is no longer used anywhere in lotus
2021-07-04 09:40:47 +02:00
Aayush Rajasekaran 069fd0a244 Add helptext to lotus chain export 2021-07-03 12:41:43 -04:00
aarshkshah1992 de13b6edc5 dont upgrade multihash 2021-07-03 14:26:03 +05:30
aarshkshah1992 303d5d6ff6 removed combined blockstore 2021-07-03 14:12:08 +05:30
aarshkshah1992 40b30d1fb1 remove multistore from Lotus 2021-07-03 14:12:08 +05:30
aarshkshah1992 dae6c757b5 lotus changes for the DAG Store 2021-07-03 14:12:08 +05:30
aarshkshah1992 31ecce3a72 draft lotus storage client CARv2 changes 2021-07-03 14:12:08 +05:30
Łukasz Magiera 13d4563c25 Merge pull request #6663 from filecoin-project/raulk/test-incremental-nonce
add an incremental nonce itest.
2021-07-02 23:33:52 +02:00
Łukasz Magiera e2f48b21ab Merge pull request #6653 from filecoin-project/fix/finalize-in-storage
storage: Fix FinalizeSector with sectors in stoage paths
2021-07-02 20:38:25 +02:00
Łukasz Magiera 8a94ab676e storage: Fix FinalizeSector with sectors in stoage paths 2021-07-02 19:54:45 +02:00
Łukasz Magiera bcb839a7d3 Merge pull request #6664 from filecoin-project/chore/fix_check-client-datacap
Fix tiny error in check-client-datacap
2021-07-02 18:24:18 +02:00
Peter Rabbitson 30efcf21f0 Fix tiny error in check-client-datacap 2021-07-02 18:15:08 +02:00
Raúl Kripalani ca40234031 update circleci config. 2021-07-02 17:04:57 +01:00
Raúl Kripalani 592b8c4f4a add an incremental nonce itest. 2021-07-02 17:04:13 +01:00
Łukasz Magiera 35c0e3cf8c Merge pull request #6658 from sunday527/master
Fix: precommit_batch method used the wrong cfg.CommitBatchWait
2021-07-02 15:18:48 +02:00
Łukasz Magiera 60ecbdee8f Merge pull request #6635 from llifezou/fix_checkTicketExpired
fix ticket expiration check
2021-07-02 15:18:04 +02:00
Anton Evangelatov adba1a792a add missing err check 2021-07-02 15:15:16 +02:00
Anton Evangelatov e9d0a25436 remove redundant flag from docs 2021-07-02 15:11:57 +02:00
Anton Evangelatov ab6e01e379 remove --enable-markets flag, read from repo 2021-07-02 15:08:25 +02:00
Anton Evangelatov 724f728f60 enable more tests 2021-07-02 14:54:09 +02:00
Anton Evangelatov 8dbae00847 fix lotus-soup 2021-07-02 12:45:56 +02:00
Anton Evangelatov 287e06995a missing flag, that will need to be refactored 2021-07-02 12:41:28 +02:00
Anton Evangelatov 9e85492b85 fix test 2021-07-02 12:24:07 +02:00
Anton Evangelatov 96245c3cfa lint 2021-07-02 12:02:36 +02:00
Anton Evangelatov 4194c7fa24 revert back optional for Miner; remove ActorAddress call in node.MinerHandler 2021-07-02 11:58:31 +02:00
zhoutian527 71e1577a62 Fix: precommit_batch method used the wrong cfg.PreCommitBatchWait 2021-07-02 15:53:21 +08:00
llifezouandŁukasz Magiera df53b97fe4 Update extern/storage-sealing/states_sealing.go
fix sector precommitted but expired judgment

Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com>
2021-07-02 11:44:46 +08:00
llifezouandAayush Rajasekaran fe3ad4fd60 Update extern/storage-sealing/states_sealing.go
fix log

Co-authored-by: Aayush Rajasekaran <arajasek94@gmail.com>
2021-07-02 11:38:04 +08:00
Łukasz Magiera 20c8250872 Merge pull request #6650 from filecoin-project/feat/agg-balancer-config
commit batch: AggregateAboveBaseFee config
2021-07-01 18:36:12 +02:00
Raúl Kripalani 1869de7662 unwire host from storage.Miner. 2021-07-01 13:53:20 +01:00
Łukasz Magiera 7c2c8b2a95 commit batch: Regression test nil FailedSectors map 2021-07-01 13:51:11 +02:00
Łukasz Magiera c094aa82ec commit batch: AggregateAboveBaseFee config 2021-07-01 13:33:54 +02:00
Łukasz Magiera 98a4be475c Merge pull request #6647 from filecoin-project/fix/nil-failedsectors-map
commit batch: Initialize the FailedSectors map
2021-07-01 12:40:15 +02:00
Łukasz Magiera 88bb9f422e commit batch: Initialize the FailedSectors map 2021-07-01 12:15:58 +02:00
llifezou 73e58f7af1 fix getTicket: sector precommitted but expired case 2021-07-01 10:53:42 +08:00
frrist d02a2a2cfa polish(statetree): accept a context in statetree diff for timeouts
- this operation can take a while, this changes gives users the option
to abort if it takes "too long".
2021-06-30 16:40:43 -07:00
Aayush RajasekaranandŁukasz Magiera 3091e2a771 Update miner/miner.go
Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com>
2021-06-30 12:15:43 -04:00
Anton Evangelatov 3aa6d03cc1 connect miner to full node , only when running markets 2021-06-30 16:45:11 +02:00
Łukasz Magiera 6a5b94ca3b Merge pull request #6638 from filecoin-project/feat/fastpath-aggsubmit-retry
Fast-path retry submitting commit aggregate if commit is still valid
2021-06-30 16:39:36 +02:00
johnli-helloworld 229d5e5c80 handleSubmitCommitAggregate() exception handling 2021-06-30 15:29:21 +02:00
Łukasz Magiera 2dad06d59f Merge pull request #6634 from GFZRZK/GFZRZK/correct_check_commit
remove precommit check in handleCommitFailed
2021-06-30 15:23:33 +02:00
Łukasz Magiera f45340461d gofmt 2021-06-30 15:19:29 +02:00
Łukasz Magiera 19a536d869 Merge pull request #6636 from johnli-helloworld/fix/batchwait
Reuse timers in sealing batch logic
2021-06-30 14:42:51 +02:00
Anton Evangelatov 4f0a96c9c7 resolved conflicts 2021-06-30 13:16:52 +02:00
Anton Evangelatov 9ec7cd7239 enable libp2p options 2021-06-30 12:55:43 +02:00
Łukasz Magiera ed2d7964ad Merge pull request #6631 from filecoin-project/feat/shed-agg-fees
shed tool to estimate aggregate network fees
2021-06-30 11:13:19 +02:00
johnli-helloworld b0b070ffe7 to optimize the batchwait 2021-06-30 16:56:40 +08:00
llifezou 3dd3476bfd fix ticket expiration check, otherwise it may cause a large number of loops to retry GetTicket when retrying PreCommit1 2021-06-30 16:32:44 +08:00
wangchao a4342f3997 remove precommit check in handleCommitFailed 2021-06-30 11:09:07 +08:00
Łukasz Magiera 022d4b548a shed tool to estimate aggregate network fees 2021-06-29 20:42:26 +02:00
Łukasz Magiera 49de60d33b Merge pull request #6625 from filecoin-project/firesWu-fix/prove-commit-aggregate
fix prove commit aggregate send token amount
2021-06-29 12:45:08 +02:00
Łukasz Magiera 7b1b082381 Merge branch 'master' into fix/prove-commit-aggregate 2021-06-29 11:48:52 +02:00
Łukasz Magiera 7d4887b1f1 Merge pull request #6621 from filecoin-project/arajasek-patch-1
Update version.go to 1.11.1
2021-06-29 11:31:22 +02:00
Łukasz Magiera df86efbd43 docsgen 2021-06-29 11:27:06 +02:00
Jerry 73704c92ba ensure agg fee is adequate 2021-06-29 14:36:26 +08:00
Jerry 5c3d67a811 fix: miner balance is not enough, so that ProveCommitAggregate msg exec failed 2021-06-29 14:06:41 +08:00
Aayush Rajasekaran 07487b6d20 Update version.go 2021-06-28 22:43:14 -04:00
Aayush Rajasekaran b8866f1d16 Envvar to disable slash filter 2021-06-28 22:00:21 -04:00
Anton Evangelatov a8d5ae5213 enable more tests 2021-06-23 13:39:03 +02:00
Anton Evangelatov 4217ec5308 make auth on remote rpc server optional 2021-06-23 13:27:03 +02:00
Anton Evangelatov 21b51328f9 adding TestDealWithMarketAndMinerNode 2021-06-23 12:44:52 +02:00
Anton Evangelatov 99646d209e fix TestFirstDealEnablesMining 2021-06-23 11:56:09 +02:00
Anton Evangelatov 7fb93d4585 refactor kit.NewDealHarness to include main miner and market node 2021-06-23 11:24:55 +02:00
Anton Evangelatov 51a4657ef7 fix SDR test 2021-06-23 11:19:25 +02:00
Anton Evangelatov d98eca7260 Merge branch 'raulk/itests-refactor-kit' into nonsense/split-market-miner-processes 2021-06-23 10:58:37 +02:00
Anton Evangelatov fc7feffaad Merge branch 'raulk/itests-refactor-kit' into nonsense/split-market-miner-processes 2021-06-22 17:37:50 +02:00
Anton Evangelatov aa584475cc fix paych and sdr tests 2021-06-22 16:48:07 +02:00
Anton Evangelatov 218c9199f3 fix testNonGenesisMiner 2021-06-22 15:51:50 +02:00
Anton Evangelatov 4f2d8b0a85 add all subsystems to deadlines and wdpost_dispute tests 2021-06-22 15:35:46 +02:00
Anton Evangelatov a828b15fbe revert MockSectorMgr 2021-06-22 15:22:08 +02:00
Anton Evangelatov 9567807144 Merge branch 'raulk/itests-refactor-kit' into nonsense/split-market-miner-processes 2021-06-22 14:39:28 +02:00
Anton Evangelatov e656aad298 regenerate docs 2021-06-22 13:36:24 +02:00
Anton Evangelatov b0d1668ab9 comment out preseal sectors 2021-06-22 13:34:45 +02:00
Anton Evangelatov 00618672f5 policy.SetPreCommitChallengeDelay to reduce WaitSeed stage time 2021-06-22 13:08:36 +02:00
Anton Evangelatov 5e10d53ca8 wip 2021-06-22 12:16:21 +02:00
Anton Evangelatov 6720463799 resolve merge conflicts 2021-06-22 11:28:23 +02:00
Anton Evangelatov 577b730415 wip 2021-06-18 18:42:34 +02:00
Anton Evangelatov 89df3cc207 Merge branch 'raulk/itests-refactor-kit' into nonsense/split-market-miner-processes 2021-06-18 12:07:15 +02:00
Anton Evangelatov 338bd042b9 Merge branch 'raulk/itests-refactor-kit' into nonsense/split-market-miner-processes 2021-06-17 18:12:48 +02:00
Anton Evangelatov d45bb14015 Merge branch 'master' into nonsense/split-market-miner-processes 2021-06-16 18:49:15 +02:00
Anton Evangelatov 323c78ef44 comment for checkV1ApiSupport 2021-06-15 14:47:11 +02:00
Anton Evangelatov 090a16316c bump miner version apiv0 2021-06-15 13:59:51 +02:00
Anton Evangelatov c0feb36e70 add missing debug 2021-06-14 11:31:55 +02:00
Anton Evangelatov 31e6fb154e resolve conflicts 2021-06-14 11:27:54 +02:00
Anton Evangelatov beb5bffaf6 fix log.Error; rename RemoteStore 2021-06-09 13:05:54 +02:00
Anton Evangelatov 9ab84bdc0a upgrade docsgen 2021-06-08 15:59:37 +02:00
Anton Evangelatov 30ba9a2751 remove double http handler decl 2021-06-08 15:36:54 +02:00
Anton Evangelatov 3f5f96dcbd go mod tidy 2021-06-08 14:58:20 +02:00
Anton Evangelatov 4dd093b160 fix piece provider test 2021-06-08 14:57:45 +02:00
Anton Evangelatov c0607a0e2a Merge branch 'master' into nonsense/split-market-miner-processes 2021-06-08 14:54:59 +02:00
Anton Evangelatov 9f3ec82cc1 initial resolution of conflicts 2021-06-08 13:01:22 +02:00
Anton Evangelatov de646a5b93 fix node builder 2021-06-07 12:16:10 +02:00
Anton Evangelatov b0cb0c1a4a do not depend on filecoin-ffi in api package 2021-06-07 11:51:25 +02:00
Anton Evangelatov 042ac8240f testplans: lotus-soup: new images with filecoin-ffi ; use default WPoStChallengeWindow 2021-06-07 11:38:23 +02:00
Anton Evangelatov ded5341da0 fixup test node builder 2021-06-04 17:22:36 +02:00
Anton Evangelatov ed634bc3a4 rebuild docs 2021-06-04 17:06:55 +02:00
Anton Evangelatov c4d10bc44e apply messagepool.NewProviderLite to lite nodes 2021-06-04 16:51:07 +02:00
Anton Evangelatov 6f125cc129 add prover to fullnode and miner builders 2021-06-04 16:26:32 +02:00
Anton Evangelatov d9a7348ae1 use masters filecoin-ffi 2021-06-04 16:20:40 +02:00
Anton Evangelatov 8bd09e39ca resolve merge conflicts 2021-06-04 16:17:00 +02:00
Anton Evangelatov c877166b4a add messagepool to test node constructor 2021-06-04 15:53:33 +02:00
Anton Evangelatov 7f234809fc make linter happy 2021-06-04 15:44:13 +02:00
Anton Evangelatov 88756f3ebf fix TestAPIDeal tests 2021-06-04 15:41:38 +02:00
Anton Evangelatov 0a79f49dc5 fix tests 2021-06-01 11:45:34 +02:00
Anton Evangelatov e4136b0d42 add modules.StorageAuthWithURL to set correct token 2021-06-01 11:42:28 +02:00
Anton Evangelatov d195a12565 Merge branch 'master' into nonsense/split-market-miner-processes 2021-05-31 11:26:11 +02:00
Anton Evangelatov 46a368d2b9 bump api ver 2021-05-27 13:35:54 +02:00
Anton Evangelatov c311520968 add missing messagepool override 2021-05-27 10:28:41 +02:00
Anton Evangelatov 9979de24db logs and defaults 2021-05-26 12:47:21 +02:00
Anton Evangelatov 8d3d3c88d4 introduce init service, refactor restore service 2021-05-20 13:25:54 +02:00
Anton Evangelatov 9a7b0b657e comment 2021-05-20 13:18:56 +02:00
Anton Evangelatov 19bd5beb96 update remoteGetSector 2021-05-20 13:15:57 +02:00
Anton Evangelatov 1a9b5760a7 add remoteGetAllocated http handler 2021-05-20 13:14:25 +02:00
Anton Evangelatov 90928991b3 remove DealInfo and DealSchedule from storage-sealing gen/main.go 2021-05-20 13:11:10 +02:00
Anton Evangelatov 4693c61305 re-arrange NodeBuilder and add storageminer_svc 2021-05-20 13:10:14 +02:00
Anton Evangelatov 76bb424de0 update StorageMinerAPI 2021-05-20 13:01:14 +02:00
Anton Evangelatov cb603c62d9 update retrievaladapter ; add piece_provider 2021-05-20 12:49:53 +02:00
Anton Evangelatov c12d802811 update reader to use ReadAtLeast 2021-05-20 12:38:38 +02:00
Anton Evangelatov 2562f2e9a6 add ReaderParamDecoder to json rpc server to lotus-miner run 2021-05-20 12:36:24 +02:00
Anton Evangelatov 2aad7b6979 update sectorstorage.New (Manager) interface 2021-05-20 12:32:29 +02:00
Anton Evangelatov 1295c924e1 confirm that Miner struct satisfies sectorblocks.SectorBuilder 2021-05-19 13:22:00 +02:00
Anton Evangelatov 83e55dc09e move handleProvingSector to correct file - states_proving.go 2021-05-19 13:17:59 +02:00
Anton Evangelatov 55401116bb add UnpaddedByteIndex.Valid() 2021-05-19 13:16:29 +02:00
Anton Evangelatov e275b54f55 export PartialFile and OpenPartialFile 2021-05-19 13:14:16 +02:00
Anton Evangelatov 87ed228fd3 extract pushUrl and fix return type for worker RPC v0 2021-05-19 13:10:56 +02:00
Anton Evangelatov a989f60e27 add SectorAddPieceToAny and SectorUnsealPiece to StorageMiner iface; model moved to api package - PieceDealInfo, DealSchedule 2021-05-19 13:05:07 +02:00
chadwick2143 2cb3c89570 Fix bugs in sectors extend --v1-sectors 2021-04-20 14:00:01 +08:00
zgfzgf 640d6fa474 optimize code 2021-04-06 22:40:05 +08:00
zgfzgf ef08bd48b5 add election backtest 2021-04-03 11:52:30 +08:00
196 changed files with 9095 additions and 4061 deletions
+20
View File
@@ -806,11 +806,21 @@ workflows:
suite: itest-gateway
target: "./itests/gateway_test.go"
- test:
name: test-itest-get_messages_in_ts
suite: itest-get_messages_in_ts
target: "./itests/get_messages_in_ts_test.go"
- test:
name: test-itest-multisig
suite: itest-multisig
target: "./itests/multisig_test.go"
- test:
name: test-itest-nonce
suite: itest-nonce
target: "./itests/nonce_test.go"
- test:
name: test-itest-paych_api
suite: itest-paych_api
@@ -826,6 +836,16 @@ 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_miner_collateral
suite: itest-sector_miner_collateral
target: "./itests/sector_miner_collateral_test.go"
- test:
name: test-itest-sector_pledge
suite: itest-sector_pledge
+6
View File
@@ -0,0 +1,6 @@
# Reference
# https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-code-owners
# Global owners
# Ensure maintainers team is a requested reviewer for non-draft PRs
* @filecoin-project/lotus-maintainers
+27
View File
@@ -0,0 +1,27 @@
name: Close and mark stale issue
on:
schedule:
- cron: '0 0 * * *'
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'Oops, seems like we needed more information for this issue, please comment with more details or this issue will be closed in 24 hours.'
close-issue-message: 'This issue was closed because it is missing author input.'
stale-issue-label: 'kind/stale'
any-of-labels: 'hint/needs-author-input'
days-before-issue-stale: 5
days-before-issue-close: 1
enable-statistics: true
+2
View File
@@ -18,6 +18,8 @@ Lotus is an implementation of the Filecoin Distributed Storage Network. For more
## Building & Documentation
> Note: The default `master` branch is the dev branch, please use with caution. For the latest stable version, checkout the most recent [`Latest release`](https://github.com/filecoin-project/lotus/releases).
For complete instructions on how to build, install and setup lotus, please visit [https://docs.filecoin.io/get-started/lotus](https://docs.filecoin.io/get-started/lotus/). Basic build instructions can be found further down in this readme.
## Reporting a Vulnerability
+12 -8
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"time"
"github.com/filecoin-project/lotus/node/repo/importmgr"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer"
@@ -14,7 +15,6 @@ import (
datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-multistore"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
@@ -104,6 +104,9 @@ type FullNode interface {
// specified block.
ChainGetParentMessages(ctx context.Context, blockCid cid.Cid) ([]Message, error) //perm:read
// ChainGetMessagesInTipset returns message stores in current tipset
ChainGetMessagesInTipset(ctx context.Context, tsk types.TipSetKey) ([]Message, error) //perm:read
// ChainGetTipSetByHeight looks back for a tipset at the specified epoch.
// If there are no blocks at the specified epoch, a tipset at an earlier epoch
// will be returned.
@@ -320,7 +323,7 @@ type FullNode interface {
// ClientImport imports file under the specified path into filestore.
ClientImport(ctx context.Context, ref FileRef) (*ImportRes, error) //perm:admin
// ClientRemoveImport removes file import
ClientRemoveImport(ctx context.Context, importID multistore.StoreID) error //perm:admin
ClientRemoveImport(ctx context.Context, importID importmgr.ImportID) error //perm:admin
// ClientStartDeal proposes a deal with a miner.
ClientStartDeal(ctx context.Context, params *StartDealParams) (*cid.Cid, error) //perm:admin
// ClientStatelessDeal fire-and-forget-proposes an offline deal to a miner without subsequent tracking.
@@ -712,16 +715,17 @@ type MinerSectors struct {
type ImportRes struct {
Root cid.Cid
ImportID multistore.StoreID
ImportID importmgr.ImportID
}
type Import struct {
Key multistore.StoreID
Key importmgr.ImportID
Err string
Root *cid.Cid
Source string
FilePath string
Root *cid.Cid
Source string
FilePath string
CARv2FilePath string
}
type DealInfo struct {
@@ -904,7 +908,7 @@ type RetrievalOrder struct {
Piece *cid.Cid
Size uint64
LocalStore *multistore.StoreID // if specified, get data from local store
LocalCARV2FilePath string // if specified, get data from a local CARv2 file.
// TODO: support offset
Total types.BigInt
UnsealPrice types.BigInt
+35 -4
View File
@@ -55,6 +55,13 @@ type StorageMiner interface {
// Get the status of a given sector by ID
SectorsStatus(ctx context.Context, sid abi.SectorNumber, showOnChainInfo bool) (SectorInfo, error) //perm:read
// Add piece to an open sector. If no sectors with enough space are open,
// either a new sector will be created, or this call will block until more
// sectors can be created.
SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPieceSize, r storage.Data, d PieceDealInfo) (SectorOffset, error) //perm:admin
SectorsUnsealPiece(ctx context.Context, sector storage.SectorRef, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, commd *cid.Cid) error //perm:admin
// List all staged sectors
SectorsList(context.Context) ([]abi.SectorNumber, error) //perm:read
@@ -135,8 +142,8 @@ type StorageMiner interface {
StorageBestAlloc(ctx context.Context, allocate storiface.SectorFileType, ssize abi.SectorSize, pathType storiface.PathType) ([]stores.StorageInfo, error) //perm:admin
StorageLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) error //perm:admin
StorageTryLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) //perm:admin
StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error) //perm:admin
StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error) //perm:admin
StorageLocal(ctx context.Context) (map[stores.ID]string, error) //perm:admin
StorageStat(ctx context.Context, id stores.ID) (fsutil.FsStat, error) //perm:admin
@@ -279,15 +286,17 @@ type AddrUse int
const (
PreCommitAddr AddrUse = iota
CommitAddr
DealPublishAddr
PoStAddr
TerminateSectorsAddr
)
type AddressConfig struct {
PreCommitControl []address.Address
CommitControl []address.Address
TerminateControl []address.Address
PreCommitControl []address.Address
CommitControl []address.Address
TerminateControl []address.Address
DealPublishControl []address.Address
DisableOwnerFallback bool
DisableWorkerFallback bool
@@ -300,3 +309,25 @@ type PendingDealInfo struct {
PublishPeriodStart time.Time
PublishPeriod time.Duration
}
type SectorOffset struct {
Sector abi.SectorNumber
Offset abi.PaddedPieceSize
}
// DealInfo is a tuple of deal identity and its schedule
type PieceDealInfo struct {
PublishCid *cid.Cid
DealID abi.DealID
DealProposal *market.DealProposal
DealSchedule DealSchedule
KeepUnsealed bool
}
// DealSchedule communicates the time interval of a storage deal. The deal must
// appear in a sealed (proven) sector no later than StartEpoch, otherwise it
// is invalid.
type DealSchedule struct {
StartEpoch abi.ChainEpoch
EndEpoch abi.ChainEpoch
}
+379
View File
@@ -8,6 +8,7 @@ import (
"sort"
abi "github.com/filecoin-project/go-state-types/abi"
market "github.com/filecoin-project/specs-actors/actors/builtin/market"
paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
cid "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
@@ -738,3 +739,381 @@ func (t *SealSeed) UnmarshalCBOR(r io.Reader) error {
return nil
}
func (t *PieceDealInfo) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{165}); err != nil {
return err
}
scratch := make([]byte, 9)
// t.PublishCid (cid.Cid) (struct)
if len("PublishCid") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"PublishCid\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("PublishCid"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("PublishCid")); err != nil {
return err
}
if t.PublishCid == nil {
if _, err := w.Write(cbg.CborNull); err != nil {
return err
}
} else {
if err := cbg.WriteCidBuf(scratch, w, *t.PublishCid); err != nil {
return xerrors.Errorf("failed to write cid field t.PublishCid: %w", err)
}
}
// t.DealID (abi.DealID) (uint64)
if len("DealID") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"DealID\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("DealID"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("DealID")); err != nil {
return err
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.DealID)); err != nil {
return err
}
// t.DealProposal (market.DealProposal) (struct)
if len("DealProposal") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"DealProposal\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("DealProposal"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("DealProposal")); err != nil {
return err
}
if err := t.DealProposal.MarshalCBOR(w); err != nil {
return err
}
// t.DealSchedule (api.DealSchedule) (struct)
if len("DealSchedule") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"DealSchedule\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("DealSchedule"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("DealSchedule")); err != nil {
return err
}
if err := t.DealSchedule.MarshalCBOR(w); err != nil {
return err
}
// t.KeepUnsealed (bool) (bool)
if len("KeepUnsealed") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"KeepUnsealed\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("KeepUnsealed"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("KeepUnsealed")); err != nil {
return err
}
if err := cbg.WriteBool(w, t.KeepUnsealed); err != nil {
return err
}
return nil
}
func (t *PieceDealInfo) UnmarshalCBOR(r io.Reader) error {
*t = PieceDealInfo{}
br := cbg.GetPeeker(r)
scratch := make([]byte, 8)
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajMap {
return fmt.Errorf("cbor input should be of type map")
}
if extra > cbg.MaxLength {
return fmt.Errorf("PieceDealInfo: map struct too large (%d)", extra)
}
var name string
n := extra
for i := uint64(0); i < n; i++ {
{
sval, err := cbg.ReadStringBuf(br, scratch)
if err != nil {
return err
}
name = string(sval)
}
switch name {
// t.PublishCid (cid.Cid) (struct)
case "PublishCid":
{
b, err := br.ReadByte()
if err != nil {
return err
}
if b != cbg.CborNull[0] {
if err := br.UnreadByte(); err != nil {
return err
}
c, err := cbg.ReadCid(br)
if err != nil {
return xerrors.Errorf("failed to read cid field t.PublishCid: %w", err)
}
t.PublishCid = &c
}
}
// t.DealID (abi.DealID) (uint64)
case "DealID":
{
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.DealID = abi.DealID(extra)
}
// t.DealProposal (market.DealProposal) (struct)
case "DealProposal":
{
b, err := br.ReadByte()
if err != nil {
return err
}
if b != cbg.CborNull[0] {
if err := br.UnreadByte(); err != nil {
return err
}
t.DealProposal = new(market.DealProposal)
if err := t.DealProposal.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.DealProposal pointer: %w", err)
}
}
}
// t.DealSchedule (api.DealSchedule) (struct)
case "DealSchedule":
{
if err := t.DealSchedule.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.DealSchedule: %w", err)
}
}
// t.KeepUnsealed (bool) (bool)
case "KeepUnsealed":
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajOther {
return fmt.Errorf("booleans must be major type 7")
}
switch extra {
case 20:
t.KeepUnsealed = false
case 21:
t.KeepUnsealed = true
default:
return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra)
}
default:
// Field doesn't exist on this type, so ignore it
cbg.ScanForLinks(r, func(cid.Cid) {})
}
}
return nil
}
func (t *DealSchedule) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{162}); err != nil {
return err
}
scratch := make([]byte, 9)
// t.StartEpoch (abi.ChainEpoch) (int64)
if len("StartEpoch") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"StartEpoch\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("StartEpoch"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("StartEpoch")); err != nil {
return err
}
if t.StartEpoch >= 0 {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.StartEpoch)); err != nil {
return err
}
} else {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.StartEpoch-1)); err != nil {
return err
}
}
// t.EndEpoch (abi.ChainEpoch) (int64)
if len("EndEpoch") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"EndEpoch\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("EndEpoch"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("EndEpoch")); err != nil {
return err
}
if t.EndEpoch >= 0 {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.EndEpoch)); err != nil {
return err
}
} else {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.EndEpoch-1)); err != nil {
return err
}
}
return nil
}
func (t *DealSchedule) UnmarshalCBOR(r io.Reader) error {
*t = DealSchedule{}
br := cbg.GetPeeker(r)
scratch := make([]byte, 8)
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajMap {
return fmt.Errorf("cbor input should be of type map")
}
if extra > cbg.MaxLength {
return fmt.Errorf("DealSchedule: map struct too large (%d)", extra)
}
var name string
n := extra
for i := uint64(0); i < n; i++ {
{
sval, err := cbg.ReadStringBuf(br, scratch)
if err != nil {
return err
}
name = string(sval)
}
switch name {
// t.StartEpoch (abi.ChainEpoch) (int64)
case "StartEpoch":
{
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
var extraI int64
if err != nil {
return err
}
switch maj {
case cbg.MajUnsignedInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 positive overflow")
}
case cbg.MajNegativeInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 negative oveflow")
}
extraI = -1 - extraI
default:
return fmt.Errorf("wrong type for int64 field: %d", maj)
}
t.StartEpoch = abi.ChainEpoch(extraI)
}
// t.EndEpoch (abi.ChainEpoch) (int64)
case "EndEpoch":
{
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
var extraI int64
if err != nil {
return err
}
switch maj {
case cbg.MajUnsignedInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 positive overflow")
}
case cbg.MajNegativeInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 negative oveflow")
}
extraI = -1 - extraI
default:
return fmt.Errorf("wrong type for int64 field: %d", maj)
}
t.EndEpoch = abi.ChainEpoch(extraI)
}
default:
// Field doesn't exist on this type, so ignore it
cbg.ScanForLinks(r, func(cid.Cid) {})
}
}
return nil
}
+28 -13
View File
@@ -52,8 +52,30 @@ func NewFullNodeRPCV1(ctx context.Context, addr string, requestHeader http.Heade
return &res, closer, err
}
func getPushUrl(addr string) (string, error) {
pushUrl, err := url.Parse(addr)
if err != nil {
return "", err
}
switch pushUrl.Scheme {
case "ws":
pushUrl.Scheme = "http"
case "wss":
pushUrl.Scheme = "https"
}
///rpc/v0 -> /rpc/streams/v0/push
pushUrl.Path = path.Join(pushUrl.Path, "../streams/v0/push")
return pushUrl.String(), nil
}
// NewStorageMinerRPCV0 creates a new http jsonrpc client for miner
func NewStorageMinerRPCV0(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (v0api.StorageMiner, jsonrpc.ClientCloser, error) {
pushUrl, err := getPushUrl(addr)
if err != nil {
return nil, nil, err
}
var res v0api.StorageMinerStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
@@ -61,26 +83,19 @@ func NewStorageMinerRPCV0(ctx context.Context, addr string, requestHeader http.H
&res.Internal,
},
requestHeader,
opts...,
append([]jsonrpc.Option{
rpcenc.ReaderParamEncoder(pushUrl),
}, opts...)...,
)
return &res, closer, err
}
func NewWorkerRPCV0(ctx context.Context, addr string, requestHeader http.Header) (api.Worker, jsonrpc.ClientCloser, error) {
u, err := url.Parse(addr)
func NewWorkerRPCV0(ctx context.Context, addr string, requestHeader http.Header) (v0api.Worker, jsonrpc.ClientCloser, error) {
pushUrl, err := getPushUrl(addr)
if err != nil {
return nil, nil, err
}
switch u.Scheme {
case "ws":
u.Scheme = "http"
case "wss":
u.Scheme = "https"
}
///rpc/v0 -> /rpc/streams/v0/push
u.Path = path.Join(u.Path, "../streams/v0/push")
var res api.WorkerStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
@@ -88,7 +103,7 @@ func NewWorkerRPCV0(ctx context.Context, addr string, requestHeader http.Header)
&res.Internal,
},
requestHeader,
rpcenc.ReaderParamEncoder(u.String()),
rpcenc.ReaderParamEncoder(pushUrl),
jsonrpc.WithNoReconnect(),
jsonrpc.WithTimeout(30*time.Second),
)
+6 -2
View File
@@ -13,6 +13,8 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-multistore"
"github.com/filecoin-project/lotus/node/repo/importmgr"
"github.com/google/uuid"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-filestore"
@@ -27,7 +29,6 @@ import (
filestore2 "github.com/filecoin-project/go-fil-markets/filestore"
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/go-multistore"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
@@ -89,6 +90,7 @@ func init() {
addExample(&pid)
multistoreIDExample := multistore.StoreID(50)
storeIDExample := importmgr.ImportID(50)
addExample(bitfield.NewFromSet([]uint64{5}))
addExample(abi.RegisteredSealProof_StackedDrg32GiBV1_1)
@@ -119,6 +121,8 @@ func init() {
addExample(time.Minute)
addExample(datatransfer.TransferID(3))
addExample(datatransfer.Ongoing)
addExample(storeIDExample)
addExample(&storeIDExample)
addExample(multistoreIDExample)
addExample(&multistoreIDExample)
addExample(retrievalmarket.ClientEventDealAccepted)
@@ -175,7 +179,7 @@ func init() {
// miner specific
addExample(filestore2.Path(".lotusminer/fstmp123"))
si := multistore.StoreID(12)
si := uint64(12)
addExample(&si)
addExample(retrievalmarket.DealID(5))
addExample(abi.ActorID(1000))
+17 -2
View File
@@ -14,7 +14,6 @@ import (
retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket"
storagemarket "github.com/filecoin-project/go-fil-markets/storagemarket"
auth "github.com/filecoin-project/go-jsonrpc/auth"
multistore "github.com/filecoin-project/go-multistore"
abi "github.com/filecoin-project/go-state-types/abi"
big "github.com/filecoin-project/go-state-types/big"
crypto "github.com/filecoin-project/go-state-types/crypto"
@@ -26,6 +25,7 @@ import (
types "github.com/filecoin-project/lotus/chain/types"
marketevents "github.com/filecoin-project/lotus/markets/loggers"
dtypes "github.com/filecoin-project/lotus/node/modules/dtypes"
importmgr "github.com/filecoin-project/lotus/node/repo/importmgr"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
gomock "github.com/golang/mock/gomock"
@@ -194,6 +194,21 @@ func (mr *MockFullNodeMockRecorder) ChainGetMessage(arg0, arg1 interface{}) *gom
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetMessage", reflect.TypeOf((*MockFullNode)(nil).ChainGetMessage), arg0, arg1)
}
// ChainGetMessagesInTipset mocks base method.
func (m *MockFullNode) ChainGetMessagesInTipset(arg0 context.Context, arg1 types.TipSetKey) ([]api.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChainGetMessagesInTipset", arg0, arg1)
ret0, _ := ret[0].([]api.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ChainGetMessagesInTipset indicates an expected call of ChainGetMessagesInTipset.
func (mr *MockFullNodeMockRecorder) ChainGetMessagesInTipset(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetMessagesInTipset", reflect.TypeOf((*MockFullNode)(nil).ChainGetMessagesInTipset), arg0, arg1)
}
// ChainGetNode mocks base method.
func (m *MockFullNode) ChainGetNode(arg0 context.Context, arg1 string) (*api.IpldObject, error) {
m.ctrl.T.Helper()
@@ -716,7 +731,7 @@ func (mr *MockFullNodeMockRecorder) ClientQueryAsk(arg0, arg1, arg2 interface{})
}
// ClientRemoveImport mocks base method.
func (m *MockFullNode) ClientRemoveImport(arg0 context.Context, arg1 multistore.StoreID) error {
func (m *MockFullNode) ClientRemoveImport(arg0 context.Context, arg1 importmgr.ImportID) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ClientRemoveImport", arg0, arg1)
ret0, _ := ret[0].(error)
+34 -4
View File
@@ -13,7 +13,6 @@ import (
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/go-multistore"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline"
@@ -29,6 +28,7 @@ import (
"github.com/filecoin-project/lotus/extern/storage-sealing/sealiface"
marketevents "github.com/filecoin-project/lotus/markets/loggers"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/repo/importmgr"
"github.com/filecoin-project/specs-storage/storage"
"github.com/google/uuid"
"github.com/ipfs/go-cid"
@@ -127,6 +127,8 @@ type FullNodeStruct struct {
ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `perm:"read"`
ChainGetMessagesInTipset func(p0 context.Context, p1 types.TipSetKey) ([]Message, error) `perm:"read"`
ChainGetNode func(p0 context.Context, p1 string) (*IpldObject, error) `perm:"read"`
ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]Message, error) `perm:"read"`
@@ -197,7 +199,7 @@ type FullNodeStruct struct {
ClientQueryAsk func(p0 context.Context, p1 peer.ID, p2 address.Address) (*storagemarket.StorageAsk, error) `perm:"read"`
ClientRemoveImport func(p0 context.Context, p1 multistore.StoreID) error `perm:"admin"`
ClientRemoveImport func(p0 context.Context, p1 importmgr.ImportID) error `perm:"admin"`
ClientRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"`
@@ -665,6 +667,8 @@ type StorageMinerStruct struct {
SealingSchedDiag func(p0 context.Context, p1 bool) (interface{}, error) `perm:"admin"`
SectorAddPieceToAny func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storage.Data, p3 PieceDealInfo) (SectorOffset, error) `perm:"admin"`
SectorCommitFlush func(p0 context.Context) ([]sealiface.CommitBatchRes, error) `perm:"admin"`
SectorCommitPending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"`
@@ -703,6 +707,8 @@ type StorageMinerStruct struct {
SectorsSummary func(p0 context.Context) (map[SectorState]int, error) `perm:"read"`
SectorsUnsealPiece func(p0 context.Context, p1 storage.SectorRef, p2 storiface.UnpaddedByteIndex, p3 abi.UnpaddedPieceSize, p4 abi.SealRandomness, p5 *cid.Cid) error `perm:"admin"`
SectorsUpdate func(p0 context.Context, p1 abi.SectorNumber, p2 SectorState) error `perm:"admin"`
StorageAddLocal func(p0 context.Context, p1 string) error `perm:"admin"`
@@ -1097,6 +1103,14 @@ func (s *FullNodeStub) ChainGetMessage(p0 context.Context, p1 cid.Cid) (*types.M
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) ChainGetMessagesInTipset(p0 context.Context, p1 types.TipSetKey) ([]Message, error) {
return s.Internal.ChainGetMessagesInTipset(p0, p1)
}
func (s *FullNodeStub) ChainGetMessagesInTipset(p0 context.Context, p1 types.TipSetKey) ([]Message, error) {
return *new([]Message), xerrors.New("method not supported")
}
func (s *FullNodeStruct) ChainGetNode(p0 context.Context, p1 string) (*IpldObject, error) {
return s.Internal.ChainGetNode(p0, p1)
}
@@ -1377,11 +1391,11 @@ func (s *FullNodeStub) ClientQueryAsk(p0 context.Context, p1 peer.ID, p2 address
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) ClientRemoveImport(p0 context.Context, p1 multistore.StoreID) error {
func (s *FullNodeStruct) ClientRemoveImport(p0 context.Context, p1 importmgr.ImportID) error {
return s.Internal.ClientRemoveImport(p0, p1)
}
func (s *FullNodeStub) ClientRemoveImport(p0 context.Context, p1 multistore.StoreID) error {
func (s *FullNodeStub) ClientRemoveImport(p0 context.Context, p1 importmgr.ImportID) error {
return xerrors.New("method not supported")
}
@@ -3153,6 +3167,14 @@ func (s *StorageMinerStub) SealingSchedDiag(p0 context.Context, p1 bool) (interf
return nil, xerrors.New("method not supported")
}
func (s *StorageMinerStruct) SectorAddPieceToAny(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storage.Data, p3 PieceDealInfo) (SectorOffset, error) {
return s.Internal.SectorAddPieceToAny(p0, p1, p2, p3)
}
func (s *StorageMinerStub) SectorAddPieceToAny(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storage.Data, p3 PieceDealInfo) (SectorOffset, error) {
return *new(SectorOffset), xerrors.New("method not supported")
}
func (s *StorageMinerStruct) SectorCommitFlush(p0 context.Context) ([]sealiface.CommitBatchRes, error) {
return s.Internal.SectorCommitFlush(p0)
}
@@ -3305,6 +3327,14 @@ func (s *StorageMinerStub) SectorsSummary(p0 context.Context) (map[SectorState]i
return *new(map[SectorState]int), xerrors.New("method not supported")
}
func (s *StorageMinerStruct) SectorsUnsealPiece(p0 context.Context, p1 storage.SectorRef, p2 storiface.UnpaddedByteIndex, p3 abi.UnpaddedPieceSize, p4 abi.SealRandomness, p5 *cid.Cid) error {
return s.Internal.SectorsUnsealPiece(p0, p1, p2, p3, p4, p5)
}
func (s *StorageMinerStub) SectorsUnsealPiece(p0 context.Context, p1 storage.SectorRef, p2 storiface.UnpaddedByteIndex, p3 abi.UnpaddedPieceSize, p4 abi.SealRandomness, p5 *cid.Cid) error {
return xerrors.New("method not supported")
}
func (s *StorageMinerStruct) SectorsUpdate(p0 context.Context, p1 abi.SectorNumber, p2 SectorState) error {
return s.Internal.SectorsUpdate(p0, p1, p2)
}
+5 -2
View File
@@ -8,10 +8,10 @@ import (
datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-multistore"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/lotus/node/repo/importmgr"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer"
@@ -92,6 +92,9 @@ type FullNode interface {
// specified block.
ChainGetParentMessages(ctx context.Context, blockCid cid.Cid) ([]api.Message, error) //perm:read
// ChainGetMessagesInTipset returns message stores in current tipset
ChainGetMessagesInTipset(ctx context.Context, tsk types.TipSetKey) ([]api.Message, error) //perm:read
// ChainGetTipSetByHeight looks back for a tipset at the specified epoch.
// If there are no blocks at the specified epoch, a tipset at an earlier epoch
// will be returned.
@@ -301,7 +304,7 @@ type FullNode interface {
// ClientImport imports file under the specified path into filestore.
ClientImport(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) //perm:admin
// ClientRemoveImport removes file import
ClientRemoveImport(ctx context.Context, importID multistore.StoreID) error //perm:admin
ClientRemoveImport(ctx context.Context, importID importmgr.ImportID) error //perm:admin
// ClientStartDeal proposes a deal with a miner.
ClientStartDeal(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) //perm:admin
// ClientStatelessDeal fire-and-forget-proposes an offline deal to a miner without subsequent tracking.
+14 -4
View File
@@ -10,7 +10,6 @@ import (
datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-multistore"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline"
@@ -22,6 +21,7 @@ import (
"github.com/filecoin-project/lotus/chain/types"
marketevents "github.com/filecoin-project/lotus/markets/loggers"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/repo/importmgr"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer"
"golang.org/x/xerrors"
@@ -45,6 +45,8 @@ type FullNodeStruct struct {
ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `perm:"read"`
ChainGetMessagesInTipset func(p0 context.Context, p1 types.TipSetKey) ([]api.Message, error) `perm:"read"`
ChainGetNode func(p0 context.Context, p1 string) (*api.IpldObject, error) `perm:"read"`
ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]api.Message, error) `perm:"read"`
@@ -115,7 +117,7 @@ type FullNodeStruct struct {
ClientQueryAsk func(p0 context.Context, p1 peer.ID, p2 address.Address) (*storagemarket.StorageAsk, error) `perm:"read"`
ClientRemoveImport func(p0 context.Context, p1 multistore.StoreID) error `perm:"admin"`
ClientRemoveImport func(p0 context.Context, p1 importmgr.ImportID) error `perm:"admin"`
ClientRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"`
@@ -514,6 +516,14 @@ func (s *FullNodeStub) ChainGetMessage(p0 context.Context, p1 cid.Cid) (*types.M
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) ChainGetMessagesInTipset(p0 context.Context, p1 types.TipSetKey) ([]api.Message, error) {
return s.Internal.ChainGetMessagesInTipset(p0, p1)
}
func (s *FullNodeStub) ChainGetMessagesInTipset(p0 context.Context, p1 types.TipSetKey) ([]api.Message, error) {
return *new([]api.Message), xerrors.New("method not supported")
}
func (s *FullNodeStruct) ChainGetNode(p0 context.Context, p1 string) (*api.IpldObject, error) {
return s.Internal.ChainGetNode(p0, p1)
}
@@ -794,11 +804,11 @@ func (s *FullNodeStub) ClientQueryAsk(p0 context.Context, p1 peer.ID, p2 address
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) ClientRemoveImport(p0 context.Context, p1 multistore.StoreID) error {
func (s *FullNodeStruct) ClientRemoveImport(p0 context.Context, p1 importmgr.ImportID) error {
return s.Internal.ClientRemoveImport(p0, p1)
}
func (s *FullNodeStub) ClientRemoveImport(p0 context.Context, p1 multistore.StoreID) error {
func (s *FullNodeStub) ClientRemoveImport(p0 context.Context, p1 importmgr.ImportID) error {
return xerrors.New("method not supported")
}
+17 -2
View File
@@ -14,7 +14,6 @@ import (
retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket"
storagemarket "github.com/filecoin-project/go-fil-markets/storagemarket"
auth "github.com/filecoin-project/go-jsonrpc/auth"
multistore "github.com/filecoin-project/go-multistore"
abi "github.com/filecoin-project/go-state-types/abi"
big "github.com/filecoin-project/go-state-types/big"
crypto "github.com/filecoin-project/go-state-types/crypto"
@@ -26,6 +25,7 @@ import (
types "github.com/filecoin-project/lotus/chain/types"
marketevents "github.com/filecoin-project/lotus/markets/loggers"
dtypes "github.com/filecoin-project/lotus/node/modules/dtypes"
importmgr "github.com/filecoin-project/lotus/node/repo/importmgr"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
gomock "github.com/golang/mock/gomock"
@@ -194,6 +194,21 @@ func (mr *MockFullNodeMockRecorder) ChainGetMessage(arg0, arg1 interface{}) *gom
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetMessage", reflect.TypeOf((*MockFullNode)(nil).ChainGetMessage), arg0, arg1)
}
// ChainGetMessagesInTipset mocks base method.
func (m *MockFullNode) ChainGetMessagesInTipset(arg0 context.Context, arg1 types.TipSetKey) ([]api.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChainGetMessagesInTipset", arg0, arg1)
ret0, _ := ret[0].([]api.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ChainGetMessagesInTipset indicates an expected call of ChainGetMessagesInTipset.
func (mr *MockFullNodeMockRecorder) ChainGetMessagesInTipset(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetMessagesInTipset", reflect.TypeOf((*MockFullNode)(nil).ChainGetMessagesInTipset), arg0, arg1)
}
// ChainGetNode mocks base method.
func (m *MockFullNode) ChainGetNode(arg0 context.Context, arg1 string) (*api.IpldObject, error) {
m.ctrl.T.Helper()
@@ -716,7 +731,7 @@ func (mr *MockFullNodeMockRecorder) ClientQueryAsk(arg0, arg1, arg2 interface{})
}
// ClientRemoveImport mocks base method.
func (m *MockFullNode) ClientRemoveImport(arg0 context.Context, arg1 multistore.StoreID) error {
func (m *MockFullNode) ClientRemoveImport(arg0 context.Context, arg1 importmgr.ImportID) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ClientRemoveImport", arg0, arg1)
ret0, _ := ret[0].(error)
+1 -1
View File
@@ -57,7 +57,7 @@ var (
FullAPIVersion0 = newVer(1, 3, 0)
FullAPIVersion1 = newVer(2, 1, 0)
MinerAPIVersion0 = newVer(1, 1, 0)
MinerAPIVersion0 = newVer(1, 2, 0)
WorkerAPIVersion0 = newVer(1, 1, 0)
)
+133 -48
View File
@@ -5,7 +5,7 @@ import (
"fmt"
"io"
"runtime"
"sync/atomic"
"sync"
"github.com/dgraph-io/badger/v2"
"github.com/dgraph-io/badger/v2/options"
@@ -73,20 +73,16 @@ func (b *badgerLogger) Warningf(format string, args ...interface{}) {
}
const (
stateOpen int64 = iota
stateOpen = iota
stateClosing
stateClosed
)
// Blockstore is a badger-backed IPLD blockstore.
//
// NOTE: once Close() is called, methods will try their best to return
// ErrBlockstoreClosed. This will guaranteed to happen for all subsequent
// operation calls after Close() has returned, but it may not happen for
// operations in progress. Those are likely to fail with a different error.
type Blockstore struct {
// state is accessed atomically
state int64
stateLk sync.RWMutex
state int
viewers sync.WaitGroup
DB *badger.DB
@@ -97,6 +93,8 @@ type Blockstore struct {
var _ blockstore.Blockstore = (*Blockstore)(nil)
var _ blockstore.Viewer = (*Blockstore)(nil)
var _ blockstore.BlockstoreIterator = (*Blockstore)(nil)
var _ blockstore.BlockstoreGC = (*Blockstore)(nil)
var _ io.Closer = (*Blockstore)(nil)
// Open creates a new badger-backed blockstore, with the supplied options.
@@ -124,53 +122,82 @@ func Open(opts Options) (*Blockstore, error) {
// Close closes the store. If the store has already been closed, this noops and
// returns an error, even if the first closure resulted in error.
func (b *Blockstore) Close() error {
if !atomic.CompareAndSwapInt64(&b.state, stateOpen, stateClosing) {
b.stateLk.Lock()
if b.state != stateOpen {
b.stateLk.Unlock()
return nil
}
b.state = stateClosing
b.stateLk.Unlock()
defer func() {
b.stateLk.Lock()
b.state = stateClosed
b.stateLk.Unlock()
}()
// wait for all accesses to complete
b.viewers.Wait()
defer atomic.StoreInt64(&b.state, stateClosed)
return b.DB.Close()
}
func (b *Blockstore) access() error {
b.stateLk.RLock()
defer b.stateLk.RUnlock()
if b.state != stateOpen {
return ErrBlockstoreClosed
}
b.viewers.Add(1)
return nil
}
func (b *Blockstore) isOpen() bool {
b.stateLk.RLock()
defer b.stateLk.RUnlock()
return b.state == stateOpen
}
// CollectGarbage runs garbage collection on the value log
func (b *Blockstore) CollectGarbage() error {
if atomic.LoadInt64(&b.state) != stateOpen {
return ErrBlockstoreClosed
if err := b.access(); err != nil {
return err
}
defer b.viewers.Done()
// compact first to gather the necessary statistics for GC
nworkers := runtime.NumCPU() / 2
if nworkers < 2 {
nworkers = 2
}
err := b.DB.Flatten(nworkers)
if err != nil {
return err
}
var err error
for err == nil {
err = b.DB.RunValueLogGC(0.125)
}
if err == badger.ErrNoRewrite {
// not really an error in this case
// not really an error in this case, it signals the end of GC
return nil
}
return err
}
// Compact runs a synchronous compaction
func (b *Blockstore) Compact() error {
if atomic.LoadInt64(&b.state) != stateOpen {
return ErrBlockstoreClosed
}
nworkers := runtime.NumCPU() / 2
if nworkers < 2 {
nworkers = 2
}
return b.DB.Flatten(nworkers)
}
// View implements blockstore.Viewer, which leverages zero-copy read-only
// access to values.
func (b *Blockstore) View(cid cid.Cid, fn func([]byte) error) error {
if atomic.LoadInt64(&b.state) != stateOpen {
return ErrBlockstoreClosed
if err := b.access(); err != nil {
return err
}
defer b.viewers.Done()
k, pooled := b.PooledStorageKey(cid)
if pooled {
@@ -191,9 +218,10 @@ func (b *Blockstore) View(cid cid.Cid, fn func([]byte) error) error {
// Has implements Blockstore.Has.
func (b *Blockstore) Has(cid cid.Cid) (bool, error) {
if atomic.LoadInt64(&b.state) != stateOpen {
return false, ErrBlockstoreClosed
if err := b.access(); err != nil {
return false, err
}
defer b.viewers.Done()
k, pooled := b.PooledStorageKey(cid)
if pooled {
@@ -221,9 +249,10 @@ func (b *Blockstore) Get(cid cid.Cid) (blocks.Block, error) {
return nil, blockstore.ErrNotFound
}
if atomic.LoadInt64(&b.state) != stateOpen {
return nil, ErrBlockstoreClosed
if err := b.access(); err != nil {
return nil, err
}
defer b.viewers.Done()
k, pooled := b.PooledStorageKey(cid)
if pooled {
@@ -250,9 +279,10 @@ func (b *Blockstore) Get(cid cid.Cid) (blocks.Block, error) {
// GetSize implements Blockstore.GetSize.
func (b *Blockstore) GetSize(cid cid.Cid) (int, error) {
if atomic.LoadInt64(&b.state) != stateOpen {
return -1, ErrBlockstoreClosed
if err := b.access(); err != nil {
return 0, err
}
defer b.viewers.Done()
k, pooled := b.PooledStorageKey(cid)
if pooled {
@@ -279,9 +309,10 @@ func (b *Blockstore) GetSize(cid cid.Cid) (int, error) {
// Put implements Blockstore.Put.
func (b *Blockstore) Put(block blocks.Block) error {
if atomic.LoadInt64(&b.state) != stateOpen {
return ErrBlockstoreClosed
if err := b.access(); err != nil {
return err
}
defer b.viewers.Done()
k, pooled := b.PooledStorageKey(block.Cid())
if pooled {
@@ -299,9 +330,10 @@ func (b *Blockstore) Put(block blocks.Block) error {
// PutMany implements Blockstore.PutMany.
func (b *Blockstore) PutMany(blocks []blocks.Block) error {
if atomic.LoadInt64(&b.state) != stateOpen {
return ErrBlockstoreClosed
if err := b.access(); err != nil {
return err
}
defer b.viewers.Done()
// toReturn tracks the byte slices to return to the pool, if we're using key
// prefixing. we can't return each slice to the pool after each Set, because
@@ -338,9 +370,10 @@ func (b *Blockstore) PutMany(blocks []blocks.Block) error {
// DeleteBlock implements Blockstore.DeleteBlock.
func (b *Blockstore) DeleteBlock(cid cid.Cid) error {
if atomic.LoadInt64(&b.state) != stateOpen {
return ErrBlockstoreClosed
if err := b.access(); err != nil {
return err
}
defer b.viewers.Done()
k, pooled := b.PooledStorageKey(cid)
if pooled {
@@ -353,9 +386,10 @@ func (b *Blockstore) DeleteBlock(cid cid.Cid) error {
}
func (b *Blockstore) DeleteMany(cids []cid.Cid) error {
if atomic.LoadInt64(&b.state) != stateOpen {
return ErrBlockstoreClosed
if err := b.access(); err != nil {
return err
}
defer b.viewers.Done()
// toReturn tracks the byte slices to return to the pool, if we're using key
// prefixing. we can't return each slice to the pool after each Set, because
@@ -392,8 +426,8 @@ func (b *Blockstore) DeleteMany(cids []cid.Cid) error {
// AllKeysChan implements Blockstore.AllKeysChan.
func (b *Blockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
if atomic.LoadInt64(&b.state) != stateOpen {
return nil, ErrBlockstoreClosed
if err := b.access(); err != nil {
return nil, err
}
txn := b.DB.NewTransaction(false)
@@ -405,6 +439,7 @@ func (b *Blockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
ch := make(chan cid.Cid)
go func() {
defer b.viewers.Done()
defer close(ch)
defer iter.Close()
@@ -415,7 +450,7 @@ func (b *Blockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
if ctx.Err() != nil {
return // context has fired.
}
if atomic.LoadInt64(&b.state) != stateOpen {
if !b.isOpen() {
// open iterators will run even after the database is closed...
return // closing, yield.
}
@@ -442,6 +477,56 @@ func (b *Blockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
return ch, nil
}
// Implementation of BlockstoreIterator interface
func (b *Blockstore) ForEachKey(f func(cid.Cid) error) error {
if err := b.access(); err != nil {
return err
}
defer b.viewers.Done()
txn := b.DB.NewTransaction(false)
defer txn.Discard()
opts := badger.IteratorOptions{PrefetchSize: 100}
if b.prefixing {
opts.Prefix = b.prefix
}
iter := txn.NewIterator(opts)
defer iter.Close()
var buf []byte
for iter.Rewind(); iter.Valid(); iter.Next() {
if !b.isOpen() {
return ErrBlockstoreClosed
}
k := iter.Item().Key()
if b.prefixing {
k = k[b.prefixLen:]
}
klen := base32.RawStdEncoding.DecodedLen(len(k))
if klen > len(buf) {
buf = make([]byte, klen)
}
n, err := base32.RawStdEncoding.Decode(buf, k)
if err != nil {
return err
}
c := cid.NewCidV1(cid.Raw, buf[:n])
err = f(c)
if err != nil {
return err
}
}
return nil
}
// HashOnRead implements Blockstore.HashOnRead. It is not supported by this
// blockstore.
func (b *Blockstore) HashOnRead(_ bool) {
+10
View File
@@ -30,6 +30,16 @@ type BatchDeleter interface {
DeleteMany(cids []cid.Cid) error
}
// BlockstoreIterator is a trait for efficient iteration
type BlockstoreIterator interface {
ForEachKey(func(cid.Cid) error) error
}
// BlockstoreGC is a trait for blockstores that support online garbage collection
type BlockstoreGC interface {
CollectGarbage() error
}
// WrapIDStore wraps the underlying blockstore in an "identity" blockstore.
// The ID store filters out all puts for blocks with CIDs using the "identity"
// hash function. It also extracts inlined blocks from CIDs using the identity
+66
View File
@@ -0,0 +1,66 @@
package blockstore
import (
"context"
"io"
blocks "github.com/ipfs/go-block-format"
cid "github.com/ipfs/go-cid"
)
var _ Blockstore = (*discardstore)(nil)
type discardstore struct {
bs Blockstore
}
func NewDiscardStore(bs Blockstore) Blockstore {
return &discardstore{bs: bs}
}
func (b *discardstore) Has(cid cid.Cid) (bool, error) {
return b.bs.Has(cid)
}
func (b *discardstore) HashOnRead(hor bool) {
b.bs.HashOnRead(hor)
}
func (b *discardstore) Get(cid cid.Cid) (blocks.Block, error) {
return b.bs.Get(cid)
}
func (b *discardstore) GetSize(cid cid.Cid) (int, error) {
return b.bs.GetSize(cid)
}
func (b *discardstore) View(cid cid.Cid, f func([]byte) error) error {
return b.bs.View(cid, f)
}
func (b *discardstore) Put(blk blocks.Block) error {
return nil
}
func (b *discardstore) PutMany(blks []blocks.Block) error {
return nil
}
func (b *discardstore) DeleteBlock(cid cid.Cid) error {
return nil
}
func (b *discardstore) DeleteMany(cids []cid.Cid) error {
return nil
}
func (b *discardstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
return b.bs.AllKeysChan(ctx)
}
func (b *discardstore) Close() error {
if c, ok := b.bs.(io.Closer); ok {
return c.Close()
}
return nil
}
+72
View File
@@ -0,0 +1,72 @@
# SplitStore: An actively scalable blockstore for the Filecoin chain
The SplitStore was first introduced in lotus v1.5.1, as an experiment
in reducing the performance impact of large blockstores.
With lotus v1.11.1, we introduce the next iteration in design and
implementation, which we call SplitStore v1.
The new design (see [#6474](https://github.com/filecoin-project/lotus/pull/6474)
evolves the splitstore to be a freestanding compacting blockstore that
allows us to keep a small (60-100GB) working set in a hot blockstore
and reliably archive out of scope objects in a coldstore. The
coldstore can also be a discard store, whereby out of scope objects
are discarded or a regular badger blockstore (the default), which can
be periodically garbage collected according to configurable user
retention policies.
To enable the splitstore, edit `.lotus/config.toml` and add the following:
```
[Chainstore]
EnableSplitstore = true
```
If you intend to use the discard coldstore, your also need to add the following:
```
[Chainstore.Splitstore]
ColdStoreType = "discard"
```
In general you _should not_ have to use the discard store, unless you
are running a network booster or have very constrained hardware with
not enough disk space to maintain a coldstore, even with garbage
collection.
## Operation
When the splitstore is first enabled, the existing blockstore becomes
the coldstore and a fresh hotstore is initialized.
The hotstore is warmed up on first startup so as to load all chain
headers and state roots in the current head. This allows us to
immediately gain the performance benefits of a smallerblockstore which
can be substantial for full archival nodes.
All new writes are directed to the hotstore, while reads first hit the
hotstore, with fallback to the coldstore.
Once 5 finalities have ellapsed, and every finality henceforth, the
blockstore _compacts_. Compaction is the process of moving all
unreachable objects within the last 4 finalities from the hotstore to
the coldstore. If the system is configured with a discard coldstore,
these objects are discarded. Note that chain headers, all the way to
genesis, are considered reachable. Stateroots and messages are
considered reachable only within the last 4 finalities, unless there
is a live reference to them.
## Compaction
Compaction works transactionally with the following algorithm:
- We prepare a transaction, whereby all i/o referenced objects through the API are tracked.
- We walk the chain and mark reachable objects, keeping 4 finalities of state roots and messages and all headers all the way to genesis.
- Once the chain walk is complete, we begin full transaction protection with concurrent marking; we walk and mark all references created during the chain walk. On the same time, all I/O through the API concurrently marks objects as live references.
- We collect cold objects by iterating through the hotstore and checking the mark set; if an object is not marked, then it is candidate for purge.
- When running with a coldstore, we next copy all cold objects to the coldstore.
- At this point we are ready to begin purging:
- We sort cold objects heaviest first, so as to never delete the consituents of a DAG before the DAG itself (which would leave dangling references)
- We delete in small batches taking a lock; each batch is checked again for marks, from the concurrent transactional mark, so as to never delete anything live
- We then end the transaction and compact/gc the hotstore.
## Coldstore Garbage Collection
TBD -- see [#6577](https://github.com/filecoin-project/lotus/issues/6577)
+273
View File
@@ -0,0 +1,273 @@
package splitstore
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime/debug"
"strings"
"sync"
"time"
"go.uber.org/multierr"
"golang.org/x/xerrors"
blocks "github.com/ipfs/go-block-format"
cid "github.com/ipfs/go-cid"
)
type debugLog struct {
readLog, writeLog, deleteLog, stackLog *debugLogOp
stackMx sync.Mutex
stackMap map[string]string
}
type debugLogOp struct {
path string
mx sync.Mutex
log *os.File
count int
}
func openDebugLog(path string) (*debugLog, error) {
basePath := filepath.Join(path, "debug")
err := os.MkdirAll(basePath, 0755)
if err != nil {
return nil, err
}
readLog, err := openDebugLogOp(basePath, "read.log")
if err != nil {
return nil, err
}
writeLog, err := openDebugLogOp(basePath, "write.log")
if err != nil {
_ = readLog.Close()
return nil, err
}
deleteLog, err := openDebugLogOp(basePath, "delete.log")
if err != nil {
_ = readLog.Close()
_ = writeLog.Close()
return nil, err
}
stackLog, err := openDebugLogOp(basePath, "stack.log")
if err != nil {
_ = readLog.Close()
_ = writeLog.Close()
_ = deleteLog.Close()
return nil, xerrors.Errorf("error opening stack log: %w", err)
}
return &debugLog{
readLog: readLog,
writeLog: writeLog,
deleteLog: deleteLog,
stackLog: stackLog,
stackMap: make(map[string]string),
}, nil
}
func (d *debugLog) LogReadMiss(cid cid.Cid) {
if d == nil {
return
}
stack := d.getStack()
err := d.readLog.Log("%s %s %s\n", d.timestamp(), cid, stack)
if err != nil {
log.Warnf("error writing read log: %s", err)
}
}
func (d *debugLog) LogWrite(blk blocks.Block) {
if d == nil {
return
}
var stack string
if enableDebugLogWriteTraces {
stack = " " + d.getStack()
}
err := d.writeLog.Log("%s %s%s\n", d.timestamp(), blk.Cid(), stack)
if err != nil {
log.Warnf("error writing write log: %s", err)
}
}
func (d *debugLog) LogWriteMany(blks []blocks.Block) {
if d == nil {
return
}
var stack string
if enableDebugLogWriteTraces {
stack = " " + d.getStack()
}
now := d.timestamp()
for _, blk := range blks {
err := d.writeLog.Log("%s %s%s\n", now, blk.Cid(), stack)
if err != nil {
log.Warnf("error writing write log: %s", err)
break
}
}
}
func (d *debugLog) LogDelete(cids []cid.Cid) {
if d == nil {
return
}
now := d.timestamp()
for _, c := range cids {
err := d.deleteLog.Log("%s %s\n", now, c)
if err != nil {
log.Warnf("error writing delete log: %s", err)
break
}
}
}
func (d *debugLog) Flush() {
if d == nil {
return
}
// rotate non-empty logs
d.readLog.Rotate()
d.writeLog.Rotate()
d.deleteLog.Rotate()
d.stackLog.Rotate()
}
func (d *debugLog) Close() error {
if d == nil {
return nil
}
err1 := d.readLog.Close()
err2 := d.writeLog.Close()
err3 := d.deleteLog.Close()
err4 := d.stackLog.Close()
return multierr.Combine(err1, err2, err3, err4)
}
func (d *debugLog) getStack() string {
sk := d.getNormalizedStackTrace()
hash := sha256.Sum256([]byte(sk))
key := string(hash[:])
d.stackMx.Lock()
repr, ok := d.stackMap[key]
if !ok {
repr = hex.EncodeToString(hash[:])
d.stackMap[key] = repr
err := d.stackLog.Log("%s\n%s\n", repr, sk)
if err != nil {
log.Warnf("error writing stack trace for %s: %s", repr, err)
}
}
d.stackMx.Unlock()
return repr
}
func (d *debugLog) getNormalizedStackTrace() string {
sk := string(debug.Stack())
// Normalization for deduplication
// skip first line -- it's the goroutine
// for each line that ends in a ), remove the call args -- these are the registers
lines := strings.Split(sk, "\n")[1:]
for i, line := range lines {
if len(line) > 0 && line[len(line)-1] == ')' {
idx := strings.LastIndex(line, "(")
if idx < 0 {
continue
}
lines[i] = line[:idx]
}
}
return strings.Join(lines, "\n")
}
func (d *debugLog) timestamp() string {
ts, _ := time.Now().MarshalText()
return string(ts)
}
func openDebugLogOp(basePath, name string) (*debugLogOp, error) {
path := filepath.Join(basePath, name)
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
return nil, xerrors.Errorf("error opening %s: %w", name, err)
}
return &debugLogOp{path: path, log: file}, nil
}
func (d *debugLogOp) Close() error {
d.mx.Lock()
defer d.mx.Unlock()
return d.log.Close()
}
func (d *debugLogOp) Log(template string, arg ...interface{}) error {
d.mx.Lock()
defer d.mx.Unlock()
d.count++
_, err := fmt.Fprintf(d.log, template, arg...)
return err
}
func (d *debugLogOp) Rotate() {
d.mx.Lock()
defer d.mx.Unlock()
if d.count == 0 {
return
}
err := d.log.Close()
if err != nil {
log.Warnf("error closing log (file: %s): %s", d.path, err)
return
}
arxivPath := fmt.Sprintf("%s-%d", d.path, time.Now().Unix())
err = os.Rename(d.path, arxivPath)
if err != nil {
log.Warnf("error moving log (file: %s): %s", d.path, err)
return
}
go func() {
cmd := exec.Command("gzip", arxivPath)
err := cmd.Run()
if err != nil {
log.Warnf("error compressing log (file: %s): %s", arxivPath, err)
}
}()
d.count = 0
d.log, err = os.OpenFile(d.path, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
log.Warnf("error opening log (file: %s): %s", d.path, err)
return
}
}
+8 -8
View File
@@ -1,26 +1,26 @@
package splitstore
import (
"path/filepath"
"errors"
"golang.org/x/xerrors"
cid "github.com/ipfs/go-cid"
)
var errMarkSetClosed = errors.New("markset closed")
// MarkSet is a utility to keep track of seen CID, and later query for them.
//
// * If the expected dataset is large, it can be backed by a datastore (e.g. bbolt).
// * If a probabilistic result is acceptable, it can be backed by a bloom filter (default).
// * If a probabilistic result is acceptable, it can be backed by a bloom filter
type MarkSet interface {
Mark(cid.Cid) error
Has(cid.Cid) (bool, error)
Close() error
SetConcurrent()
}
// markBytes is deliberately a non-nil empty byte slice for serialization.
var markBytes = []byte{}
type MarkSetEnv interface {
Create(name string, sizeHint int64) (MarkSet, error)
Close() error
@@ -28,10 +28,10 @@ type MarkSetEnv interface {
func OpenMarkSetEnv(path string, mtype string) (MarkSetEnv, error) {
switch mtype {
case "", "bloom":
case "bloom":
return NewBloomMarkSetEnv()
case "bolt":
return NewBoltMarkSetEnv(filepath.Join(path, "markset.bolt"))
case "map":
return NewMapMarkSetEnv()
default:
return nil, xerrors.Errorf("unknown mark set type %s", mtype)
}
+30
View File
@@ -3,6 +3,7 @@ package splitstore
import (
"crypto/rand"
"crypto/sha256"
"sync"
"golang.org/x/xerrors"
@@ -21,7 +22,9 @@ var _ MarkSetEnv = (*BloomMarkSetEnv)(nil)
type BloomMarkSet struct {
salt []byte
mx sync.RWMutex
bf *bbloom.Bloom
ts bool
}
var _ MarkSet = (*BloomMarkSet)(nil)
@@ -64,14 +67,41 @@ func (s *BloomMarkSet) saltedKey(cid cid.Cid) []byte {
}
func (s *BloomMarkSet) Mark(cid cid.Cid) error {
if s.ts {
s.mx.Lock()
defer s.mx.Unlock()
}
if s.bf == nil {
return errMarkSetClosed
}
s.bf.Add(s.saltedKey(cid))
return nil
}
func (s *BloomMarkSet) Has(cid cid.Cid) (bool, error) {
if s.ts {
s.mx.RLock()
defer s.mx.RUnlock()
}
if s.bf == nil {
return false, errMarkSetClosed
}
return s.bf.Has(s.saltedKey(cid)), nil
}
func (s *BloomMarkSet) Close() error {
if s.ts {
s.mx.Lock()
defer s.mx.Unlock()
}
s.bf = nil
return nil
}
func (s *BloomMarkSet) SetConcurrent() {
s.ts = true
}
-81
View File
@@ -1,81 +0,0 @@
package splitstore
import (
"time"
"golang.org/x/xerrors"
cid "github.com/ipfs/go-cid"
bolt "go.etcd.io/bbolt"
)
type BoltMarkSetEnv struct {
db *bolt.DB
}
var _ MarkSetEnv = (*BoltMarkSetEnv)(nil)
type BoltMarkSet struct {
db *bolt.DB
bucketId []byte
}
var _ MarkSet = (*BoltMarkSet)(nil)
func NewBoltMarkSetEnv(path string) (*BoltMarkSetEnv, error) {
db, err := bolt.Open(path, 0644,
&bolt.Options{
Timeout: 1 * time.Second,
NoSync: true,
})
if err != nil {
return nil, err
}
return &BoltMarkSetEnv{db: db}, nil
}
func (e *BoltMarkSetEnv) Create(name string, hint int64) (MarkSet, error) {
bucketId := []byte(name)
err := e.db.Update(func(tx *bolt.Tx) error {
_, err := tx.CreateBucketIfNotExists(bucketId)
if err != nil {
return xerrors.Errorf("error creating bolt db bucket %s: %w", name, err)
}
return nil
})
if err != nil {
return nil, err
}
return &BoltMarkSet{db: e.db, bucketId: bucketId}, nil
}
func (e *BoltMarkSetEnv) Close() error {
return e.db.Close()
}
func (s *BoltMarkSet) Mark(cid cid.Cid) error {
return s.db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket(s.bucketId)
return b.Put(cid.Hash(), markBytes)
})
}
func (s *BoltMarkSet) Has(cid cid.Cid) (result bool, err error) {
err = s.db.View(func(tx *bolt.Tx) error {
b := tx.Bucket(s.bucketId)
v := b.Get(cid.Hash())
result = v != nil
return nil
})
return result, err
}
func (s *BoltMarkSet) Close() error {
return s.db.Update(func(tx *bolt.Tx) error {
return tx.DeleteBucket(s.bucketId)
})
}
+75
View File
@@ -0,0 +1,75 @@
package splitstore
import (
"sync"
cid "github.com/ipfs/go-cid"
)
type MapMarkSetEnv struct{}
var _ MarkSetEnv = (*MapMarkSetEnv)(nil)
type MapMarkSet struct {
mx sync.RWMutex
set map[string]struct{}
ts bool
}
var _ MarkSet = (*MapMarkSet)(nil)
func NewMapMarkSetEnv() (*MapMarkSetEnv, error) {
return &MapMarkSetEnv{}, nil
}
func (e *MapMarkSetEnv) Create(name string, sizeHint int64) (MarkSet, error) {
return &MapMarkSet{
set: make(map[string]struct{}, sizeHint),
}, nil
}
func (e *MapMarkSetEnv) Close() error {
return nil
}
func (s *MapMarkSet) Mark(cid cid.Cid) error {
if s.ts {
s.mx.Lock()
defer s.mx.Unlock()
}
if s.set == nil {
return errMarkSetClosed
}
s.set[string(cid.Hash())] = struct{}{}
return nil
}
func (s *MapMarkSet) Has(cid cid.Cid) (bool, error) {
if s.ts {
s.mx.RLock()
defer s.mx.RUnlock()
}
if s.set == nil {
return false, errMarkSetClosed
}
_, ok := s.set[string(cid.Hash())]
return ok, nil
}
func (s *MapMarkSet) Close() error {
if s.ts {
s.mx.Lock()
defer s.mx.Unlock()
}
s.set = nil
return nil
}
func (s *MapMarkSet) SetConcurrent() {
s.ts = true
}
+2 -2
View File
@@ -8,8 +8,8 @@ import (
"github.com/multiformats/go-multihash"
)
func TestBoltMarkSet(t *testing.T) {
testMarkSet(t, "bolt")
func TestMapMarkSet(t *testing.T) {
testMarkSet(t, "map")
}
func TestBloomMarkSet(t *testing.T) {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+114
View File
@@ -0,0 +1,114 @@
package splitstore
import (
"context"
"errors"
blocks "github.com/ipfs/go-block-format"
cid "github.com/ipfs/go-cid"
bstore "github.com/filecoin-project/lotus/blockstore"
)
type exposedSplitStore struct {
s *SplitStore
}
var _ bstore.Blockstore = (*exposedSplitStore)(nil)
func (s *SplitStore) Expose() bstore.Blockstore {
return &exposedSplitStore{s: s}
}
func (es *exposedSplitStore) DeleteBlock(_ cid.Cid) error {
return errors.New("DeleteBlock: operation not supported")
}
func (es *exposedSplitStore) DeleteMany(_ []cid.Cid) error {
return errors.New("DeleteMany: operation not supported")
}
func (es *exposedSplitStore) Has(c cid.Cid) (bool, error) {
if isIdentiyCid(c) {
return true, nil
}
has, err := es.s.hot.Has(c)
if has || err != nil {
return has, err
}
return es.s.cold.Has(c)
}
func (es *exposedSplitStore) Get(c cid.Cid) (blocks.Block, error) {
if isIdentiyCid(c) {
data, err := decodeIdentityCid(c)
if err != nil {
return nil, err
}
return blocks.NewBlockWithCid(data, c)
}
blk, err := es.s.hot.Get(c)
switch err {
case bstore.ErrNotFound:
return es.s.cold.Get(c)
default:
return blk, err
}
}
func (es *exposedSplitStore) GetSize(c cid.Cid) (int, error) {
if isIdentiyCid(c) {
data, err := decodeIdentityCid(c)
if err != nil {
return 0, err
}
return len(data), nil
}
size, err := es.s.hot.GetSize(c)
switch err {
case bstore.ErrNotFound:
return es.s.cold.GetSize(c)
default:
return size, err
}
}
func (es *exposedSplitStore) Put(blk blocks.Block) error {
return es.s.Put(blk)
}
func (es *exposedSplitStore) PutMany(blks []blocks.Block) error {
return es.s.PutMany(blks)
}
func (es *exposedSplitStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
return es.s.AllKeysChan(ctx)
}
func (es *exposedSplitStore) HashOnRead(enabled bool) {}
func (es *exposedSplitStore) View(c cid.Cid, f func([]byte) error) error {
if isIdentiyCid(c) {
data, err := decodeIdentityCid(c)
if err != nil {
return err
}
return f(data)
}
err := es.s.hot.View(c, f)
switch err {
case bstore.ErrNotFound:
return es.s.cold.View(c, f)
default:
return err
}
}
+30
View File
@@ -0,0 +1,30 @@
package splitstore
import (
"fmt"
"time"
bstore "github.com/filecoin-project/lotus/blockstore"
)
func (s *SplitStore) gcHotstore() {
if err := s.gcBlockstoreOnline(s.hot); err != nil {
log.Warnf("error garbage collecting hostore: %s", err)
}
}
func (s *SplitStore) gcBlockstoreOnline(b bstore.Blockstore) error {
if gc, ok := b.(bstore.BlockstoreGC); ok {
log.Info("garbage collecting blockstore")
startGC := time.Now()
if err := gc.CollectGarbage(); err != nil {
return err
}
log.Infow("garbage collecting hotstore done", "took", time.Since(startGC))
return nil
}
return fmt.Errorf("blockstore doesn't support online gc: %T", b)
}
+150 -96
View File
@@ -2,6 +2,7 @@ package splitstore
import (
"context"
"errors"
"fmt"
"sync"
"sync/atomic"
@@ -13,6 +14,7 @@ import (
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/mock"
blocks "github.com/ipfs/go-block-format"
cid "github.com/ipfs/go-cid"
datastore "github.com/ipfs/go-datastore"
dssync "github.com/ipfs/go-datastore/sync"
@@ -21,22 +23,34 @@ import (
func init() {
CompactionThreshold = 5
CompactionCold = 1
CompactionBoundary = 2
logging.SetLogLevel("splitstore", "DEBUG")
}
func testSplitStore(t *testing.T, cfg *Config) {
chain := &mockChain{t: t}
// genesis
genBlock := mock.MkBlock(nil, 0, 0)
genTs := mock.TipSet(genBlock)
chain.push(genTs)
// the myriads of stores
ds := dssync.MutexWrap(datastore.NewMapDatastore())
hot := blockstore.NewMemorySync()
cold := blockstore.NewMemorySync()
hot := newMockStore()
cold := newMockStore()
// this is necessary to avoid the garbage mock puts in the blocks
garbage := blocks.NewBlock([]byte{1, 2, 3})
err := cold.Put(garbage)
if err != nil {
t.Fatal(err)
}
// genesis
genBlock := mock.MkBlock(nil, 0, 0)
genBlock.Messages = garbage.Cid()
genBlock.ParentMessageReceipts = garbage.Cid()
genBlock.ParentStateRoot = garbage.Cid()
genBlock.Timestamp = uint64(time.Now().Unix())
genTs := mock.TipSet(genBlock)
chain.push(genTs)
// put the genesis block to cold store
blk, err := genBlock.ToStorageBlock()
@@ -62,12 +76,22 @@ func testSplitStore(t *testing.T, cfg *Config) {
}
// make some tipsets, but not enough to cause compaction
mkBlock := func(curTs *types.TipSet, i int) *types.TipSet {
mkBlock := func(curTs *types.TipSet, i int, stateRoot blocks.Block) *types.TipSet {
blk := mock.MkBlock(curTs, uint64(i), uint64(i))
blk.Messages = garbage.Cid()
blk.ParentMessageReceipts = garbage.Cid()
blk.ParentStateRoot = stateRoot.Cid()
blk.Timestamp = uint64(time.Now().Unix())
sblk, err := blk.ToStorageBlock()
if err != nil {
t.Fatal(err)
}
err = ss.Put(stateRoot)
if err != nil {
t.Fatal(err)
}
err = ss.Put(sblk)
if err != nil {
t.Fatal(err)
@@ -78,18 +102,6 @@ func testSplitStore(t *testing.T, cfg *Config) {
return ts
}
mkGarbageBlock := func(curTs *types.TipSet, i int) {
blk := mock.MkBlock(curTs, uint64(i), uint64(i))
sblk, err := blk.ToStorageBlock()
if err != nil {
t.Fatal(err)
}
err = ss.Put(sblk)
if err != nil {
t.Fatal(err)
}
}
waitForCompaction := func() {
for atomic.LoadInt32(&ss.compacting) == 1 {
time.Sleep(100 * time.Millisecond)
@@ -98,105 +110,63 @@ func testSplitStore(t *testing.T, cfg *Config) {
curTs := genTs
for i := 1; i < 5; i++ {
curTs = mkBlock(curTs, i)
stateRoot := blocks.NewBlock([]byte{byte(i), 3, 3, 7})
curTs = mkBlock(curTs, i, stateRoot)
waitForCompaction()
}
mkGarbageBlock(genTs, 1)
// count objects in the cold and hot stores
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
countBlocks := func(bs blockstore.Blockstore) int {
count := 0
ch, err := bs.AllKeysChan(ctx)
if err != nil {
t.Fatal(err)
}
for range ch {
_ = bs.(blockstore.BlockstoreIterator).ForEachKey(func(_ cid.Cid) error {
count++
}
return nil
})
return count
}
coldCnt := countBlocks(cold)
hotCnt := countBlocks(hot)
if coldCnt != 1 {
t.Errorf("expected %d blocks, but got %d", 1, coldCnt)
if coldCnt != 2 {
t.Errorf("expected %d blocks, but got %d", 2, coldCnt)
}
if hotCnt != 5 {
t.Errorf("expected %d blocks, but got %d", 5, hotCnt)
if hotCnt != 10 {
t.Errorf("expected %d blocks, but got %d", 10, hotCnt)
}
// trigger a compaction
for i := 5; i < 10; i++ {
curTs = mkBlock(curTs, i)
stateRoot := blocks.NewBlock([]byte{byte(i), 3, 3, 7})
curTs = mkBlock(curTs, i, stateRoot)
waitForCompaction()
}
coldCnt = countBlocks(cold)
hotCnt = countBlocks(hot)
if !cfg.EnableFullCompaction {
if coldCnt != 5 {
t.Errorf("expected %d cold blocks, but got %d", 5, coldCnt)
}
if hotCnt != 5 {
t.Errorf("expected %d hot blocks, but got %d", 5, hotCnt)
}
if coldCnt != 5 {
t.Errorf("expected %d cold blocks, but got %d", 5, coldCnt)
}
if cfg.EnableFullCompaction && !cfg.EnableGC {
if coldCnt != 3 {
t.Errorf("expected %d cold blocks, but got %d", 3, coldCnt)
}
if hotCnt != 7 {
t.Errorf("expected %d hot blocks, but got %d", 7, hotCnt)
}
}
if cfg.EnableFullCompaction && cfg.EnableGC {
if coldCnt != 2 {
t.Errorf("expected %d cold blocks, but got %d", 2, coldCnt)
}
if hotCnt != 7 {
t.Errorf("expected %d hot blocks, but got %d", 7, hotCnt)
}
if hotCnt != 17 {
t.Errorf("expected %d hot blocks, but got %d", 17, hotCnt)
}
// Make sure we can revert without panicking.
chain.revert(2)
}
func TestSplitStoreSimpleCompaction(t *testing.T) {
testSplitStore(t, &Config{TrackingStoreType: "mem"})
}
func TestSplitStoreFullCompactionWithoutGC(t *testing.T) {
testSplitStore(t, &Config{
TrackingStoreType: "mem",
EnableFullCompaction: true,
})
}
func TestSplitStoreFullCompactionWithGC(t *testing.T) {
testSplitStore(t, &Config{
TrackingStoreType: "mem",
EnableFullCompaction: true,
EnableGC: true,
})
func TestSplitStoreCompaction(t *testing.T) {
testSplitStore(t, &Config{MarkSetType: "map"})
}
type mockChain struct {
t testing.TB
sync.Mutex
genesis *types.BlockHeader
tipsets []*types.TipSet
listener func(revert []*types.TipSet, apply []*types.TipSet) error
}
@@ -204,6 +174,9 @@ type mockChain struct {
func (c *mockChain) push(ts *types.TipSet) {
c.Lock()
c.tipsets = append(c.tipsets, ts)
if c.genesis == nil {
c.genesis = ts.Blocks()[0]
}
c.Unlock()
if c.listener != nil {
@@ -242,7 +215,7 @@ func (c *mockChain) GetTipsetByHeight(_ context.Context, epoch abi.ChainEpoch, _
return nil, fmt.Errorf("bad epoch %d", epoch)
}
return c.tipsets[iEpoch-1], nil
return c.tipsets[iEpoch], nil
}
func (c *mockChain) GetHeaviestTipSet() *types.TipSet {
@@ -256,24 +229,105 @@ func (c *mockChain) SubscribeHeadChanges(change func(revert []*types.TipSet, app
c.listener = change
}
func (c *mockChain) WalkSnapshot(_ context.Context, ts *types.TipSet, epochs abi.ChainEpoch, _ bool, _ bool, f func(cid.Cid) error) error {
c.Lock()
defer c.Unlock()
type mockStore struct {
mx sync.Mutex
set map[cid.Cid]blocks.Block
}
start := int(ts.Height()) - 1
end := start - int(epochs)
if end < 0 {
end = -1
func newMockStore() *mockStore {
return &mockStore{set: make(map[cid.Cid]blocks.Block)}
}
func (b *mockStore) Has(cid cid.Cid) (bool, error) {
b.mx.Lock()
defer b.mx.Unlock()
_, ok := b.set[cid]
return ok, nil
}
func (b *mockStore) HashOnRead(hor bool) {}
func (b *mockStore) Get(cid cid.Cid) (blocks.Block, error) {
b.mx.Lock()
defer b.mx.Unlock()
blk, ok := b.set[cid]
if !ok {
return nil, blockstore.ErrNotFound
}
for i := start; i > end; i-- {
ts := c.tipsets[i]
for _, cid := range ts.Cids() {
err := f(cid)
if err != nil {
return err
}
}
return blk, nil
}
func (b *mockStore) GetSize(cid cid.Cid) (int, error) {
blk, err := b.Get(cid)
if err != nil {
return 0, err
}
return len(blk.RawData()), nil
}
func (b *mockStore) View(cid cid.Cid, f func([]byte) error) error {
blk, err := b.Get(cid)
if err != nil {
return err
}
return f(blk.RawData())
}
func (b *mockStore) Put(blk blocks.Block) error {
b.mx.Lock()
defer b.mx.Unlock()
b.set[blk.Cid()] = blk
return nil
}
func (b *mockStore) PutMany(blks []blocks.Block) error {
b.mx.Lock()
defer b.mx.Unlock()
for _, blk := range blks {
b.set[blk.Cid()] = blk
}
return nil
}
func (b *mockStore) DeleteBlock(cid cid.Cid) error {
b.mx.Lock()
defer b.mx.Unlock()
delete(b.set, cid)
return nil
}
func (b *mockStore) DeleteMany(cids []cid.Cid) error {
b.mx.Lock()
defer b.mx.Unlock()
for _, c := range cids {
delete(b.set, c)
}
return nil
}
func (b *mockStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
return nil, errors.New("not implemented")
}
func (b *mockStore) ForEachKey(f func(cid.Cid) error) error {
b.mx.Lock()
defer b.mx.Unlock()
for c := range b.set {
err := f(c)
if err != nil {
return err
}
}
return nil
}
func (b *mockStore) Close() error {
return nil
}
+67
View File
@@ -0,0 +1,67 @@
package splitstore
import (
"encoding/binary"
"golang.org/x/xerrors"
cid "github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"
"github.com/filecoin-project/go-state-types/abi"
)
func epochToBytes(epoch abi.ChainEpoch) []byte {
return uint64ToBytes(uint64(epoch))
}
func bytesToEpoch(buf []byte) abi.ChainEpoch {
return abi.ChainEpoch(bytesToUint64(buf))
}
func int64ToBytes(i int64) []byte {
return uint64ToBytes(uint64(i))
}
func bytesToInt64(buf []byte) int64 {
return int64(bytesToUint64(buf))
}
func uint64ToBytes(i uint64) []byte {
buf := make([]byte, 16)
n := binary.PutUvarint(buf, i)
return buf[:n]
}
func bytesToUint64(buf []byte) uint64 {
i, _ := binary.Uvarint(buf)
return i
}
func isUnitaryObject(c cid.Cid) bool {
pre := c.Prefix()
switch pre.Codec {
case cid.FilCommitmentSealed, cid.FilCommitmentUnsealed:
return true
default:
return pre.MhType == mh.IDENTITY
}
}
func isIdentiyCid(c cid.Cid) bool {
return c.Prefix().MhType == mh.IDENTITY
}
func decodeIdentityCid(c cid.Cid) ([]byte, error) {
dmh, err := mh.Decode(c.Hash())
if err != nil {
return nil, xerrors.Errorf("error decoding identity cid %s: %w", c, err)
}
// sanity check
if dmh.Code != mh.IDENTITY {
return nil, xerrors.Errorf("error decoding identity cid %s: hash type is not identity", c)
}
return dmh.Digest, nil
}
+126
View File
@@ -0,0 +1,126 @@
package splitstore
import (
"sync/atomic"
"time"
"golang.org/x/xerrors"
blocks "github.com/ipfs/go-block-format"
cid "github.com/ipfs/go-cid"
bstore "github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/chain/types"
)
// warmup acuiqres the compaction lock and spawns a goroutine to warm up the hotstore;
// this is necessary when we sync from a snapshot or when we enable the splitstore
// on top of an existing blockstore (which becomes the coldstore).
func (s *SplitStore) warmup(curTs *types.TipSet) error {
if !atomic.CompareAndSwapInt32(&s.compacting, 0, 1) {
return xerrors.Errorf("error locking compaction")
}
go func() {
defer atomic.StoreInt32(&s.compacting, 0)
log.Info("warming up hotstore")
start := time.Now()
err := s.doWarmup(curTs)
if err != nil {
log.Errorf("error warming up hotstore: %s", err)
return
}
log.Infow("warm up done", "took", time.Since(start))
}()
return nil
}
// the actual warmup procedure; it walks the chain loading all state roots at the boundary
// and headers all the way up to genesis.
// objects are written in batches so as to minimize overhead.
func (s *SplitStore) doWarmup(curTs *types.TipSet) error {
epoch := curTs.Height()
batchHot := make([]blocks.Block, 0, batchSize)
count := int64(0)
xcount := int64(0)
missing := int64(0)
err := s.walkChain(curTs, epoch, false,
func(c cid.Cid) error {
if isUnitaryObject(c) {
return errStopWalk
}
count++
has, err := s.hot.Has(c)
if err != nil {
return err
}
if has {
return nil
}
blk, err := s.cold.Get(c)
if err != nil {
if err == bstore.ErrNotFound {
missing++
return nil
}
return err
}
xcount++
batchHot = append(batchHot, blk)
if len(batchHot) == batchSize {
err = s.hot.PutMany(batchHot)
if err != nil {
return err
}
batchHot = batchHot[:0]
}
return nil
})
if err != nil {
return err
}
if len(batchHot) > 0 {
err = s.hot.PutMany(batchHot)
if err != nil {
return err
}
}
log.Infow("warmup stats", "visited", count, "warm", xcount, "missing", missing)
s.markSetSize = count + count>>2 // overestimate a bit
err = s.ds.Put(markSetSizeKey, int64ToBytes(s.markSetSize))
if err != nil {
log.Warnf("error saving mark set size: %s", err)
}
// save the warmup epoch
err = s.ds.Put(warmupEpochKey, epochToBytes(epoch))
if err != nil {
return xerrors.Errorf("error saving warm up epoch: %w", err)
}
s.mx.Lock()
s.warmupEpoch = epoch
s.mx.Unlock()
// also save the compactionIndex, as this is used as an indicator of warmup for upgraded nodes
err = s.ds.Put(compactionIndexKey, int64ToBytes(s.compactionIndex))
if err != nil {
return xerrors.Errorf("error saving compaction index: %w", err)
}
return nil
}
-109
View File
@@ -1,109 +0,0 @@
package splitstore
import (
"path/filepath"
"sync"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
cid "github.com/ipfs/go-cid"
)
// TrackingStore is a persistent store that tracks blocks that are added
// to the hotstore, tracking the epoch at which they are written.
type TrackingStore interface {
Put(cid.Cid, abi.ChainEpoch) error
PutBatch([]cid.Cid, abi.ChainEpoch) error
Get(cid.Cid) (abi.ChainEpoch, error)
Delete(cid.Cid) error
DeleteBatch([]cid.Cid) error
ForEach(func(cid.Cid, abi.ChainEpoch) error) error
Sync() error
Close() error
}
// OpenTrackingStore opens a tracking store of the specified type in the
// specified path.
func OpenTrackingStore(path string, ttype string) (TrackingStore, error) {
switch ttype {
case "", "bolt":
return OpenBoltTrackingStore(filepath.Join(path, "tracker.bolt"))
case "mem":
return NewMemTrackingStore(), nil
default:
return nil, xerrors.Errorf("unknown tracking store type %s", ttype)
}
}
// NewMemTrackingStore creates an in-memory tracking store.
// This is only useful for test or situations where you don't want to open the
// real tracking store (eg concurrent read only access on a node's datastore)
func NewMemTrackingStore() *MemTrackingStore {
return &MemTrackingStore{tab: make(map[cid.Cid]abi.ChainEpoch)}
}
// MemTrackingStore is a simple in-memory tracking store
type MemTrackingStore struct {
sync.Mutex
tab map[cid.Cid]abi.ChainEpoch
}
var _ TrackingStore = (*MemTrackingStore)(nil)
func (s *MemTrackingStore) Put(cid cid.Cid, epoch abi.ChainEpoch) error {
s.Lock()
defer s.Unlock()
s.tab[cid] = epoch
return nil
}
func (s *MemTrackingStore) PutBatch(cids []cid.Cid, epoch abi.ChainEpoch) error {
s.Lock()
defer s.Unlock()
for _, cid := range cids {
s.tab[cid] = epoch
}
return nil
}
func (s *MemTrackingStore) Get(cid cid.Cid) (abi.ChainEpoch, error) {
s.Lock()
defer s.Unlock()
epoch, ok := s.tab[cid]
if ok {
return epoch, nil
}
return 0, xerrors.Errorf("missing tracking epoch for %s", cid)
}
func (s *MemTrackingStore) Delete(cid cid.Cid) error {
s.Lock()
defer s.Unlock()
delete(s.tab, cid)
return nil
}
func (s *MemTrackingStore) DeleteBatch(cids []cid.Cid) error {
s.Lock()
defer s.Unlock()
for _, cid := range cids {
delete(s.tab, cid)
}
return nil
}
func (s *MemTrackingStore) ForEach(f func(cid.Cid, abi.ChainEpoch) error) error {
s.Lock()
defer s.Unlock()
for cid, epoch := range s.tab {
err := f(cid, epoch)
if err != nil {
return err
}
}
return nil
}
func (s *MemTrackingStore) Sync() error { return nil }
func (s *MemTrackingStore) Close() error { return nil }
-120
View File
@@ -1,120 +0,0 @@
package splitstore
import (
"time"
"golang.org/x/xerrors"
cid "github.com/ipfs/go-cid"
bolt "go.etcd.io/bbolt"
"github.com/filecoin-project/go-state-types/abi"
)
type BoltTrackingStore struct {
db *bolt.DB
bucketId []byte
}
var _ TrackingStore = (*BoltTrackingStore)(nil)
func OpenBoltTrackingStore(path string) (*BoltTrackingStore, error) {
opts := &bolt.Options{
Timeout: 1 * time.Second,
NoSync: true,
}
db, err := bolt.Open(path, 0644, opts)
if err != nil {
return nil, err
}
bucketId := []byte("tracker")
err = db.Update(func(tx *bolt.Tx) error {
_, err := tx.CreateBucketIfNotExists(bucketId)
if err != nil {
return xerrors.Errorf("error creating bolt db bucket %s: %w", string(bucketId), err)
}
return nil
})
if err != nil {
_ = db.Close()
return nil, err
}
return &BoltTrackingStore{db: db, bucketId: bucketId}, nil
}
func (s *BoltTrackingStore) Put(cid cid.Cid, epoch abi.ChainEpoch) error {
val := epochToBytes(epoch)
return s.db.Batch(func(tx *bolt.Tx) error {
b := tx.Bucket(s.bucketId)
return b.Put(cid.Hash(), val)
})
}
func (s *BoltTrackingStore) PutBatch(cids []cid.Cid, epoch abi.ChainEpoch) error {
val := epochToBytes(epoch)
return s.db.Batch(func(tx *bolt.Tx) error {
b := tx.Bucket(s.bucketId)
for _, cid := range cids {
err := b.Put(cid.Hash(), val)
if err != nil {
return err
}
}
return nil
})
}
func (s *BoltTrackingStore) Get(cid cid.Cid) (epoch abi.ChainEpoch, err error) {
err = s.db.View(func(tx *bolt.Tx) error {
b := tx.Bucket(s.bucketId)
val := b.Get(cid.Hash())
if val == nil {
return xerrors.Errorf("missing tracking epoch for %s", cid)
}
epoch = bytesToEpoch(val)
return nil
})
return epoch, err
}
func (s *BoltTrackingStore) Delete(cid cid.Cid) error {
return s.db.Batch(func(tx *bolt.Tx) error {
b := tx.Bucket(s.bucketId)
return b.Delete(cid.Hash())
})
}
func (s *BoltTrackingStore) DeleteBatch(cids []cid.Cid) error {
return s.db.Batch(func(tx *bolt.Tx) error {
b := tx.Bucket(s.bucketId)
for _, cid := range cids {
err := b.Delete(cid.Hash())
if err != nil {
return xerrors.Errorf("error deleting %s", cid)
}
}
return nil
})
}
func (s *BoltTrackingStore) ForEach(f func(cid.Cid, abi.ChainEpoch) error) error {
return s.db.View(func(tx *bolt.Tx) error {
b := tx.Bucket(s.bucketId)
return b.ForEach(func(k, v []byte) error {
cid := cid.NewCidV1(cid.Raw, k)
epoch := bytesToEpoch(v)
return f(cid, epoch)
})
})
}
func (s *BoltTrackingStore) Sync() error {
return s.db.Sync()
}
func (s *BoltTrackingStore) Close() error {
return s.db.Close()
}
-130
View File
@@ -1,130 +0,0 @@
package splitstore
import (
"io/ioutil"
"testing"
cid "github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash"
"github.com/filecoin-project/go-state-types/abi"
)
func TestBoltTrackingStore(t *testing.T) {
testTrackingStore(t, "bolt")
}
func testTrackingStore(t *testing.T, tsType string) {
t.Helper()
makeCid := func(key string) cid.Cid {
h, err := multihash.Sum([]byte(key), multihash.SHA2_256, -1)
if err != nil {
t.Fatal(err)
}
return cid.NewCidV1(cid.Raw, h)
}
mustHave := func(s TrackingStore, cid cid.Cid, epoch abi.ChainEpoch) {
val, err := s.Get(cid)
if err != nil {
t.Fatal(err)
}
if val != epoch {
t.Fatal("epoch mismatch")
}
}
mustNotHave := func(s TrackingStore, cid cid.Cid) {
_, err := s.Get(cid)
if err == nil {
t.Fatal("expected error")
}
}
path, err := ioutil.TempDir("", "snoop-test.*")
if err != nil {
t.Fatal(err)
}
s, err := OpenTrackingStore(path, tsType)
if err != nil {
t.Fatal(err)
}
k1 := makeCid("a")
k2 := makeCid("b")
k3 := makeCid("c")
k4 := makeCid("d")
s.Put(k1, 1) //nolint
s.Put(k2, 2) //nolint
s.Put(k3, 3) //nolint
s.Put(k4, 4) //nolint
mustHave(s, k1, 1)
mustHave(s, k2, 2)
mustHave(s, k3, 3)
mustHave(s, k4, 4)
s.Delete(k1) // nolint
s.Delete(k2) // nolint
mustNotHave(s, k1)
mustNotHave(s, k2)
mustHave(s, k3, 3)
mustHave(s, k4, 4)
s.PutBatch([]cid.Cid{k1}, 1) //nolint
s.PutBatch([]cid.Cid{k2}, 2) //nolint
mustHave(s, k1, 1)
mustHave(s, k2, 2)
mustHave(s, k3, 3)
mustHave(s, k4, 4)
allKeys := map[string]struct{}{
k1.String(): {},
k2.String(): {},
k3.String(): {},
k4.String(): {},
}
err = s.ForEach(func(k cid.Cid, _ abi.ChainEpoch) error {
_, ok := allKeys[k.String()]
if !ok {
t.Fatal("unexpected key")
}
delete(allKeys, k.String())
return nil
})
if err != nil {
t.Fatal(err)
}
if len(allKeys) != 0 {
t.Fatal("not all keys were returned")
}
// no close and reopen and ensure the keys still exist
err = s.Close()
if err != nil {
t.Fatal(err)
}
s, err = OpenTrackingStore(path, tsType)
if err != nil {
t.Fatal(err)
}
mustHave(s, k1, 1)
mustHave(s, k2, 2)
mustHave(s, k3, 3)
mustHave(s, k4, 4)
s.Close() //nolint:errcheck
}
+2 -2
View File
@@ -1,2 +1,2 @@
/dns4/bootstrap-0.interop.fildev.network/tcp/1347/p2p/12D3KooWN86wA54r3v9M8bBYbc1vK9W1ehHDxVGPRaoeUYuXF8R7
/dns4/bootstrap-1.interop.fildev.network/tcp/1347/p2p/12D3KooWNZ41kev8mtBZgWe43qam1VX9pJyf87jnaisQP2urZZ2M
/dns4/bootstrap-0.interop.fildev.network/tcp/1347/p2p/12D3KooWLGPq9JL1xwL6gHok7HSNxtK1Q5kyfg4Hk69ifRPghn4i
/dns4/bootstrap-1.interop.fildev.network/tcp/1347/p2p/12D3KooWFYS1f31zafv8mqqYu8U3hEqYvaZ6avWzYU3BmZdpyH3h
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -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.1-dev"
func UserVersion() string {
if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" {
+27
View File
@@ -196,6 +196,33 @@ func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) ab
}
}
// SetProviderCollateralSupplyTarget sets the percentage of normalized circulating
// supply that must be covered by provider collateral in a deal. This should
// only be used for testing.
func SetProviderCollateralSupplyTarget(num, denom big.Int) {
market2.ProviderCollateralSupplyTarget = builtin2.BigFrac{
Numerator: num,
Denominator: denom,
}
market3.ProviderCollateralSupplyTarget = builtin3.BigFrac{
Numerator: num,
Denominator: denom,
}
market4.ProviderCollateralSupplyTarget = builtin4.BigFrac{
Numerator: num,
Denominator: denom,
}
market5.ProviderCollateralSupplyTarget = builtin5.BigFrac{
Numerator: num,
Denominator: denom,
}
}
func DealProviderCollateralBounds(
size abi.PaddedPieceSize, verified bool,
rawBytePower, qaPower, baselinePower abi.StoragePower,
+14
View File
@@ -132,6 +132,20 @@ func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) ab
}
}
// SetProviderCollateralSupplyTarget sets the percentage of normalized circulating
// supply that must be covered by provider collateral in a deal. This should
// only be used for testing.
func SetProviderCollateralSupplyTarget(num, denom big.Int) {
{{range .versions}}
{{if (ge . 2)}}
market{{.}}.ProviderCollateralSupplyTarget = builtin{{.}}.BigFrac{
Numerator: num,
Denominator: denom,
}
{{end}}
{{end}}
}
func DealProviderCollateralBounds(
size abi.PaddedPieceSize, verified bool,
rawBytePower, qaPower, baselinePower abi.StoragePower,
+31 -26
View File
@@ -547,7 +547,7 @@ func (st *StateTree) Version() types.StateTreeVersion {
return st.version
}
func Diff(oldTree, newTree *StateTree) (map[string]types.Actor, error) {
func Diff(ctx context.Context, oldTree, newTree *StateTree) (map[string]types.Actor, error) {
out := map[string]types.Actor{}
var (
@@ -555,33 +555,38 @@ func Diff(oldTree, newTree *StateTree) (map[string]types.Actor, error) {
buf = bytes.NewReader(nil)
)
if err := newTree.root.ForEach(&ncval, func(k string) error {
var act types.Actor
select {
case <-ctx.Done():
return ctx.Err()
default:
var act types.Actor
addr, err := address.NewFromBytes([]byte(k))
if err != nil {
return xerrors.Errorf("address in state tree was not valid: %w", err)
addr, err := address.NewFromBytes([]byte(k))
if err != nil {
return xerrors.Errorf("address in state tree was not valid: %w", err)
}
found, err := oldTree.root.Get(abi.AddrKey(addr), &ocval)
if err != nil {
return err
}
if found && bytes.Equal(ocval.Raw, ncval.Raw) {
return nil // not changed
}
buf.Reset(ncval.Raw)
err = act.UnmarshalCBOR(buf)
buf.Reset(nil)
if err != nil {
return err
}
out[addr.String()] = act
return nil
}
found, err := oldTree.root.Get(abi.AddrKey(addr), &ocval)
if err != nil {
return err
}
if found && bytes.Equal(ocval.Raw, ncval.Raw) {
return nil // not changed
}
buf.Reset(ncval.Raw)
err = act.UnmarshalCBOR(buf)
buf.Reset(nil)
if err != nil {
return err
}
out[addr.String()] = act
return nil
}); err != nil {
return nil, err
}
+12 -8
View File
@@ -297,22 +297,26 @@ func TestForkRefuseCall(t *testing.T) {
t.Fatal(err)
}
pts, err := cg.ChainStore().LoadTipSet(ts.TipSet.TipSet().Parents())
require.NoError(t, err)
parentHeight := pts.Height()
currentHeight := ts.TipSet.TipSet().Height()
// CallWithGas calls _at_ the current tipset.
ret, err := sm.CallWithGas(ctx, m, nil, ts.TipSet.TipSet())
switch ts.TipSet.TipSet().Height() {
case testForkHeight, testForkHeight + 1:
if parentHeight <= testForkHeight && currentHeight >= testForkHeight {
// If I had a fork, or I _will_ have a fork, it should fail.
require.Equal(t, ErrExpensiveFork, err)
default:
} else {
require.NoError(t, err)
require.True(t, ret.MsgRct.ExitCode.IsSuccess())
}
// Call just runs on the parent state for a tipset, so we only
// expect an error at the fork height.
// Call always applies the message to the "next block" after the tipset's parent state.
ret, err = sm.Call(ctx, m, ts.TipSet.TipSet())
switch ts.TipSet.TipSet().Height() {
case testForkHeight + 1:
if parentHeight == testForkHeight {
require.Equal(t, ErrExpensiveFork, err)
default:
} else {
require.NoError(t, err)
require.True(t, ret.MsgRct.ExitCode.IsSuccess())
}
+4 -3
View File
@@ -279,7 +279,7 @@ func (tu *syncTestUtil) addSourceNode(gen int) {
stop, err := node.New(tu.ctx,
node.FullAPI(&out),
node.Online(),
node.Base(),
node.Repo(sourceRepo),
node.MockHost(tu.mn),
node.Test(),
@@ -310,10 +310,11 @@ func (tu *syncTestUtil) addClientNode() int {
var out api.FullNode
r := repo.NewMemory(nil)
stop, err := node.New(tu.ctx,
node.FullAPI(&out),
node.Online(),
node.Repo(repo.NewMemory(nil)),
node.Base(),
node.Repo(r),
node.MockHost(tu.mn),
node.Test(),
+5
View File
@@ -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 {
+3 -1
View File
@@ -1030,7 +1030,9 @@ var ChainExportCmd = &cli.Command{
ArgsUsage: "[outputPath]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "tipset",
Name: "tipset",
Usage: "specify tipset to start the export from",
Value: "@head",
},
&cli.Int64Flag{
Name: "recent-stateroots",
+56 -57
View File
@@ -25,6 +25,7 @@ import (
"github.com/fatih/color"
datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/lotus/node/repo/importmgr"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-cidutil/cidenc"
"github.com/libp2p/go-libp2p-core/peer"
@@ -34,7 +35,6 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-multistore"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
@@ -174,18 +174,18 @@ var clientDropCmd = &cli.Command{
defer closer()
ctx := ReqContext(cctx)
var ids []multistore.StoreID
var ids []uint64
for i, s := range cctx.Args().Slice() {
id, err := strconv.ParseInt(s, 10, 0)
id, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return xerrors.Errorf("parsing %d-th import ID: %w", i, err)
}
ids = append(ids, multistore.StoreID(id))
ids = append(ids, id)
}
for _, id := range ids {
if err := api.ClientRemoveImport(ctx, id); err != nil {
if err := api.ClientRemoveImport(ctx, importmgr.ImportID(id)); err != nil {
return xerrors.Errorf("removing import %d: %w", id, err)
}
}
@@ -1104,8 +1104,8 @@ var clientRetrieveCmd = &cli.Command{
for _, i := range imports {
if i.Root != nil && i.Root.Equals(file) {
order = &lapi.RetrievalOrder{
Root: file,
LocalStore: &i.Key,
Root: file,
LocalCARV2FilePath: i.CARv2FilePath,
Total: big.Zero(),
UnsealPrice: big.Zero(),
@@ -1231,9 +1231,9 @@ var clientListRetrievalsCmd = &cli.Command{
Usage: "print verbose deal details",
},
&cli.BoolFlag{
Name: "color",
Usage: "use color in display output",
Value: true,
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
},
&cli.BoolFlag{
Name: "show-failed",
@@ -1250,6 +1250,10 @@ var clientListRetrievalsCmd = &cli.Command{
},
},
Action: func(cctx *cli.Context) error {
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
@@ -1258,7 +1262,6 @@ var clientListRetrievalsCmd = &cli.Command{
ctx := ReqContext(cctx)
verbose := cctx.Bool("verbose")
color := cctx.Bool("color")
watch := cctx.Bool("watch")
showFailed := cctx.Bool("show-failed")
completed := cctx.Bool("completed")
@@ -1278,7 +1281,7 @@ var clientListRetrievalsCmd = &cli.Command{
tm.Clear()
tm.MoveCursor(1, 1)
err = outputRetrievalDeals(ctx, tm.Screen, localDeals, verbose, color, showFailed, completed)
err = outputRetrievalDeals(ctx, tm.Screen, localDeals, verbose, showFailed, completed)
if err != nil {
return err
}
@@ -1304,7 +1307,7 @@ var clientListRetrievalsCmd = &cli.Command{
}
}
return outputRetrievalDeals(ctx, cctx.App.Writer, localDeals, verbose, color, showFailed, completed)
return outputRetrievalDeals(ctx, cctx.App.Writer, localDeals, verbose, showFailed, completed)
},
}
@@ -1312,7 +1315,7 @@ func isTerminalError(status retrievalmarket.DealStatus) bool {
// should patch this in go-fil-markets but to solve the problem immediate and not have buggy output
return retrievalmarket.IsTerminalError(status) || status == retrievalmarket.DealStatusErrored || status == retrievalmarket.DealStatusCancelled
}
func outputRetrievalDeals(ctx context.Context, out io.Writer, localDeals []lapi.RetrievalInfo, verbose bool, color bool, showFailed bool, completed bool) error {
func outputRetrievalDeals(ctx context.Context, out io.Writer, localDeals []lapi.RetrievalInfo, verbose bool, showFailed bool, completed bool) error {
var deals []api.RetrievalInfo
for _, deal := range localDeals {
if !showFailed && isTerminalError(deal.Status) {
@@ -1348,13 +1351,13 @@ func outputRetrievalDeals(ctx context.Context, out io.Writer, localDeals []lapi.
w := tablewriter.New(tableColumns...)
for _, d := range deals {
w.Write(toRetrievalOutput(d, color, verbose))
w.Write(toRetrievalOutput(d, verbose))
}
return w.Flush(out)
}
func toRetrievalOutput(d api.RetrievalInfo, color bool, verbose bool) map[string]interface{} {
func toRetrievalOutput(d api.RetrievalInfo, verbose bool) map[string]interface{} {
payloadCID := d.PayloadCID.String()
provider := d.Provider.String()
@@ -1367,7 +1370,7 @@ func toRetrievalOutput(d api.RetrievalInfo, color bool, verbose bool) map[string
"PayloadCID": payloadCID,
"DealId": d.ID,
"Provider": provider,
"Status": retrievalStatusString(color, d.Status),
"Status": retrievalStatusString(d.Status),
"PricePerByte": types.FIL(d.PricePerByte),
"Received": units.BytesSize(float64(d.BytesReceived)),
"TotalPaid": types.FIL(d.TotalPaid),
@@ -1397,19 +1400,17 @@ func toRetrievalOutput(d api.RetrievalInfo, color bool, verbose bool) map[string
return retrievalOutput
}
func retrievalStatusString(c bool, status retrievalmarket.DealStatus) string {
func retrievalStatusString(status retrievalmarket.DealStatus) string {
s := retrievalmarket.DealStatuses[status]
if !c {
switch {
case isTerminalError(status):
return color.RedString(s)
case retrievalmarket.IsTerminalSuccess(status):
return color.GreenString(s)
default:
return s
}
if isTerminalError(status) {
return color.RedString(s)
}
if retrievalmarket.IsTerminalSuccess(status) {
return color.GreenString(s)
}
return s
}
var clientInspectDealCmd = &cli.Command{
@@ -1804,9 +1805,9 @@ var clientListDeals = &cli.Command{
Usage: "print verbose deal details",
},
&cli.BoolFlag{
Name: "color",
Usage: "use color in display output",
Value: true,
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
},
&cli.BoolFlag{
Name: "show-failed",
@@ -1818,6 +1819,10 @@ var clientListDeals = &cli.Command{
},
},
Action: func(cctx *cli.Context) error {
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
@@ -1826,7 +1831,6 @@ var clientListDeals = &cli.Command{
ctx := ReqContext(cctx)
verbose := cctx.Bool("verbose")
color := cctx.Bool("color")
watch := cctx.Bool("watch")
showFailed := cctx.Bool("show-failed")
@@ -1845,7 +1849,7 @@ var clientListDeals = &cli.Command{
tm.Clear()
tm.MoveCursor(1, 1)
err = outputStorageDeals(ctx, tm.Screen, api, localDeals, verbose, color, showFailed)
err = outputStorageDeals(ctx, tm.Screen, api, localDeals, verbose, showFailed)
if err != nil {
return err
}
@@ -1871,7 +1875,7 @@ var clientListDeals = &cli.Command{
}
}
return outputStorageDeals(ctx, cctx.App.Writer, api, localDeals, verbose, color, showFailed)
return outputStorageDeals(ctx, cctx.App.Writer, api, localDeals, verbose, showFailed)
},
}
@@ -1894,7 +1898,7 @@ func dealFromDealInfo(ctx context.Context, full v0api.FullNode, head *types.TipS
}
}
func outputStorageDeals(ctx context.Context, out io.Writer, full v0api.FullNode, localDeals []lapi.DealInfo, verbose bool, color bool, showFailed bool) error {
func outputStorageDeals(ctx context.Context, out io.Writer, full v0api.FullNode, localDeals []lapi.DealInfo, verbose bool, showFailed bool) error {
sort.Slice(localDeals, func(i, j int) bool {
return localDeals[i].CreationTime.Before(localDeals[j].CreationTime)
})
@@ -1946,7 +1950,7 @@ func outputStorageDeals(ctx context.Context, out io.Writer, full v0api.FullNode,
d.LocalDeal.ProposalCid,
d.LocalDeal.DealID,
d.LocalDeal.Provider,
dealStateString(color, d.LocalDeal.State),
dealStateString(d.LocalDeal.State),
onChain,
slashed,
d.LocalDeal.PieceCID,
@@ -1995,7 +1999,7 @@ func outputStorageDeals(ctx context.Context, out io.Writer, full v0api.FullNode,
"DealCid": propcid,
"DealId": d.LocalDeal.DealID,
"Provider": d.LocalDeal.Provider,
"State": dealStateString(color, d.LocalDeal.State),
"State": dealStateString(d.LocalDeal.State),
"On Chain?": onChain,
"Slashed?": slashed,
"PieceCID": piece,
@@ -2010,12 +2014,8 @@ func outputStorageDeals(ctx context.Context, out io.Writer, full v0api.FullNode,
return w.Flush(out)
}
func dealStateString(c bool, state storagemarket.StorageDealStatus) string {
func dealStateString(state storagemarket.StorageDealStatus) string {
s := storagemarket.DealStates[state]
if !c {
return s
}
switch state {
case storagemarket.StorageDealError, storagemarket.StorageDealExpired:
return color.RedString(s)
@@ -2334,9 +2334,9 @@ var clientListTransfers = &cli.Command{
Usage: "print verbose transfer details",
},
&cli.BoolFlag{
Name: "color",
Usage: "use color in display output",
Value: true,
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
},
&cli.BoolFlag{
Name: "completed",
@@ -2352,6 +2352,10 @@ var clientListTransfers = &cli.Command{
},
},
Action: func(cctx *cli.Context) error {
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
@@ -2366,7 +2370,6 @@ var clientListTransfers = &cli.Command{
verbose := cctx.Bool("verbose")
completed := cctx.Bool("completed")
color := cctx.Bool("color")
watch := cctx.Bool("watch")
showFailed := cctx.Bool("show-failed")
if watch {
@@ -2380,7 +2383,7 @@ var clientListTransfers = &cli.Command{
tm.MoveCursor(1, 1)
OutputDataTransferChannels(tm.Screen, channels, verbose, completed, color, showFailed)
OutputDataTransferChannels(tm.Screen, channels, verbose, completed, showFailed)
tm.Flush()
@@ -2405,13 +2408,13 @@ var clientListTransfers = &cli.Command{
}
}
}
OutputDataTransferChannels(os.Stdout, channels, verbose, completed, color, showFailed)
OutputDataTransferChannels(os.Stdout, channels, verbose, completed, showFailed)
return nil
},
}
// OutputDataTransferChannels generates table output for a list of channels
func OutputDataTransferChannels(out io.Writer, channels []lapi.DataTransferChannel, verbose, completed, color, showFailed bool) {
func OutputDataTransferChannels(out io.Writer, channels []lapi.DataTransferChannel, verbose, completed, showFailed bool) {
sort.Slice(channels, func(i, j int) bool {
return channels[i].TransferID < channels[j].TransferID
})
@@ -2441,7 +2444,7 @@ func OutputDataTransferChannels(out io.Writer, channels []lapi.DataTransferChann
tablewriter.Col("Voucher"),
tablewriter.NewLineCol("Message"))
for _, channel := range sendingChannels {
w.Write(toChannelOutput(color, "Sending To", channel, verbose))
w.Write(toChannelOutput("Sending To", channel, verbose))
}
w.Flush(out) //nolint:errcheck
@@ -2455,17 +2458,13 @@ func OutputDataTransferChannels(out io.Writer, channels []lapi.DataTransferChann
tablewriter.Col("Voucher"),
tablewriter.NewLineCol("Message"))
for _, channel := range receivingChannels {
w.Write(toChannelOutput(color, "Receiving From", channel, verbose))
w.Write(toChannelOutput("Receiving From", channel, verbose))
}
w.Flush(out) //nolint:errcheck
}
func channelStatusString(useColor bool, status datatransfer.Status) string {
func channelStatusString(status datatransfer.Status) string {
s := datatransfer.Statuses[status]
if !useColor {
return s
}
switch status {
case datatransfer.Failed, datatransfer.Cancelled:
return color.RedString(s)
@@ -2476,7 +2475,7 @@ func channelStatusString(useColor bool, status datatransfer.Status) string {
}
}
func toChannelOutput(useColor bool, otherPartyColumn string, channel lapi.DataTransferChannel, verbose bool) map[string]interface{} {
func toChannelOutput(otherPartyColumn string, channel lapi.DataTransferChannel, verbose bool) map[string]interface{} {
rootCid := channel.BaseCID.String()
otherParty := channel.OtherPeer.String()
if !verbose {
@@ -2496,7 +2495,7 @@ func toChannelOutput(useColor bool, otherPartyColumn string, channel lapi.DataTr
return map[string]interface{}{
"ID": channel.TransferID,
"Status": channelStatusString(useColor, channel.Status),
"Status": channelStatusString(channel.Status),
otherPartyColumn: otherParty,
"Root Cid": rootCid,
"Initiated?": initiated,
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -695,7 +695,7 @@ var StateListActorsCmd = &cli.Command{
var StateGetActorCmd = &cli.Command{
Name: "get-actor",
Usage: "Print actor information",
ArgsUsage: "[actorrAddress]",
ArgsUsage: "[actorAddress]",
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
+10
View File
@@ -3,10 +3,13 @@ package cli
import (
"context"
"fmt"
"os"
"time"
"github.com/fatih/color"
"github.com/hako/durafmt"
"github.com/ipfs/go-cid"
"github.com/mattn/go-isatty"
"github.com/filecoin-project/go-state-types/abi"
@@ -15,6 +18,13 @@ import (
"github.com/filecoin-project/lotus/chain/types"
)
// Set the global default, to be overridden by individual cli flags in order
func init() {
color.NoColor = os.Getenv("GOLOG_LOG_FMT") != "color" &&
!isatty.IsTerminal(os.Stdout.Fd()) &&
!isatty.IsCygwinTerminal(os.Stdout.Fd())
}
func parseTipSet(ctx context.Context, api v0api.FullNode, vals []string) (*types.TipSet, error) {
var headers []*types.BlockHeader
for _, c := range vals {
+1 -1
View File
@@ -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, "", " ")
+1 -1
View File
@@ -572,7 +572,7 @@ var genesisCarCmd = &cli.Command{
}
ofile := c.String("out")
jrnl := journal.NilJournal()
bstor := blockstore.NewMemorySync()
bstor := blockstore.WrapIDStore(blockstore.NewMemorySync())
sbldr := vm.Syscalls(ffiwrapper.ProofVerifier)
_, err := testing.MakeGenesis(ofile, c.Args().First())(bstor, sbldr, jrnl)()
return err
+6 -3
View File
@@ -265,12 +265,15 @@ var actorControlList = &cli.Command{
Name: "verbose",
},
&cli.BoolFlag{
Name: "color",
Value: true,
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
},
},
Action: func(cctx *cli.Context) error {
color.NoColor = !cctx.Bool("color")
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}
var maddr address.Address
if act := cctx.String("actor"); act != "" {
+101
View File
@@ -1,10 +1,16 @@
package main
import (
"context"
"encoding/binary"
"fmt"
"math/rand"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
@@ -18,6 +24,7 @@ var electionCmd = &cli.Command{
Subcommands: []*cli.Command{
electionRunDummy,
electionEstimate,
electionBacktest,
},
}
@@ -124,3 +131,97 @@ var electionEstimate = &cli.Command{
return nil
},
}
var electionBacktest = &cli.Command{
Name: "backtest",
Usage: "Backtest elections with given miner",
ArgsUsage: "[minerAddress]",
Flags: []cli.Flag{
&cli.Uint64Flag{
Name: "height",
Usage: "blockchain head height",
},
&cli.IntFlag{
Name: "count",
Usage: "number of won elections to look for",
Value: 120,
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return xerrors.Errorf("GetFullNodeAPI: %w", err)
}
defer closer()
ctx := lcli.ReqContext(cctx)
var head *types.TipSet
if cctx.IsSet("height") {
head, err = api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Uint64("height")), types.EmptyTSK)
if err != nil {
return xerrors.Errorf("ChainGetTipSetByHeight: %w", err)
}
} else {
head, err = api.ChainHead(ctx)
if err != nil {
return xerrors.Errorf("ChainHead: %w", err)
}
}
miner, err := address.NewFromString(cctx.Args().First())
if err != nil {
return xerrors.Errorf("miner address: %w", err)
}
count := cctx.Int("count")
if count < 1 {
return xerrors.Errorf("count: %d", count)
}
fmt.Println("height, winCount")
roundEnd := head.Height() + abi.ChainEpoch(1)
for i := 0; i < count; {
for round := head.Height() + abi.ChainEpoch(1); round <= roundEnd; round++ {
i++
win, err := backTestWinner(ctx, miner, round, head, api)
if err == nil && win != nil {
fmt.Printf("%d, %d\n", round, win.WinCount)
}
}
roundEnd = head.Height()
head, err = api.ChainGetTipSet(ctx, head.Parents())
if err != nil {
break
}
}
return nil
},
}
func backTestWinner(ctx context.Context, miner address.Address, round abi.ChainEpoch, ts *types.TipSet, api v0api.FullNode) (*types.ElectionProof, error) {
mbi, err := api.MinerGetBaseInfo(ctx, miner, round, ts.Key())
if err != nil {
return nil, xerrors.Errorf("failed to get mining base info: %w", err)
}
if mbi == nil {
return nil, nil
}
if !mbi.EligibleForMining {
return nil, nil
}
brand := mbi.PrevBeaconEntry
bvals := mbi.BeaconEntries
if len(bvals) > 0 {
brand = bvals[len(bvals)-1]
}
winner, err := gen.IsRoundWinner(ctx, ts, round, miner, brand, mbi, api)
if err != nil {
return nil, xerrors.Errorf("failed to check if we win next round: %w", err)
}
return winner, nil
}
+30
View File
@@ -8,8 +8,10 @@ import (
"strings"
"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{
@@ -17,6 +19,7 @@ var mathCmd = &cli.Command{
Usage: "utility commands around doing math on a list of numbers",
Subcommands: []*cli.Command{
mathSumCmd,
mathAggFeesCmd,
},
}
@@ -101,3 +104,30 @@ var mathSumCmd = &cli.Command{
return nil
},
}
var mathAggFeesCmd = &cli.Command{
Name: "agg-fees",
Flags: []cli.Flag{
&cli.IntFlag{
Name: "size",
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(miner5.AggregateNetworkFee(as, bf)))
return nil
},
}
+27 -10
View File
@@ -2,10 +2,12 @@ package main
import (
"encoding/json"
corebig "math/big"
"os"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
filbig "github.com/filecoin-project/go-state-types/big"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/ipfs/go-cid"
"github.com/urfave/cli/v2"
@@ -21,13 +23,16 @@ type networkTotalsOutput struct {
}
type networkTotals struct {
UniqueCids int `json:"total_unique_cids"`
UniqueProviders int `json:"total_unique_providers"`
UniqueClients int `json:"total_unique_clients"`
TotalDeals int `json:"total_num_deals"`
TotalBytes int64 `json:"total_stored_data_size"`
FilplusTotalDeals int `json:"filplus_total_num_deals"`
FilplusTotalBytes int64 `json:"filplus_total_stored_data_size"`
QaNetworkPower filbig.Int `json:"total_qa_power"`
RawNetworkPower filbig.Int `json:"total_raw_capacity"`
CapacityCarryingData float64 `json:"capacity_fraction_carrying_data"`
UniqueCids int `json:"total_unique_cids"`
UniqueProviders int `json:"total_unique_providers"`
UniqueClients int `json:"total_unique_clients"`
TotalDeals int `json:"total_num_deals"`
TotalBytes int64 `json:"total_stored_data_size"`
FilplusTotalDeals int `json:"filplus_total_num_deals"`
FilplusTotalBytes int64 `json:"filplus_total_stored_data_size"`
seenClient map[address.Address]bool
seenProvider map[address.Address]bool
@@ -66,10 +71,17 @@ var storageStatsCmd = &cli.Command{
return err
}
power, err := api.StateMinerPower(ctx, address.Address{}, head.Key())
if err != nil {
return err
}
netTotals := networkTotals{
seenClient: make(map[address.Address]bool),
seenProvider: make(map[address.Address]bool),
seenPieceCid: make(map[cid.Cid]bool),
QaNetworkPower: power.TotalPower.QualityAdjPower,
RawNetworkPower: power.TotalPower.RawBytePower,
seenClient: make(map[address.Address]bool),
seenProvider: make(map[address.Address]bool),
seenPieceCid: make(map[cid.Cid]bool),
}
deals, err := api.StateMarketDeals(ctx, head.Key())
@@ -103,6 +115,11 @@ var storageStatsCmd = &cli.Command{
netTotals.UniqueClients = len(netTotals.seenClient)
netTotals.UniqueProviders = len(netTotals.seenProvider)
netTotals.CapacityCarryingData, _ = new(corebig.Rat).SetFrac(
corebig.NewInt(netTotals.TotalBytes),
netTotals.RawNetworkPower.Int,
).Float64()
return json.NewEncoder(os.Stdout).Encode(
networkTotalsOutput{
Epoch: int64(head.Height()),
+20 -3
View File
@@ -388,12 +388,15 @@ var actorControlList = &cli.Command{
Name: "verbose",
},
&cli.BoolFlag{
Name: "color",
Value: true,
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
},
},
Action: func(cctx *cli.Context) error {
color.NoColor = !cctx.Bool("color")
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
@@ -435,6 +438,7 @@ var actorControlList = &cli.Command{
commit := map[address.Address]struct{}{}
precommit := map[address.Address]struct{}{}
terminate := map[address.Address]struct{}{}
dealPublish := map[address.Address]struct{}{}
post := map[address.Address]struct{}{}
for _, ca := range mi.ControlAddresses {
@@ -471,6 +475,16 @@ var actorControlList = &cli.Command{
terminate[ca] = struct{}{}
}
for _, ca := range ac.DealPublishControl {
ca, err := api.StateLookupID(ctx, ca, types.EmptyTSK)
if err != nil {
return err
}
delete(post, ca)
dealPublish[ca] = struct{}{}
}
printKey := func(name string, a address.Address) {
b, err := api.WalletBalance(ctx, a)
if err != nil {
@@ -515,6 +529,9 @@ var actorControlList = &cli.Command{
if _, ok := terminate[a]; ok {
uses = append(uses, color.YellowString("terminate"))
}
if _, ok := dealPublish[a]; ok {
uses = append(uses, color.MagentaString("deals"))
}
tw.Write(map[string]interface{}{
"name": name,
+1 -1
View File
@@ -49,7 +49,7 @@ func TestMinerAllInfo(t *testing.T) {
t.Run("pre-info-all", run)
dh := kit.NewDealHarness(t, client, miner)
dh := kit.NewDealHarness(t, client, miner, miner)
deal, res, inPath := dh.MakeOnlineDeal(context.Background(), kit.MakeFullDealParams{Rseed: 6})
outPath := dh.PerformRetrieval(context.Background(), deal, res.Root, false)
kit.AssertFilesEqual(t, inPath, outPath)
+84 -22
View File
@@ -5,7 +5,10 @@ import (
"fmt"
"math"
corebig "math/big"
"os"
"sort"
"strings"
"text/tabwriter"
"time"
"github.com/fatih/color"
@@ -14,6 +17,7 @@ import (
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
@@ -45,8 +49,6 @@ var infoCmd = &cli.Command{
}
func infoCmdAct(cctx *cli.Context) error {
color.NoColor = !cctx.Bool("color")
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
return err
@@ -222,29 +224,89 @@ func infoCmdAct(cctx *cli.Context) error {
return err
}
var nactiveDeals, nVerifDeals, ndeals uint64
var activeDealBytes, activeVerifDealBytes, dealBytes abi.PaddedPieceSize
for _, deal := range deals {
if deal.State == storagemarket.StorageDealError {
continue
}
ndeals++
dealBytes += deal.Proposal.PieceSize
if deal.State == storagemarket.StorageDealActive {
nactiveDeals++
activeDealBytes += deal.Proposal.PieceSize
if deal.Proposal.VerifiedDeal {
nVerifDeals++
activeVerifDealBytes += deal.Proposal.PieceSize
}
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)
}
}
fmt.Printf("Deals: %d, %s\n", ndeals, types.SizeStr(types.NewInt(uint64(dealBytes))))
fmt.Printf("\tActive: %d, %s (Verified: %d, %s)\n", nactiveDeals, types.SizeStr(types.NewInt(uint64(activeDealBytes))), nVerifDeals, types.SizeStr(types.NewInt(uint64(activeVerifDealBytes))))
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()
+6 -4
View File
@@ -121,7 +121,8 @@ var initCmd = &cli.Command{
},
},
Subcommands: []*cli.Command{
initRestoreCmd,
restoreCmd,
serviceCmd,
},
Action: func(cctx *cli.Context) error {
log.Info("Initializing lotus miner")
@@ -317,10 +318,10 @@ func migratePreSealMeta(ctx context.Context, api v1api.FullNode, metadata string
Size: abi.PaddedPieceSize(meta.SectorSize),
PieceCID: commD,
},
DealInfo: &sealing.DealInfo{
DealInfo: &lapi.PieceDealInfo{
DealID: dealID,
DealProposal: &sector.Deal,
DealSchedule: sealing.DealSchedule{
DealSchedule: lapi.DealSchedule{
StartEpoch: sector.Deal.StartEpoch,
EndEpoch: sector.Deal.EndEpoch,
},
@@ -470,7 +471,6 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api v1api.FullNode
AllowCommit: true,
AllowUnseal: true,
}, wsts, smsts)
if err != nil {
return err
}
@@ -734,6 +734,8 @@ func createStorageMiner(ctx context.Context, api v1api.FullNode, peerid peer.ID,
return retval.IDAddress, nil
}
// checkV1ApiSupport uses v0 api version to signal support for v1 API
// trying to query the v1 api on older lotus versions would get a 404, which can happen for any number of other reasons
func checkV1ApiSupport(ctx context.Context, cctx *cli.Context) error {
// check v0 api version to make sure it supports v1 api
api0, closer, err := lcli.GetFullNodeAPI(cctx)
+220 -205
View File
@@ -22,6 +22,7 @@ import (
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
@@ -30,7 +31,7 @@ import (
"github.com/filecoin-project/lotus/node/repo"
)
var initRestoreCmd = &cli.Command{
var restoreCmd = &cli.Command{
Name: "restore",
Usage: "Initialize a lotus miner repo from a backup",
Flags: []cli.Flag{
@@ -49,129 +50,11 @@ var initRestoreCmd = &cli.Command{
},
ArgsUsage: "[backupFile]",
Action: func(cctx *cli.Context) error {
log.Info("Initializing lotus miner using a backup")
if cctx.Args().Len() != 1 {
return xerrors.Errorf("expected 1 argument")
}
ctx := lcli.ReqContext(cctx)
log.Info("Initializing lotus miner using a backup")
log.Info("Trying to connect to full node RPC")
if err := checkV1ApiSupport(ctx, cctx); err != nil {
return err
}
api, closer, err := lcli.GetFullNodeAPIV1(cctx) // TODO: consider storing full node address in config
if err != nil {
return err
}
defer closer()
log.Info("Checking full node version")
v, err := api.Version(ctx)
if err != nil {
return err
}
if !v.APIVersion.EqMajorMinor(lapi.FullAPIVersion1) {
return xerrors.Errorf("Remote API version didn't match (expected %s, remote %s)", lapi.FullAPIVersion1, v.APIVersion)
}
if !cctx.Bool("nosync") {
if err := lcli.SyncWait(ctx, &v0api.WrapperV1Full{FullNode: api}, false); err != nil {
return xerrors.Errorf("sync wait: %w", err)
}
}
bf, err := homedir.Expand(cctx.Args().First())
if err != nil {
return xerrors.Errorf("expand backup file path: %w", err)
}
st, err := os.Stat(bf)
if err != nil {
return xerrors.Errorf("stat backup file (%s): %w", bf, err)
}
f, err := os.Open(bf)
if err != nil {
return xerrors.Errorf("opening backup file: %w", err)
}
defer f.Close() // nolint:errcheck
log.Info("Checking if repo exists")
repoPath := cctx.String(FlagMinerRepo)
r, err := repo.NewFS(repoPath)
if err != nil {
return err
}
ok, err := r.Exists()
if err != nil {
return err
}
if ok {
return xerrors.Errorf("repo at '%s' is already initialized", cctx.String(FlagMinerRepo))
}
log.Info("Initializing repo")
if err := r.Init(repo.StorageMiner); err != nil {
return err
}
lr, err := r.Lock(repo.StorageMiner)
if err != nil {
return err
}
defer lr.Close() //nolint:errcheck
if cctx.IsSet("config") {
log.Info("Restoring config")
cf, err := homedir.Expand(cctx.String("config"))
if err != nil {
return xerrors.Errorf("expanding config path: %w", err)
}
_, err = os.Stat(cf)
if err != nil {
return xerrors.Errorf("stat config file (%s): %w", cf, err)
}
var cerr error
err = lr.SetConfig(func(raw interface{}) {
rcfg, ok := raw.(*config.StorageMiner)
if !ok {
cerr = xerrors.New("expected miner config")
return
}
ff, err := config.FromFile(cf, rcfg)
if err != nil {
cerr = xerrors.Errorf("loading config: %w", err)
return
}
*rcfg = *ff.(*config.StorageMiner)
})
if cerr != nil {
return cerr
}
if err != nil {
return xerrors.Errorf("setting config: %w", err)
}
} else {
log.Warn("--config NOT SET, WILL USE DEFAULT VALUES")
}
var storageCfg *stores.StorageConfig
if cctx.IsSet("storage-config") {
log.Info("Restoring storage path config")
cf, err := homedir.Expand(cctx.String("storage-config"))
if err != nil {
return xerrors.Errorf("expanding storage config path: %w", err)
@@ -182,101 +65,233 @@ var initRestoreCmd = &cli.Command{
return xerrors.Errorf("reading storage config: %w", err)
}
var cerr error
err = lr.SetStorage(func(scfg *stores.StorageConfig) {
cerr = json.Unmarshal(cfb, scfg)
})
if cerr != nil {
return xerrors.Errorf("unmarshalling storage config: %w", cerr)
}
storageCfg = &stores.StorageConfig{}
err = json.Unmarshal(cfb, storageCfg)
if err != nil {
return xerrors.Errorf("setting storage config: %w", err)
return xerrors.Errorf("cannot unmarshal json for storage config: %w", err)
}
} else {
log.Warn("--storage-config NOT SET. NO SECTOR PATHS WILL BE CONFIGURED")
}
log.Info("Restoring metadata backup")
if err := restore(ctx, cctx, storageCfg, nil, func(api lapi.FullNode, maddr address.Address, peerid peer.ID, mi miner.MinerInfo) error {
log.Info("Checking proof parameters")
mds, err := lr.Datastore(context.TODO(), "/metadata")
if err != nil {
return err
}
if err := paramfetch.GetParams(ctx, build.ParametersJSON(), build.SrsJSON(), uint64(mi.SectorSize)); err != nil {
return xerrors.Errorf("fetching proof parameters: %w", err)
}
bar := pb.New64(st.Size())
br := bar.NewProxyReader(f)
bar.ShowTimeLeft = true
bar.ShowPercent = true
bar.ShowSpeed = true
bar.Units = pb.U_BYTES
log.Info("Configuring miner actor")
bar.Start()
err = backupds.RestoreInto(br, mds)
bar.Finish()
if err := configureStorageMiner(ctx, api, maddr, peerid, big.Zero()); err != nil {
return err
}
if err != nil {
return xerrors.Errorf("restoring metadata: %w", err)
}
log.Info("Checking actor metadata")
abytes, err := mds.Get(datastore.NewKey("miner-address"))
if err != nil {
return xerrors.Errorf("getting actor address from metadata datastore: %w", err)
}
maddr, err := address.NewFromBytes(abytes)
if err != nil {
return xerrors.Errorf("parsing actor address: %w", err)
}
log.Info("ACTOR ADDRESS: ", maddr.String())
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("getting miner info: %w", err)
}
log.Info("SECTOR SIZE: ", units.BytesSize(float64(mi.SectorSize)))
wk, err := api.StateAccountKey(ctx, mi.Worker, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("resolving worker key: %w", err)
}
has, err := api.WalletHas(ctx, wk)
if err != nil {
return xerrors.Errorf("checking worker address: %w", err)
}
if !has {
return xerrors.Errorf("worker address %s for miner actor %s not present in full node wallet", mi.Worker, maddr)
}
log.Info("Checking proof parameters")
if err := paramfetch.GetParams(ctx, build.ParametersJSON(), build.SrsJSON(), uint64(mi.SectorSize)); err != nil {
return xerrors.Errorf("fetching proof parameters: %w", err)
}
log.Info("Initializing libp2p identity")
p2pSk, err := makeHostKey(lr)
if err != nil {
return xerrors.Errorf("make host key: %w", err)
}
peerid, err := peer.IDFromPrivateKey(p2pSk)
if err != nil {
return xerrors.Errorf("peer ID from private key: %w", err)
}
log.Info("Configuring miner actor")
if err := configureStorageMiner(ctx, api, maddr, peerid, big.Zero()); err != nil {
return nil
}); err != nil {
return err
}
return nil
},
}
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 {
if cctx.Args().Len() != 1 {
return xerrors.Errorf("expected 1 argument")
}
log.Info("Trying to connect to full node RPC")
api, closer, err := lcli.GetFullNodeAPIV1(cctx) // TODO: consider storing full node address in config
if err != nil {
return err
}
defer closer()
log.Info("Checking full node version")
v, err := api.Version(ctx)
if err != nil {
return err
}
if !v.APIVersion.EqMajorMinor(lapi.FullAPIVersion1) {
return xerrors.Errorf("Remote API version didn't match (expected %s, remote %s)", lapi.FullAPIVersion1, v.APIVersion)
}
if !cctx.Bool("nosync") {
if err := lcli.SyncWait(ctx, &v0api.WrapperV1Full{FullNode: api}, false); err != nil {
return xerrors.Errorf("sync wait: %w", err)
}
}
bf, err := homedir.Expand(cctx.Args().First())
if err != nil {
return xerrors.Errorf("expand backup file path: %w", err)
}
st, err := os.Stat(bf)
if err != nil {
return xerrors.Errorf("stat backup file (%s): %w", bf, err)
}
f, err := os.Open(bf)
if err != nil {
return xerrors.Errorf("opening backup file: %w", err)
}
defer f.Close() // nolint:errcheck
log.Info("Checking if repo exists")
repoPath := cctx.String(FlagMinerRepo)
r, err := repo.NewFS(repoPath)
if err != nil {
return err
}
ok, err := r.Exists()
if err != nil {
return err
}
if ok {
return xerrors.Errorf("repo at '%s' is already initialized", cctx.String(FlagMinerRepo))
}
log.Info("Initializing repo")
if err := r.Init(repo.StorageMiner); err != nil {
return err
}
lr, err := r.Lock(repo.StorageMiner)
if err != nil {
return err
}
defer lr.Close() //nolint:errcheck
if cctx.IsSet("config") {
log.Info("Restoring config")
cf, err := homedir.Expand(cctx.String("config"))
if err != nil {
return xerrors.Errorf("expanding config path: %w", err)
}
_, err = os.Stat(cf)
if err != nil {
return xerrors.Errorf("stat config file (%s): %w", cf, err)
}
var cerr error
err = lr.SetConfig(func(raw interface{}) {
rcfg, ok := raw.(*config.StorageMiner)
if !ok {
cerr = xerrors.New("expected miner config")
return
}
ff, err := config.FromFile(cf, rcfg)
if err != nil {
cerr = xerrors.Errorf("loading config: %w", err)
return
}
*rcfg = *ff.(*config.StorageMiner)
if manageConfig != nil {
cerr = manageConfig(rcfg)
}
})
if cerr != nil {
return cerr
}
if err != nil {
return xerrors.Errorf("setting config: %w", err)
}
} else {
log.Warn("--config NOT SET, WILL USE DEFAULT VALUES")
}
if strConfig != nil {
log.Info("Restoring storage path config")
err = lr.SetStorage(func(scfg *stores.StorageConfig) {
*scfg = *strConfig
})
if err != nil {
return xerrors.Errorf("setting storage config: %w", err)
}
} else {
log.Warn("--storage-config NOT SET. NO SECTOR PATHS WILL BE CONFIGURED")
}
log.Info("Restoring metadata backup")
mds, err := lr.Datastore(context.TODO(), "/metadata")
if err != nil {
return err
}
bar := pb.New64(st.Size())
br := bar.NewProxyReader(f)
bar.ShowTimeLeft = true
bar.ShowPercent = true
bar.ShowSpeed = true
bar.Units = pb.U_BYTES
bar.Start()
err = backupds.RestoreInto(br, mds)
bar.Finish()
if err != nil {
return xerrors.Errorf("restoring metadata: %w", err)
}
log.Info("Checking actor metadata")
abytes, err := mds.Get(datastore.NewKey("miner-address"))
if err != nil {
return xerrors.Errorf("getting actor address from metadata datastore: %w", err)
}
maddr, err := address.NewFromBytes(abytes)
if err != nil {
return xerrors.Errorf("parsing actor address: %w", err)
}
log.Info("ACTOR ADDRESS: ", maddr.String())
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("getting miner info: %w", err)
}
log.Info("SECTOR SIZE: ", units.BytesSize(float64(mi.SectorSize)))
wk, err := api.StateAccountKey(ctx, mi.Worker, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("resolving worker key: %w", err)
}
has, err := api.WalletHas(ctx, wk)
if err != nil {
return xerrors.Errorf("checking worker address: %w", err)
}
if !has {
return xerrors.Errorf("worker address %s for miner actor %s not present in full node wallet", mi.Worker, maddr)
}
log.Info("Initializing libp2p identity")
p2pSk, err := makeHostKey(lr)
if err != nil {
return xerrors.Errorf("make host key: %w", err)
}
peerid, err := peer.IDFromPrivateKey(p2pSk)
if err != nil {
return xerrors.Errorf("peer ID from private key: %w", err)
}
return after(api, maddr, peerid, mi)
}
+152
View File
@@ -0,0 +1,152 @@
package main
import (
"context"
"strings"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/big"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/client"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
lcli "github.com/filecoin-project/lotus/cli"
cliutil "github.com/filecoin-project/lotus/cli/util"
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
"github.com/filecoin-project/lotus/node/config"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
)
const (
MarketsService = "markets"
)
var serviceCmd = &cli.Command{
Name: "service",
Usage: "Initialize a lotus miner sub-service",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config",
Usage: "config file (config.toml)",
Required: true,
},
&cli.BoolFlag{
Name: "nosync",
Usage: "don't check full-node sync status",
},
&cli.StringSliceFlag{
Name: "type",
Usage: "type of service to be enabled",
},
&cli.StringFlag{
Name: "api-sealer",
Usage: "sealer API info (lotus-miner auth api-info --perm=admin)",
},
&cli.StringFlag{
Name: "api-sector-index",
Usage: "sector Index API info (lotus-miner auth api-info --perm=admin)",
},
},
ArgsUsage: "[backupFile]",
Action: func(cctx *cli.Context) error {
ctx := lcli.ReqContext(cctx)
log.Info("Initializing lotus miner service")
es := EnabledServices(cctx.StringSlice("type"))
if len(es) == 0 {
return xerrors.Errorf("at least one module must be enabled")
}
// we should remove this as soon as we have more service types and not just `markets`
if !es.Contains(MarketsService) {
return xerrors.Errorf("markets module must be enabled")
}
if !cctx.IsSet("api-sealer") {
return xerrors.Errorf("--api-sealer is required without the sealer module enabled")
}
if !cctx.IsSet("api-sector-index") {
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 {
cfg.Subsystems.EnableMarkets = es.Contains(MarketsService)
cfg.Subsystems.EnableMining = false
cfg.Subsystems.EnableSealing = false
cfg.Subsystems.EnableSectorStorage = false
if !cfg.Subsystems.EnableSealing {
ai, err := checkApiInfo(ctx, cctx.String("api-sealer"))
if err != nil {
return xerrors.Errorf("checking sealer API: %w", err)
}
cfg.Subsystems.SealerApiInfo = ai
}
if !cfg.Subsystems.EnableSectorStorage {
ai, err := checkApiInfo(ctx, cctx.String("api-sector-index"))
if err != nil {
return xerrors.Errorf("checking sector index API: %w", err)
}
cfg.Subsystems.SectorIndexApiInfo = ai
}
return nil
}, func(api lapi.FullNode, maddr address.Address, peerid peer.ID, mi miner.MinerInfo) error {
if es.Contains(MarketsService) {
log.Info("Configuring miner actor")
if err := configureStorageMiner(ctx, api, maddr, peerid, big.Zero()); err != nil {
return err
}
}
return nil
}); err != nil {
return err
}
return nil
},
}
type EnabledServices []string
func (es EnabledServices) Contains(name string) bool {
for _, s := range es {
if s == name {
return true
}
}
return false
}
func checkApiInfo(ctx context.Context, ai string) (string, error) {
ai = strings.TrimPrefix(strings.TrimSpace(ai), "MINER_API_INFO=")
info := cliutil.ParseApiInfo(ai)
addr, err := info.DialArgs("v0")
if err != nil {
return "", xerrors.Errorf("could not get DialArgs: %w", err)
}
log.Infof("Checking api version of %s", addr)
api, closer, err := client.NewStorageMinerRPCV0(ctx, addr, info.AuthHeader())
if err != nil {
return "", err
}
defer closer()
v, err := api.Version(ctx)
if err != nil {
return "", xerrors.Errorf("checking version: %w", err)
}
if !v.APIVersion.EqMajorMinor(lapi.MinerAPIVersion0) {
return "", xerrors.Errorf("remote service API version didn't match (expected %s, remote %s)", lapi.MinerAPIVersion0, v.APIVersion)
}
return ai, nil
}
+10 -1
View File
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"github.com/fatih/color"
logging "github.com/ipfs/go-log/v2"
"github.com/urfave/cli/v2"
"go.opencensus.io/trace"
@@ -61,9 +62,14 @@ func main() {
trace.UnregisterExporter(jaeger)
jaeger = tracing.SetupJaegerTracing("lotus/" + cmd.Name)
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}
if originBefore != nil {
return originBefore(cctx)
}
return nil
}
}
@@ -81,7 +87,10 @@ func main() {
Aliases: []string{"a"},
},
&cli.BoolFlag{
Name: "color",
// examined in the Before above
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
},
&cli.StringFlag{
Name: "repo",
+10 -6
View File
@@ -15,6 +15,7 @@ import (
tm "github.com/buger/goterm"
"github.com/docker/go-units"
"github.com/fatih/color"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-cidutil/cidenc"
"github.com/libp2p/go-libp2p-core/peer"
@@ -752,9 +753,9 @@ var transfersListCmd = &cli.Command{
Usage: "print verbose transfer details",
},
&cli.BoolFlag{
Name: "color",
Usage: "use color in display output",
Value: true,
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
},
&cli.BoolFlag{
Name: "completed",
@@ -770,6 +771,10 @@ var transfersListCmd = &cli.Command{
},
},
Action: func(cctx *cli.Context) error {
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}
api, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
return err
@@ -784,7 +789,6 @@ var transfersListCmd = &cli.Command{
verbose := cctx.Bool("verbose")
completed := cctx.Bool("completed")
color := cctx.Bool("color")
watch := cctx.Bool("watch")
showFailed := cctx.Bool("show-failed")
if watch {
@@ -798,7 +802,7 @@ var transfersListCmd = &cli.Command{
tm.MoveCursor(1, 1)
lcli.OutputDataTransferChannels(tm.Screen, channels, verbose, completed, color, showFailed)
lcli.OutputDataTransferChannels(tm.Screen, channels, verbose, completed, showFailed)
tm.Flush()
@@ -823,7 +827,7 @@ var transfersListCmd = &cli.Command{
}
}
}
lcli.OutputDataTransferChannels(os.Stdout, channels, verbose, completed, color, showFailed)
lcli.OutputDataTransferChannels(os.Stdout, channels, verbose, completed, showFailed)
return nil
},
}
-6
View File
@@ -36,8 +36,6 @@ var provingFaultsCmd = &cli.Command{
Name: "faults",
Usage: "View the currently known proving faulty sectors information",
Action: func(cctx *cli.Context) error {
color.NoColor = !cctx.Bool("color")
api, acloser, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
@@ -90,8 +88,6 @@ var provingInfoCmd = &cli.Command{
Name: "info",
Usage: "View current state information",
Action: func(cctx *cli.Context) error {
color.NoColor = !cctx.Bool("color")
api, acloser, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
@@ -197,8 +193,6 @@ var provingDeadlinesCmd = &cli.Command{
Name: "deadlines",
Usage: "View the current proving period deadlines information",
Action: func(cctx *cli.Context) error {
color.NoColor = !cctx.Bool("color")
api, acloser, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
+34 -9
View File
@@ -22,6 +22,7 @@ import (
"github.com/filecoin-project/lotus/lib/ulimit"
"github.com/filecoin-project/lotus/metrics"
"github.com/filecoin-project/lotus/node"
"github.com/filecoin-project/lotus/node/config"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/repo"
)
@@ -118,13 +119,33 @@ var runCmd = &cli.Command{
return xerrors.Errorf("repo at '%s' is not initialized, run 'lotus-miner init' to set it up", minerRepoPath)
}
lr, err := r.Lock(repo.StorageMiner)
if err != nil {
return err
}
c, err := lr.Config()
if err != nil {
return err
}
cfg, ok := c.(*config.StorageMiner)
if !ok {
return xerrors.Errorf("invalid config for repo, got: %T", c)
}
bootstrapLibP2P := cfg.Subsystems.EnableMarkets
err = lr.Close()
if err != nil {
return err
}
shutdownChan := make(chan struct{})
var minerapi api.StorageMiner
stop, err := node.New(ctx,
node.StorageMiner(&minerapi),
node.StorageMiner(&minerapi, cfg.Subsystems),
node.Override(new(dtypes.ShutdownChan), shutdownChan),
node.Online(),
node.Base(),
node.Repo(r),
node.ApplyIf(func(s *node.Settings) bool { return cctx.IsSet("miner-api") },
@@ -142,14 +163,18 @@ var runCmd = &cli.Command{
return xerrors.Errorf("getting API endpoint: %w", err)
}
// Bootstrap with full node
remoteAddrs, err := nodeApi.NetAddrsListen(ctx)
if err != nil {
return xerrors.Errorf("getting full node libp2p address: %w", err)
}
if bootstrapLibP2P {
log.Infof("Bootstrapping libp2p network with full node")
if err := minerapi.NetConnect(ctx, remoteAddrs); err != nil {
return xerrors.Errorf("connecting to full node (libp2p): %w", err)
// Bootstrap with full node
remoteAddrs, err := nodeApi.NetAddrsListen(ctx)
if err != nil {
return xerrors.Errorf("getting full node libp2p address: %w", err)
}
if err := minerapi.NetConnect(ctx, remoteAddrs); err != nil {
return xerrors.Errorf("connecting to full node (libp2p): %w", err)
}
}
log.Infof("Remote version %s", v)
+16 -4
View File
@@ -36,10 +36,16 @@ var sealingWorkersCmd = &cli.Command{
Name: "workers",
Usage: "list workers",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "color"},
&cli.BoolFlag{
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
},
},
Action: func(cctx *cli.Context) error {
color.NoColor = !cctx.Bool("color")
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
@@ -127,14 +133,20 @@ var sealingJobsCmd = &cli.Command{
Name: "jobs",
Usage: "list running jobs",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "color"},
&cli.BoolFlag{
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
},
&cli.BoolFlag{
Name: "show-ret-done",
Usage: "show returned but not consumed calls",
},
},
Action: func(cctx *cli.Context) error {
color.NoColor = !cctx.Bool("color")
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
+22 -5
View File
@@ -161,9 +161,10 @@ var sectorsListCmd = &cli.Command{
Usage: "show removed sectors",
},
&cli.BoolFlag{
Name: "color",
Aliases: []string{"c"},
Value: true,
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
Aliases: []string{"c"},
},
&cli.BoolFlag{
Name: "fast",
@@ -183,7 +184,9 @@ var sectorsListCmd = &cli.Command{
},
},
Action: func(cctx *cli.Context) error {
color.NoColor = !cctx.Bool("color")
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
@@ -436,6 +439,12 @@ var sectorsExtendCmd = &cli.Command{
Usage: "when extending v1 sectors, don't try to extend sectors by fewer than this number of epochs",
Required: false,
},
&cli.Int64Flag{
Name: "expiration-ignore",
Value: 120,
Usage: "when extending v1 sectors, skip sectors whose current expiration is less than <ignore> epochs from now",
Required: false,
},
&cli.Int64Flag{
Name: "expiration-cutoff",
Usage: "when extending v1 sectors, skip sectors whose current expiration is more than <cutoff> epochs from now (infinity if unspecified)",
@@ -494,6 +503,10 @@ var sectorsExtendCmd = &cli.Command{
continue
}
if si.Expiration < (head.Height() + abi.ChainEpoch(cctx.Int64("expiration-ignore"))) {
continue
}
if cctx.IsSet("expiration-cutoff") {
if si.Expiration > (head.Height() + abi.ChainEpoch(cctx.Int64("expiration-cutoff"))) {
continue
@@ -508,6 +521,10 @@ var sectorsExtendCmd = &cli.Command{
// Set the new expiration to 48 hours less than the theoretical maximum lifetime
newExp := ml - (miner3.WPoStProvingPeriod * 2) + si.Activation
if withinTolerance(si.Expiration, newExp) || si.Expiration >= newExp {
continue
}
p, err := api.StateSectorPartition(ctx, maddr, si.SectorNumber, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("getting sector location for sector %d: %w", si.SectorNumber, err)
@@ -525,7 +542,7 @@ var sectorsExtendCmd = &cli.Command{
} else {
added := false
for exp := range es {
if withinTolerance(exp, newExp) {
if withinTolerance(exp, newExp) && newExp >= exp && exp > si.Expiration {
es[exp] = append(es[exp], uint64(si.SectorNumber))
added = true
break
+15 -6
View File
@@ -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, "", " ")
@@ -166,13 +166,19 @@ var storageListCmd = &cli.Command{
Name: "list",
Usage: "list local storage paths",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "color"},
&cli.BoolFlag{
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
},
},
Subcommands: []*cli.Command{
storageListSectorsCmd,
},
Action: func(cctx *cli.Context) error {
color.NoColor = !cctx.Bool("color")
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
@@ -478,12 +484,15 @@ var storageListSectorsCmd = &cli.Command{
Usage: "get list of all sector files",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "color",
Value: true,
Name: "color",
Usage: "use color in display output",
DefaultText: "depends on output being a TTY",
},
},
Action: func(cctx *cli.Context) error {
color.NoColor = !cctx.Bool("color")
if cctx.IsSet("color") {
color.NoColor = !cctx.Bool("color")
}
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
+1 -1
View File
@@ -314,7 +314,7 @@ var DaemonCmd = &cli.Command{
stop, err := node.New(ctx,
node.FullAPI(&api, node.Lite(isLite)),
node.Online(),
node.Base(),
node.Repo(r),
node.Override(new(dtypes.Bootstrapper), isBootstrapper),
+77 -2
View File
@@ -98,6 +98,7 @@
* [SealingAbort](#SealingAbort)
* [SealingSchedDiag](#SealingSchedDiag)
* [Sector](#Sector)
* [SectorAddPieceToAny](#SectorAddPieceToAny)
* [SectorCommitFlush](#SectorCommitFlush)
* [SectorCommitPending](#SectorCommitPending)
* [SectorGetExpectedSealDuration](#SectorGetExpectedSealDuration)
@@ -118,6 +119,7 @@
* [SectorsRefs](#SectorsRefs)
* [SectorsStatus](#SectorsStatus)
* [SectorsSummary](#SectorsSummary)
* [SectorsUnsealPiece](#SectorsUnsealPiece)
* [SectorsUpdate](#SectorsUpdate)
* [Storage](#Storage)
* [StorageAddLocal](#StorageAddLocal)
@@ -227,6 +229,7 @@ Response:
"PreCommitControl": null,
"CommitControl": null,
"TerminateControl": null,
"DealPublishControl": null,
"DisableOwnerFallback": true,
"DisableWorkerFallback": true
}
@@ -685,7 +688,6 @@ Response:
"SlashEpoch": 10101,
"FastRetrieval": true,
"Message": "string value",
"StoreID": 12,
"FundsReserved": "0",
"Ref": {
"TransferType": "string value",
@@ -704,7 +706,8 @@ Response:
"Responder": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
"ID": 3
},
"SectorNumber": 9
"SectorNumber": 9,
"CARv2FilePath": "string value"
}
```
@@ -1560,6 +1563,54 @@ Response: `{}`
## Sector
### SectorAddPieceToAny
Add piece to an open sector. If no sectors with enough space are open,
either a new sector will be created, or this call will block until more
sectors can be created.
Perms: admin
Inputs:
```json
[
1024,
{},
{
"PublishCid": null,
"DealID": 5432,
"DealProposal": {
"PieceCID": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
"PieceSize": 1032,
"VerifiedDeal": true,
"Client": "f01234",
"Provider": "f01234",
"Label": "string value",
"StartEpoch": 10101,
"EndEpoch": 10101,
"StoragePricePerEpoch": "0",
"ProviderCollateral": "0",
"ClientCollateral": "0"
},
"DealSchedule": {
"StartEpoch": 10101,
"EndEpoch": 10101
},
"KeepUnsealed": true
}
]
```
Response:
```json
{
"Sector": 9,
"Offset": 1032
}
```
### SectorCommitFlush
SectorCommitFlush immediately sends a Commit message with sectors aggregated for Commit.
Returns null if message wasn't sent
@@ -1860,6 +1911,30 @@ Response:
}
```
### SectorsUnsealPiece
Perms: admin
Inputs:
```json
[
{
"ID": {
"Miner": 1000,
"Number": 9
},
"ProofType": 8
},
1040384,
1024,
null,
null
]
```
Response: `{}`
### SectorsUpdate
+25 -2
View File
@@ -17,6 +17,7 @@
* [ChainGetBlockMessages](#ChainGetBlockMessages)
* [ChainGetGenesis](#ChainGetGenesis)
* [ChainGetMessage](#ChainGetMessage)
* [ChainGetMessagesInTipset](#ChainGetMessagesInTipset)
* [ChainGetNode](#ChainGetNode)
* [ChainGetParentMessages](#ChainGetParentMessages)
* [ChainGetParentReceipts](#ChainGetParentReceipts)
@@ -533,6 +534,28 @@ Response:
}
```
### ChainGetMessagesInTipset
ChainGetMessagesInTipset returns message stores in current tipset
Perms: read
Inputs:
```json
[
[
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
{
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
}
]
]
```
Response: `null`
### ChainGetNode
@@ -1444,7 +1467,7 @@ Inputs:
},
"Piece": null,
"Size": 42,
"LocalStore": 12,
"LocalCARV2FilePath": "string value",
"Total": "0",
"UnsealPrice": "0",
"PaymentInterval": 42,
@@ -1498,7 +1521,7 @@ Inputs:
},
"Piece": null,
"Size": 42,
"LocalStore": 12,
"LocalCARV2FilePath": "string value",
"Total": "0",
"UnsealPrice": "0",
"PaymentInterval": 42,
+25 -2
View File
@@ -17,6 +17,7 @@
* [ChainGetBlockMessages](#ChainGetBlockMessages)
* [ChainGetGenesis](#ChainGetGenesis)
* [ChainGetMessage](#ChainGetMessage)
* [ChainGetMessagesInTipset](#ChainGetMessagesInTipset)
* [ChainGetNode](#ChainGetNode)
* [ChainGetParentMessages](#ChainGetParentMessages)
* [ChainGetParentReceipts](#ChainGetParentReceipts)
@@ -535,6 +536,28 @@ Response:
}
```
### ChainGetMessagesInTipset
ChainGetMessagesInTipset returns message stores in current tipset
Perms: read
Inputs:
```json
[
[
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
{
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
}
]
]
```
Response: `null`
### ChainGetNode
@@ -1446,7 +1469,7 @@ Inputs:
},
"Piece": null,
"Size": 42,
"LocalStore": 12,
"LocalCARV2FilePath": "string value",
"Total": "0",
"UnsealPrice": "0",
"PaymentInterval": 42,
@@ -1500,7 +1523,7 @@ Inputs:
},
"Piece": null,
"Size": 42,
"LocalStore": 12,
"LocalCARV2FilePath": "string value",
"Total": "0",
"UnsealPrice": "0",
"PaymentInterval": 42,
+29 -9
View File
@@ -7,7 +7,7 @@ USAGE:
lotus-miner [global options] command [command options] [arguments...]
VERSION:
1.11.0-dev
1.11.1-dev
COMMANDS:
init Initialize a lotus miner repo
@@ -41,7 +41,7 @@ COMMANDS:
GLOBAL OPTIONS:
--actor value, -a value specify other actor to check state for (read only)
--color (default: false)
--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]
--help, -h show help (default: false)
--version, -v print the version (default: false)
@@ -57,6 +57,7 @@ USAGE:
COMMANDS:
restore Initialize a lotus miner repo from a backup
service Initialize a lotus miner sub-service
help, h Shows a list of commands or help for one command
OPTIONS:
@@ -93,6 +94,24 @@ OPTIONS:
```
### lotus-miner init service
```
NAME:
lotus-miner init service - Initialize a lotus miner sub-service
USAGE:
lotus-miner init service [command options] [backupFile]
OPTIONS:
--config value config file (config.toml)
--nosync don't check full-node sync status (default: false)
--type value type of service to be enabled
--api-sealer value sealer API info (lotus-miner auth api-info --perm=admin)
--api-sector-index value sector Index API info (lotus-miner auth api-info --perm=admin)
--help, -h show help (default: false)
```
## lotus-miner run
```
NAME:
@@ -295,7 +314,7 @@ USAGE:
OPTIONS:
--verbose (default: false)
--color (default: true)
--color use color in display output (default: depends on output being a TTY)
--help, -h show help (default: false)
```
@@ -888,7 +907,7 @@ USAGE:
OPTIONS:
--verbose, -v print verbose transfer details (default: false)
--color use color in display output (default: true)
--color use color in display output (default: depends on output being a TTY)
--completed show completed data transfers (default: false)
--watch watch deal updates in real-time, rather than a one time list (default: false)
--show-failed show failed/cancelled transfers (default: false)
@@ -1344,7 +1363,7 @@ USAGE:
OPTIONS:
--show-removed show removed sectors (default: false)
--color, -c (default: true)
--color, -c use color in display output (default: depends on output being a TTY)
--fast don't show on-chain info for better performance (default: false)
--events display number of events the sector has received (default: false)
--seal-time display how long it took for the sector to be sealed (default: false)
@@ -1405,6 +1424,7 @@ OPTIONS:
--new-expiration value new expiration epoch (default: 0)
--v1-sectors renews all v1 sectors up to the maximum possible lifetime (default: false)
--tolerance value when extending v1 sectors, don't try to extend sectors by fewer than this number of epochs (default: 20160)
--expiration-ignore value when extending v1 sectors, skip sectors whose current expiration is less than <ignore> epochs from now (default: 120)
--expiration-cutoff value when extending v1 sectors, skip sectors whose current expiration is more than <cutoff> epochs from now (infinity if unspecified) (default: 0)
--help, -h show help (default: false)
@@ -1739,7 +1759,7 @@ COMMANDS:
help, h Shows a list of commands or help for one command
OPTIONS:
--color (default: false)
--color use color in display output (default: depends on output being a TTY)
--help, -h show help (default: false)
--version, -v print the version (default: false)
@@ -1754,7 +1774,7 @@ USAGE:
lotus-miner storage list sectors [command options] [arguments...]
OPTIONS:
--color (default: true)
--color use color in display output (default: depends on output being a TTY)
--help, -h show help (default: false)
```
@@ -1816,7 +1836,7 @@ USAGE:
lotus-miner sealing jobs [command options] [arguments...]
OPTIONS:
--color (default: false)
--color use color in display output (default: depends on output being a TTY)
--show-ret-done show returned but not consumed calls (default: false)
--help, -h show help (default: false)
@@ -1831,7 +1851,7 @@ USAGE:
lotus-miner sealing workers [command options] [arguments...]
OPTIONS:
--color (default: false)
--color use color in display output (default: depends on output being a TTY)
--help, -h show help (default: false)
```
+1 -1
View File
@@ -7,7 +7,7 @@ USAGE:
lotus-worker [global options] command [command options] [arguments...]
VERSION:
1.11.0-dev
1.11.1-dev
COMMANDS:
run Start lotus worker
+6 -6
View File
@@ -7,7 +7,7 @@ USAGE:
lotus [global options] command [command options] [arguments...]
VERSION:
1.11.0-dev
1.11.1-dev
COMMANDS:
daemon Start a lotus daemon process
@@ -535,7 +535,7 @@ CATEGORY:
OPTIONS:
--verbose, -v print verbose deal details (default: false)
--color use color in display output (default: true)
--color use color in display output (default: depends on output being a TTY)
--show-failed show failed/failing deals (default: true)
--completed show completed retrievals (default: false)
--watch watch deal updates in real-time, rather than a one time list (default: false)
@@ -609,7 +609,7 @@ CATEGORY:
OPTIONS:
--verbose, -v print verbose deal details (default: false)
--color use color in display output (default: true)
--color use color in display output (default: depends on output being a TTY)
--show-failed show failed/failing deals (default: false)
--watch watch deal updates in real-time, rather than a one time list (default: false)
--help, -h show help (default: false)
@@ -747,7 +747,7 @@ CATEGORY:
OPTIONS:
--verbose, -v print verbose transfer details (default: false)
--color use color in display output (default: true)
--color use color in display output (default: depends on output being a TTY)
--completed show completed data transfers (default: false)
--watch watch deal updates in real-time, rather than a one time list (default: false)
--show-failed show failed/cancelled transfers (default: false)
@@ -1673,7 +1673,7 @@ NAME:
lotus state get-actor - Print actor information
USAGE:
lotus state get-actor [command options] [actorrAddress]
lotus state get-actor [command options] [actorAddress]
OPTIONS:
--help, -h show help (default: false)
@@ -2140,7 +2140,7 @@ USAGE:
lotus chain export [command options] [outputPath]
OPTIONS:
--tipset value
--tipset value specify tipset to start the export from (default: "@head")
--recent-stateroots value specify the number of recent state roots to include in the export (default: 0)
--skip-old-msgs (default: false)
--help, -h show help (default: false)
@@ -43,13 +43,8 @@ Testing an RC:
- [ ] **Stage 1 - Internal Testing**
- Binaries
- [ ] Ensure the RC release has downloadable binaries
- [ ] Validate the binary is able to run on at least one platform
- Upgrade our testnet infra
- [ ] 1 bootstrap node
- [ ] 1 miner
- [ ] Scratch nodes
- [ ] Wait 24 hours, confirm nodes stay in sync
- [ ] Remaining testnet infra
- Upgrade our mainnet infra
- [ ] Subset of development full archival nodes
- [ ] Subset of bootstrappers (1 per region)
+1 -1
View File
@@ -11,7 +11,6 @@ import (
"os"
"runtime"
"github.com/filecoin-project/lotus/extern/sector-storage/partialfile"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
@@ -24,6 +23,7 @@ import (
commpffi "github.com/filecoin-project/go-commp-utils/ffiwrapper"
"github.com/filecoin-project/go-commp-utils/zerocomm"
"github.com/filecoin-project/lotus/extern/sector-storage/fr32"
"github.com/filecoin-project/lotus/extern/sector-storage/partialfile"
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
)
+1 -1
View File
@@ -1,13 +1,13 @@
package ffiwrapper
import (
"github.com/filecoin-project/lotus/extern/sector-storage/partialfile"
"golang.org/x/xerrors"
rlepluslazy "github.com/filecoin-project/go-bitfield/rle"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/extern/sector-storage/partialfile"
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
)
+16 -3
View File
@@ -29,8 +29,6 @@ var log = logging.Logger("advmgr")
var ErrNoWorkers = errors.New("no suitable workers found")
type URLs []string
type Worker interface {
storiface.WorkerCalls
@@ -528,10 +526,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
+4 -4
View File
@@ -75,6 +75,10 @@ func (mgr *SectorMgr) NewSector(ctx context.Context, sector storage.SectorRef) e
return nil
}
func (mgr *SectorMgr) SectorsUnsealPiece(ctx context.Context, sector storage.SectorRef, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, commd *cid.Cid) error {
panic("SectorMgr: unsealing piece: implement me")
}
func (mgr *SectorMgr) AddPiece(ctx context.Context, sectorID storage.SectorRef, existingPieces []abi.UnpaddedPieceSize, size abi.UnpaddedPieceSize, r io.Reader) (abi.PieceInfo, error) {
log.Warn("Add piece: ", sectorID, size, sectorID.ProofType)
@@ -496,10 +500,6 @@ func (mgr *SectorMgr) ReturnFetch(ctx context.Context, callID storiface.CallID,
panic("not supported")
}
func (mgr *SectorMgr) SectorsUnsealPiece(ctx context.Context, sector storage.SectorRef, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, commd *cid.Cid) error {
return nil
}
func (m mockVerifProver) VerifySeal(svi proof5.SealVerifyInfo) (bool, error) {
plen, err := svi.SealProof.ProofSize()
if err != nil {
+2 -1
View File
@@ -7,7 +7,6 @@ import (
"syscall"
"github.com/detailyang/go-fallocate"
logging "github.com/ipfs/go-log/v2"
"golang.org/x/xerrors"
rlepluslazy "github.com/filecoin-project/go-bitfield/rle"
@@ -15,6 +14,8 @@ import (
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
logging "github.com/ipfs/go-log/v2"
)
var log = logging.Logger("partialfile")
+3 -4
View File
@@ -7,12 +7,12 @@ import (
"os"
"strconv"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/extern/sector-storage/partialfile"
"github.com/gorilla/mux"
logging "github.com/ipfs/go-log/v2"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/extern/sector-storage/partialfile"
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
"github.com/filecoin-project/lotus/extern/sector-storage/tarutil"
@@ -53,11 +53,10 @@ func (handler *FetchHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
mux := mux.NewRouter()
mux.HandleFunc("/remote/stat/{id}", handler.remoteStatFs).Methods("GET")
mux.HandleFunc("/remote/{type}/{id}/{spt}/allocated/{offset}/{size}", handler.remoteGetAllocated).Methods("GET")
mux.HandleFunc("/remote/{type}/{id}", handler.remoteGetSector).Methods("GET")
mux.HandleFunc("/remote/{type}/{id}", handler.remoteDeleteSector).Methods("DELETE")
mux.HandleFunc("/remote/{type}/{id}/{spt}/allocated/{offset}/{size}", handler.remoteGetAllocated).Methods("GET")
mux.ServeHTTP(w, r)
}
+2
View File
@@ -66,6 +66,8 @@ type SectorIndex interface { // part of storage-miner api
// atomically acquire locks on all sector file types. close ctx to unlock
StorageLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) error
StorageTryLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error)
StorageList(ctx context.Context) (map[ID][]Decl, error)
}
type Decl struct {
+2
View File
@@ -158,6 +158,8 @@ func (p *path) sectorPath(sid abi.SectorID, fileType storiface.SectorFileType) s
return filepath.Join(p.local, fileType.String(), storiface.SectorName(sid))
}
type URLs []string
func NewLocal(ctx context.Context, ls LocalStorage, index SectorIndex, urls []string) (*Local, error) {
l := &Local{
localStorage: ls,
+16 -1
View File
@@ -1,7 +1,7 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: index.go
// Package mock_stores is a generated GoMock package.
// Package mocks is a generated GoMock package.
package mocks
import (
@@ -125,6 +125,21 @@ func (mr *MockSectorIndexMockRecorder) StorageInfo(arg0, arg1 interface{}) *gomo
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageInfo", reflect.TypeOf((*MockSectorIndex)(nil).StorageInfo), arg0, arg1)
}
// StorageList mocks base method.
func (m *MockSectorIndex) StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StorageList", ctx)
ret0, _ := ret[0].(map[stores.ID][]stores.Decl)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StorageList indicates an expected call of StorageList.
func (mr *MockSectorIndexMockRecorder) StorageList(ctx interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageList", reflect.TypeOf((*MockSectorIndex)(nil).StorageList), ctx)
}
// StorageLock mocks base method.
func (m *MockSectorIndex) StorageLock(ctx context.Context, sector abi.SectorID, read, write storiface.SectorFileType) error {
m.ctrl.T.Helper()
+1 -1
View File
@@ -1,7 +1,7 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: interface.go
// Package mock_stores is a generated GoMock package.
// Package mocks is a generated GoMock package.
package mocks
import (
+26 -25
View File
@@ -297,6 +297,32 @@ func (r *Remote) fetch(ctx context.Context, url, outname string) error {
}
}
func (r *Remote) checkAllocated(ctx context.Context, url string, spt abi.RegisteredSealProof, offset, size abi.PaddedPieceSize) (bool, error) {
url = fmt.Sprintf("%s/%d/allocated/%d/%d", url, spt, offset.Unpadded(), size.Unpadded())
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return false, xerrors.Errorf("request: %w", err)
}
req.Header = r.auth.Clone()
fmt.Printf("req using header: %#v \n", r.auth)
req = req.WithContext(ctx)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return false, xerrors.Errorf("do request: %w", err)
}
defer resp.Body.Close() // nolint
switch resp.StatusCode {
case http.StatusOK:
return true, nil
case http.StatusRequestedRangeNotSatisfiable:
return false, nil
default:
return false, xerrors.Errorf("unexpected http response: %d", resp.StatusCode)
}
}
func (r *Remote) MoveStorage(ctx context.Context, s storage.SectorRef, types storiface.SectorFileType) error {
// Make sure we have the data local
_, _, err := r.AcquireSector(ctx, s, types, storiface.FTNone, storiface.PathStorage, storiface.AcquireMove)
@@ -419,31 +445,6 @@ func (r *Remote) FsStat(ctx context.Context, id ID) (fsutil.FsStat, error) {
return out, nil
}
func (r *Remote) checkAllocated(ctx context.Context, url string, spt abi.RegisteredSealProof, offset, size abi.PaddedPieceSize) (bool, error) {
url = fmt.Sprintf("%s/%d/allocated/%d/%d", url, spt, offset.Unpadded(), size.Unpadded())
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return false, xerrors.Errorf("request: %w", err)
}
req.Header = r.auth.Clone()
req = req.WithContext(ctx)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return false, xerrors.Errorf("do request: %w", err)
}
defer resp.Body.Close() // nolint
switch resp.StatusCode {
case http.StatusOK:
return true, nil
case http.StatusRequestedRangeNotSatisfiable:
return false, nil
default:
return false, xerrors.Errorf("unexpected http response: %d", resp.StatusCode)
}
}
func (r *Remote) readRemote(ctx context.Context, url string, offset, size abi.PaddedPieceSize) (io.ReadCloser, error) {
if len(r.limit) >= cap(r.limit) {
log.Infof("Throttling remote read, %d already running", len(r.limit))
+4 -382
View File
@@ -8,7 +8,7 @@ import (
"sort"
abi "github.com/filecoin-project/go-state-types/abi"
market "github.com/filecoin-project/specs-actors/actors/builtin/market"
api "github.com/filecoin-project/lotus/api"
miner "github.com/filecoin-project/specs-actors/actors/builtin/miner"
cid "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
@@ -46,7 +46,7 @@ func (t *Piece) MarshalCBOR(w io.Writer) error {
return err
}
// t.DealInfo (sealing.DealInfo) (struct)
// t.DealInfo (api.PieceDealInfo) (struct)
if len("DealInfo") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"DealInfo\" was too long")
}
@@ -107,7 +107,7 @@ func (t *Piece) UnmarshalCBOR(r io.Reader) error {
}
}
// t.DealInfo (sealing.DealInfo) (struct)
// t.DealInfo (api.PieceDealInfo) (struct)
case "DealInfo":
{
@@ -120,7 +120,7 @@ func (t *Piece) UnmarshalCBOR(r io.Reader) error {
if err := br.UnreadByte(); err != nil {
return err
}
t.DealInfo = new(DealInfo)
t.DealInfo = new(api.PieceDealInfo)
if err := t.DealInfo.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.DealInfo pointer: %w", err)
}
@@ -136,384 +136,6 @@ func (t *Piece) UnmarshalCBOR(r io.Reader) error {
return nil
}
func (t *DealInfo) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{165}); err != nil {
return err
}
scratch := make([]byte, 9)
// t.PublishCid (cid.Cid) (struct)
if len("PublishCid") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"PublishCid\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("PublishCid"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("PublishCid")); err != nil {
return err
}
if t.PublishCid == nil {
if _, err := w.Write(cbg.CborNull); err != nil {
return err
}
} else {
if err := cbg.WriteCidBuf(scratch, w, *t.PublishCid); err != nil {
return xerrors.Errorf("failed to write cid field t.PublishCid: %w", err)
}
}
// t.DealID (abi.DealID) (uint64)
if len("DealID") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"DealID\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("DealID"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("DealID")); err != nil {
return err
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.DealID)); err != nil {
return err
}
// t.DealProposal (market.DealProposal) (struct)
if len("DealProposal") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"DealProposal\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("DealProposal"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("DealProposal")); err != nil {
return err
}
if err := t.DealProposal.MarshalCBOR(w); err != nil {
return err
}
// t.DealSchedule (sealing.DealSchedule) (struct)
if len("DealSchedule") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"DealSchedule\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("DealSchedule"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("DealSchedule")); err != nil {
return err
}
if err := t.DealSchedule.MarshalCBOR(w); err != nil {
return err
}
// t.KeepUnsealed (bool) (bool)
if len("KeepUnsealed") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"KeepUnsealed\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("KeepUnsealed"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("KeepUnsealed")); err != nil {
return err
}
if err := cbg.WriteBool(w, t.KeepUnsealed); err != nil {
return err
}
return nil
}
func (t *DealInfo) UnmarshalCBOR(r io.Reader) error {
*t = DealInfo{}
br := cbg.GetPeeker(r)
scratch := make([]byte, 8)
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajMap {
return fmt.Errorf("cbor input should be of type map")
}
if extra > cbg.MaxLength {
return fmt.Errorf("DealInfo: map struct too large (%d)", extra)
}
var name string
n := extra
for i := uint64(0); i < n; i++ {
{
sval, err := cbg.ReadStringBuf(br, scratch)
if err != nil {
return err
}
name = string(sval)
}
switch name {
// t.PublishCid (cid.Cid) (struct)
case "PublishCid":
{
b, err := br.ReadByte()
if err != nil {
return err
}
if b != cbg.CborNull[0] {
if err := br.UnreadByte(); err != nil {
return err
}
c, err := cbg.ReadCid(br)
if err != nil {
return xerrors.Errorf("failed to read cid field t.PublishCid: %w", err)
}
t.PublishCid = &c
}
}
// t.DealID (abi.DealID) (uint64)
case "DealID":
{
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.DealID = abi.DealID(extra)
}
// t.DealProposal (market.DealProposal) (struct)
case "DealProposal":
{
b, err := br.ReadByte()
if err != nil {
return err
}
if b != cbg.CborNull[0] {
if err := br.UnreadByte(); err != nil {
return err
}
t.DealProposal = new(market.DealProposal)
if err := t.DealProposal.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.DealProposal pointer: %w", err)
}
}
}
// t.DealSchedule (sealing.DealSchedule) (struct)
case "DealSchedule":
{
if err := t.DealSchedule.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.DealSchedule: %w", err)
}
}
// t.KeepUnsealed (bool) (bool)
case "KeepUnsealed":
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajOther {
return fmt.Errorf("booleans must be major type 7")
}
switch extra {
case 20:
t.KeepUnsealed = false
case 21:
t.KeepUnsealed = true
default:
return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra)
}
default:
// Field doesn't exist on this type, so ignore it
cbg.ScanForLinks(r, func(cid.Cid) {})
}
}
return nil
}
func (t *DealSchedule) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{162}); err != nil {
return err
}
scratch := make([]byte, 9)
// t.StartEpoch (abi.ChainEpoch) (int64)
if len("StartEpoch") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"StartEpoch\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("StartEpoch"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("StartEpoch")); err != nil {
return err
}
if t.StartEpoch >= 0 {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.StartEpoch)); err != nil {
return err
}
} else {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.StartEpoch-1)); err != nil {
return err
}
}
// t.EndEpoch (abi.ChainEpoch) (int64)
if len("EndEpoch") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"EndEpoch\" was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("EndEpoch"))); err != nil {
return err
}
if _, err := io.WriteString(w, string("EndEpoch")); err != nil {
return err
}
if t.EndEpoch >= 0 {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.EndEpoch)); err != nil {
return err
}
} else {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.EndEpoch-1)); err != nil {
return err
}
}
return nil
}
func (t *DealSchedule) UnmarshalCBOR(r io.Reader) error {
*t = DealSchedule{}
br := cbg.GetPeeker(r)
scratch := make([]byte, 8)
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajMap {
return fmt.Errorf("cbor input should be of type map")
}
if extra > cbg.MaxLength {
return fmt.Errorf("DealSchedule: map struct too large (%d)", extra)
}
var name string
n := extra
for i := uint64(0); i < n; i++ {
{
sval, err := cbg.ReadStringBuf(br, scratch)
if err != nil {
return err
}
name = string(sval)
}
switch name {
// t.StartEpoch (abi.ChainEpoch) (int64)
case "StartEpoch":
{
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
var extraI int64
if err != nil {
return err
}
switch maj {
case cbg.MajUnsignedInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 positive overflow")
}
case cbg.MajNegativeInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 negative oveflow")
}
extraI = -1 - extraI
default:
return fmt.Errorf("wrong type for int64 field: %d", maj)
}
t.StartEpoch = abi.ChainEpoch(extraI)
}
// t.EndEpoch (abi.ChainEpoch) (int64)
case "EndEpoch":
{
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
var extraI int64
if err != nil {
return err
}
switch maj {
case cbg.MajUnsignedInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 positive overflow")
}
case cbg.MajNegativeInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 negative oveflow")
}
extraI = -1 - extraI
default:
return fmt.Errorf("wrong type for int64 field: %d", maj)
}
t.EndEpoch = abi.ChainEpoch(extraI)
}
default:
// Field doesn't exist on this type, so ignore it
cbg.ScanForLinks(r, func(cid.Cid) {})
}
}
return nil
}
func (t *SectorInfo) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
+1 -1
View File
@@ -62,7 +62,7 @@ func checkPieces(ctx context.Context, maddr address.Address, si SectorInfo, api
}
if proposal.PieceCID != p.Piece.PieceCID {
return &ErrInvalidDeals{xerrors.Errorf("piece %d (of %d) of sector %d refers deal %d with wrong PieceCID: %x != %x", i, len(si.Pieces), si.SectorNumber, p.DealInfo.DealID, p.Piece.PieceCID, proposal.PieceCID)}
return &ErrInvalidDeals{xerrors.Errorf("piece %d (of %d) of sector %d refers deal %d with wrong PieceCID: %s != %s", i, len(si.Pieces), si.SectorNumber, p.DealInfo.DealID, p.Piece.PieceCID, proposal.PieceCID)}
}
if p.Piece.Size != proposal.PieceSize {
+88 -21
View File
@@ -7,10 +7,6 @@ import (
"sync"
"time"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
@@ -18,13 +14,16 @@ import (
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/network"
miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner"
proof5 "github.com/filecoin-project/specs-actors/v5/actors/runtime/proof"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"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/sector-storage/ffiwrapper"
"github.com/filecoin-project/lotus/extern/storage-sealing/sealiface"
"github.com/filecoin-project/lotus/node/config"
@@ -32,6 +31,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 {
@@ -43,6 +45,7 @@ type CommitBatcherApi interface {
StateSectorPreCommitInfo(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok TipSetToken) (*miner.SectorPreCommitOnChainInfo, error)
StateMinerInitialPledgeCollateral(context.Context, address.Address, miner.SectorPreCommitInfo, TipSetToken) (big.Int, error)
StateNetworkVersion(ctx context.Context, tok TipSetToken) (network.Version, error)
StateMinerAvailableBalance(context.Context, address.Address, TipSetToken) (big.Int, error)
}
type AggregateInput struct {
@@ -103,6 +106,7 @@ func (b *CommitBatcher) run() {
panic(err)
}
timer := time.NewTimer(b.batchWait(cfg.CommitBatchWait, cfg.CommitBatchSlack))
for {
if forceRes != nil {
forceRes <- lastMsg
@@ -118,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
@@ -129,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
@@ -157,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)
@@ -170,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) {
@@ -193,8 +206,26 @@ func (b *CommitBatcher) maybeStartBatch(notif bool) ([]sealiface.CommitBatchRes,
var res []sealiface.CommitBatchRes
if total < cfg.MinCommitBatch || total < miner5.MinAggregatedSectors {
res, err = b.processIndividually()
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(cfg)
} else {
res, err = b.processBatch(cfg)
}
@@ -229,7 +260,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(),
@@ -305,16 +338,22 @@ 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)
goodFunds := big.Add(maxFee, big.Add(collateral, aggFee))
needFunds := big.Add(collateral, aggFee)
needFunds, err = collateralSendAmount(b.mctx, b.api, b.maddr, cfg, needFunds)
if err != nil {
return []sealiface.CommitBatchRes{res}, err
}
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)
}
@@ -326,12 +365,26 @@ func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBa
return []sealiface.CommitBatchRes{res}, nil
}
func (b *CommitBatcher) processIndividually() ([]sealiface.CommitBatchRes, error) {
func (b *CommitBatcher) processIndividually(cfg sealiface.Config) ([]sealiface.CommitBatchRes, 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()
}
}
tok, _, err := b.api.ChainHead(b.mctx)
if err != nil {
return nil, err
@@ -341,10 +394,11 @@ 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)
mcid, err := b.processSingle(cfg, mi, &avail, sn, info, tok)
if err != nil {
log.Errorf("process single error: %+v", err) // todo: return to user
r.FailedSectors[sn] = err.Error()
@@ -358,7 +412,7 @@ func (b *CommitBatcher) processIndividually() ([]sealiface.CommitBatchRes, error
return res, nil
}
func (b *CommitBatcher) processSingle(mi miner.MinerInfo, sn abi.SectorNumber, info AggregateInput, tok TipSetToken) (cid.Cid, error) {
func (b *CommitBatcher) processSingle(cfg sealiface.Config, mi miner.MinerInfo, avail *abi.TokenAmount, sn abi.SectorNumber, info AggregateInput, tok TipSetToken) (cid.Cid, error) {
enc := new(bytes.Buffer)
params := &miner.ProveCommitSectorParams{
SectorNumber: sn,
@@ -374,6 +428,19 @@ func (b *CommitBatcher) processSingle(mi miner.MinerInfo, sn abi.SectorNumber, i
return cid.Undef, err
}
if cfg.CollateralFromMinerBalance {
c := big.Sub(collateral, *avail)
*avail = big.Sub(*avail, collateral)
collateral = c
if collateral.LessThan(big.Zero()) {
collateral = big.Zero()
}
if (*avail).LessThan(big.Zero()) {
*avail = big.Zero()
}
}
goodFunds := big.Add(collateral, big.Int(b.feeCfg.MaxCommitGasFee))
from, _, err := b.addrSel(b.mctx, mi, api.CommitAddr, goodFunds, collateral)
+100 -15
View File
@@ -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, 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)
@@ -153,14 +156,40 @@ 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)
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(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 +212,11 @@ func TestCommitBatcher(t *testing.T) {
}
}
flush := func(expect []abi.SectorNumber) action {
flush := func(expect []abi.SectorNumber, aboveBalancer, failOnePCI bool) action {
return func(t *testing.T, s *mocks.MockCommitBatcherApi, pcb *sealing.CommitBatcher) promise {
_ = expectSend(expect)(t, s, pcb)
_ = expectSend(expect, aboveBalancer, failOnePCI)(t, s, pcb)
batch := len(expect) >= minBatch
batch := len(expect) >= minBatch && aboveBalancer
r, err := pcb.Flush(ctx)
require.NoError(t, err)
@@ -198,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 {
@@ -209,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)
}
}
}
@@ -227,33 +270,75 @@ 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, false),
},
},
"addTwo": {
"addTwo-aboveBalancer": {
actions: []action{
addSectors(getSectors(2)),
waitPending(2),
flush(getSectors(2)),
flush(getSectors(2), true, false),
},
},
"addAte": {
"addAte-aboveBalancer": {
actions: []action{
addSectors(getSectors(8)),
waitPending(8),
flush(getSectors(8)),
flush(getSectors(8), true, false),
},
},
"addMax": {
"addMax-aboveBalancer": {
actions: []action{
expectSend(getSectors(maxBatch)),
expectSend(getSectors(maxBatch), true, false),
addSectors(getSectors(maxBatch)),
},
},
"addSingle-belowBalancer": {
actions: []action{
addSector(0),
waitPending(1),
flush([]abi.SectorNumber{0}, false, false),
},
},
"addTwo-belowBalancer": {
actions: []action{
addSectors(getSectors(2)),
waitPending(2),
flush(getSectors(2), false, false),
},
},
"addAte-belowBalancer": {
actions: []action{
addSectors(getSectors(8)),
waitPending(8),
flush(getSectors(8), false, false),
},
},
"addMax-belowBalancer": {
actions: []action{
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 {
+1
View File
@@ -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),
-2
View File
@@ -12,8 +12,6 @@ import (
func main() {
err := gen.WriteMapEncodersToFile("./cbor_gen.go", "sealing",
sealing.Piece{},
sealing.DealInfo{},
sealing.DealSchedule{},
sealing.SectorInfo{},
sealing.Log{},
)
+10 -9
View File
@@ -14,6 +14,7 @@ import (
"github.com/filecoin-project/go-statemachine"
"github.com/filecoin-project/specs-storage/storage"
"github.com/filecoin-project/lotus/api"
sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
"github.com/filecoin-project/lotus/extern/storage-sealing/sealiface"
@@ -236,34 +237,34 @@ func (m *Sealing) handleAddPieceFailed(ctx statemachine.Context, sector SectorIn
return nil
}
func (m *Sealing) AddPieceToAnySector(ctx context.Context, size abi.UnpaddedPieceSize, data storage.Data, deal DealInfo) (abi.SectorNumber, abi.PaddedPieceSize, error) {
func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPieceSize, data storage.Data, deal api.PieceDealInfo) (api.SectorOffset, error) {
log.Infof("Adding piece for deal %d (publish msg: %s)", deal.DealID, deal.PublishCid)
if (padreader.PaddedSize(uint64(size))) != size {
return 0, 0, xerrors.Errorf("cannot allocate unpadded piece")
return api.SectorOffset{}, xerrors.Errorf("cannot allocate unpadded piece")
}
sp, err := m.currentSealProof(ctx)
if err != nil {
return 0, 0, xerrors.Errorf("getting current seal proof type: %w", err)
return api.SectorOffset{}, xerrors.Errorf("getting current seal proof type: %w", err)
}
ssize, err := sp.SectorSize()
if err != nil {
return 0, 0, err
return api.SectorOffset{}, err
}
if size > abi.PaddedPieceSize(ssize).Unpadded() {
return 0, 0, xerrors.Errorf("piece cannot fit into a sector")
return api.SectorOffset{}, xerrors.Errorf("piece cannot fit into a sector")
}
if _, err := deal.DealProposal.Cid(); err != nil {
return 0, 0, xerrors.Errorf("getting proposal CID: %w", err)
return api.SectorOffset{}, xerrors.Errorf("getting proposal CID: %w", err)
}
m.inputLk.Lock()
if _, exist := m.pendingPieces[proposalCID(deal)]; exist {
m.inputLk.Unlock()
return 0, 0, xerrors.Errorf("piece for deal %s already pending", proposalCID(deal))
return api.SectorOffset{}, xerrors.Errorf("piece for deal %s already pending", proposalCID(deal))
}
resCh := make(chan struct {
@@ -295,7 +296,7 @@ func (m *Sealing) AddPieceToAnySector(ctx context.Context, size abi.UnpaddedPiec
res := <-resCh
return res.sn, res.offset.Padded(), res.err
return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err
}
// called with m.inputLk
@@ -454,7 +455,7 @@ func (m *Sealing) StartPacking(sid abi.SectorNumber) error {
return m.sectors.Send(uint64(sid), SectorStartPacking{})
}
func proposalCID(deal DealInfo) cid.Cid {
func proposalCID(deal api.PieceDealInfo) cid.Cid {
pc, err := deal.DealProposal.Cid()
if err != nil {
log.Errorf("DealProposal.Cid error: %+v", err)
+15
View File
@@ -88,6 +88,21 @@ func (mr *MockCommitBatcherApiMockRecorder) SendMsg(arg0, arg1, arg2, arg3, arg4
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMsg", reflect.TypeOf((*MockCommitBatcherApi)(nil).SendMsg), arg0, arg1, arg2, arg3, arg4, arg5, arg6)
}
// StateMinerAvailableBalance mocks base method.
func (m *MockCommitBatcherApi) StateMinerAvailableBalance(arg0 context.Context, arg1 address.Address, arg2 sealing.TipSetToken) (big.Int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateMinerAvailableBalance", arg0, arg1, arg2)
ret0, _ := ret[0].(big.Int)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateMinerAvailableBalance indicates an expected call of StateMinerAvailableBalance.
func (mr *MockCommitBatcherApiMockRecorder) StateMinerAvailableBalance(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateMinerAvailableBalance", reflect.TypeOf((*MockCommitBatcherApi)(nil).StateMinerAvailableBalance), arg0, arg1, arg2)
}
// StateMinerInfo mocks base method.
func (m *MockCommitBatcherApi) StateMinerInfo(arg0 context.Context, arg1 address.Address, arg2 sealing.TipSetToken) (miner.MinerInfo, error) {
m.ctrl.T.Helper()
+15
View File
@@ -71,6 +71,21 @@ func (mr *MockPreCommitBatcherApiMockRecorder) SendMsg(arg0, arg1, arg2, arg3, a
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMsg", reflect.TypeOf((*MockPreCommitBatcherApi)(nil).SendMsg), arg0, arg1, arg2, arg3, arg4, arg5, arg6)
}
// StateMinerAvailableBalance mocks base method.
func (m *MockPreCommitBatcherApi) StateMinerAvailableBalance(arg0 context.Context, arg1 address.Address, arg2 sealing.TipSetToken) (big.Int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateMinerAvailableBalance", arg0, arg1, arg2)
ret0, _ := ret[0].(big.Int)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateMinerAvailableBalance indicates an expected call of StateMinerAvailableBalance.
func (mr *MockPreCommitBatcherApiMockRecorder) StateMinerAvailableBalance(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateMinerAvailableBalance", reflect.TypeOf((*MockPreCommitBatcherApi)(nil).StateMinerAvailableBalance), arg0, arg1, arg2)
}
// StateMinerInfo mocks base method.
func (m *MockPreCommitBatcherApi) StateMinerInfo(arg0 context.Context, arg1 address.Address, arg2 sealing.TipSetToken) (miner.MinerInfo, error) {
m.ctrl.T.Helper()
+24 -9
View File
@@ -7,9 +7,6 @@ import (
"sync"
"time"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
@@ -20,7 +17,9 @@ import (
miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner"
"github.com/filecoin-project/lotus/api"
"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/extern/storage-sealing/sealiface"
"github.com/filecoin-project/lotus/node/config"
)
@@ -30,6 +29,7 @@ import (
type PreCommitBatcherApi interface {
SendMsg(ctx context.Context, from, to address.Address, method abi.MethodNum, value, maxFee abi.TokenAmount, params []byte) (cid.Cid, error)
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)
}
@@ -88,6 +88,7 @@ func (b *PreCommitBatcher) run() {
panic(err)
}
timer := time.NewTimer(b.batchWait(cfg.PreCommitBatchWait, cfg.PreCommitBatchSlack))
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.PreCommitBatchWait, cfg.PreCommitBatchSlack))
}
}
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) {
@@ -216,6 +226,11 @@ 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)

Some files were not shown because too many files have changed in this diff Show More