Compare commits

...
237 Commits
Author SHA1 Message Date
Aayush Rajasekaran 4121063ca4 Merge pull request #3905 from filecoin-project/asr/changelog
Lotus version 0.7.1
2020-09-17 21:32:04 -04:00
Aayush Rajasekaran aa081dbc6d Lotus version 0.7.1 2020-09-17 21:31:47 -04:00
Łukasz Magiera 984eee8cd6 Merge pull request #3909 from filecoin-project/fix/post-no-skip
wdpost: Only add proven partitions to message params
2020-09-18 03:14:05 +02:00
Łukasz Magiera 26bbd9fb9d wdpost: append is hard 2020-09-18 03:00:31 +02:00
Łukasz Magiera 57c1eac37a gofmt 2020-09-18 02:40:01 +02:00
Łukasz Magiera 8419dda84b wdpost: Only add proven partitions to message params 2020-09-18 02:39:08 +02:00
Łukasz Magiera dcc5643473 shed: Even more bitfield utils 2020-09-18 02:38:30 +02:00
Aayush Rajasekaran 1a101e53a6 Merge pull request #3906 from filecoin-project/feat/upgrade-markets-v0.6.1
Upgrade markets v0.6.1
2020-09-17 15:45:53 -04:00
hannahhoward a894c1e8e6 feat(markets): upgrade markets v0.6.1 2020-09-17 12:30:26 -07:00
Łukasz Magiera b85b50afbc shed: bitfield intersect command 2020-09-17 20:37:35 +02:00
Łukasz Magiera 97064f1d15 Merge pull request #3886 from filecoin-project/feat/retrieval-set-get-ask
Add get-ask, set-ask retrieval commands
2020-09-17 10:32:41 +02:00
Ingar Shu f56602c588 Specify retrieval price in FIL/GiB 2020-09-16 14:30:04 -07:00
Łukasz Magiera c66ebc50c1 Merge pull request #3875 from filecoin-project/feat/break-on-stop-sleep
break out of mining loop when stop is called during niceSleep
2020-09-16 23:11:04 +02:00
Ingar Shu 2aef7f7c07 Clarify help text units 2020-09-16 13:56:46 -07:00
Ingar Shu 665d23cb8e Add set-ask, get-ask retrieval CLI 2020-09-16 13:56:46 -07:00
Łukasz Magiera 3b00c6838a Merge remote-tracking branch 'origin/master' into feat/break-on-stop-sleep 2020-09-16 22:56:21 +02:00
Łukasz Magiera a6b7791d32 lint 2020-09-16 22:56:04 +02:00
Łukasz Magiera 34d31d8124 Merge pull request #3856 from filecoin-project/compile-lotus-soup-testplan
add filecoin-project oni as submodule and compile lotus-soup
2020-09-16 22:54:34 +02:00
Łukasz Magiera 6656e5a6c8 circle: test-lotus-soup -> build-lotus-soup 2020-09-16 22:47:06 +02:00
Łukasz Magiera 487765548e Merge remote-tracking branch 'origin/master' into compile-lotus-soup-testplan 2020-09-16 22:42:54 +02:00
Łukasz Magiera ecd115c002 Merge pull request #3862 from filecoin-project/compile-with-build-flag-testground
make sure lotus compiles with +testground build flag
2020-09-16 22:41:24 +02:00
Raúl Kripalani 5a8ee0dd2a Merge pull request #3861 from filecoin-project/feat/chaos-inspect-runtime 2020-09-16 15:50:08 +01:00
Raúl Kripalani 4fbb322fa2 Merge branch 'master' into feat/chaos-inspect-runtime 2020-09-16 15:37:28 +01:00
Anton Evangelatov 56f223bfc3 add go mod edit for blst deps 2020-09-16 15:19:17 +02:00
Anton Evangelatov 0ff5a71114 update oni to master 2020-09-16 15:13:28 +02:00
Anton Evangelatov b0677ab38e replace lotus and filecoin-ffi deps 2020-09-16 15:12:41 +02:00
Anton Evangelatov f4f80b25d1 add test-lotus-soup to workflows 2020-09-16 15:12:41 +02:00
Anton Evangelatov 3f67c4524e add filecoin-project oni as submodule and compile lotus-soup 2020-09-16 15:12:41 +02:00
Anton Evangelatov b4115021c5 make sure lotus compiles with +testground build flag 2020-09-16 13:43:28 +02:00
Łukasz Magiera b78ffd18c6 Merge pull request #3883 from filcloud/Update-ignore
add lotus-pcr to ignore
2020-09-16 13:39:01 +02:00
Łukasz Magiera c9a8f3b8a0 Merge pull request #3874 from filecoin-project/asr/deal-duration
Make interactive deal CLI reject deals shorter than minimum duration
2020-09-16 13:08:47 +02:00
Frank d870c74a5e add lotus-pcr to ignore 2020-09-16 19:08:47 +08:00
Łukasz Magiera 3d61a37fcf Merge pull request #3880 from filecoin-project/fix/gas-outputs-regression
fix a regression caused by #3800 (GasOutputs zero values)
2020-09-16 12:24:22 +02:00
Łukasz Magiera 0c41522ebf Merge pull request #3873 from filecoin-project/unify-wdpost-log
Use `window post` for window PoSt related log messages.
2020-09-16 12:00:45 +02:00
Raúl Kripalani 362fc180ec fix a regression caused by #3800. 2020-09-16 10:54:26 +01:00
Łukasz Magiera 2db7b8c998 Merge pull request #3872 from zgfzgf/master
Replace fx.Extract with fx.Populate
2020-09-16 11:50:59 +02:00
Aayush Rajasekaran e04331b07c Merge pull request #3682 from filecoin-project/asr/chainstore-state-tree
Sever chainstore's dependence on the state tree
2020-09-16 00:39:26 -04:00
Travis Person 808051d34e break out of mining loop when stop is called during niceSleep 2020-09-16 02:06:40 +00:00
Aayush Rajasekaran e2cf0c4d4c Make interactive deal CLI reject deals shorter than minimum duration 2020-09-15 21:24:30 -04:00
jennijuju 5c69249ba3 Use window post for window PoSt related log messages. 2020-09-15 21:22:29 -04:00
zgfzgf fa9be9a627 Replace fx.Extract with fx.Populate 2020-09-16 09:14:56 +08:00
Aayush Rajasekaran 937ff4e9ae Add a sync test around blocks with bad nonce messages 2020-09-15 20:55:11 -04:00
Aayush Rajasekaran 952f2c2f1e Sever chainstore's dependence on the state tree 2020-09-15 20:41:34 -04:00
Alan Shaw ed4caac9bf fix: remove network version and total fil 2020-09-15 22:24:09 +01:00
Jakub Sztandera 0c1c19c6ef Merge pull request #3867 from filecoin-project/feat/lotus-bench-repo-dir
allow specification of repo directory in lotus-bench
2020-09-15 23:21:04 +02:00
whyrusleeping 24756ac056 allow specification of repo directory in lotus-bench 2020-09-15 11:55:54 -07:00
Łukasz Magiera d4a7732d0a Merge pull request #3800 from filecoin-project/asr/gascost
Add an API to get detailed gas costs for a message
2020-09-15 19:13:20 +02:00
Alan Shaw ae326ce65d feat: add inspect runtime method to chaos actor 2020-09-15 15:43:37 +01:00
Łukasz Magiera 531b7bf92d Merge pull request #3848 from filecoin-project/feat/state-sector-cli
cli: state sector command
2020-09-15 15:30:04 +02:00
Łukasz Magiera 84fa22110f fix lint 2020-09-15 12:09:43 +02:00
Łukasz Magiera e22aa74865 Merge pull request #3780 from filecoin-project/feat/lotus-gateway
implement initial lotus-gateway program
2020-09-15 12:07:59 +02:00
Łukasz Magiera 285fc69f6a gateway: address review 2020-09-15 11:50:08 +02:00
Łukasz Magiera 72216fe917 Merge pull request #3647 from filecoin-project/fix/enable-strict-basefee-check
re-enable baseFee lower bound check
2020-09-15 11:38:28 +02:00
Łukasz Magiera 692027f625 Merge pull request #3819 from zgfzgf/zgfzgf
optimize Settings.nodeType
2020-09-15 10:42:23 +02:00
Łukasz Magiera 801e01bca0 Merge pull request #3778 from filecoin-project/feat/less-restrictive-read-piece-lock
Allow retrievals while sealing
2020-09-15 10:34:00 +02:00
Łukasz Magiera 6665a9ca69 Merge pull request #3845 from filecoin-project/sync-manager
syncer: make SyncManager an interface.
2020-09-15 10:28:48 +02:00
Łukasz Magiera 1c02a417db Merge pull request #3850 from filecoin-project/asr/msig-avail
Fix MsigGetAvailableBalance
2020-09-15 10:22:27 +02:00
Łukasz Magiera 9ec26e776d Merge pull request #3851 from filecoin-project/fix/paych-status-commands
Fix payment channel status commands
2020-09-15 10:21:16 +02:00
Łukasz Magiera cf82483420 Merge pull request #3689 from filecoin-project/feat/batch-window-PoST
storage: split window PoST submission into multiple messages
2020-09-15 10:17:22 +02:00
Dirk McCormick db998e9c0f fix: storage - move rand generation after proofs 2020-09-15 09:52:55 +02:00
Dirk McCormick f0f15f899c feat: split window PoST messages into batches 2020-09-15 09:43:18 +02:00
hannahhoward 7dc091052a feat(manager): less restrictive storage lock
Use initial less restrictive storage lock when trying to read unsealed data before acquiring more
restrictive lock needed for unsealing
2020-09-14 18:48:14 -07:00
hannahhoward 17e44af542 docs(api): fix api docs 2020-09-14 18:44:45 -07:00
hannahhoward ac8ef29d35 fix(paych): add paych status from to cmd
add missing from to status to list
2020-09-14 18:42:10 -07:00
hannahhoward 48e47ddc23 fix(paych): fix paych status command line 2020-09-14 18:42:10 -07:00
Aayush Rajasekaran 6acd3d6028 Fix MsigGetAvailableBalance 2020-09-14 21:12:32 -04:00
Łukasz Magiera 7fd5c81674 cli: state sector command 2020-09-15 01:36:49 +02:00
Steven Allen f9ea3935ff Merge pull request #3846 from filecoin-project/steb/specs-actors-0.9.10
Update specs-actors to 0.9.10
2020-09-14 14:45:04 -07:00
Steven Allen 9804310cc8 Update specs-actors to 0.9.10
Moves the Keyer type (and helpers) into go-state-types.
2020-09-14 14:32:57 -07:00
Aayush Rajasekaran 07e574db44 Merge pull request #3844 from filecoin-project/steb/specs-actors-0.9.9
Update to specs-actors 0.9.9
2020-09-14 17:19:03 -04:00
Raúl Kripalani dd841f32db syncer: make SyncManager an interface. 2020-09-14 21:58:59 +01:00
Łukasz Magiera 665f93bbb7 Merge pull request #3839 from filecoin-project/fix/skipped-skipping
wdpost: Skip sectors correctly
2020-09-14 21:56:43 +02:00
Steven Allen 32eeb96ce7 Update to specs-actors 0.9.9
This patch changes the runtime interfaces, to make it possible to abstract over them.
2020-09-14 12:47:39 -07:00
vyzo 172bfacae0 compute baseFee for check even in null rounds 2020-09-14 22:20:26 +03:00
vyzo 0a5494dd79 use the factor in getBaseFeeLowerBound 2020-09-14 22:13:37 +03:00
vyzo 044202b37f use conservative base fee lower bound factor for strict checks 2020-09-14 22:13:37 +03:00
vyzo d68ec37942 reenable baseFee lower bound check 2020-09-14 22:13:37 +03:00
Aayush Rajasekaran 0edcae9e04 Fixup new command 2020-09-14 14:40:38 -04:00
Aayush Rajasekaran d1850ea27d Add an API to get detailed gas costs for a message 2020-09-14 14:40:13 -04:00
Aayush Rajasekaran 60a031a713 Lower devnet block time 2020-09-14 14:40:13 -04:00
Łukasz Magiera 8a05fe86d6 wdpost: Skip sectors correctly 2020-09-14 20:33:54 +02:00
Mike Greenberg 8a21198f56 Merge pull request #3765 from ggq89/master
optimize definition of state_heights
2020-09-14 14:19:31 -04:00
Whyrusleeping b212368a70 Merge pull request #2455 from filecoin-project/inmem-journal
make journal pluggable; record deals, sealing, wdpost, mempool events
2020-09-14 11:17:21 -07:00
Raúl Kripalani 954ff32503 fix transitive api dependency on ffi. 2020-09-14 19:01:35 +01:00
Raúl Kripalani 7c13fa95d1 Merge branch 'master' into inmem-journal 2020-09-14 17:01:36 +01:00
Raúl Kripalani 09e9d6d778 deal journal events: wire into markets subscriptions. 2020-09-14 16:20:01 +01:00
Raúl Kripalani 86607452d7 circleci: make lint expend all cores. (#3831)
* circleci: make lint expend all cores.

* i hate yaml.

* now i hate it even more.
2020-09-14 14:18:53 +02:00
Raúl Kripalani 05aa5f2d38 allow customizing disabled journal events + tests. 2020-09-14 13:01:03 +01:00
Raúl Kripalani 6d29d75724 Merge branch 'master' into inmem-journal 2020-09-14 12:17:45 +01:00
Łukasz Magiera 3a34856dfe Merge pull request #3822 from filcloud/issue-2495-make-nested-dir
make nested dir
2020-09-14 13:06:14 +02:00
Aarsh Shah 973738d30f Merge pull request #3767 from filecoin-project/fix/addpiece-retry
Retry Add Piece.
2020-09-14 15:44:48 +05:30
Albert·Gou 747b34c2c8 Update sync.go 2020-09-14 18:00:17 +08:00
Frank dcae513487 make nested dir 2020-09-14 16:49:35 +08:00
Łukasz Magiera 18c025f10e Merge pull request #3777 from filecoin-project/feat/plan-20-blocks
Increase the FeeCap estimation to 20 blocks in a future
2020-09-14 10:20:17 +02:00
Albert·Gou e45a7749b0 Update sync.go 2020-09-14 16:20:01 +08:00
Albert·Gou b7ea145f38 Merge remote-tracking branch 'upstream/master' into master 2020-09-14 16:17:10 +08:00
Aarsh Shah 6c61ff0e9e log error 2020-09-14 12:04:50 +05:30
zgfzgf 45a5eaf913 optimize Settings.nodeType 2020-09-14 11:00:08 +08:00
whyrusleeping 3401cb349b add mpool push and chainHead 2020-09-11 23:07:20 -07:00
whyrusleeping 8b9a3ea6c3 implement initial lotus-gateway program 2020-09-11 20:01:37 -07:00
Jakub Sztandera d5aef296ea Increase the FeeCap estimation to 20 blocks in a future
FeeCap will be set to 10x the current running rate

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-11 21:59:51 +02:00
Łukasz Magiera aa83a4c1f5 Merge pull request #3772 from filecoin-project/fix/prune-protect-local
don't prune locally published messages
2020-09-11 21:46:21 +02:00
Łukasz Magiera b83463ca76 Merge pull request #3774 from filecoin-project/fix/paych-status-missing
add paych status command to list
2020-09-11 21:45:25 +02:00
Łukasz Magiera c1ca24e8bc Merge pull request #3775 from filecoin-project/fix/markets-message-cid-update
Fix for PublishDeals message cid changing due to gas
2020-09-11 21:44:56 +02:00
vyzo b78fe0b898 fix deadlock 2020-09-11 21:40:25 +03:00
vyzo bf1036c78f rename priority variable to protected 2020-09-11 21:12:11 +03:00
Ingar Shu 2e3ff9e401 Update market client/provider adapters to WaitForMessage API 2020-09-11 11:00:42 -07:00
Aarsh Shah eabdf74946 changes as per review 2020-09-11 23:15:57 +05:30
vyzo cf9820137c don't prune locally published messages 2020-09-11 20:32:52 +03:00
Raúl Kripalani c017d0fbaf Merge pull request #3768 from filecoin-project/fix/chaos-tests
fix: chaos tests
2020-09-11 15:45:02 +01:00
Alan Shaw 16f7d5801b fix: chaos tests 2020-09-11 15:25:59 +01:00
Aarsh Shah 62b2963781 retry add piece 2020-09-11 16:58:09 +05:30
Raúl Kripalani cd9858420f Merge pull request #3736 from filecoin-project/test/chaos-tests 2020-09-11 12:18:27 +01:00
Łukasz Magiera 4410da98be Merge pull request #3766 from filecoin-project/fix/mpool-prune
refactor getBaseFeeLowerBound, use it to prune less aggressively
2020-09-11 11:40:26 +02:00
Łukasz Magiera b89aa02d77 Merge pull request #3710 from filecoin-project/feat/window-post-faulty-sectors
windowed post generation now returns faulty sectors
2020-09-11 11:15:32 +02:00
vyzo 3dfb3e641b refactor getBaseFeeLowerBound, use it to prune less aggressively 2020-09-11 12:15:03 +03:00
Łukasz Magiera a3f228d05a Merge pull request #3739 from filecoin-project/upd/badger
Upgrade badger
2020-09-11 11:14:39 +02:00
Łukasz Magiera eaf9ebc2ca Merge pull request #3752 from filecoin-project/fix/mpool-replace-auto
Fix mpool replace --auto
2020-09-11 11:12:35 +02:00
Łukasz Magiera 55e4183825 Merge pull request #3754 from filecoin-project/feat/shed-export
Add faster and slimmer option to chain export via lotus-shed
2020-09-11 11:10:41 +02:00
Łukasz Magiera aeb3437a9f lint, docsgen 2020-09-11 10:55:10 +02:00
Albert·Gou 6e7de3c8d9 optimize definition of state_heights
In the same parentstateroot, the one with the smallest height should be selected
2020-09-11 16:52:48 +08:00
Łukasz Magiera d0175392c0 Merge remote-tracking branch 'origin/master' into feat/window-post-faulty-sectors 2020-09-11 10:47:39 +02:00
Łukasz Magiera c4b3970c70 mod tidy 2020-09-11 10:41:24 +02:00
whyrusleeping 72eb17d314 wire skip old messages option through the api 2020-09-10 17:40:47 -07:00
whyrusleeping 0efe5ee7d5 include some other changes 2020-09-10 17:32:30 -07:00
whyrusleeping 0e3dd3cb3b Add faster and slimmer option to chain export via lotus-shed 2020-09-10 17:28:25 -07:00
hannahhoward 56b237e7b8 fix(paych): add status command to list
Add paych status cmd to list of payment channel sub commands
2020-09-10 16:00:23 -07:00
Jakub Sztandera 2865a0367b Fix mpool replace --auto
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-11 00:59:57 +02:00
Aayush Rajasekaran 232cc320bd Merge pull request #3747 from filecoin-project/ntwk-0.7.0
Ntwk 0.7.0
2020-09-10 18:07:06 -04:00
Aayush Rajasekaran e7edc46daf Lotus version 0.7.0 2020-09-10 17:56:54 -04:00
Jakub Sztandera 6813ab4e65 Add additional metrics
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 17:41:55 -04:00
Jakub Sztandera fd714cbceb Remove PackingEfficiency consideration from base fee in an upgrade
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 17:41:55 -04:00
whyrusleeping db6bd890d9 condition randomness changes on fork height
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 17:41:55 -04:00
Steven Allen 7a46c5ff31 [WIP] Fix ticket randomness
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 17:41:55 -04:00
Aayush Rajasekaran 98a9042c07 Use newest network version in genesiss setup stuff 2020-09-10 17:41:55 -04:00
Aayush Rajasekaran 4170e18dea fix testground build 2020-09-10 17:41:55 -04:00
Aayush Rajasekaran 230ef2484d fix tests 2020-09-10 17:41:55 -04:00
Aayush Rajasekaran beba92aed4 Improve network versioning logic 2020-09-10 17:41:55 -04:00
Aayush Rajasekaran cbb693e99e Update docs 2020-09-10 17:41:55 -04:00
Aayush Rajasekaran 774e068436 Update to specs-actors v0.9.8 2020-09-10 17:41:55 -04:00
Aayush Rajasekaran 86ba21029d Update to go state types 001afaca718c 2020-09-10 17:41:55 -04:00
Aayush Rajasekaran 316ac61875 Update to go state types 3ca0d2890090 2020-09-10 17:41:55 -04:00
Jakub Sztandera d5d264d13b Add fork point
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 17:41:55 -04:00
Jakub Sztandera c71e1adc93 Integrate multiple drand networks with pubsub
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 17:41:55 -04:00
Jakub Sztandera 564d0ae974 Upgrade drand
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 17:41:55 -04:00
Jakub Sztandera 9a48ec194e Add DrandSchedule to testground params
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 17:41:55 -04:00
Jakub Sztandera bb0a7f91cc Fix drand non-test
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 17:41:55 -04:00
Jakub Sztandera 73e54352cd Fix off by one
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 17:41:55 -04:00
Jakub Sztandera 64fa6fd9e5 Draw the rest of the owl
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 17:41:55 -04:00
Jakub Sztandera 2d3f92aeed Introduce beacon Schedule
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 17:41:55 -04:00
Jakub Sztandera df5750a21c go mod tidy
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 23:15:56 +02:00
Łukasz Magiera e996a5246b Merge remote-tracking branch 'origin/master' into feat/window-post-faulty-sectors 2020-09-10 22:18:17 +02:00
Łukasz Magiera bbac86f745 gofmt, mod tidy 2020-09-10 22:07:20 +02:00
Łukasz Magiera 22556fb24c Add fil-blst submodule 2020-09-10 22:04:08 +02:00
Łukasz Magiera 2374cb1bc5 Update ffi 2020-09-10 21:44:01 +02:00
Łukasz Magiera c7b0241a48 ffiwrapper: Test skipping corrupted sectors in PoSt 2020-09-10 21:19:26 +02:00
Jakub Sztandera dc85a276cd Upgrade badger
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-10 19:17:48 +02:00
Łukasz Magiera 9e9856bb45 Merge pull request #3590 from filecoin-project/asr/multisig
Multisig API additions
2020-09-10 17:04:48 +02:00
Łukasz Magiera 890e6280df Merge pull request #3669 from filecoin-project/feat/independent-version-numbers
build: Separate API versions per node type
2020-09-10 17:00:32 +02:00
Alan Shaw c94ff3430c refactor: use nil value 2020-09-10 14:51:30 +01:00
Łukasz Magiera da7e4b3a09 Merge pull request #3735 from filecoin-project/deps/update-pubsub
update go-libp2p-pubsub@master
2020-09-10 15:35:28 +02:00
Alan Shaw a214069586 chore: appease linter 2020-09-10 14:30:52 +01:00
Alan Shaw d4b185be5e test: add chaos actor tests 2020-09-10 14:23:39 +01:00
Raúl Kripalani 747a7de168 Merge pull request #3733 from filecoin-project/feat/chaos-abort-2 2020-09-10 14:20:34 +01:00
vyzo bfa47b3663 update go-libp2p-pubsub@master 2020-09-10 16:11:23 +03:00
Alan Shaw 0e7f14159a refactor: another rename 2020-09-10 12:06:00 +01:00
Alan Shaw b755ce9528 refactor: renames 2020-09-10 12:03:13 +01:00
Alan Shaw f3cae55bd4 feat: chaos abort 2020-09-10 11:31:34 +01:00
Łukasz Magiera f64bd55bc6 Merge pull request #3720 from filecoin-project/fix/increase-precommit2-retry-counter
Increase the number of times precommit2 is attempted before moving back to precommit1
2020-09-10 11:52:01 +02:00
Łukasz Magiera 4c8bb846ea Merge pull request #3724 from filecoin-project/fix/relax-strictness-push
relax mpool add strictness checks for local pushes
2020-09-10 11:51:02 +02:00
Łukasz Magiera bd14fb90fc Merge pull request #3729 from filecoin-project/fix/statediff-ci
ci: fix statediff build; make optional.
2020-09-10 11:49:04 +02:00
Raúl Kripalani 9e5bce90f4 ci: fix statediff build; make optional. 2020-09-10 10:41:18 +01:00
vyzo 72c7d4c886 relax mpool add strictness checks for local pushes
So that a node can have more than 1k pending messages for its own local addresses.
2020-09-10 09:55:50 +03:00
lanzafame 558b637b07 Increase the number of times precommit2 is attempted before moving back to precommit1 2020-09-10 13:52:21 +10:00
Whyrusleeping 767341b279 Merge pull request #3437 from filecoin-project/feat/mpool-stats-cmd
add a simple command to watch messages sitting in the mempool
2020-09-09 18:29:42 -07:00
Łukasz Magiera 5e7737f55d wdpost: Handle skipped sectors correctly 2020-09-10 02:59:37 +02:00
whyrusleeping c73916b4e7 fix the linter 2020-09-09 17:37:49 -07:00
whyrusleeping 0361ca1c39 add some bits about windowed post 2020-09-09 17:18:55 -07:00
Aayush Rajasekaran cd4cd22928 Merge pull request #3717 from filecoin-project/asr/checkpoint-msg
Fix IsAncestorOf
2020-09-09 19:49:47 -04:00
Aayush Rajasekaran e1a0cf6ca5 Add a checkpoint test 2020-09-09 19:21:48 -04:00
Łukasz Magiera 73bb9d5afb Merge pull request #3715 from filecoin-project/fix/chainwatch/partition-diff
fix(chainwatch): compare prev miner with cur miner
2020-09-10 01:19:58 +02:00
Aayush Rajasekaran 183df4c135 Fix IsAncestorOf 2020-09-09 19:09:55 -04:00
frrist f2b238f50a fix(chainwatch): compare prev miner with cur miner
- bug was comparing cur miner with cur miner
2020-09-09 15:30:30 -07:00
whyrusleeping 09194aa613 print better error when losing connection 2020-09-09 15:19:54 -07:00
whyrusleeping e58327d4ed rename LE tag to quantile 2020-09-09 15:19:54 -07:00
whyrusleeping 8414aa6e4b more metrics! 2020-09-09 15:19:54 -07:00
whyrusleeping 7d1d690eb7 lets get some metrics 2020-09-09 15:19:54 -07:00
whyrusleeping 47ad7ccb5f some more stats 2020-09-09 15:19:54 -07:00
whyrusleeping 679c4183e7 add a simple command to watch messages sitting in the mempool 2020-09-09 15:19:53 -07:00
Aayush Rajasekaran 8807c75c51 Fix warn message 2020-09-09 18:17:05 -04:00
Łukasz Magiera be9d8f7ce3 Merge pull request #3712 from filecoin-project/asr/devnet
Fix devnets
2020-09-09 23:15:36 +02:00
Aayush Rajasekaran a7a43a1124 Fix devnets 2020-09-09 17:10:35 -04:00
whyrusleeping 7a6ceebb34 windowed post generation now returns faulty sectors 2020-09-09 14:00:15 -07:00
Łukasz Magiera 38863d3025 build: Separate API versions per node type 2020-09-08 21:14:53 +02:00
Aayush Rajasekaran 88c04ce959 Update docs 2020-09-06 03:51:06 -04:00
Aayush Rajasekaran 5ead23a8d4 Msig: Add CLI commands to propose, approve, or cancel adding signers 2020-09-06 03:46:07 -04:00
Aayush Rajasekaran d0ccb54aba Msig: Add RPC endpoints to propose, approve, or cancel adding signers 2020-09-06 01:52:30 -04:00
Aayush Rajasekaran aaad01105e Msig: Introduce an API & CLI to calculate amount that vests between 2 tipsets 2020-09-05 23:42:31 -04:00
Raúl Kripalani 35a8f7ebca Merge branch 'master' into inmem-journal 2020-09-04 21:02:28 +01:00
Raúl Kripalani 0a4c473a7c fix dangling import. 2020-09-04 12:14:27 +01:00
Raúl Kripalani 1ec534d607 Merge branch 'master' into inmem-journal 2020-09-04 10:55:40 +01:00
Raúl Kripalani 905168e72e fix lint errors. 2020-09-04 10:54:56 +01:00
Raúl Kripalani d46f684bb8 fix test following merge. 2020-09-04 00:05:44 +01:00
Raúl Kripalani 97ff90f8fa fix imports. 2020-09-03 15:51:26 +01:00
Raúl Kripalani 4554c4bda9 fix lotus-bench stale import. 2020-09-02 19:54:13 +01:00
Raúl Kripalani 3206f92063 Merge branch 'master' into inmem-journal 2020-09-02 19:50:52 +01:00
Raúl Kripalani fd04a19544 go mod tidy. 2020-09-02 19:46:57 +01:00
Raúl Kripalani f046af337a split wdpost event into finer-grained ones. 2020-09-02 19:45:25 +01:00
Raúl Kripalani ac152abc75 shuffle code to journal wdpost events. 2020-09-02 19:15:25 +01:00
Raúl Kripalani 0b6a182a44 move InitJournalKey to the top; add godcs on invoke order. 2020-09-02 19:15:07 +01:00
Raúl Kripalani cb8e105a94 reduce diff noise. 2020-08-26 16:44:06 +01:00
Raúl Kripalani efdfd3ee3e Merge branch 'master' into inmem-journal 2020-08-26 16:38:23 +01:00
Raúl Kripalani 4e1ef09751 make journal a global var. 2020-08-26 16:09:37 +01:00
Raúl Kripalani cc859d3948 journal: wdpost: record proofs_processed even if no eligible partitions. 2020-08-11 16:49:18 +01:00
Raúl Kripalani 200b0f72cc mpool/repub: only record in journal if actually repubbing. 2020-08-11 15:06:13 +01:00
Raúl Kripalani 8f19fff1ec fix tests. 2020-08-11 14:47:02 +01:00
Raúl Kripalani b534ab9d3c panic recovery in MaybeRecordEvent; handle nil current tipsets in wdpost. 2020-08-11 14:28:00 +01:00
Raúl Kripalani 2ea5abdfb5 wire journal into miner. 2020-08-11 13:48:32 +01:00
Raúl Kripalani d53c6f2599 storage-fsm: emit sealing state transition notifications. 2020-08-11 13:23:40 +01:00
Raúl Kripalani 5e2c28d7e9 add comment. 2020-08-11 13:10:22 +01:00
Raúl Kripalani bca516b028 Merge remote-tracking branch 'origin/next' into inmem-journal 2020-08-11 12:42:39 +01:00
Raúl Kripalani 92598237c3 Merge branch 'next' into inmem-journal 2020-08-11 12:41:11 +01:00
Raúl Kripalani 5074ce5a38 move in-mem journal to Project Oni. 2020-08-10 15:02:15 +01:00
Raúl Kripalani b8475114ba Merge branch 'next' into inmem-journal 2020-07-21 17:42:51 +01:00
Raúl Kripalani 443473f833 fix tests. 2020-07-21 17:37:06 +01:00
Raúl Kripalani 4e82cf369c rename journal entries to journal events. 2020-07-21 17:32:01 +01:00
Raúl Kripalani d547c2588c record deals events in journal. 2020-07-21 17:26:44 +01:00
Raúl Kripalani cb8e209f78 journal: disable noisy message pool events. 2020-07-21 13:13:09 +01:00
Raúl Kripalani 3bd9d55a15 message pool: write message(s) in journal entries. 2020-07-21 13:10:29 +01:00
Raúl Kripalani d6e6eedd58 pipe sealing events to the journal. 2020-07-21 13:02:51 +01:00
Raúl Kripalani 7459ec6bba add mpool journal events; fix dependency injection. 2020-07-20 16:37:32 +01:00
Raúl Kripalani 226786c1da wip 2020-07-20 14:45:17 +01:00
Raúl Kripalani 4d2d8b2d11 Merge branch 'next' into inmem-journal 2020-07-20 10:38:58 +01:00
Raúl Kripalani becbff0b13 add NilJournal; fix call sites to ChainStore constructor. 2020-07-17 19:10:47 +01:00
Raúl Kripalani 4bcf01938c use new journal from chain/store pkg. 2020-07-17 18:54:26 +01:00
Raúl Kripalani bef7d64e66 refactor EventType construction. 2020-07-17 18:35:15 +01:00
Raúl Kripalani 695f6cfe45 wip in-memory journal. 2020-07-17 14:34:42 +01:00
136 changed files with 4963 additions and 1092 deletions
+24 -3
View File
@@ -231,11 +231,11 @@ jobs:
- run:
name: install statediff globally
command: |
## statediff is optional; we succeed even if compilation fails.
mkdir -p /tmp/statediff
git clone https://github.com/filecoin-project/statediff.git /tmp/statediff
cd /tmp/statediff
go generate ./...
go install ./cmd/statediff
go install ./cmd/statediff || exit 0
- run:
name: go test
environment:
@@ -254,6 +254,25 @@ jobs:
path: /tmp/test-reports
- store_artifacts:
path: /tmp/test-artifacts/conformance-coverage.html
build-lotus-soup:
description: |
Compile `lotus-soup` Testground test plan using the current version of Lotus.
parameters:
<<: *test-params
executor: << parameters.executor >>
steps:
- install-deps
- prepare
- run: cd extern/oni && git submodule sync
- run: cd extern/oni && git submodule update --init
- run: cd extern/filecoin-ffi && make
- run:
name: "replace lotus, filecoin-ffi, blst and fil-blst deps"
command: cd extern/oni/lotus-soup && go mod edit -replace github.com/filecoin-project/lotus=../../../ && go mod edit -replace github.com/filecoin-project/filecoin-ffi=../../filecoin-ffi && go mod edit -replace github.com/supranational/blst=../../fil-blst/blst && go mod edit -replace github.com/filecoin-project/fil-blst=../../fil-blst
- run:
name: "build lotus-soup testplan"
command: pushd extern/oni/lotus-soup && go build -tags=testground .
build-macos:
description: build darwin lotus binary
@@ -400,7 +419,8 @@ workflows:
version: 2.1
ci:
jobs:
- lint-all
- lint-all:
concurrency: "16" # expend all docker 2xlarge CPUs.
- mod-tidy-check
- gofmt
- cbor-gen-check
@@ -427,6 +447,7 @@ workflows:
test-suite-name: conformance-bleeding-edge
packages: "./conformance"
vectors-branch: master
- build-lotus-soup
- build-debug
- build-all:
requires:
+2
View File
@@ -10,6 +10,8 @@
/lotus-fountain
/lotus-stats
/lotus-bench
/lotus-gateway
/lotus-pcr
/bench.json
/lotuspond/front/node_modules
/lotuspond/front/build
+6
View File
@@ -8,3 +8,9 @@
[submodule "extern/test-vectors"]
path = extern/test-vectors
url = https://github.com/filecoin-project/test-vectors.git
[submodule "extern/fil-blst"]
path = extern/fil-blst
url = https://github.com/filecoin-project/fil-blst.git
[submodule "extern/oni"]
path = extern/oni
url = https://github.com/filecoin-project/oni
+79 -1
View File
@@ -1,5 +1,84 @@
# Lotus changelog
# 0.7.1 / 2020-09-17
This optional release of Lotus introduces some critical fixes to the window PoSt process. It also upgrades some core dependencies, and introduces many improvements to the mining process, deal-making cycle, and overall User Experience.
## Changes
#### Some notable improvements:
- Correctly construct params for `SubmitWindowedPoSt` messages (https://github.com/filecoin-project/lotus/pull/3909)
- Skip sectors correctly for Window PoSt (https://github.com/filecoin-project/lotus/pull/3839)
- Split window PoST submission into multiple messages (https://github.com/filecoin-project/lotus/pull/3689)
- Improve journal coverage (https://github.com/filecoin-project/lotus/pull/2455)
- Allow retrievals while sealing (https://github.com/filecoin-project/lotus/pull/3778)
- Don't prune locally published messages (https://github.com/filecoin-project/lotus/pull/3772)
- Add get-ask, set-ask retrieval commands (https://github.com/filecoin-project/lotus/pull/3886)
- Consistently name winning and window post in logs (https://github.com/filecoin-project/lotus/pull/3873))
- Add auto flag to mpool replace (https://github.com/filecoin-project/lotus/pull/3752))
#### Dependencies
- Upgrade markets to `v0.6.1` (https://github.com/filecoin-project/lotus/pull/3906)
- Upgrade specs-actors to `v0.9.10` (https://github.com/filecoin-project/lotus/pull/3846)
- Upgrade badger (https://github.com/filecoin-project/lotus/pull/3739)
# 0.7.0 / 2020-09-10
This consensus-breaking release of Lotus is designed to test a network upgrade on the space race testnet. The changes that break consensus are:
- Upgrading the Drand network used from the test Drand network to the League of Entropy main drand network. This is the same Drand network that will be used in the Filecoin mainnet.
- Upgrading to specs-actors v0.9.8, which adds a new method to the Multisig actor.
## Changes
#### Core Lotus
- Fix IsAncestorOf (https://github.com/filecoin-project/lotus/pull/3717)
- Update to specs-actors v0.9.8 (https://github.com/filecoin-project/lotus/pull/3725)
- Increase chain throughput by 20% (https://github.com/filecoin-project/lotus/pull/3732)
- Updare to go-libp2p-pubsub `master` (https://github.com/filecoin-project/lotus/pull/3735)
- Drand upgrade (https://github.com/filecoin-project/lotus/pull/3670)
- Multisig API additions (https://github.com/filecoin-project/lotus/pull/3590)
#### Storage Miner
- Increase the number of times precommit2 is attempted before moving back to precommit1 (https://github.com/filecoin-project/lotus/pull/3720)
#### Message pool
- Relax mpool add strictness checks for local pushes (https://github.com/filecoin-project/lotus/pull/3724)
#### Maintenance
- Fix devnets (https://github.com/filecoin-project/lotus/pull/3712)
- Fix(chainwatch): compare prev miner with cur miner (https://github.com/filecoin-project/lotus/pull/3715)
- CI: fix statediff build; make optional (https://github.com/filecoin-project/lotus/pull/3729)
- Feat: Chaos abort (https://github.com/filecoin-project/lotus/pull/3733)
## Contributors
The following contributors had commits go into this release.
We are grateful for every contribution!
| Contributor | Commits | Lines ± |
|--------------------|---------|---------------|
| arajasek | 28 | +1144/-239 |
| Kubuxu | 19 | +452/-261 |
| whyrusleeping | 13 | +456/-87 |
| vyzo | 11 | +318/-20 |
| raulk | 10 | +1289/-350 |
| magik6k | 6 | +188/-55 |
| dirkmc | 3 | +31/-8 |
| alanshaw | 3 | +176/-37 |
| Stebalien | 2 | +9/-12 |
| lanzafame | 1 | +1/-1 |
| frrist | 1 | +1/-1 |
| mishmosh | 1 | +1/-1 |
| nonsense | 1 | +1/-0 |
# 0.6.2 / 2020-09-09
This release introduces some critical fixes to message selection and gas estimation logic. It also adds the ability for nodes to mark a certain tipset as checkpointed, as well as various minor improvements and bugfixes.
@@ -38,7 +117,6 @@ This release introduces some critical fixes to message selection and gas estimat
- Paych: add docs on how to use paych status (https://github.com/filecoin-project/lotus/pull/3690)
- Initial CODEOWNERS (https://github.com/filecoin-project/lotus/pull/3691)
# 0.6.1 / 2020-09-08
This optional release introduces a minor improvement to the sync process, ensuring nodes don't fall behind and then resync.
+6
View File
@@ -92,6 +92,12 @@ lotus-shed: $(BUILD_DEPS)
.PHONY: lotus-shed
BINS+=lotus-shed
lotus-gateway: $(BUILD_DEPS)
rm -f lotus-gateway
go build $(GOFLAGS) -o lotus-gateway ./cmd/lotus-gateway
.PHONY: lotus-gateway
BINS+=lotus-gateway
build: lotus lotus-miner lotus-worker
@[[ $$(type -P "lotus") ]] && echo "Caution: you have \
an existing lotus binary in your PATH. This may cause problems if you don't run 'sudo make install'" || true
+38 -7
View File
@@ -5,6 +5,8 @@ import (
"fmt"
"time"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/specs-actors/actors/runtime/proof"
"github.com/ipfs/go-cid"
@@ -116,7 +118,8 @@ type FullNode interface {
// The exported chain data includes the header chain from the given tipset
// back to genesis, the entire genesis state, and the most recent 'nroots'
// state trees.
ChainExport(ctx context.Context, nroots abi.ChainEpoch, tsk types.TipSetKey) (<-chan []byte, error)
// If oldmsgskip is set, messages from before the requested roots are also not included.
ChainExport(ctx context.Context, nroots abi.ChainEpoch, oldmsgskip bool, tsk types.TipSetKey) (<-chan []byte, error)
// MethodGroup: Beacon
// The Beacon method group contains methods for interacting with the random beacon (DRAND)
@@ -318,7 +321,7 @@ type FullNode interface {
StateMinerActiveSectors(context.Context, address.Address, types.TipSetKey) ([]*ChainSectorInfo, error)
// StateMinerProvingDeadline calculates the deadline at some epoch for a proving period
// and returns the deadline-related calculations.
StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*miner.DeadlineInfo, error)
StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error)
// StateMinerPower returns the power of the indicated miner
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error)
// StateMinerInfo returns info about the indicated miner
@@ -351,6 +354,8 @@ type FullNode interface {
StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*SectorLocation, error)
// StateSearchMsg searches for a message in the chain, and returns its receipt and the tipset where it was executed
StateSearchMsg(context.Context, cid.Cid) (*MsgLookup, error)
// StateMsgGasCost searches for a message in the chain, and returns details of the messages gas costs, including the penalty and miner tip
StateMsgGasCost(context.Context, cid.Cid, types.TipSetKey) (*MsgGasCost, error)
// StateWaitMsg looks back in the chain for a message. If not found, it blocks until the
// message arrives on chain, and gets to the indicated confidence depth.
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error)
@@ -397,6 +402,9 @@ type FullNode interface {
// MsigGetAvailableBalance returns the portion of a multisig's balance that can be withdrawn or spent
MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
// MsigGetVested returns the amount of FIL that vested in a multisig in a certain period.
// It takes the following params: <multisig address>, <start epoch>, <end epoch>
MsigGetVested(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error)
// MsigCreate creates a multisig wallet
// It takes the following params: <required number of senders>, <approving addresses>, <unlock duration>
//<initial balance>, <sender address of the create msg>, <gas price>
@@ -413,17 +421,29 @@ type FullNode interface {
// It takes the following params: <multisig address>, <proposed message ID>, <recipient address>, <value to transfer>,
// <sender address of the cancel msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigCancel(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
// MsigAddPropose proposes adding a signer in the multisig
// It takes the following params: <multisig address>, <sender address of the propose msg>,
// <new signer>, <whether the number of required signers should be increased>
MsigAddPropose(context.Context, address.Address, address.Address, address.Address, bool) (cid.Cid, error)
// MsigAddApprove approves a previously proposed AddSigner message
// It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
// <proposer address>, <new signer>, <whether the number of required signers should be increased>
MsigAddApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, bool) (cid.Cid, error)
// MsigAddCancel cancels a previously proposed AddSigner message
// It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
// <new signer>, <whether the number of required signers should be increased>
MsigAddCancel(context.Context, address.Address, address.Address, uint64, address.Address, bool) (cid.Cid, error)
// MsigSwapPropose proposes swapping 2 signers in the multisig
// It takes the following params: <multisig address>, <sender address of the propose msg>,
// <old signer> <new signer>
// <old signer>, <new signer>
MsigSwapPropose(context.Context, address.Address, address.Address, address.Address, address.Address) (cid.Cid, error)
// MsigSwapApprove approves a previously proposed SwapSigner
// It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
// <proposer address>, <old signer> <new signer>
// <proposer address>, <old signer>, <new signer>
MsigSwapApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, address.Address) (cid.Cid, error)
// MsigSwapCancel cancels a previously proposed SwapSigner message
// It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
// <old signer> <new signer>
// <old signer>, <new signer>
MsigSwapCancel(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error)
MarketEnsureAvailable(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error)
@@ -434,8 +454,8 @@ type FullNode interface {
PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*ChannelInfo, error)
PaychGetWaitReady(context.Context, cid.Cid) (address.Address, error)
PaychAvailableFunds(ch address.Address) (*ChannelAvailableFunds, error)
PaychAvailableFundsByFromTo(from, to address.Address) (*ChannelAvailableFunds, error)
PaychAvailableFunds(ctx context.Context, ch address.Address) (*ChannelAvailableFunds, error)
PaychAvailableFundsByFromTo(ctx context.Context, from, to address.Address) (*ChannelAvailableFunds, error)
PaychList(context.Context) ([]address.Address, error)
PaychStatus(context.Context, address.Address) (*PaychStatus, error)
PaychSettle(context.Context, address.Address) (cid.Cid, error)
@@ -513,6 +533,17 @@ type MsgLookup struct {
Height abi.ChainEpoch
}
type MsgGasCost struct {
Message cid.Cid // Can be different than requested, in case it was replaced, but only gas values changed
GasUsed abi.TokenAmount
BaseFeeBurn abi.TokenAmount
OverEstimationBurn abi.TokenAmount
MinerPenalty abi.TokenAmount
MinerTip abi.TokenAmount
Refund abi.TokenAmount
TotalCost abi.TokenAmount
}
type BlockMessages struct {
BlsMessages []*types.Message
SecpkMessages []*types.SignedMessage
+38 -11
View File
@@ -5,6 +5,8 @@ import (
"io"
"time"
"github.com/filecoin-project/go-state-types/dline"
"github.com/ipfs/go-cid"
metrics "github.com/libp2p/go-libp2p-core/metrics"
"github.com/libp2p/go-libp2p-core/network"
@@ -93,7 +95,7 @@ type FullNodeStruct struct {
ChainGetNode func(ctx context.Context, p string) (*api.IpldObject, error) `perm:"read"`
ChainGetMessage func(context.Context, cid.Cid) (*types.Message, error) `perm:"read"`
ChainGetPath func(context.Context, types.TipSetKey, types.TipSetKey) ([]*api.HeadChange, error) `perm:"read"`
ChainExport func(context.Context, abi.ChainEpoch, types.TipSetKey) (<-chan []byte, error) `perm:"read"`
ChainExport func(context.Context, abi.ChainEpoch, bool, types.TipSetKey) (<-chan []byte, error) `perm:"read"`
BeaconGetEntry func(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) `perm:"read"`
@@ -162,7 +164,7 @@ type FullNodeStruct struct {
StateNetworkName func(context.Context) (dtypes.NetworkName, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address, *bitfield.BitField, bool, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerActiveSectors func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerProvingDeadline func(context.Context, address.Address, types.TipSetKey) (*miner.DeadlineInfo, error) `perm:"read"`
StateMinerProvingDeadline func(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) `perm:"read"`
StateMinerInfo func(context.Context, address.Address, types.TipSetKey) (api.MinerInfo, error) `perm:"read"`
StateMinerDeadlines func(context.Context, address.Address, types.TipSetKey) ([]*miner.Deadline, error) `perm:"read"`
@@ -181,6 +183,7 @@ type FullNodeStruct struct {
StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"`
StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"`
StateReadState func(context.Context, address.Address, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
StateMsgGasCost func(context.Context, cid.Cid, types.TipSetKey) (*api.MsgGasCost, error) `perm:"read"`
StateWaitMsg func(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) `perm:"read"`
StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"`
StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
@@ -201,10 +204,14 @@ type FullNodeStruct struct {
StateCirculatingSupply func(context.Context, types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"`
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
MsigGetVested func(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) `perm:"read"`
MsigCreate func(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
MsigPropose func(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
MsigApprove func(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
MsigCancel func(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
MsigAddPropose func(context.Context, address.Address, address.Address, address.Address, bool) (cid.Cid, error) `perm:"sign"`
MsigAddApprove func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, bool) (cid.Cid, error) `perm:"sign"`
MsigAddCancel func(context.Context, address.Address, address.Address, uint64, address.Address, bool) (cid.Cid, error) `perm:"sign"`
MsigSwapPropose func(context.Context, address.Address, address.Address, address.Address, address.Address) (cid.Cid, error) `perm:"sign"`
MsigSwapApprove func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, address.Address) (cid.Cid, error) `perm:"sign"`
MsigSwapCancel func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error) `perm:"sign"`
@@ -213,8 +220,8 @@ type FullNodeStruct struct {
PaychGet func(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) `perm:"sign"`
PaychGetWaitReady func(context.Context, cid.Cid) (address.Address, error) `perm:"sign"`
PaychAvailableFunds func(address.Address) (*api.ChannelAvailableFunds, error) `perm:"sign"`
PaychAvailableFundsByFromTo func(address.Address, address.Address) (*api.ChannelAvailableFunds, error) `perm:"sign"`
PaychAvailableFunds func(context.Context, address.Address) (*api.ChannelAvailableFunds, error) `perm:"sign"`
PaychAvailableFundsByFromTo func(context.Context, address.Address, address.Address) (*api.ChannelAvailableFunds, error) `perm:"sign"`
PaychList func(context.Context) ([]address.Address, error) `perm:"read"`
PaychStatus func(context.Context, address.Address) (*api.PaychStatus, error) `perm:"read"`
PaychSettle func(context.Context, address.Address) (cid.Cid, error) `perm:"sign"`
@@ -686,8 +693,8 @@ func (c *FullNodeStruct) ChainGetPath(ctx context.Context, from types.TipSetKey,
return c.Internal.ChainGetPath(ctx, from, to)
}
func (c *FullNodeStruct) ChainExport(ctx context.Context, nroots abi.ChainEpoch, tsk types.TipSetKey) (<-chan []byte, error) {
return c.Internal.ChainExport(ctx, nroots, tsk)
func (c *FullNodeStruct) ChainExport(ctx context.Context, nroots abi.ChainEpoch, iom bool, tsk types.TipSetKey) (<-chan []byte, error) {
return c.Internal.ChainExport(ctx, nroots, iom, tsk)
}
func (c *FullNodeStruct) BeaconGetEntry(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) {
@@ -734,7 +741,7 @@ func (c *FullNodeStruct) StateMinerActiveSectors(ctx context.Context, addr addre
return c.Internal.StateMinerActiveSectors(ctx, addr, tsk)
}
func (c *FullNodeStruct) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*miner.DeadlineInfo, error) {
func (c *FullNodeStruct) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) {
return c.Internal.StateMinerProvingDeadline(ctx, addr, tsk)
}
@@ -810,6 +817,10 @@ func (c *FullNodeStruct) StateReadState(ctx context.Context, addr address.Addres
return c.Internal.StateReadState(ctx, addr, tsk)
}
func (c *FullNodeStruct) StateMsgGasCost(ctx context.Context, msgc cid.Cid, tsk types.TipSetKey) (*api.MsgGasCost, error) {
return c.Internal.StateMsgGasCost(ctx, msgc, tsk)
}
func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid, confidence uint64) (*api.MsgLookup, error) {
return c.Internal.StateWaitMsg(ctx, msgc, confidence)
}
@@ -882,6 +893,10 @@ func (c *FullNodeStruct) MsigGetAvailableBalance(ctx context.Context, a address.
return c.Internal.MsigGetAvailableBalance(ctx, a, tsk)
}
func (c *FullNodeStruct) MsigGetVested(ctx context.Context, a address.Address, sTsk types.TipSetKey, eTsk types.TipSetKey) (types.BigInt, error) {
return c.Internal.MsigGetVested(ctx, a, sTsk, eTsk)
}
func (c *FullNodeStruct) MsigCreate(ctx context.Context, req uint64, addrs []address.Address, duration abi.ChainEpoch, val types.BigInt, src address.Address, gp types.BigInt) (cid.Cid, error) {
return c.Internal.MsigCreate(ctx, req, addrs, duration, val, src, gp)
}
@@ -898,6 +913,18 @@ func (c *FullNodeStruct) MsigCancel(ctx context.Context, msig address.Address, t
return c.Internal.MsigCancel(ctx, msig, txID, to, amt, src, method, params)
}
func (c *FullNodeStruct) MsigAddPropose(ctx context.Context, msig address.Address, src address.Address, newAdd address.Address, inc bool) (cid.Cid, error) {
return c.Internal.MsigAddPropose(ctx, msig, src, newAdd, inc)
}
func (c *FullNodeStruct) MsigAddApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, newAdd address.Address, inc bool) (cid.Cid, error) {
return c.Internal.MsigAddApprove(ctx, msig, src, txID, proposer, newAdd, inc)
}
func (c *FullNodeStruct) MsigAddCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, newAdd address.Address, inc bool) (cid.Cid, error) {
return c.Internal.MsigAddCancel(ctx, msig, src, txID, newAdd, inc)
}
func (c *FullNodeStruct) MsigSwapPropose(ctx context.Context, msig address.Address, src address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
return c.Internal.MsigSwapPropose(ctx, msig, src, oldAdd, newAdd)
}
@@ -922,12 +949,12 @@ func (c *FullNodeStruct) PaychGetWaitReady(ctx context.Context, sentinel cid.Cid
return c.Internal.PaychGetWaitReady(ctx, sentinel)
}
func (c *FullNodeStruct) PaychAvailableFunds(ch address.Address) (*api.ChannelAvailableFunds, error) {
return c.Internal.PaychAvailableFunds(ch)
func (c *FullNodeStruct) PaychAvailableFunds(ctx context.Context, ch address.Address) (*api.ChannelAvailableFunds, error) {
return c.Internal.PaychAvailableFunds(ctx, ch)
}
func (c *FullNodeStruct) PaychAvailableFundsByFromTo(from, to address.Address) (*api.ChannelAvailableFunds, error) {
return c.Internal.PaychAvailableFundsByFromTo(from, to)
func (c *FullNodeStruct) PaychAvailableFundsByFromTo(ctx context.Context, from, to address.Address) (*api.ChannelAvailableFunds, error) {
return c.Internal.PaychAvailableFundsByFromTo(ctx, from, to)
}
func (c *FullNodeStruct) PaychList(ctx context.Context) ([]address.Address, error) {
+1 -1
View File
@@ -105,7 +105,7 @@ func init() {
addExample(network.Connected)
addExample(dtypes.NetworkName("lotus"))
addExample(api.SyncStateStage(1))
addExample(build.APIVersion)
addExample(build.FullAPIVersion)
addExample(api.PCHInbound)
addExample(time.Minute)
addExample(datatransfer.TransferID(3))
+2
View File
@@ -65,6 +65,8 @@ func TestApis(t *testing.T, b APIBuilder) {
var OneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}}
func (ts *testSuite) testVersion(t *testing.T) {
build.RunningNodeType = build.NodeFull
ctx := context.Background()
apis, _ := ts.makeNodes(t, 1, OneMiner)
api := apis[0]
+1 -1
View File
@@ -192,7 +192,7 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
// Drop the partition
err = parts[0].Sectors.ForEach(func(sid uint64) error {
return miner.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).MarkFailed(abi.SectorID{
return miner.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).MarkCorrupted(abi.SectorID{
Miner: abi.ActorID(mid),
Number: abi.SectorNumber(sid),
}, true)
+17 -6
View File
@@ -1,15 +1,26 @@
package build
import "github.com/filecoin-project/lotus/node/modules/dtypes"
import (
"sort"
var DrandNetwork = DrandIncentinet
func DrandConfig() dtypes.DrandConfig {
return DrandConfigs[DrandNetwork]
}
"github.com/filecoin-project/lotus/node/modules/dtypes"
)
type DrandEnum int
func DrandConfigSchedule() dtypes.DrandSchedule {
out := dtypes.DrandSchedule{}
for start, config := range DrandSchedule {
out = append(out, dtypes.DrandPoint{Start: start, Config: DrandConfigs[config]})
}
sort.Slice(out, func(i, j int) bool {
return out[i].Start < out[j].Start
})
return out
}
const (
DrandMainnet DrandEnum = iota + 1
DrandTestnet
+7 -1
View File
@@ -10,9 +10,15 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
)
const UpgradeBreezeHeight = 0
const UpgradeBreezeHeight = -1
const BreezeGasTampingDuration = 0
const UpgradeSmokeHeight = -1
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
}
func init() {
power.ConsensusMinerMinPower = big.NewInt(2048)
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
+8
View File
@@ -36,3 +36,11 @@ func MessagesTopic(netName dtypes.NetworkName) string { return "/fil/msgs/" + st
func DhtProtocolName(netName dtypes.NetworkName) protocol.ID {
return protocol.ID("/fil/kad/" + string(netName))
}
func UseNewestNetwork() bool {
// TODO: Put these in a container we can iterate over
if UpgradeBreezeHeight <= 0 && UpgradeSmokeHeight <= 0 {
return true
}
return false
}
+3
View File
@@ -5,6 +5,8 @@ package build
import (
"math/big"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
@@ -20,6 +22,7 @@ const UnixfsLinksPerLevel = 1024
// Consensus / Network
const AllowableClockDriftSecs = uint64(1)
const NewestNetworkVersion = network.Version2
// Epochs
const ForkLengthThreshold = Finality
+10 -1
View File
@@ -11,6 +11,7 @@ import (
"math/big"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
)
@@ -70,6 +71,14 @@ var (
PackingEfficiencyNum int64 = 4
PackingEfficiencyDenom int64 = 5
UpgradeBreezeHeight abi.ChainEpoch = 0
UpgradeBreezeHeight abi.ChainEpoch = -1
BreezeGasTampingDuration abi.ChainEpoch = 0
UpgradeSmokeHeight abi.ChainEpoch = -1
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
}
NewestNetworkVersion = network.Version2
)
+7
View File
@@ -12,9 +12,16 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin/power"
)
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandIncentinet,
UpgradeSmokeHeight: DrandMainnet,
}
const UpgradeBreezeHeight = 41280
const BreezeGasTampingDuration = 120
const UpgradeSmokeHeight = 51000
func init() {
power.ConsensusMinerMinPower = big.NewInt(10 << 40)
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
+37 -4
View File
@@ -1,6 +1,10 @@
package build
import "fmt"
import (
"fmt"
"golang.org/x/xerrors"
)
var CurrentCommit string
var BuildType int
@@ -25,7 +29,7 @@ func buildType() string {
}
// BuildVersion is the local build version, set by build system
const BuildVersion = "0.6.2"
const BuildVersion = "0.7.1"
func UserVersion() string {
return BuildVersion + buildType() + CurrentCommit
@@ -52,8 +56,37 @@ func (ve Version) EqMajorMinor(v2 Version) bool {
return ve&minorMask == v2&minorMask
}
// APIVersion is a semver version of the rpc api exposed
var APIVersion Version = newVer(0, 14, 0)
type NodeType int
const (
NodeUnknown NodeType = iota
NodeFull
NodeMiner
NodeWorker
)
var RunningNodeType NodeType
func VersionForType(nodeType NodeType) (Version, error) {
switch nodeType {
case NodeFull:
return FullAPIVersion, nil
case NodeMiner:
return MinerAPIVersion, nil
case NodeWorker:
return WorkerAPIVersion, nil
default:
return Version(0), xerrors.Errorf("unknown node type %d", nodeType)
}
}
// semver versions of the rpc api exposed
var (
FullAPIVersion = newVer(0, 15, 0)
MinerAPIVersion = newVer(0, 14, 0)
WorkerAPIVersion = newVer(0, 14, 0)
)
//nolint:varcheck,deadcode
const (
+67 -6
View File
@@ -18,6 +18,23 @@ type Response struct {
Err error
}
type Schedule []BeaconPoint
func (bs Schedule) BeaconForEpoch(e abi.ChainEpoch) RandomBeacon {
for i := len(bs) - 1; i >= 0; i-- {
bp := bs[i]
if e >= bp.Start {
return bp.Beacon
}
}
return bs[0].Beacon
}
type BeaconPoint struct {
Start abi.ChainEpoch
Beacon RandomBeacon
}
// RandomBeacon represents a system that provides randomness to Lotus.
// Other components interrogate the RandomBeacon to acquire randomness that's
// valid for a specific chain epoch. Also to verify beacon entries that have
@@ -25,11 +42,30 @@ type Response struct {
type RandomBeacon interface {
Entry(context.Context, uint64) <-chan Response
VerifyEntry(types.BeaconEntry, types.BeaconEntry) error
MaxBeaconRoundForEpoch(abi.ChainEpoch, types.BeaconEntry) uint64
MaxBeaconRoundForEpoch(abi.ChainEpoch) uint64
}
func ValidateBlockValues(b RandomBeacon, h *types.BlockHeader, prevEntry types.BeaconEntry) error {
maxRound := b.MaxBeaconRoundForEpoch(h.Height, prevEntry)
func ValidateBlockValues(bSchedule Schedule, h *types.BlockHeader, parentEpoch abi.ChainEpoch,
prevEntry types.BeaconEntry) error {
{
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
currBeacon := bSchedule.BeaconForEpoch(h.Height)
if parentBeacon != currBeacon {
if len(h.BeaconEntries) != 2 {
return xerrors.Errorf("expected two beacon entries at beacon fork, got %d", len(h.BeaconEntries))
}
err := currBeacon.VerifyEntry(h.BeaconEntries[1], h.BeaconEntries[0])
if err != nil {
return xerrors.Errorf("beacon at fork point invalid: (%v, %v): %w",
h.BeaconEntries[1], h.BeaconEntries[0], err)
}
return nil
}
}
// TODO: fork logic
b := bSchedule.BeaconForEpoch(h.Height)
maxRound := b.MaxBeaconRoundForEpoch(h.Height)
if maxRound == prevEntry.Round {
if len(h.BeaconEntries) != 0 {
return xerrors.Errorf("expected not to have any beacon entries in this block, got %d", len(h.BeaconEntries))
@@ -56,10 +92,35 @@ func ValidateBlockValues(b RandomBeacon, h *types.BlockHeader, prevEntry types.B
return nil
}
func BeaconEntriesForBlock(ctx context.Context, beacon RandomBeacon, round abi.ChainEpoch, prev types.BeaconEntry) ([]types.BeaconEntry, error) {
func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, epoch abi.ChainEpoch, parentEpoch abi.ChainEpoch, prev types.BeaconEntry) ([]types.BeaconEntry, error) {
{
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
currBeacon := bSchedule.BeaconForEpoch(epoch)
if parentBeacon != currBeacon {
// Fork logic
round := currBeacon.MaxBeaconRoundForEpoch(epoch)
out := make([]types.BeaconEntry, 2)
rch := currBeacon.Entry(ctx, round-1)
res := <-rch
if res.Err != nil {
return nil, xerrors.Errorf("getting entry %d returned error: %w", round-1, res.Err)
}
out[0] = res.Entry
rch = currBeacon.Entry(ctx, round)
res = <-rch
if res.Err != nil {
return nil, xerrors.Errorf("getting entry %d returned error: %w", round, res.Err)
}
out[1] = res.Entry
return out, nil
}
}
beacon := bSchedule.BeaconForEpoch(epoch)
start := build.Clock.Now()
maxRound := beacon.MaxBeaconRoundForEpoch(round, prev)
maxRound := beacon.MaxBeaconRoundForEpoch(epoch)
if maxRound == prev.Round {
return nil, nil
}
@@ -82,7 +143,7 @@ func BeaconEntriesForBlock(ctx context.Context, beacon RandomBeacon, round abi.C
out = append(out, resp.Entry)
cur = resp.Entry.Round - 1
case <-ctx.Done():
return nil, xerrors.Errorf("context timed out waiting on beacon entry to come back for round %d: %w", round, ctx.Err())
return nil, xerrors.Errorf("context timed out waiting on beacon entry to come back for epoch %d: %w", epoch, ctx.Err())
}
}
+1 -1
View File
@@ -187,7 +187,7 @@ func (db *DrandBeacon) VerifyEntry(curr types.BeaconEntry, prev types.BeaconEntr
return err
}
func (db *DrandBeacon) MaxBeaconRoundForEpoch(filEpoch abi.ChainEpoch, prevEntry types.BeaconEntry) uint64 {
func (db *DrandBeacon) MaxBeaconRoundForEpoch(filEpoch abi.ChainEpoch) uint64 {
// TODO: sometimes the genesis time for filecoin is zero and this goes negative
latestTs := ((uint64(filEpoch) * db.filRoundTime) + db.filGenTime) - db.filRoundTime
dround := (latestTs - db.drandGenTime) / uint64(db.interval.Seconds())
+1 -1
View File
@@ -12,7 +12,7 @@ import (
)
func TestPrintGroupInfo(t *testing.T) {
server := build.DrandConfig().Servers[0]
server := build.DrandConfigs[build.DrandIncentinet].Servers[0]
c, err := hclient.New(server, nil, nil)
assert.NoError(t, err)
cg := c.(interface {
+1 -5
View File
@@ -53,11 +53,7 @@ func (mb *mockBeacon) VerifyEntry(from types.BeaconEntry, to types.BeaconEntry)
return nil
}
func (mb *mockBeacon) IsEntryForEpoch(e types.BeaconEntry, epoch abi.ChainEpoch, nulls int) (bool, error) {
return int64(e.Round) <= int64(epoch) && int64(epoch)-int64(nulls) >= int64(e.Round), nil
}
func (mb *mockBeacon) MaxBeaconRoundForEpoch(epoch abi.ChainEpoch, prevEntry types.BeaconEntry) uint64 {
func (mb *mockBeacon) MaxBeaconRoundForEpoch(epoch abi.ChainEpoch) uint64 {
return uint64(epoch)
}
+2 -4
View File
@@ -27,7 +27,6 @@ type heightEvents struct {
}
func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
ctx, span := trace.StartSpan(e.ctx, "events.HeightHeadChange")
defer span.End()
span.AddAttributes(trace.Int64Attribute("endHeight", int64(app[0].Height())))
@@ -145,12 +144,11 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
}
// ChainAt invokes the specified `HeightHandler` when the chain reaches the
// specified height+confidence threshold. If the chain is rolled-back under the
// specified height, `RevertHandler` will be called.
// specified height+confidence threshold. If the chain is rolled-back under the
// specified height, `RevertHandler` will be called.
//
// ts passed to handlers is the tipset at the specified, or above, if lower tipsets were null
func (e *heightEvents) ChainAt(hnd HeightHandler, rev RevertHandler, confidence int, h abi.ChainEpoch) error {
e.lk.Lock() // Tricky locking, check your locks if you modify this function!
best, err := e.tsc.best()
+2 -1
View File
@@ -3,6 +3,7 @@ package state
import (
"bytes"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/util/adt"
typegen "github.com/whyrusleeping/cbor-gen"
)
@@ -69,7 +70,7 @@ func DiffAdtArray(preArr, curArr *adt.Array, out AdtArrayDiff) error {
// Modify should be called when a value is modified in the map
// Remove should be called when a value is removed from the map
type AdtMapDiff interface {
AsKey(key string) (adt.Keyer, error)
AsKey(key string) (abi.Keyer, error)
Add(key string, val *typegen.Deferred) error
Modify(key string, from, to *typegen.Deferred) error
Remove(key string, val *typegen.Deferred) error
+17 -16
View File
@@ -11,6 +11,7 @@ import (
cbornode "github.com/ipfs/go-ipld-cbor"
typegen "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
@@ -78,21 +79,21 @@ func TestDiffAdtMap(t *testing.T) {
mapA := adt.MakeEmptyMap(ctxstoreA)
mapB := adt.MakeEmptyMap(ctxstoreB)
require.NoError(t, mapA.Put(adt.UIntKey(0), runtime.CBORBytes([]byte{0}))) // delete
require.NoError(t, mapA.Put(abi.UIntKey(0), runtime.CBORBytes([]byte{0}))) // delete
require.NoError(t, mapA.Put(adt.UIntKey(1), runtime.CBORBytes([]byte{0}))) // modify
require.NoError(t, mapB.Put(adt.UIntKey(1), runtime.CBORBytes([]byte{1})))
require.NoError(t, mapA.Put(abi.UIntKey(1), runtime.CBORBytes([]byte{0}))) // modify
require.NoError(t, mapB.Put(abi.UIntKey(1), runtime.CBORBytes([]byte{1})))
require.NoError(t, mapA.Put(adt.UIntKey(2), runtime.CBORBytes([]byte{1}))) // delete
require.NoError(t, mapA.Put(abi.UIntKey(2), runtime.CBORBytes([]byte{1}))) // delete
require.NoError(t, mapA.Put(adt.UIntKey(3), runtime.CBORBytes([]byte{0}))) // noop
require.NoError(t, mapB.Put(adt.UIntKey(3), runtime.CBORBytes([]byte{0})))
require.NoError(t, mapA.Put(abi.UIntKey(3), runtime.CBORBytes([]byte{0}))) // noop
require.NoError(t, mapB.Put(abi.UIntKey(3), runtime.CBORBytes([]byte{0})))
require.NoError(t, mapA.Put(adt.UIntKey(4), runtime.CBORBytes([]byte{0}))) // modify
require.NoError(t, mapB.Put(adt.UIntKey(4), runtime.CBORBytes([]byte{6})))
require.NoError(t, mapA.Put(abi.UIntKey(4), runtime.CBORBytes([]byte{0}))) // modify
require.NoError(t, mapB.Put(abi.UIntKey(4), runtime.CBORBytes([]byte{6})))
require.NoError(t, mapB.Put(adt.UIntKey(5), runtime.CBORBytes{8})) // add
require.NoError(t, mapB.Put(adt.UIntKey(6), runtime.CBORBytes{9})) // add
require.NoError(t, mapB.Put(abi.UIntKey(5), runtime.CBORBytes{8})) // add
require.NoError(t, mapB.Put(abi.UIntKey(6), runtime.CBORBytes{9})) // add
changes := new(TestDiffMap)
@@ -134,12 +135,12 @@ type TestDiffMap struct {
var _ AdtMapDiff = &TestDiffMap{}
func (t *TestDiffMap) AsKey(key string) (adt.Keyer, error) {
k, err := adt.ParseUIntKey(key)
func (t *TestDiffMap) AsKey(key string) (abi.Keyer, error) {
k, err := abi.ParseUIntKey(key)
if err != nil {
return nil, err
}
return adt.UIntKey(k), nil
return abi.UIntKey(k), nil
}
func (t *TestDiffMap) Add(key string, val *typegen.Deferred) error {
@@ -148,7 +149,7 @@ func (t *TestDiffMap) Add(key string, val *typegen.Deferred) error {
if err != nil {
return err
}
k, err := adt.ParseUIntKey(key)
k, err := abi.ParseUIntKey(key)
if err != nil {
return err
}
@@ -172,7 +173,7 @@ func (t *TestDiffMap) Modify(key string, from, to *typegen.Deferred) error {
return err
}
k, err := adt.ParseUIntKey(key)
k, err := abi.ParseUIntKey(key)
if err != nil {
return err
}
@@ -198,7 +199,7 @@ func (t *TestDiffMap) Remove(key string, val *typegen.Deferred) error {
if err != nil {
return err
}
k, err := adt.ParseUIntKey(key)
k, err := abi.ParseUIntKey(key)
if err != nil {
return err
}
+4 -4
View File
@@ -537,8 +537,8 @@ type MinerPreCommitChanges struct {
Removed []miner.SectorPreCommitOnChainInfo
}
func (m *MinerPreCommitChanges) AsKey(key string) (adt.Keyer, error) {
sector, err := adt.ParseUIntKey(key)
func (m *MinerPreCommitChanges) AsKey(key string) (abi.Keyer, error) {
sector, err := abi.ParseUIntKey(key)
if err != nil {
return nil, err
}
@@ -662,12 +662,12 @@ type AddressChange struct {
type DiffInitActorStateFunc func(ctx context.Context, oldState *init_.State, newState *init_.State) (changed bool, user UserData, err error)
func (i *InitActorAddressChanges) AsKey(key string) (adt.Keyer, error) {
func (i *InitActorAddressChanges) AsKey(key string) (abi.Keyer, error) {
addr, err := address.NewFromBytes([]byte(key))
if err != nil {
return nil, err
}
return adt.AddrKey(addr), nil
return abi.AddrKey(addr), nil
}
func (i *InitActorAddressChanges) Add(key string, val *typegen.Deferred) error {
+5 -5
View File
@@ -59,7 +59,7 @@ type ChainGen struct {
cs *store.ChainStore
beacon beacon.RandomBeacon
beacon beacon.Schedule
sm *stmgr.StateManager
@@ -252,7 +252,7 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
miners := []address.Address{maddr1, maddr2}
beac := beacon.NewMockBeacon(time.Second)
beac := beacon.Schedule{{Start: 0, Beacon: beacon.NewMockBeacon(time.Second)}}
//beac, err := drand.NewDrandBeacon(tpl.Timestamp, build.BlockDelaySecs)
//if err != nil {
//return nil, xerrors.Errorf("creating drand beacon: %w", err)
@@ -338,7 +338,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
prev := mbi.PrevBeaconEntry
entries, err := beacon.BeaconEntriesForBlock(ctx, cg.beacon, round, prev)
entries, err := beacon.BeaconEntriesForBlock(ctx, cg.beacon, round, pts.Height(), prev)
if err != nil {
return nil, nil, nil, xerrors.Errorf("get beacon entries for block: %w", err)
}
@@ -358,7 +358,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
return nil, nil, nil, xerrors.Errorf("failed to cbor marshal address: %w", err)
}
if len(entries) == 0 {
if round > build.UpgradeSmokeHeight {
buf.Write(pts.MinTicket().VRFProof)
}
@@ -559,7 +559,7 @@ type mca struct {
w *wallet.Wallet
sm *stmgr.StateManager
pv ffiwrapper.Verifier
bcn beacon.RandomBeacon
bcn beacon.Schedule
}
func (mca mca) ChainGetRandomnessFromTickets(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) {
+3 -3
View File
@@ -6,7 +6,7 @@ import (
"encoding/json"
"fmt"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/go-state-types/network"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
@@ -406,8 +406,8 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
verifNeeds := make(map[address.Address]abi.PaddedPieceSize)
var sum abi.PaddedPieceSize
nwv := func(context.Context, abi.ChainEpoch) runtime.NetworkVersion {
return runtime.NetworkVersion1
nwv := func(context.Context, abi.ChainEpoch) network.Version {
return build.NewestNetworkVersion
}
vmopt := vm.VMOpts{
+6 -2
View File
@@ -6,6 +6,10 @@ import (
"fmt"
"math/rand"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/state"
"github.com/ipfs/go-cid"
@@ -61,8 +65,8 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
return big.Zero(), nil
}
nwv := func(context.Context, abi.ChainEpoch) runtime.NetworkVersion {
return runtime.NetworkVersion1
nwv := func(context.Context, abi.ChainEpoch) network.Version {
return build.NewestNetworkVersion
}
vmopt := &vm.VMOpts{
+5 -4
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/util/adt"
@@ -50,7 +51,7 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi
fmt.Printf("init set %s t0%d\n", e, counter)
value := cbg.CborInt(counter)
if err := amap.Put(adt.AddrKey(e), &value); err != nil {
if err := amap.Put(abi.AddrKey(e), &value); err != nil {
return 0, nil, nil, err
}
counter = counter + 1
@@ -77,7 +78,7 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi
fmt.Printf("init set %s t0%d\n", ainfo.Owner, counter)
value := cbg.CborInt(counter)
if err := amap.Put(adt.AddrKey(ainfo.Owner), &value); err != nil {
if err := amap.Put(abi.AddrKey(ainfo.Owner), &value); err != nil {
return 0, nil, nil, err
}
counter = counter + 1
@@ -95,7 +96,7 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi
return 0, nil, nil, xerrors.Errorf("unmarshaling account meta: %w", err)
}
value := cbg.CborInt(80)
if err := amap.Put(adt.AddrKey(ainfo.Owner), &value); err != nil {
if err := amap.Put(abi.AddrKey(ainfo.Owner), &value); err != nil {
return 0, nil, nil, err
}
} else if rootVerifier.Type == genesis.TMultisig {
@@ -110,7 +111,7 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi
fmt.Printf("init set %s t0%d\n", e, counter)
value := cbg.CborInt(counter)
if err := amap.Put(adt.AddrKey(e), &value); err != nil {
if err := amap.Put(abi.AddrKey(e), &value); err != nil {
return 0, nil, nil, err
}
counter = counter + 1
+93 -17
View File
@@ -12,6 +12,7 @@ import (
"time"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/hashicorp/go-multierror"
lru "github.com/hashicorp/golang-lru"
@@ -31,6 +32,7 @@ import (
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/journal"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/node/modules/dtypes"
@@ -50,6 +52,7 @@ var RepublishInterval = time.Duration(10*build.BlockDelaySecs+build.PropagationD
var minimumBaseFee = types.NewInt(uint64(build.MinimumBaseFee))
var baseFeeLowerBoundFactor = types.NewInt(10)
var baseFeeLowerBoundFactorConservative = types.NewInt(100)
var MaxActorPendingMessages = 1000
@@ -82,9 +85,25 @@ const (
localUpdates = "update"
)
// this is *temporary* mutilation until we have implemented uncapped miner penalties -- it will go
// away in the next fork.
var strictBaseFeeValidation = false
// Journal event types.
const (
evtTypeMpoolAdd = iota
evtTypeMpoolRemove
evtTypeMpoolRepub
)
// MessagePoolEvt is the journal entry for message pool events.
type MessagePoolEvt struct {
Action string
Messages []MessagePoolEvtMessage
Error error `json:",omitempty"`
}
type MessagePoolEvtMessage struct {
types.Message
CID cid.Cid
}
func init() {
// if the republish interval is too short compared to the pubsub timecache, adjust it
@@ -139,6 +158,8 @@ type MessagePool struct {
netName dtypes.NetworkName
sigValCache *lru.TwoQueueCache
evtTypes [3]journal.EventType
}
type msgSet struct {
@@ -160,6 +181,22 @@ func ComputeMinRBF(curPrem abi.TokenAmount) abi.TokenAmount {
return types.BigAdd(minPrice, types.NewInt(1))
}
func CapGasFee(msg *types.Message, maxFee abi.TokenAmount) {
if maxFee.Equals(big.Zero()) {
maxFee = types.NewInt(build.FilecoinPrecision / 10)
}
gl := types.NewInt(uint64(msg.GasLimit))
totalFee := types.BigMul(msg.GasFeeCap, gl)
if totalFee.LessThanEqual(maxFee) {
return
}
msg.GasFeeCap = big.Div(maxFee, gl)
msg.GasPremium = big.Min(msg.GasFeeCap, msg.GasPremium) // cap premium at FeeCap
}
func (ms *msgSet) add(m *types.SignedMessage, mp *MessagePool, strict bool) (bool, error) {
nextNonce := ms.nextNonce
nonceGap := false
@@ -299,6 +336,11 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*Messa
api: api,
netName: netName,
cfg: cfg,
evtTypes: [...]journal.EventType{
evtTypeMpoolAdd: journal.J.RegisterEventType("mpool", "add"),
evtTypeMpoolRemove: journal.J.RegisterEventType("mpool", "remove"),
evtTypeMpoolRepub: journal.J.RegisterEventType("mpool", "repub"),
},
}
// enable initial prunes
@@ -350,10 +392,12 @@ func (mp *MessagePool) runLoop() {
if err := mp.republishPendingMessages(); err != nil {
log.Errorf("error while republishing messages: %s", err)
}
case <-mp.pruneTrigger:
if err := mp.pruneExcessMessages(); err != nil {
log.Errorf("failed to prune excess messages from mempool: %s", err)
}
case <-mp.closer:
mp.repubTk.Stop()
return
@@ -397,18 +441,27 @@ func (mp *MessagePool) verifyMsgBeforeAdd(m *types.SignedMessage, curTs *types.T
// Note that for local messages, we always add them so that they can be accepted and republished
// automatically.
publish := local
if strictBaseFeeValidation && len(curTs.Blocks()) > 0 {
baseFee := curTs.Blocks()[0].ParentBaseFee
baseFeeLowerBound := types.BigDiv(baseFee, baseFeeLowerBoundFactor)
if m.Message.GasFeeCap.LessThan(baseFeeLowerBound) {
if local {
log.Warnf("local message will not be immediately published because GasFeeCap doesn't meet the lower bound for inclusion in the next 20 blocks (GasFeeCap: %s, baseFeeLowerBound: %s)",
m.Message.GasFeeCap, baseFeeLowerBound)
publish = false
} else {
return false, xerrors.Errorf("GasFeeCap doesn't meet base fee lower bound for inclusion in the next 20 blocks (GasFeeCap: %s, baseFeeLowerBound: %s): %w",
m.Message.GasFeeCap, baseFeeLowerBound, ErrSoftValidationFailure)
}
var baseFee big.Int
if len(curTs.Blocks()) > 0 {
baseFee = curTs.Blocks()[0].ParentBaseFee
} else {
var err error
baseFee, err = mp.api.ChainComputeBaseFee(context.TODO(), curTs)
if err != nil {
return false, xerrors.Errorf("computing basefee: %w", err)
}
}
baseFeeLowerBound := getBaseFeeLowerBound(baseFee, baseFeeLowerBoundFactorConservative)
if m.Message.GasFeeCap.LessThan(baseFeeLowerBound) {
if local {
log.Warnf("local message will not be immediately published because GasFeeCap doesn't meet the lower bound for inclusion in the next 20 blocks (GasFeeCap: %s, baseFeeLowerBound: %s)",
m.Message.GasFeeCap, baseFeeLowerBound)
publish = false
} else {
return false, xerrors.Errorf("GasFeeCap doesn't meet base fee lower bound for inclusion in the next 20 blocks (GasFeeCap: %s, baseFeeLowerBound: %s): %w",
m.Message.GasFeeCap, baseFeeLowerBound, ErrSoftValidationFailure)
}
}
@@ -590,7 +643,7 @@ func (mp *MessagePool) addTs(m *types.SignedMessage, curTs *types.TipSet, local
return false, err
}
return publish, mp.addLocked(m, true)
return publish, mp.addLocked(m, !local)
}
func (mp *MessagePool) addLoaded(m *types.SignedMessage) error {
@@ -683,6 +736,14 @@ func (mp *MessagePool) addLocked(m *types.SignedMessage, strict bool) error {
Type: api.MpoolAdd,
Message: m,
}, localUpdates)
journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolAdd], func() interface{} {
return MessagePoolEvt{
Action: "add",
Messages: []MessagePoolEvtMessage{{Message: m.Message, CID: m.Cid()}},
}
})
return nil
}
@@ -812,7 +873,7 @@ func (mp *MessagePool) PushWithNonce(ctx context.Context, addr address.Address,
return nil, err
}
if err := mp.addLocked(msg, true); err != nil {
if err := mp.addLocked(msg, false); err != nil {
return nil, xerrors.Errorf("add locked failed: %w", err)
}
if err := mp.addLocal(msg, msgb); err != nil {
@@ -845,6 +906,12 @@ func (mp *MessagePool) remove(from address.Address, nonce uint64, applied bool)
Message: m,
}, localUpdates)
journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolRemove], func() interface{} {
return MessagePoolEvt{
Action: "remove",
Messages: []MessagePoolEvtMessage{{Message: m.Message, CID: m.Cid()}}}
})
mp.currentSize--
}
@@ -1282,3 +1349,12 @@ func (mp *MessagePool) Clear(local bool) {
delete(mp.pending, a)
}
}
func getBaseFeeLowerBound(baseFee, factor types.BigInt) types.BigInt {
baseFeeLowerBound := types.BigDiv(baseFee, factor)
if baseFeeLowerBound.LessThan(minimumBaseFee) {
baseFeeLowerBound = minimumBaseFee
}
return baseFeeLowerBound
}
+15 -7
View File
@@ -46,13 +46,21 @@ func (mp *MessagePool) pruneMessages(ctx context.Context, ts *types.TipSet) erro
if err != nil {
return xerrors.Errorf("computing basefee: %w", err)
}
baseFeeLowerBound := getBaseFeeLowerBound(baseFee, baseFeeLowerBoundFactor)
pending, _ := mp.getPendingMessages(ts, ts)
// priority actors -- not pruned
priority := make(map[address.Address]struct{})
// protected actors -- not pruned
protected := make(map[address.Address]struct{})
// we never prune priority addresses
for _, actor := range mp.cfg.PriorityAddrs {
priority[actor] = struct{}{}
protected[actor] = struct{}{}
}
// we also never prune locally published messages
for actor := range mp.localAddrs {
protected[actor] = struct{}{}
}
// Collect all messages to track which ones to remove and create chains for block inclusion
@@ -61,18 +69,18 @@ func (mp *MessagePool) pruneMessages(ctx context.Context, ts *types.TipSet) erro
var chains []*msgChain
for actor, mset := range pending {
// we never prune priority actors
_, keep := priority[actor]
// we never prune protected actors
_, keep := protected[actor]
if keep {
keepCount += len(mset)
continue
}
// not a priority actor, track the messages and create chains
// not a protected actor, track the messages and create chains
for _, m := range mset {
pruneMsgs[m.Message.Cid()] = m
}
actorChains := mp.createMessageChains(actor, mset, baseFee, ts)
actorChains := mp.createMessageChains(actor, mset, baseFeeLowerBound, ts)
chains = append(chains, actorChains...)
}
+15 -5
View File
@@ -11,6 +11,7 @@ import (
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/messagepool/gasguess"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/journal"
"github.com/ipfs/go-cid"
)
@@ -27,11 +28,7 @@ func (mp *MessagePool) republishPendingMessages() error {
mp.curTsLk.Unlock()
return xerrors.Errorf("computing basefee: %w", err)
}
baseFeeLowerBound := types.BigDiv(baseFee, baseFeeLowerBoundFactor)
if baseFeeLowerBoundFactor.LessThan(minimumBaseFee) {
baseFeeLowerBound = minimumBaseFee
}
baseFeeLowerBound := getBaseFeeLowerBound(baseFee, baseFeeLowerBoundFactor)
pending := make(map[address.Address]map[uint64]*types.SignedMessage)
mp.lk.Lock()
@@ -150,6 +147,19 @@ loop:
}
}
if len(msgs) > 0 {
journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolRepub], func() interface{} {
msgs := make([]MessagePoolEvtMessage, 0, len(msgs))
for _, m := range msgs {
msgs = append(msgs, MessagePoolEvtMessage{Message: m.Message, CID: m.Cid()})
}
return MessagePoolEvt{
Action: "repub",
Messages: msgs,
}
})
}
// track most recently republished messages
republished := make(map[cid.Cid]struct{})
for _, m := range msgs[:count] {
+4 -3
View File
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
@@ -209,7 +210,7 @@ func (st *StateTree) GetActor(addr address.Address) (*types.Actor, error) {
}
var act types.Actor
if found, err := st.root.Get(adt.AddrKey(addr), &act); err != nil {
if found, err := st.root.Get(abi.AddrKey(addr), &act); err != nil {
return nil, xerrors.Errorf("hamt find failed: %w", err)
} else if !found {
return nil, types.ErrActorNotFound
@@ -254,11 +255,11 @@ func (st *StateTree) Flush(ctx context.Context) (cid.Cid, error) {
for addr, sto := range st.snaps.layers[0].actors {
if sto.Delete {
if err := st.root.Delete(adt.AddrKey(addr)); err != nil {
if err := st.root.Delete(abi.AddrKey(addr)); err != nil {
return cid.Undef, err
}
} else {
if err := st.root.Put(adt.AddrKey(addr), &sto.Act); err != nil {
if err := st.root.Put(abi.AddrKey(addr), &sto.Act); err != nil {
return cid.Undef, err
}
}
+7 -8
View File
@@ -15,7 +15,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors"
@@ -73,18 +72,18 @@ func (ta *testActor) Exports() []interface{} {
}
}
func (ta *testActor) Constructor(rt runtime.Runtime, params *adt.EmptyValue) *adt.EmptyValue {
func (ta *testActor) Constructor(rt runtime.Runtime, params *abi.EmptyValue) *abi.EmptyValue {
rt.ValidateImmediateCallerAcceptAny()
rt.State().Create(&testActorState{11})
fmt.Println("NEW ACTOR ADDRESS IS: ", rt.Message().Receiver())
rt.StateCreate(&testActorState{11})
fmt.Println("NEW ACTOR ADDRESS IS: ", rt.Receiver())
return adt.Empty
return abi.Empty
}
func (ta *testActor) TestMethod(rt runtime.Runtime, params *adt.EmptyValue) *adt.EmptyValue {
func (ta *testActor) TestMethod(rt runtime.Runtime, params *abi.EmptyValue) *abi.EmptyValue {
rt.ValidateImmediateCallerAcceptAny()
var st testActorState
rt.State().Readonly(&st)
rt.StateReadonly(&st)
if rt.CurrEpoch() > testForkHeight {
if st.HasUpgraded != 55 {
@@ -96,7 +95,7 @@ func (ta *testActor) TestMethod(rt runtime.Runtime, params *adt.EmptyValue) *adt
}
}
return adt.Empty
return abi.Empty
}
func TestForkHeightTriggers(t *testing.T) {
+12 -8
View File
@@ -5,7 +5,7 @@ import (
"fmt"
"sync"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
@@ -233,8 +233,8 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
}
receipts = append(receipts, &r.MessageReceipt)
gasReward = big.Add(gasReward, r.MinerTip)
penalty = big.Add(penalty, r.Penalty)
gasReward = big.Add(gasReward, r.GasCosts.MinerTip)
penalty = big.Add(penalty, r.GasCosts.MinerPenalty)
if cb != nil {
if err := cb(cm.Cid(), m, r); err != nil {
@@ -1124,14 +1124,18 @@ func (sm *StateManager) GetCirculatingSupply(ctx context.Context, height abi.Cha
return csi.FilCirculating, nil
}
func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoch) runtime.NetworkVersion {
if build.UpgradeBreezeHeight == 0 {
return runtime.NetworkVersion1
func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoch) network.Version {
if build.UseNewestNetwork() {
return build.NewestNetworkVersion
}
if height <= build.UpgradeBreezeHeight {
return runtime.NetworkVersion0
return network.Version0
}
return runtime.NetworkVersion1
if height <= build.UpgradeSmokeHeight {
return network.Version1
}
return build.NewestNetworkVersion
}
+7 -7
View File
@@ -120,7 +120,7 @@ func GetPowerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr addres
}
var claim power.Claim
if _, err := cm.Get(adt.AddrKey(maddr), &claim); err != nil {
if _, err := cm.Get(abi.AddrKey(maddr), &claim); err != nil {
return power.Claim{}, power.Claim{}, err
}
@@ -312,7 +312,7 @@ func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, ma
return false, err
}
ok, err := claims.Get(power.AddrKey(maddr), nil)
ok, err := claims.Get(abi.AddrKey(maddr), nil)
if err != nil {
return false, err
}
@@ -502,7 +502,7 @@ func GetLookbackTipSetForRound(ctx context.Context, sm *StateManager, ts *types.
return lbts, nil
}
func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcn beacon.RandomBeacon, tsk types.TipSetKey, round abi.ChainEpoch, maddr address.Address, pv ffiwrapper.Verifier) (*api.MiningBaseInfo, error) {
func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule, tsk types.TipSetKey, round abi.ChainEpoch, maddr address.Address, pv ffiwrapper.Verifier) (*api.MiningBaseInfo, error) {
ts, err := sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return nil, xerrors.Errorf("failed to load tipset for mining base: %w", err)
@@ -517,7 +517,7 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcn beacon.RandomBe
prev = &types.BeaconEntry{}
}
entries, err := beacon.BeaconEntriesForBlock(ctx, bcn, round, *prev)
entries, err := beacon.BeaconEntriesForBlock(ctx, bcs, round, ts.Height(), *prev)
if err != nil {
return nil, err
}
@@ -554,7 +554,7 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcn beacon.RandomBe
sectors, err := GetSectorsForWinningPoSt(ctx, pv, sm, lbst, maddr, prand)
if err != nil {
return nil, xerrors.Errorf("getting wpost proving set: %w", err)
return nil, xerrors.Errorf("getting winning post proving set: %w", err)
}
if len(sectors) == 0 {
@@ -624,8 +624,8 @@ func init() {
// Explicitly add send, it's special.
methods[builtin.MethodSend] = MethodMeta{
Name: "Send",
Params: reflect.TypeOf(new(adt.EmptyValue)),
Ret: reflect.TypeOf(new(adt.EmptyValue)),
Params: reflect.TypeOf(new(abi.EmptyValue)),
Ret: reflect.TypeOf(new(abi.EmptyValue)),
}
// Learn method names from the builtin.Methods* structs.
+12 -6
View File
@@ -11,14 +11,20 @@ import (
"golang.org/x/xerrors"
)
func computeNextBaseFee(baseFee types.BigInt, gasLimitUsed int64, noOfBlocks int) types.BigInt {
// deta := 1/PackingEfficiency * gasLimitUsed/noOfBlocks - build.BlockGasTarget
// change := baseFee * deta / BlockGasTarget / BaseFeeMaxChangeDenom
func ComputeNextBaseFee(baseFee types.BigInt, gasLimitUsed int64, noOfBlocks int, epoch abi.ChainEpoch) types.BigInt {
// deta := gasLimitUsed/noOfBlocks - build.BlockGasTarget
// change := baseFee * deta / BlockGasTarget
// nextBaseFee = baseFee + change
// nextBaseFee = max(nextBaseFee, build.MinimumBaseFee)
delta := build.PackingEfficiencyDenom * gasLimitUsed / (int64(noOfBlocks) * build.PackingEfficiencyNum)
delta -= build.BlockGasTarget
var delta int64
if epoch > build.UpgradeSmokeHeight {
delta = gasLimitUsed / int64(noOfBlocks)
delta -= build.BlockGasTarget
} else {
delta = build.PackingEfficiencyDenom * gasLimitUsed / (int64(noOfBlocks) * build.PackingEfficiencyNum)
delta -= build.BlockGasTarget
}
// cap change at 12.5% (BaseFeeMaxChangeDenom) by capping delta
if delta > build.BlockGasTarget {
@@ -73,5 +79,5 @@ func (cs *ChainStore) ComputeBaseFee(ctx context.Context, ts *types.TipSet) (abi
}
parentBaseFee := ts.Blocks()[0].ParentBaseFee
return computeNextBaseFee(parentBaseFee, totalLimit, len(ts.Blocks())), nil
return ComputeNextBaseFee(parentBaseFee, totalLimit, len(ts.Blocks()), ts.Height()), nil
}
+1 -1
View File
@@ -27,7 +27,7 @@ func TestBaseFee(t *testing.T) {
for _, test := range tests {
test := test
t.Run(fmt.Sprintf("%v", test), func(t *testing.T) {
output := computeNextBaseFee(types.NewInt(test.basefee), test.limitUsed, test.noOfBlocks)
output := ComputeNextBaseFee(types.NewInt(test.basefee), test.limitUsed, test.noOfBlocks, 0)
assert.Equal(t, fmt.Sprintf("%d", test.output), output.String())
})
}
+42 -32
View File
@@ -18,7 +18,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/journal"
bstore "github.com/filecoin-project/lotus/lib/blockstore"
@@ -72,6 +71,20 @@ func init() {
// ReorgNotifee represents a callback that gets called upon reorgs.
type ReorgNotifee func(rev, app []*types.TipSet) error
// Journal event types.
const (
evtTypeHeadChange = iota
)
type HeadChangeEvt struct {
From types.TipSetKey
FromHeight abi.ChainEpoch
To types.TipSetKey
ToHeight abi.ChainEpoch
RevertCount int
ApplyCount int
}
// ChainStore is the main point of access to chain data.
//
// Raw chain data is stored in the Blockstore, with relevant markers (genesis,
@@ -103,6 +116,8 @@ type ChainStore struct {
tsCache *lru.ARCCache
vmcalls vm.SyscallBuilder
evtTypes [1]journal.EventType
}
func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallBuilder) *ChainStore {
@@ -118,6 +133,10 @@ func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallB
vmcalls: vmcalls,
}
cs.evtTypes = [1]journal.EventType{
evtTypeHeadChange: journal.J.RegisterEventType("sync", "head_change"),
}
ci := NewChainIndex(cs.LoadTipSet)
cs.cindex = ci
@@ -344,12 +363,15 @@ func (cs *ChainStore) reorgWorker(ctx context.Context, initialNotifees []ReorgNo
continue
}
journal.Add("sync", map[string]interface{}{
"op": "headChange",
"from": r.old.Key(),
"to": r.new.Key(),
"rev": len(revert),
"apply": len(apply),
journal.J.RecordEvent(cs.evtTypes[evtTypeHeadChange], func() interface{} {
return HeadChangeEvt{
From: r.old.Key(),
FromHeight: r.old.Height(),
To: r.new.Key(),
ToHeight: r.new.Height(),
RevertCount: len(revert),
ApplyCount: len(apply),
}
})
// reverse the apply array
@@ -471,7 +493,7 @@ func (cs *ChainStore) IsAncestorOf(a, b *types.TipSet) (bool, error) {
cur := b
for !a.Equals(cur) && cur.Height() > a.Height() {
next, err := cs.LoadTipSet(b.Parents())
next, err := cs.LoadTipSet(cur.Parents())
if err != nil {
return false, err
}
@@ -744,32 +766,16 @@ type BlockMessages struct {
func (cs *ChainStore) BlockMsgsForTipset(ts *types.TipSet) ([]BlockMessages, error) {
applied := make(map[address.Address]uint64)
cst := cbor.NewCborStore(cs.bs)
st, err := state.LoadStateTree(cst, ts.Blocks()[0].ParentStateRoot)
if err != nil {
return nil, xerrors.Errorf("failed to load state tree")
}
preloadAddr := func(a address.Address) error {
if _, ok := applied[a]; !ok {
act, err := st.GetActor(a)
if err != nil {
return err
}
applied[a] = act.Nonce
}
return nil
}
selectMsg := func(m *types.Message) (bool, error) {
if err := preloadAddr(m.From); err != nil {
return false, err
// The first match for a sender is guaranteed to have correct nonce -- the block isn't valid otherwise
if _, ok := applied[m.From]; !ok {
applied[m.From] = m.Nonce
}
if applied[m.From] != m.Nonce {
return false, nil
}
applied[m.From]++
return true, nil
@@ -1159,7 +1165,7 @@ func recurseLinks(bs bstore.Blockstore, walked *cid.Set, root cid.Cid, in []cid.
return in, rerr
}
func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRoots abi.ChainEpoch, w io.Writer) error {
func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRoots abi.ChainEpoch, skipOldMsgs bool, w io.Writer) error {
if ts == nil {
ts = cs.GetHeaviestTipSet()
}
@@ -1197,9 +1203,13 @@ func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRo
return xerrors.Errorf("unmarshaling block header (cid=%s): %w", blk, err)
}
cids, err := recurseLinks(cs.bs, walked, b.Messages, []cid.Cid{b.Messages})
if err != nil {
return xerrors.Errorf("recursing messages failed: %w", err)
var cids []cid.Cid
if !skipOldMsgs || b.Height > ts.Height()-inclRecentRoots {
mcids, err := recurseLinks(cs.bs, walked, b.Messages, []cid.Cid{b.Messages})
if err != nil {
return xerrors.Errorf("recursing messages failed: %w", err)
}
cids = mcids
}
if b.Height > 0 {
+1 -1
View File
@@ -96,7 +96,7 @@ func TestChainExportImport(t *testing.T) {
}
buf := new(bytes.Buffer)
if err := cg.ChainStore().Export(context.TODO(), last, 0, buf); err != nil {
if err := cg.ChainStore().Export(context.TODO(), last, 0, false, buf); err != nil {
t.Fatal(err)
}
+23 -20
View File
@@ -58,7 +58,14 @@ import (
// the theoretical max height based on systime are quickly rejected
const MaxHeightDrift = 5
var defaultMessageFetchWindowSize = 200
var (
// LocalIncoming is the _local_ pubsub (unrelated to libp2p pubsub) topic
// where the Syncer publishes candidate chain heads to be synced.
LocalIncoming = "incoming"
log = logging.Logger("chain")
defaultMessageFetchWindowSize = 200
)
func init() {
if s := os.Getenv("LOTUS_BSYNC_MSG_WINDOW"); s != "" {
@@ -71,10 +78,6 @@ func init() {
}
}
var log = logging.Logger("chain")
var LocalIncoming = "incoming"
// Syncer is in charge of running the chain synchronization logic. As such, it
// is tasked with these functions, amongst others:
//
@@ -103,7 +106,7 @@ type Syncer struct {
store *store.ChainStore
// handle to the random beacon for verification
beacon beacon.RandomBeacon
beacon beacon.Schedule
// the state manager handles making state queries
sm *stmgr.StateManager
@@ -119,7 +122,7 @@ type Syncer struct {
self peer.ID
syncmgr *SyncManager
syncmgr SyncManager
connmgr connmgr.ConnManager
@@ -140,8 +143,10 @@ type Syncer struct {
ds dtypes.MetadataDS
}
type SyncManagerCtor func(syncFn SyncFunc) SyncManager
// NewSyncer creates a new Syncer object.
func NewSyncer(ds dtypes.MetadataDS, sm *stmgr.StateManager, exchange exchange.Client, connmgr connmgr.ConnManager, self peer.ID, beacon beacon.RandomBeacon, verifier ffiwrapper.Verifier) (*Syncer, error) {
func NewSyncer(ds dtypes.MetadataDS, sm *stmgr.StateManager, exchange exchange.Client, syncMgrCtor SyncManagerCtor, connmgr connmgr.ConnManager, self peer.ID, beacon beacon.Schedule, verifier ffiwrapper.Verifier) (*Syncer, error) {
gen, err := sm.ChainStore().GetGenesis()
if err != nil {
return nil, xerrors.Errorf("getting genesis block: %w", err)
@@ -181,7 +186,7 @@ func NewSyncer(ds dtypes.MetadataDS, sm *stmgr.StateManager, exchange exchange.C
log.Warn("*********************************************************************************************")
}
s.syncmgr = NewSyncManager(s.Sync)
s.syncmgr = syncMgrCtor(s.Sync)
return s, nil
}
@@ -648,7 +653,7 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b
}
var claim power.Claim
exist, err := cm.Get(adt.AddrKey(maddr), &claim)
exist, err := cm.Get(abi.AddrKey(maddr), &claim)
if err != nil {
return err
}
@@ -879,7 +884,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
return nil
}
if err := beacon.ValidateBlockValues(syncer.beacon, h, *prevBeacon); err != nil {
if err := beacon.ValidateBlockValues(syncer.beacon, h, baseTs.Height(), *prevBeacon); err != nil {
return xerrors.Errorf("failed to validate blocks random beacon values: %w", err)
}
return nil
@@ -891,10 +896,12 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
return xerrors.Errorf("failed to marshal miner address to cbor: %w", err)
}
beaconBase := *prevBeacon
if len(h.BeaconEntries) == 0 {
if h.Height > build.UpgradeSmokeHeight {
buf.Write(baseTs.MinTicket().VRFProof)
} else {
}
beaconBase := *prevBeacon
if len(h.BeaconEntries) != 0 {
beaconBase = h.BeaconEntries[len(h.BeaconEntries)-1]
}
@@ -984,7 +991,7 @@ func (syncer *Syncer) VerifyWinningPoStProof(ctx context.Context, h *types.Block
rand, err := store.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, h.Height, buf.Bytes())
if err != nil {
return xerrors.Errorf("failed to get randomness for verifying winningPost proof: %w", err)
return xerrors.Errorf("failed to get randomness for verifying winning post proof: %w", err)
}
mid, err := address.IDFromAddress(h.Miner)
@@ -1663,11 +1670,7 @@ func VerifyElectionPoStVRF(ctx context.Context, worker address.Address, rand []b
}
func (syncer *Syncer) State() []SyncerState {
var out []SyncerState
for _, ss := range syncer.syncmgr.syncStates {
out = append(out, ss.Snapshot())
}
return out
return syncer.syncmgr.State()
}
// MarkBad manually adds a block to the "bad blocks" cache.
+48 -16
View File
@@ -20,7 +20,28 @@ const (
type SyncFunc func(context.Context, *types.TipSet) error
type SyncManager struct {
// SyncManager manages the chain synchronization process, both at bootstrap time
// and during ongoing operation.
//
// It receives candidate chain heads in the form of tipsets from peers,
// and schedules them onto sync workers, deduplicating processing for
// already-active syncs.
type SyncManager interface {
// Start starts the SyncManager.
Start()
// Stop stops the SyncManager.
Stop()
// SetPeerHead informs the SyncManager that the supplied peer reported the
// supplied tipset.
SetPeerHead(ctx context.Context, p peer.ID, ts *types.TipSet)
// State retrieves the state of the sync workers.
State() []SyncerState
}
type syncManager struct {
lk sync.Mutex
peerHeads map[peer.ID]*types.TipSet
@@ -48,6 +69,8 @@ type SyncManager struct {
workerChan chan *types.TipSet
}
var _ SyncManager = (*syncManager)(nil)
type syncResult struct {
ts *types.TipSet
success bool
@@ -55,8 +78,8 @@ type syncResult struct {
const syncWorkerCount = 3
func NewSyncManager(sync SyncFunc) *SyncManager {
return &SyncManager{
func NewSyncManager(sync SyncFunc) SyncManager {
return &syncManager{
bspThresh: 1,
peerHeads: make(map[peer.ID]*types.TipSet),
syncTargets: make(chan *types.TipSet),
@@ -69,18 +92,18 @@ func NewSyncManager(sync SyncFunc) *SyncManager {
}
}
func (sm *SyncManager) Start() {
func (sm *syncManager) Start() {
go sm.syncScheduler()
for i := 0; i < syncWorkerCount; i++ {
go sm.syncWorker(i)
}
}
func (sm *SyncManager) Stop() {
func (sm *syncManager) Stop() {
close(sm.stop)
}
func (sm *SyncManager) SetPeerHead(ctx context.Context, p peer.ID, ts *types.TipSet) {
func (sm *syncManager) SetPeerHead(ctx context.Context, p peer.ID, ts *types.TipSet) {
sm.lk.Lock()
defer sm.lk.Unlock()
sm.peerHeads[p] = ts
@@ -105,6 +128,14 @@ func (sm *SyncManager) SetPeerHead(ctx context.Context, p peer.ID, ts *types.Tip
sm.incomingTipSets <- ts
}
func (sm *syncManager) State() []SyncerState {
ret := make([]SyncerState, 0, len(sm.syncStates))
for _, s := range sm.syncStates {
ret = append(ret, s.Snapshot())
}
return ret
}
type syncBucketSet struct {
buckets []*syncTargetBucket
}
@@ -234,7 +265,7 @@ func (stb *syncTargetBucket) heaviestTipSet() *types.TipSet {
return best
}
func (sm *SyncManager) selectSyncTarget() (*types.TipSet, error) {
func (sm *syncManager) selectSyncTarget() (*types.TipSet, error) {
var buckets syncBucketSet
var peerHeads []*types.TipSet
@@ -258,7 +289,7 @@ func (sm *SyncManager) selectSyncTarget() (*types.TipSet, error) {
return buckets.Heaviest(), nil
}
func (sm *SyncManager) syncScheduler() {
func (sm *syncManager) syncScheduler() {
for {
select {
@@ -280,7 +311,7 @@ func (sm *SyncManager) syncScheduler() {
}
}
func (sm *SyncManager) scheduleIncoming(ts *types.TipSet) {
func (sm *syncManager) scheduleIncoming(ts *types.TipSet) {
log.Debug("scheduling incoming tipset sync: ", ts.Cids())
if sm.getBootstrapState() == BSStateSelected {
sm.setBootstrapState(BSStateScheduled)
@@ -328,10 +359,11 @@ func (sm *SyncManager) scheduleIncoming(ts *types.TipSet) {
}
}
func (sm *SyncManager) scheduleProcessResult(res *syncResult) {
func (sm *syncManager) scheduleProcessResult(res *syncResult) {
if res.success && sm.getBootstrapState() != BSStateComplete {
sm.setBootstrapState(BSStateComplete)
}
delete(sm.activeSyncs, res.ts.Key())
relbucket := sm.activeSyncTips.PopRelated(res.ts)
if relbucket != nil {
@@ -360,7 +392,7 @@ func (sm *SyncManager) scheduleProcessResult(res *syncResult) {
}
}
func (sm *SyncManager) scheduleWorkSent() {
func (sm *syncManager) scheduleWorkSent() {
hts := sm.nextSyncTarget.heaviestTipSet()
sm.activeSyncs[hts.Key()] = hts
@@ -372,7 +404,7 @@ func (sm *SyncManager) scheduleWorkSent() {
}
}
func (sm *SyncManager) syncWorker(id int) {
func (sm *syncManager) syncWorker(id int) {
ss := &SyncerState{}
sm.syncStates[id] = ss
for {
@@ -397,7 +429,7 @@ func (sm *SyncManager) syncWorker(id int) {
}
}
func (sm *SyncManager) syncedPeerCount() int {
func (sm *syncManager) syncedPeerCount() int {
var count int
for _, ts := range sm.peerHeads {
if ts.Height() > 0 {
@@ -407,19 +439,19 @@ func (sm *SyncManager) syncedPeerCount() int {
return count
}
func (sm *SyncManager) getBootstrapState() int {
func (sm *syncManager) getBootstrapState() int {
sm.bssLk.Lock()
defer sm.bssLk.Unlock()
return sm.bootstrapState
}
func (sm *SyncManager) setBootstrapState(v int) {
func (sm *syncManager) setBootstrapState(v int) {
sm.bssLk.Lock()
defer sm.bssLk.Unlock()
sm.bootstrapState = v
}
func (sm *SyncManager) IsBootstrapped() bool {
func (sm *syncManager) IsBootstrapped() bool {
sm.bssLk.Lock()
defer sm.bssLk.Unlock()
return sm.bootstrapState == BSStateComplete
+7 -7
View File
@@ -17,7 +17,7 @@ type syncOp struct {
done func()
}
func runSyncMgrTest(t *testing.T, tname string, thresh int, tf func(*testing.T, *SyncManager, chan *syncOp)) {
func runSyncMgrTest(t *testing.T, tname string, thresh int, tf func(*testing.T, *syncManager, chan *syncOp)) {
syncTargets := make(chan *syncOp)
sm := NewSyncManager(func(ctx context.Context, ts *types.TipSet) error {
ch := make(chan struct{})
@@ -27,7 +27,7 @@ func runSyncMgrTest(t *testing.T, tname string, thresh int, tf func(*testing.T,
}
<-ch
return nil
})
}).(*syncManager)
sm.bspThresh = thresh
sm.Start()
@@ -77,12 +77,12 @@ func TestSyncManager(t *testing.T) {
c3 := mock.TipSet(mock.MkBlock(b, 3, 5))
d := mock.TipSet(mock.MkBlock(c1, 4, 5))
runSyncMgrTest(t, "testBootstrap", 1, func(t *testing.T, sm *SyncManager, stc chan *syncOp) {
runSyncMgrTest(t, "testBootstrap", 1, func(t *testing.T, sm *syncManager, stc chan *syncOp) {
sm.SetPeerHead(ctx, "peer1", c1)
assertGetSyncOp(t, stc, c1)
})
runSyncMgrTest(t, "testBootstrap", 2, func(t *testing.T, sm *SyncManager, stc chan *syncOp) {
runSyncMgrTest(t, "testBootstrap", 2, func(t *testing.T, sm *syncManager, stc chan *syncOp) {
sm.SetPeerHead(ctx, "peer1", c1)
assertNoOp(t, stc)
@@ -90,7 +90,7 @@ func TestSyncManager(t *testing.T) {
assertGetSyncOp(t, stc, c1)
})
runSyncMgrTest(t, "testSyncAfterBootstrap", 1, func(t *testing.T, sm *SyncManager, stc chan *syncOp) {
runSyncMgrTest(t, "testSyncAfterBootstrap", 1, func(t *testing.T, sm *syncManager, stc chan *syncOp) {
sm.SetPeerHead(ctx, "peer1", b)
assertGetSyncOp(t, stc, b)
@@ -101,7 +101,7 @@ func TestSyncManager(t *testing.T) {
assertGetSyncOp(t, stc, c2)
})
runSyncMgrTest(t, "testCoalescing", 1, func(t *testing.T, sm *SyncManager, stc chan *syncOp) {
runSyncMgrTest(t, "testCoalescing", 1, func(t *testing.T, sm *syncManager, stc chan *syncOp) {
sm.SetPeerHead(ctx, "peer1", a)
assertGetSyncOp(t, stc, a)
@@ -122,7 +122,7 @@ func TestSyncManager(t *testing.T) {
assertGetSyncOp(t, stc, d)
})
runSyncMgrTest(t, "testSyncIncomingTipset", 1, func(t *testing.T, sm *SyncManager, stc chan *syncOp) {
runSyncMgrTest(t, "testSyncIncomingTipset", 1, func(t *testing.T, sm *syncManager, stc chan *syncOp) {
sm.SetPeerHead(ctx, "peer1", a)
assertGetSyncOp(t, stc, a)
+86 -1
View File
@@ -662,6 +662,49 @@ func TestDuplicateNonce(t *testing.T) {
require.Equal(t, includedMsg, mft[0].VMMessage().Cid(), "messages for tipset didn't contain expected message")
}
// This test asserts that a block that includes a message with bad nonce can't be synced. A nonce is "bad" if it can't
// be applied on the parent state.
func TestBadNonce(t *testing.T) {
H := 10
tu := prepSyncTest(t, H)
base := tu.g.CurTipset
// Produce a message from the banker with a bad nonce
makeBadMsg := func() *types.SignedMessage {
ba, err := tu.nds[0].StateGetActor(context.TODO(), tu.g.Banker(), base.TipSet().Key())
require.NoError(t, err)
msg := types.Message{
To: tu.g.Banker(),
From: tu.g.Banker(),
Nonce: ba.Nonce + 5,
Value: types.NewInt(1),
Method: 0,
GasLimit: 100_000_000,
GasFeeCap: types.NewInt(0),
GasPremium: types.NewInt(0),
}
sig, err := tu.g.Wallet().Sign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes())
require.NoError(t, err)
return &types.SignedMessage{
Message: msg,
Signature: *sig,
}
}
msgs := make([][]*types.SignedMessage, 1)
msgs[0] = []*types.SignedMessage{makeBadMsg()}
tu.mineOnBlock(base, 0, []int{0}, true, true, msgs)
}
func BenchmarkSyncBasic(b *testing.B) {
for i := 0; i < b.N; i++ {
runSyncBenchLength(b, 100)
@@ -709,7 +752,7 @@ func TestSyncInputs(t *testing.T) {
}
}
func TestSyncCheckpoint(t *testing.T) {
func TestSyncCheckpointHead(t *testing.T) {
H := 10
tu := prepSyncTest(t, H)
@@ -750,3 +793,45 @@ func TestSyncCheckpoint(t *testing.T) {
require.Equal(tu.t, p1Head, a.TipSet())
tu.assertBad(p1, b.TipSet())
}
func TestSyncCheckpointEarlierThanHead(t *testing.T) {
H := 10
tu := prepSyncTest(t, H)
p1 := tu.addClientNode()
p2 := tu.addClientNode()
fmt.Println("GENESIS: ", tu.g.Genesis().Cid())
tu.loadChainToNode(p1)
tu.loadChainToNode(p2)
base := tu.g.CurTipset
fmt.Println("Mining base: ", base.TipSet().Cids(), base.TipSet().Height())
// The two nodes fork at this point into 'a' and 'b'
a1 := tu.mineOnBlock(base, p1, []int{0}, true, false, nil)
a := tu.mineOnBlock(a1, p1, []int{0}, true, false, nil)
a = tu.mineOnBlock(a, p1, []int{0}, true, false, nil)
tu.waitUntilSyncTarget(p1, a.TipSet())
tu.checkpointTs(p1, a1.TipSet().Key())
require.NoError(t, tu.g.ResyncBankerNonce(a1.TipSet()))
// chain B will now be heaviest
b := tu.mineOnBlock(base, p2, []int{1}, true, false, nil)
b = tu.mineOnBlock(b, p2, []int{1}, true, false, nil)
b = tu.mineOnBlock(b, p2, []int{1}, true, false, nil)
b = tu.mineOnBlock(b, p2, []int{1}, true, false, nil)
fmt.Println("A: ", a.Cids(), a.TipSet().Height())
fmt.Println("B: ", b.Cids(), b.TipSet().Height())
// Now for the fun part!! p1 should mark p2's head as BAD.
require.NoError(t, tu.mn.LinkAll())
tu.connect(p1, p2)
tu.waitUntilNodeHasTs(p1, b.TipSet().Key())
p1Head := tu.getHead(p1)
require.Equal(tu.t, p1Head, a.TipSet())
tu.assertBad(p1, b.TipSet())
}
+12 -7
View File
@@ -22,6 +22,17 @@ type GasOutputs struct {
GasBurned int64
}
// ZeroGasOutputs returns a logically zeroed GasOutputs.
func ZeroGasOutputs() GasOutputs {
return GasOutputs{
BaseFeeBurn: big.Zero(),
OverEstimationBurn: big.Zero(),
MinerPenalty: big.Zero(),
MinerTip: big.Zero(),
Refund: big.Zero(),
}
}
// ComputeGasOverestimationBurn computes amount of gas to be refunded and amount of gas to be burned
// Result is (refund, burn)
func ComputeGasOverestimationBurn(gasUsed, gasLimit int64) (int64, int64) {
@@ -58,13 +69,7 @@ func ComputeGasOverestimationBurn(gasUsed, gasLimit int64) (int64, int64) {
func ComputeGasOutputs(gasUsed, gasLimit int64, baseFee, feeCap, gasPremium abi.TokenAmount) GasOutputs {
gasUsedBig := big.NewInt(gasUsed)
out := GasOutputs{
BaseFeeBurn: big.Zero(),
OverEstimationBurn: big.Zero(),
MinerPenalty: big.Zero(),
MinerTip: big.Zero(),
Refund: big.Zero(),
}
out := ZeroGasOutputs()
baseFeeToPay := baseFee
if baseFee.Cmp(feeCap.Int) > 0 {
+3 -5
View File
@@ -15,6 +15,7 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/cron"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
@@ -27,9 +28,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin/system"
"github.com/filecoin-project/specs-actors/actors/runtime"
vmr "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
)
type Invoker struct {
@@ -47,7 +45,7 @@ func NewInvoker() *Invoker {
}
// add builtInCode using: register(cid, singleton)
inv.Register(builtin.SystemActorCodeID, system.Actor{}, adt.EmptyValue{})
inv.Register(builtin.SystemActorCodeID, system.Actor{}, abi.EmptyValue{})
inv.Register(builtin.InitActorCodeID, init_.Actor{}, init_.State{})
inv.Register(builtin.RewardActorCodeID, reward.Actor{}, reward.State{})
inv.Register(builtin.CronActorCodeID, cron.Actor{}, cron.State{})
@@ -66,7 +64,7 @@ func (inv *Invoker) Invoke(codeCid cid.Cid, rt runtime.Runtime, method abi.Metho
code, ok := inv.builtInCode[codeCid]
if !ok {
log.Errorf("no code for actor %s (Addr: %s)", codeCid, rt.Message().Receiver())
log.Errorf("no code for actor %s (Addr: %s)", codeCid, rt.Receiver())
return nil, aerrors.Newf(exitcode.SysErrorIllegalActor, "no code for actor %s(%d)(%s)", codeCid, method, hex.EncodeToString(params))
}
if method >= abi.MethodNum(len(code)) || code[method] == nil {
+5 -4
View File
@@ -5,6 +5,8 @@ import (
"io"
"testing"
"github.com/filecoin-project/go-state-types/abi"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/stretchr/testify/assert"
cbg "github.com/whyrusleeping/cbor-gen"
@@ -13,7 +15,6 @@ import (
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
)
type basicContract struct{}
@@ -60,17 +61,17 @@ func (b basicContract) Exports() []interface{} {
}
}
func (basicContract) InvokeSomething0(rt runtime.Runtime, params *basicParams) *adt.EmptyValue {
func (basicContract) InvokeSomething0(rt runtime.Runtime, params *basicParams) *abi.EmptyValue {
rt.Abortf(exitcode.ExitCode(params.B), "params.B")
return nil
}
func (basicContract) BadParam(rt runtime.Runtime, params *basicParams) *adt.EmptyValue {
func (basicContract) BadParam(rt runtime.Runtime, params *basicParams) *abi.EmptyValue {
rt.Abortf(255, "bad params")
return nil
}
func (basicContract) InvokeSomething10(rt runtime.Runtime, params *basicParams) *adt.EmptyValue {
func (basicContract) InvokeSomething10(rt runtime.Runtime, params *basicParams) *abi.EmptyValue {
rt.Abortf(exitcode.ExitCode(params.B+10), "params.B")
return nil
}
+58 -73
View File
@@ -8,18 +8,19 @@ import (
gruntime "runtime"
"time"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/go-state-types/network"
rtt "github.com/filecoin-project/go-state-types/rt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/runtime"
vmr "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
rt0 "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen"
ipldcbor "github.com/ipfs/go-ipld-cbor"
"go.opencensus.io/trace"
"golang.org/x/xerrors"
@@ -30,20 +31,20 @@ import (
)
type Runtime struct {
types.Message
rt0.Syscalls
ctx context.Context
vm *VM
state *state.StateTree
vmsg vmr.Message
height abi.ChainEpoch
cst cbor.IpldStore
cst ipldcbor.IpldStore
pricelist Pricelist
gasAvailable int64
gasUsed int64
sys runtime.Syscalls
// address that started invoke chain
origin address.Address
originNonce uint64
@@ -56,7 +57,7 @@ type Runtime struct {
lastGasCharge *types.GasTrace
}
func (rt *Runtime) NetworkVersion() vmr.NetworkVersion {
func (rt *Runtime) NetworkVersion() network.Version {
return rt.vm.GetNtwkVersion(rt.ctx, rt.CurrEpoch())
}
@@ -84,11 +85,11 @@ type notFoundErr interface {
IsNotFound() bool
}
func (rt *Runtime) Get(c cid.Cid, o vmr.CBORUnmarshaler) bool {
func (rt *Runtime) StoreGet(c cid.Cid, o cbor.Unmarshaler) bool {
if err := rt.cst.Get(context.TODO(), c, o); err != nil {
var nfe notFoundErr
if xerrors.As(err, &nfe) && nfe.IsNotFound() {
if xerrors.As(err, new(cbor.SerializationError)) {
if xerrors.As(err, new(ipldcbor.SerializationError)) {
panic(aerrors.Newf(exitcode.ErrSerialization, "failed to unmarshal cbor object %s", err))
}
return false
@@ -99,10 +100,10 @@ func (rt *Runtime) Get(c cid.Cid, o vmr.CBORUnmarshaler) bool {
return true
}
func (rt *Runtime) Put(x vmr.CBORMarshaler) cid.Cid {
func (rt *Runtime) StorePut(x cbor.Marshaler) cid.Cid {
c, err := rt.cst.Put(context.TODO(), x)
if err != nil {
if xerrors.As(err, new(cbor.SerializationError)) {
if xerrors.As(err, new(ipldcbor.SerializationError)) {
panic(aerrors.Newf(exitcode.ErrSerialization, "failed to marshal cbor object %s", err))
}
panic(aerrors.Fatalf("failed to put cbor object: %s", err))
@@ -110,7 +111,7 @@ func (rt *Runtime) Put(x vmr.CBORMarshaler) cid.Cid {
return c
}
var _ vmr.Runtime = (*Runtime)(nil)
var _ rt0.Runtime = (*Runtime)(nil)
func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) {
defer func() {
@@ -136,9 +137,9 @@ func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.Act
switch ret := ret.(type) {
case []byte:
return ret, nil
case *adt.EmptyValue:
case *abi.EmptyValue:
return nil, nil
case cbg.CBORMarshaler:
case cbor.Marshaler:
buf := new(bytes.Buffer)
if err := ret.MarshalCBOR(buf); err != nil {
return nil, aerrors.Absorb(err, 2, "failed to marshal response to cbor")
@@ -151,17 +152,13 @@ func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.Act
}
}
func (rt *Runtime) Message() vmr.Message {
return rt.vmsg
}
func (rt *Runtime) ValidateImmediateCallerAcceptAny() {
rt.abortIfAlreadyValidated()
return
}
func (rt *Runtime) CurrentBalance() abi.TokenAmount {
b, err := rt.GetBalance(rt.Message().Receiver())
b, err := rt.GetBalance(rt.Receiver())
if err != nil {
rt.Abortf(err.RetCode(), "get current balance: %v", err)
}
@@ -197,10 +194,6 @@ func (rt *Runtime) GetRandomnessFromBeacon(personalization crypto.DomainSeparati
return res
}
func (rt *Runtime) Store() vmr.Store {
return rt
}
func (rt *Runtime) NewActorAddress() address.Address {
var b bytes.Buffer
oa, _ := ResolveToKeyAddr(rt.vm.cstate, rt.vm.cst, rt.origin)
@@ -257,7 +250,7 @@ func (rt *Runtime) CreateActor(codeID cid.Cid, address address.Address) {
// May only be called by the actor itself.
func (rt *Runtime) DeleteActor(beneficiary address.Address) {
rt.chargeGas(rt.Pricelist().OnDeleteActor())
act, err := rt.state.GetActor(rt.Message().Receiver())
act, err := rt.state.GetActor(rt.Receiver())
if err != nil {
if xerrors.Is(err, types.ErrActorNotFound) {
rt.Abortf(exitcode.SysErrorIllegalActor, "failed to load actor in delete actor: %s", err)
@@ -266,36 +259,32 @@ func (rt *Runtime) DeleteActor(beneficiary address.Address) {
}
if !act.Balance.IsZero() {
// Transfer the executing actor's balance to the beneficiary
if err := rt.vm.transfer(rt.Message().Receiver(), beneficiary, act.Balance); err != nil {
if err := rt.vm.transfer(rt.Receiver(), beneficiary, act.Balance); err != nil {
panic(aerrors.Fatalf("failed to transfer balance to beneficiary actor: %s", err))
}
}
// Delete the executing actor
if err := rt.state.DeleteActor(rt.Message().Receiver()); err != nil {
if err := rt.state.DeleteActor(rt.Receiver()); err != nil {
panic(aerrors.Fatalf("failed to delete actor: %s", err))
}
_ = rt.chargeGasSafe(gasOnActorExec)
}
func (rt *Runtime) Syscalls() vmr.Syscalls {
return rt.sys
}
func (rt *Runtime) StartSpan(name string) vmr.TraceSpan {
func (rt *Runtime) StartSpan(name string) func() {
panic("implement me")
}
func (rt *Runtime) ValidateImmediateCallerIs(as ...address.Address) {
rt.abortIfAlreadyValidated()
imm := rt.Message().Caller()
imm := rt.Caller()
for _, a := range as {
if imm == a {
return
}
}
rt.Abortf(exitcode.SysErrForbidden, "caller %s is not one of %s", rt.Message().Caller(), as)
rt.Abortf(exitcode.SysErrForbidden, "caller %s is not one of %s", rt.Caller(), as)
}
func (rt *Runtime) Context() context.Context {
@@ -313,7 +302,7 @@ func (rt *Runtime) AbortStateMsg(msg string) {
func (rt *Runtime) ValidateImmediateCallerType(ts ...cid.Cid) {
rt.abortIfAlreadyValidated()
callerCid, ok := rt.GetActorCodeCID(rt.Message().Caller())
callerCid, ok := rt.GetActorCodeCID(rt.Caller())
if !ok {
panic(aerrors.Fatalf("failed to lookup code cid for caller"))
}
@@ -333,11 +322,11 @@ type dumbWrapperType struct {
val []byte
}
func (dwt *dumbWrapperType) Into(um vmr.CBORUnmarshaler) error {
func (dwt *dumbWrapperType) Into(um cbor.Unmarshaler) error {
return um.UnmarshalCBOR(bytes.NewReader(dwt.val))
}
func (rt *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMarshaler, value abi.TokenAmount) (vmr.SendReturn, exitcode.ExitCode) {
func (rt *Runtime) Send(to address.Address, method abi.MethodNum, m cbor.Marshaler, value abi.TokenAmount, out cbor.Er) exitcode.ExitCode {
if !rt.allowInternal {
rt.Abortf(exitcode.SysErrorIllegalActor, "runtime.Send() is currently disallowed")
}
@@ -350,16 +339,20 @@ func (rt *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMars
params = buf.Bytes()
}
ret, err := rt.internalSend(rt.Message().Receiver(), to, method, value, params)
ret, err := rt.internalSend(rt.Receiver(), to, method, value, params)
if err != nil {
if err.IsFatal() {
panic(err)
}
log.Warnf("vmctx send failed: to: %s, method: %d: ret: %d, err: %s", to, method, ret, err)
return &dumbWrapperType{nil}, err.RetCode()
return err.RetCode()
}
_ = rt.chargeGasSafe(gasOnActorExec)
return &dumbWrapperType{ret}, 0
if err := out.UnmarshalCBOR(bytes.NewReader(ret)); err != nil {
rt.Abortf(exitcode.ErrSerialization, "failed to unmarshal return value: %s", err)
}
return 0
}
func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum, value types.BigInt, params []byte) ([]byte, aerrors.ActorError) {
@@ -403,49 +396,41 @@ func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum,
return ret, errSend
}
func (rt *Runtime) State() vmr.StateHandle {
return &shimStateHandle{rt: rt}
}
type shimStateHandle struct {
rt *Runtime
}
func (ssh *shimStateHandle) Create(obj vmr.CBORMarshaler) {
c := ssh.rt.Put(obj)
err := ssh.rt.stateCommit(EmptyObjectCid, c)
func (rt *Runtime) StateCreate(obj cbor.Marshaler) {
c := rt.StorePut(obj)
err := rt.stateCommit(EmptyObjectCid, c)
if err != nil {
panic(fmt.Errorf("failed to commit state after creating object: %w", err))
}
}
func (ssh *shimStateHandle) Readonly(obj vmr.CBORUnmarshaler) {
act, err := ssh.rt.state.GetActor(ssh.rt.Message().Receiver())
func (rt *Runtime) StateReadonly(obj cbor.Unmarshaler) {
act, err := rt.state.GetActor(rt.Receiver())
if err != nil {
ssh.rt.Abortf(exitcode.SysErrorIllegalArgument, "failed to get actor for Readonly state: %s", err)
rt.Abortf(exitcode.SysErrorIllegalArgument, "failed to get actor for Readonly state: %s", err)
}
ssh.rt.Get(act.Head, obj)
rt.StoreGet(act.Head, obj)
}
func (ssh *shimStateHandle) Transaction(obj vmr.CBORer, f func()) {
func (rt *Runtime) StateTransaction(obj cbor.Er, f func()) {
if obj == nil {
ssh.rt.Abortf(exitcode.SysErrorIllegalActor, "Must not pass nil to Transaction()")
rt.Abortf(exitcode.SysErrorIllegalActor, "Must not pass nil to Transaction()")
}
act, err := ssh.rt.state.GetActor(ssh.rt.Message().Receiver())
act, err := rt.state.GetActor(rt.Receiver())
if err != nil {
ssh.rt.Abortf(exitcode.SysErrorIllegalActor, "failed to get actor for Transaction: %s", err)
rt.Abortf(exitcode.SysErrorIllegalActor, "failed to get actor for Transaction: %s", err)
}
baseState := act.Head
ssh.rt.Get(baseState, obj)
rt.StoreGet(baseState, obj)
ssh.rt.allowInternal = false
rt.allowInternal = false
f()
ssh.rt.allowInternal = true
rt.allowInternal = true
c := ssh.rt.Put(obj)
c := rt.StorePut(obj)
err = ssh.rt.stateCommit(baseState, c)
err = rt.stateCommit(baseState, c)
if err != nil {
panic(fmt.Errorf("failed to commit state after transaction: %w", err))
}
@@ -465,7 +450,7 @@ func (rt *Runtime) GetBalance(a address.Address) (types.BigInt, aerrors.ActorErr
func (rt *Runtime) stateCommit(oldh, newh cid.Cid) aerrors.ActorError {
// TODO: we can make this more efficient in the future...
act, err := rt.state.GetActor(rt.Message().Receiver())
act, err := rt.state.GetActor(rt.Receiver())
if err != nil {
return aerrors.Escalate(err, "failed to get actor to commit state")
}
@@ -476,7 +461,7 @@ func (rt *Runtime) stateCommit(oldh, newh cid.Cid) aerrors.ActorError {
act.Head = newh
if err := rt.state.SetActor(rt.Message().Receiver(), act); err != nil {
if err := rt.state.SetActor(rt.Receiver(), act); err != nil {
return aerrors.Fatalf("failed to set actor in commit state: %s", err)
}
@@ -571,15 +556,15 @@ func (rt *Runtime) abortIfAlreadyValidated() {
rt.callerValidated = true
}
func (rt *Runtime) Log(level vmr.LogLevel, msg string, args ...interface{}) {
func (rt *Runtime) Log(level rtt.LogLevel, msg string, args ...interface{}) {
switch level {
case vmr.DEBUG:
case rtt.DEBUG:
actorLog.Debugf(msg, args...)
case vmr.INFO:
case rtt.INFO:
actorLog.Infof(msg, args...)
case vmr.WARN:
case rtt.WARN:
actorLog.Warnf(msg, args...)
case vmr.ERROR:
case rtt.ERROR:
actorLog.Errorf(msg, args...)
}
}
+1 -1
View File
@@ -42,6 +42,6 @@ func TestRuntimePutErrors(t *testing.T) {
cst: cbor.NewCborStore(nil),
}
rt.Put(&NotAVeryGoodMarshaler{})
rt.StorePut(&NotAVeryGoodMarshaler{})
t.Error("expected panic")
}
+26 -23
View File
@@ -7,7 +7,7 @@ import (
"reflect"
"time"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/go-state-types/network"
bstore "github.com/filecoin-project/lotus/lib/blockstore"
@@ -116,7 +116,7 @@ func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin addres
Blocks: &gasChargingBlocks{rt.chargeGasFunc(2), rt.pricelist, vm.cst.Blocks},
Atlas: vm.cst.Atlas,
}
rt.sys = pricedSyscalls{
rt.Syscalls = pricedSyscalls{
under: vm.Syscalls(ctx, vm.cstate, rt.cst),
chargeGas: rt.chargeGasFunc(1),
pl: rt.pricelist,
@@ -128,7 +128,7 @@ func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin addres
rt.Abortf(exitcode.SysErrInvalidReceiver, "resolve msg.From address failed")
}
vmm.From = resF
rt.vmsg = &vmm
rt.Message = vmm
return rt
}
@@ -142,7 +142,7 @@ func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message, origin
}
type CircSupplyCalculator func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error)
type NtwkVersionGetter func(context.Context, abi.ChainEpoch) runtime.NetworkVersion
type NtwkVersionGetter func(context.Context, abi.ChainEpoch) network.Version
type VM struct {
cstate *state.StateTree
@@ -201,10 +201,9 @@ type Rand interface {
type ApplyRet struct {
types.MessageReceipt
ActorErr aerrors.ActorError
Penalty types.BigInt
MinerTip types.BigInt
ExecutionTrace types.ExecutionTrace
Duration time.Duration
GasCosts GasOutputs
}
func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
@@ -328,8 +327,7 @@ func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*Ap
},
ActorErr: actorErr,
ExecutionTrace: rt.executionTrace,
Penalty: types.NewInt(0),
MinerTip: types.NewInt(0),
GasCosts: GasOutputs{},
Duration: time.Since(start),
}, actorErr
}
@@ -357,14 +355,15 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
msgGasCost := msgGas.Total()
// this should never happen, but is currently still exercised by some tests
if msgGasCost > msg.GasLimit {
gasOutputs := ZeroGasOutputs()
gasOutputs.MinerPenalty = types.BigMul(vm.baseFee, abi.NewTokenAmount(msgGasCost))
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrOutOfGas,
GasUsed: 0,
},
Penalty: types.BigMul(vm.baseFee, abi.NewTokenAmount(msgGasCost)),
GasCosts: gasOutputs,
Duration: time.Since(start),
MinerTip: big.Zero(),
}, nil
}
@@ -375,15 +374,16 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
// this should never happen, but is currently still exercised by some tests
if err != nil {
if xerrors.Is(err, types.ErrActorNotFound) {
gasOutputs := ZeroGasOutputs()
gasOutputs.MinerPenalty = minerPenaltyAmount
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrSenderInvalid,
GasUsed: 0,
},
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "actor not found: %s", msg.From),
Penalty: minerPenaltyAmount,
GasCosts: gasOutputs,
Duration: time.Since(start),
MinerTip: big.Zero(),
}, nil
}
return nil, xerrors.Errorf("failed to look up from actor: %w", err)
@@ -391,19 +391,22 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
// this should never happen, but is currently still exercised by some tests
if !fromActor.Code.Equals(builtin.AccountActorCodeID) {
gasOutputs := ZeroGasOutputs()
gasOutputs.MinerPenalty = minerPenaltyAmount
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrSenderInvalid,
GasUsed: 0,
},
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "send from not account actor: %s", fromActor.Code),
Penalty: minerPenaltyAmount,
GasCosts: gasOutputs,
Duration: time.Since(start),
MinerTip: big.Zero(),
}, nil
}
if msg.Nonce != fromActor.Nonce {
gasOutputs := ZeroGasOutputs()
gasOutputs.MinerPenalty = minerPenaltyAmount
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrSenderStateInvalid,
@@ -411,14 +414,16 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
},
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
"actor nonce invalid: msg:%d != state:%d", msg.Nonce, fromActor.Nonce),
Penalty: minerPenaltyAmount,
GasCosts: gasOutputs,
Duration: time.Since(start),
MinerTip: big.Zero(),
}, nil
}
gascost := types.BigMul(types.NewInt(uint64(msg.GasLimit)), msg.GasFeeCap)
if fromActor.Balance.LessThan(gascost) {
gasOutputs := ZeroGasOutputs()
gasOutputs.MinerPenalty = minerPenaltyAmount
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrSenderStateInvalid,
@@ -426,9 +431,8 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
},
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
"actor balance less than needed: %s < %s", types.FIL(fromActor.Balance), types.FIL(gascost)),
Penalty: minerPenaltyAmount,
GasCosts: gasOutputs,
Duration: time.Since(start),
MinerTip: big.Zero(),
}, nil
}
@@ -521,8 +525,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
},
ActorErr: actorErr,
ExecutionTrace: rt.executionTrace,
Penalty: gasOutputs.MinerPenalty,
MinerTip: gasOutputs.MinerTip,
GasCosts: gasOutputs,
Duration: time.Since(start),
}, nil
}
@@ -700,9 +703,9 @@ func (vm *VM) Invoke(act *types.Actor, rt *Runtime, method abi.MethodNum, params
defer span.End()
if span.IsRecordingEvents() {
span.AddAttributes(
trace.StringAttribute("to", rt.Message().Receiver().String()),
trace.StringAttribute("to", rt.Receiver().String()),
trace.Int64Attribute("method", int64(method)),
trace.StringAttribute("value", rt.Message().ValueReceived().String()),
trace.StringAttribute("value", rt.ValueReceived().String()),
)
}
@@ -722,7 +725,7 @@ func (vm *VM) SetInvoker(i *Invoker) {
vm.inv = i
}
func (vm *VM) GetNtwkVersion(ctx context.Context, ce abi.ChainEpoch) runtime.NetworkVersion {
func (vm *VM) GetNtwkVersion(ctx context.Context, ce abi.ChainEpoch) network.Version {
return vm.ntwkVersion(ctx, ce)
}
+11 -2
View File
@@ -659,7 +659,7 @@ func handleHamtEpoch(ctx context.Context, api api.FullNode, r cid.Cid) error {
}
return mp.ForEach(nil, func(key string) error {
ik, err := adt.ParseIntKey(key)
ik, err := abi.ParseIntKey(key)
if err != nil {
return err
}
@@ -844,6 +844,9 @@ var chainExportCmd = &cli.Command{
Name: "recent-stateroots",
Usage: "specify the number of recent state roots to include in the export",
},
&cli.BoolFlag{
Name: "skip-old-msgs",
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
@@ -878,7 +881,13 @@ var chainExportCmd = &cli.Command{
return err
}
stream, err := api.ChainExport(ctx, rsrs, ts.Key())
skipold := cctx.Bool("skip-old-msgs")
if rsrs == 0 && skipold {
return fmt.Errorf("must pass recent stateroots along with skip-old-msgs")
}
stream, err := api.ChainExport(ctx, rsrs, skipold, ts.Key())
if err != nil {
return err
}
+7
View File
@@ -12,6 +12,8 @@ import (
"text/tabwriter"
"time"
"github.com/filecoin-project/specs-actors/actors/builtin"
tm "github.com/buger/goterm"
"github.com/docker/go-units"
"github.com/fatih/color"
@@ -527,6 +529,11 @@ func interactiveDeal(cctx *cli.Context) error {
continue
}
if days < int(build.MinDealDuration/builtin.EpochsInDay) {
printErr(xerrors.Errorf("minimum duration is %d days", int(build.MinDealDuration/builtin.EpochsInDay)))
continue
}
state = "miner"
case "miner":
fmt.Print("Miner Address (t0..): ")
+20 -3
View File
@@ -303,6 +303,10 @@ var mpoolReplaceCmd = &cli.Command{
Name: "auto",
Usage: "automatically reprice the specified message",
},
&cli.StringFlag{
Name: "max-fee",
Usage: "Spend up to X FIL for this message (applicable for auto mode)",
},
},
ArgsUsage: "[from] [nonce]",
Action: func(cctx *cli.Context) error {
@@ -353,17 +357,30 @@ var mpoolReplaceCmd = &cli.Command{
msg := found.Message
if cctx.Bool("auto") {
minRBF := messagepool.ComputeMinRBF(msg.GasPremium)
var mss *lapi.MessageSendSpec
if cctx.IsSet("max-fee") {
maxFee, err := types.BigFromString(cctx.String("max-fee"))
if err != nil {
return fmt.Errorf("parsing max-spend: %w", err)
}
mss = &lapi.MessageSendSpec{
MaxFee: maxFee,
}
}
// msg.GasLimit = 0 // TODO: need to fix the way we estimate gas limits to account for the messages already being in the mempool
msg.GasFeeCap = abi.NewTokenAmount(0)
msg.GasPremium = abi.NewTokenAmount(0)
retm, err := api.GasEstimateMessageGas(ctx, &msg, &lapi.MessageSendSpec{}, types.EmptyTSK)
retm, err := api.GasEstimateMessageGas(ctx, &msg, mss, types.EmptyTSK)
if err != nil {
return fmt.Errorf("failed to estimate gas values: %w", err)
}
msg.GasFeeCap = retm.GasFeeCap
minRBF := messagepool.ComputeMinRBF(msg.GasPremium)
msg.GasPremium = big.Max(retm.GasPremium, minRBF)
msg.GasFeeCap = big.Max(retm.GasFeeCap, msg.GasPremium)
messagepool.CapGasFee(&msg, mss.Get().MaxFee)
} else {
msg.GasLimit = cctx.Int64("gas-limit")
msg.GasPremium, err = types.BigFromString(cctx.String("gas-premium"))
+298 -2
View File
@@ -37,9 +37,13 @@ var multisigCmd = &cli.Command{
msigInspectCmd,
msigProposeCmd,
msigApproveCmd,
msigAddProposeCmd,
msigAddApproveCmd,
msigAddCancelCmd,
msigSwapProposeCmd,
msigSwapApproveCmd,
msigSwapCancelCmd,
msigVestedCmd,
},
}
@@ -506,6 +510,236 @@ var msigApproveCmd = &cli.Command{
},
}
var msigAddProposeCmd = &cli.Command{
Name: "add-propose",
Usage: "Propose to add a signer",
ArgsUsage: "[multisigAddress signer]",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "increase-threshold",
Usage: "whether the number of required signers should be increased",
},
&cli.StringFlag{
Name: "from",
Usage: "account to send the propose message from",
},
},
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 2 {
return ShowHelp(cctx, fmt.Errorf("must pass multisig address and signer address"))
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return err
}
addr, err := address.NewFromString(cctx.Args().Get(1))
if err != nil {
return err
}
var from address.Address
if cctx.IsSet("from") {
f, err := address.NewFromString(cctx.String("from"))
if err != nil {
return err
}
from = f
} else {
defaddr, err := api.WalletDefaultAddress(ctx)
if err != nil {
return err
}
from = defaddr
}
msgCid, err := api.MsigAddPropose(ctx, msig, from, addr, cctx.Bool("increase-threshold"))
if err != nil {
return err
}
fmt.Println("sent add proposal in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
if err != nil {
return err
}
if wait.Receipt.ExitCode != 0 {
return fmt.Errorf("add proposal returned exit %d", wait.Receipt.ExitCode)
}
return nil
},
}
var msigAddApproveCmd = &cli.Command{
Name: "add-approve",
Usage: "Approve a message to add a signer",
ArgsUsage: "[multisigAddress proposerAddress txId newAddress increaseThreshold]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
Usage: "account to send the approve message from",
},
},
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 5 {
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, proposer address, transaction id, new signer address, whether to increase threshold"))
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return err
}
prop, err := address.NewFromString(cctx.Args().Get(1))
if err != nil {
return err
}
txid, err := strconv.ParseUint(cctx.Args().Get(2), 10, 64)
if err != nil {
return err
}
newAdd, err := address.NewFromString(cctx.Args().Get(3))
if err != nil {
return err
}
inc, err := strconv.ParseBool(cctx.Args().Get(4))
if err != nil {
return err
}
var from address.Address
if cctx.IsSet("from") {
f, err := address.NewFromString(cctx.String("from"))
if err != nil {
return err
}
from = f
} else {
defaddr, err := api.WalletDefaultAddress(ctx)
if err != nil {
return err
}
from = defaddr
}
msgCid, err := api.MsigAddApprove(ctx, msig, from, txid, prop, newAdd, inc)
if err != nil {
return err
}
fmt.Println("sent add approval in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
if err != nil {
return err
}
if wait.Receipt.ExitCode != 0 {
return fmt.Errorf("add approval returned exit %d", wait.Receipt.ExitCode)
}
return nil
},
}
var msigAddCancelCmd = &cli.Command{
Name: "add-cancel",
Usage: "Cancel a message to add a signer",
ArgsUsage: "[multisigAddress txId newAddress increaseThreshold]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
Usage: "account to send the approve message from",
},
},
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 4 {
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, transaction id, new signer address, whether to increase threshold"))
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return err
}
txid, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
if err != nil {
return err
}
newAdd, err := address.NewFromString(cctx.Args().Get(2))
if err != nil {
return err
}
inc, err := strconv.ParseBool(cctx.Args().Get(3))
if err != nil {
return err
}
var from address.Address
if cctx.IsSet("from") {
f, err := address.NewFromString(cctx.String("from"))
if err != nil {
return err
}
from = f
} else {
defaddr, err := api.WalletDefaultAddress(ctx)
if err != nil {
return err
}
from = defaddr
}
msgCid, err := api.MsigAddCancel(ctx, msig, from, txid, newAdd, inc)
if err != nil {
return err
}
fmt.Println("sent add cancellation in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
if err != nil {
return err
}
if wait.Receipt.ExitCode != 0 {
return fmt.Errorf("add cancellation returned exit %d", wait.Receipt.ExitCode)
}
return nil
},
}
var msigSwapProposeCmd = &cli.Command{
Name: "swap-propose",
Usage: "Propose to swap signers",
@@ -722,7 +956,7 @@ var msigSwapCancelCmd = &cli.Command{
return err
}
fmt.Println("sent swap approval in message: ", msgCid)
fmt.Println("sent swap cancellation in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
if err != nil {
@@ -730,9 +964,71 @@ var msigSwapCancelCmd = &cli.Command{
}
if wait.Receipt.ExitCode != 0 {
return fmt.Errorf("swap approval returned exit %d", wait.Receipt.ExitCode)
return fmt.Errorf("swap cancellation returned exit %d", wait.Receipt.ExitCode)
}
return nil
},
}
var msigVestedCmd = &cli.Command{
Name: "vested",
Usage: "Gets the amount vested in an msig between two epochs",
ArgsUsage: "[multisigAddress]",
Flags: []cli.Flag{
&cli.Int64Flag{
Name: "start-epoch",
Usage: "start epoch to measure vesting from",
Value: 0,
},
&cli.Int64Flag{
Name: "end-epoch",
Usage: "end epoch to stop measure vesting at",
Value: -1,
},
},
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 1 {
return ShowHelp(cctx, fmt.Errorf("must pass multisig address"))
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return err
}
start, err := api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Int64("start-epoch")), types.EmptyTSK)
if err != nil {
return err
}
var end *types.TipSet
if cctx.Int64("end-epoch") < 0 {
end, err = LoadTipSet(ctx, cctx, api)
if err != nil {
return err
}
} else {
end, err = api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Int64("end-epoch")), types.EmptyTSK)
if err != nil {
return err
}
}
ret, err := api.MsigGetVested(ctx, msig, start.Key(), end.Key())
if err != nil {
return err
}
fmt.Printf("Vested: %s between %d and %d\n", types.FIL(ret), start.Height(), end.Height())
return nil
},
}
+6 -2
View File
@@ -28,6 +28,8 @@ var paychCmd = &cli.Command{
paychListCmd,
paychVoucherCmd,
paychSettleCmd,
paychStatusCmd,
paychStatusByFromToCmd,
paychCloseCmd,
},
}
@@ -102,6 +104,7 @@ var paychStatusByFromToCmd = &cli.Command{
if cctx.Args().Len() != 2 {
return ShowHelp(cctx, fmt.Errorf("must pass two arguments: <from address> <to address>"))
}
ctx := ReqContext(cctx)
from, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
@@ -119,7 +122,7 @@ var paychStatusByFromToCmd = &cli.Command{
}
defer closer()
avail, err := api.PaychAvailableFundsByFromTo(from, to)
avail, err := api.PaychAvailableFundsByFromTo(ctx, from, to)
if err != nil {
return err
}
@@ -137,6 +140,7 @@ var paychStatusCmd = &cli.Command{
if cctx.Args().Len() != 1 {
return ShowHelp(cctx, fmt.Errorf("must pass an argument: <channel address>"))
}
ctx := ReqContext(cctx)
ch, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
@@ -149,7 +153,7 @@ var paychStatusCmd = &cli.Command{
}
defer closer()
avail, err := api.PaychAvailableFunds(ch)
avail, err := api.PaychAvailableFunds(ctx, ch)
if err != nil {
return err
}
+153 -5
View File
@@ -27,6 +27,7 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/exported"
@@ -53,6 +54,7 @@ var stateCmd = &cli.Command{
stateListActorsCmd,
stateListMinersCmd,
stateCircSupplyCmd,
stateSectorCmd,
stateGetActorCmd,
stateLookupIDCmd,
stateReplaySetCmd,
@@ -64,6 +66,7 @@ var stateCmd = &cli.Command{
stateGetDealSetCmd,
stateWaitMsgCmd,
stateSearchMsgCmd,
stateMsgCostCmd,
stateMinerInfo,
stateMarketCmd,
},
@@ -118,11 +121,18 @@ var stateMinerInfo = &cli.Command{
}
fmt.Println()
cd, err := api.StateMinerProvingDeadline(ctx, addr, ts.Key())
if err != nil {
return xerrors.Errorf("getting miner info: %w", err)
}
fmt.Printf("Proving Period Start:\t%s\n", EpochTime(cd.CurrentEpoch, cd.PeriodStart))
return nil
},
}
func parseTipSetString(ts string) ([]cid.Cid, error) {
func ParseTipSetString(ts string) ([]cid.Cid, error) {
strs := strings.Split(ts, ",")
var cids []cid.Cid
@@ -160,7 +170,7 @@ func ParseTipSetRef(ctx context.Context, api api.FullNode, tss string) (*types.T
return api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(h), types.EmptyTSK)
}
cids, err := parseTipSetString(tss)
cids, err := ParseTipSetString(tss)
if err != nil {
return nil, err
}
@@ -1303,6 +1313,60 @@ var stateSearchMsgCmd = &cli.Command{
},
}
var stateMsgCostCmd = &cli.Command{
Name: "msg-cost",
Usage: "Get the detailed gas costs of a message",
ArgsUsage: "[messageCid]",
Action: func(cctx *cli.Context) error {
if !cctx.Args().Present() {
return fmt.Errorf("must specify message cid to get gas costs for")
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
msg, err := cid.Decode(cctx.Args().First())
if err != nil {
return err
}
tsk := types.EmptyTSK
ts, err := LoadTipSet(ctx, cctx, api)
if err != nil {
return err
}
if ts != nil {
tsk = ts.Key()
}
mgc, err := api.StateMsgGasCost(ctx, msg, tsk)
if err != nil {
return err
}
if mgc != nil {
fmt.Printf("Message CID: %s", mgc.Message)
fmt.Printf("\nGas Used: %d", mgc.GasUsed)
fmt.Printf("\nBase Fee Burn: %d", mgc.BaseFeeBurn)
fmt.Printf("\nOverestimation Burn: %d", mgc.OverEstimationBurn)
fmt.Printf("\nMiner Tip: %d", mgc.MinerTip)
fmt.Printf("\nRefund: %d", mgc.Refund)
fmt.Printf("\nTotal Cost: %d", mgc.TotalCost)
fmt.Printf("\nMiner Penalty: %d", mgc.MinerPenalty)
} else {
fmt.Print("message was not found on chain")
}
return nil
},
}
var stateCallCmd = &cli.Command{
Name: "call",
Usage: "Invoke a method on an actor locally",
@@ -1384,7 +1448,7 @@ var stateCallCmd = &cli.Command{
}
if ret.MsgRct.ExitCode != 0 {
return fmt.Errorf("invocation failed (exit: %d): %s", ret.MsgRct.ExitCode, ret.Error)
return fmt.Errorf("invocation failed (exit: %d, gasUsed: %d): %s", ret.MsgRct.ExitCode, ret.MsgRct.GasUsed, ret.Error)
}
s, err := formatOutput(cctx.String("ret"), ret.MsgRct.Return)
@@ -1392,6 +1456,7 @@ var stateCallCmd = &cli.Command{
return fmt.Errorf("failed to format output: %s", err)
}
fmt.Printf("gas used: %d\n", ret.MsgRct.GasUsed)
fmt.Printf("return: %s\n", s)
return nil
@@ -1465,11 +1530,11 @@ func parseParamsForMethod(act cid.Cid, method uint64, args []string) ([]byte, er
f := methods[method]
rf := reflect.TypeOf(f)
if rf.NumIn() != 3 {
if rf.NumIn() != 2 {
return nil, fmt.Errorf("expected referenced method to have three arguments")
}
paramObj := rf.In(2).Elem()
paramObj := rf.In(1).Elem()
if paramObj.NumField() != len(args) {
return nil, fmt.Errorf("not enough arguments given to call that method (expecting %d)", paramObj.NumField())
}
@@ -1489,6 +1554,18 @@ func parseParamsForMethod(act cid.Cid, method uint64, args []string) ([]byte, er
return nil, err
}
p.Elem().Field(i).Set(reflect.ValueOf(val))
case reflect.TypeOf(abi.ChainEpoch(0)):
val, err := strconv.ParseInt(args[i], 10, 64)
if err != nil {
return nil, err
}
p.Elem().Field(i).Set(reflect.ValueOf(abi.ChainEpoch(val)))
case reflect.TypeOf(big.Int{}):
val, err := big.FromString(args[i])
if err != nil {
return nil, err
}
p.Elem().Field(i).Set(reflect.ValueOf(val))
case reflect.TypeOf(peer.ID("")):
pid, err := peer.Decode(args[i])
if err != nil {
@@ -1540,6 +1617,77 @@ var stateCircSupplyCmd = &cli.Command{
},
}
var stateSectorCmd = &cli.Command{
Name: "sector",
Usage: "Get miner sector info",
ArgsUsage: "[miner address] [sector number]",
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
if cctx.Args().Len() != 2 {
return xerrors.Errorf("expected 2 params")
}
ts, err := LoadTipSet(ctx, cctx, api)
if err != nil {
return err
}
if ts == nil {
ts, err = api.ChainHead(ctx)
if err != nil {
return err
}
}
maddr, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return err
}
sid, err := strconv.ParseInt(cctx.Args().Get(1), 10, 64)
if err != nil {
return err
}
si, err := api.StateSectorGetInfo(ctx, maddr, abi.SectorNumber(sid), ts.Key())
if err != nil {
return err
}
fmt.Println("SectorNumber: ", si.SectorNumber)
fmt.Println("SealProof: ", si.SealProof)
fmt.Println("SealedCID: ", si.SealedCID)
fmt.Println("DealIDs: ", si.DealIDs)
fmt.Println()
fmt.Println("Activation: ", EpochTime(ts.Height(), si.Activation))
fmt.Println("Expiration: ", EpochTime(ts.Height(), si.Expiration))
fmt.Println()
fmt.Println("DealWeight: ", si.DealWeight)
fmt.Println("VerifiedDealWeight: ", si.VerifiedDealWeight)
fmt.Println("InitialPledge: ", types.FIL(si.InitialPledge))
fmt.Println("ExpectedDayReward: ", types.FIL(si.ExpectedDayReward))
fmt.Println("ExpectedStoragePledge: ", types.FIL(si.ExpectedStoragePledge))
fmt.Println()
sp, err := api.StateSectorPartition(ctx, maddr, abi.SectorNumber(sid), ts.Key())
if err != nil {
return err
}
fmt.Println("Deadline: ", sp.Deadline)
fmt.Println("Partition: ", sp.Partition)
return nil
},
}
var stateMarketCmd = &cli.Command{
Name: "market",
Usage: "Inspect the storage market actor",
+20 -1
View File
@@ -2,10 +2,16 @@ package cli
import (
"context"
"fmt"
"time"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
)
func parseTipSet(ctx context.Context, api api.FullNode, vals []string) (*types.TipSet, error) {
@@ -26,3 +32,16 @@ func parseTipSet(ctx context.Context, api api.FullNode, vals []string) (*types.T
return types.NewTipSet(headers)
}
func EpochTime(curr, e abi.ChainEpoch) string {
switch {
case curr > e:
return fmt.Sprintf("%d (%s ago)", e, time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(curr-e)))
case curr == e:
return fmt.Sprintf("%d (now)", e)
case curr < e:
return fmt.Sprintf("%d (in %s)", e, time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(e-curr)))
}
panic("math broke")
}
+13 -3
View File
@@ -56,6 +56,10 @@ var importBenchCmd = &cli.Command{
Usage: "set the parallelism factor for batch seal verification",
Value: runtime.NumCPU(),
},
&cli.StringFlag{
Name: "repodir",
Usage: "set the repo directory for the lotus bench run (defaults to /tmp)",
},
},
Action: func(cctx *cli.Context) error {
vm.BatchSealVerifyParallelism = cctx.Int("batch-seal-verify-threads")
@@ -70,9 +74,15 @@ var importBenchCmd = &cli.Command{
}
defer cfi.Close() //nolint:errcheck // read only file
tdir, err := ioutil.TempDir("", "lotus-import-bench")
if err != nil {
return err
var tdir string
if rdir := cctx.String("repodir"); rdir != "" {
tdir = rdir
} else {
tmp, err := ioutil.TempDir("", "lotus-import-bench")
if err != nil {
return err
}
tdir = tmp
}
bds, err := badger.NewDatastore(tdir, nil)
+2 -2
View File
@@ -387,7 +387,7 @@ var sealBenchCmd = &cli.Command{
return err
}
if !ok {
log.Error("post verification failed")
log.Error("window post verification failed")
}
verifyWindowpost1 := time.Now()
@@ -403,7 +403,7 @@ var sealBenchCmd = &cli.Command{
return err
}
if !ok {
log.Error("post verification failed")
log.Error("window post verification failed")
}
verifyWindowpost2 := time.Now()
+2 -2
View File
@@ -221,7 +221,7 @@ func (p *Processor) processMiners(ctx context.Context, minerTips map[types.TipSe
var claim power.Claim
// get miner claim from power actors claim map and store if found, else the miner had no claim at
// this tipset
found, err := minersClaims.Get(adt.AddrKey(act.addr), &claim)
found, err := minersClaims.Get(abi.AddrKey(act.addr), &claim)
if err != nil {
return nil, err
}
@@ -694,7 +694,7 @@ func (p *Processor) getMinerSectorChanges(ctx context.Context, m minerActorInfo)
}
func (p *Processor) diffMinerPartitions(ctx context.Context, m minerActorInfo, events chan<- *MinerSectorsEvent) error {
prevMiner, err := p.getMinerStateAt(ctx, m.common.addr, m.common.tsKey)
prevMiner, err := p.getMinerStateAt(ctx, m.common.addr, m.common.parentTsKey)
if err != nil {
return err
}
+2 -1
View File
@@ -136,7 +136,8 @@ create unique index if not exists block_cid_uindex
on blocks (cid,height);
create materialized view if not exists state_heights
as select distinct height, parentstateroot from blocks;
as select min(b.height) height, b.parentstateroot
from blocks b group by b.parentstateroot;
create index if not exists state_heights_height_index
on state_heights (height);
+90
View File
@@ -0,0 +1,90 @@
package main
import (
"context"
"fmt"
"time"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
"go.opencensus.io/trace"
)
const LookbackCap = time.Hour
var (
ErrLookbackTooLong = fmt.Errorf("lookbacks of more than %s are disallowed", LookbackCap)
)
type GatewayAPI struct {
api api.FullNode
}
func (a *GatewayAPI) getTipsetTimestamp(ctx context.Context, tsk types.TipSetKey) (time.Time, error) {
if tsk.IsEmpty() {
return time.Now(), nil
}
ts, err := a.api.ChainGetTipSet(ctx, tsk)
if err != nil {
return time.Time{}, err
}
return time.Unix(int64(ts.Blocks()[0].Timestamp), 0), nil
}
func (a *GatewayAPI) checkTipset(ctx context.Context, ts types.TipSetKey) error {
when, err := a.getTipsetTimestamp(ctx, ts)
if err != nil {
return err
}
if time.Since(when) > time.Hour {
return ErrLookbackTooLong
}
return nil
}
func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
ctx, span := trace.StartSpan(ctx, "StateGetActor")
defer span.End()
if err := a.checkTipset(ctx, ts); err != nil {
return nil, fmt.Errorf("bad tipset: %w", err)
}
return a.api.StateGetActor(ctx, actor, ts)
}
func (a *GatewayAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
ctx, span := trace.StartSpan(ctx, "ChainHead")
defer span.End()
// TODO: cache and invalidate cache when timestamp is up (or have internal ChainNotify)
return a.api.ChainHead(ctx)
}
func (a *GatewayAPI) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
ctx, span := trace.StartSpan(ctx, "ChainGetTipSet")
defer span.End()
if err := a.checkTipset(ctx, tsk); err != nil {
return nil, fmt.Errorf("bad tipset: %w", err)
}
// TODO: since we're limiting lookbacks, should just cache this (could really even cache the json response bytes)
return a.api.ChainGetTipSet(ctx, tsk)
}
func (a *GatewayAPI) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
ctx, span := trace.StartSpan(ctx, "MpoolPush")
defer span.End()
// TODO: additional anti-spam checks
return a.api.MpoolPush(ctx, sm)
}
+112
View File
@@ -0,0 +1,112 @@
package main
import (
"context"
"net"
"net/http"
"os"
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/lotus/build"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/lib/lotuslog"
logging "github.com/ipfs/go-log"
"github.com/gorilla/mux"
"github.com/urfave/cli/v2"
)
var log = logging.Logger("gateway")
func main() {
lotuslog.SetupLogLevels()
local := []*cli.Command{
runCmd,
}
app := &cli.App{
Name: "lotus-gateway",
Usage: "Public API server for lotus",
Version: build.UserVersion(),
Flags: []cli.Flag{
&cli.StringFlag{
Name: "repo",
EnvVars: []string{"LOTUS_PATH"},
Value: "~/.lotus", // TODO: Consider XDG_DATA_HOME
},
},
Commands: local,
}
app.Setup()
if err := app.Run(os.Args); err != nil {
log.Warnf("%+v", err)
return
}
}
var runCmd = &cli.Command{
Name: "run",
Usage: "Start api server",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "listen",
Usage: "host address and port the api server will listen on",
Value: "0.0.0.0:2346",
},
},
Action: func(cctx *cli.Context) error {
log.Info("Starting lotus gateway")
ctx := lcli.ReqContext(cctx)
ctx, cancel := context.WithCancel(ctx)
defer cancel()
api, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
address := cctx.String("listen")
mux := mux.NewRouter()
log.Info("Setting up API endpoint at " + address)
rpcServer := jsonrpc.NewServer()
rpcServer.Register("Filecoin", &GatewayAPI{api: api})
mux.Handle("/rpc/v0", rpcServer)
mux.PathPrefix("/").Handler(http.DefaultServeMux)
/*ah := &auth.Handler{
Verify: nodeApi.AuthVerify,
Next: mux.ServeHTTP,
}*/
srv := &http.Server{
Handler: mux,
BaseContext: func(listener net.Listener) context.Context {
return ctx
},
}
go func() {
<-ctx.Done()
log.Warn("Shutting down...")
if err := srv.Shutdown(context.TODO()); err != nil {
log.Errorf("shutting down RPC server failed: %s", err)
}
log.Warn("Graceful shutdown successful")
}()
nl, err := net.Listen("tcp", address)
if err != nil {
return err
}
return srv.Serve(nl)
},
}
+4 -2
View File
@@ -45,6 +45,8 @@ const FlagWorkerRepo = "worker-repo"
const FlagWorkerRepoDeprecation = "workerrepo"
func main() {
build.RunningNodeType = build.NodeWorker
lotuslog.SetupLogLevels()
local := []*cli.Command{
@@ -187,8 +189,8 @@ var runCmd = &cli.Command{
if err != nil {
return err
}
if v.APIVersion != build.APIVersion {
return xerrors.Errorf("lotus-miner API version doesn't match: local: %s", api.Version{APIVersion: build.APIVersion})
if v.APIVersion != build.MinerAPIVersion {
return xerrors.Errorf("lotus-miner API version doesn't match: expected: %s", api.Version{APIVersion: build.MinerAPIVersion})
}
log.Infof("Remote version %s", v)
+1 -1
View File
@@ -21,7 +21,7 @@ type worker struct {
}
func (w *worker) Version(context.Context) (build.Version, error) {
return build.APIVersion, nil
return build.WorkerAPIVersion, nil
}
func (w *worker) StorageAddLocal(ctx context.Context, path string) error {
+173 -31
View File
@@ -4,6 +4,7 @@ import (
"encoding/base64"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
@@ -28,6 +29,9 @@ var bitFieldCmd = &cli.Command{
bitFieldRunsCmd,
bitFieldStatCmd,
bitFieldDecodeCmd,
bitFieldIntersectCmd,
bitFieldEncodeCmd,
bitFieldSubCmd,
},
}
@@ -200,38 +204,9 @@ var bitFieldDecodeCmd = &cli.Command{
},
},
Action: func(cctx *cli.Context) error {
var val string
if cctx.Args().Present() {
val = cctx.Args().Get(0)
} else {
b, err := ioutil.ReadAll(os.Stdin)
if err != nil {
return err
}
val = string(b)
}
var dec []byte
switch cctx.String("enc") {
case "base64":
d, err := base64.StdEncoding.DecodeString(val)
if err != nil {
return fmt.Errorf("decoding base64 value: %w", err)
}
dec = d
case "hex":
d, err := hex.DecodeString(val)
if err != nil {
return fmt.Errorf("decoding hex value: %w", err)
}
dec = d
default:
return fmt.Errorf("unrecognized encoding: %s", cctx.String("enc"))
}
rle, err := bitfield.NewFromBytes(dec)
rle, err := decode(cctx, 0)
if err != nil {
return xerrors.Errorf("failed to parse bitfield: %w", err)
return err
}
vals, err := rle.All(100000000000)
@@ -243,3 +218,170 @@ var bitFieldDecodeCmd = &cli.Command{
return nil
},
}
var bitFieldIntersectCmd = &cli.Command{
Name: "intersect",
Description: "intersect 2 bitfields and print the resulting bitfield as base64",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "enc",
Value: "base64",
Usage: "specify input encoding to parse",
},
},
Action: func(cctx *cli.Context) error {
b, err := decode(cctx, 1)
if err != nil {
return err
}
a, err := decode(cctx, 0)
if err != nil {
return err
}
o, err := bitfield.IntersectBitField(a, b)
if err != nil {
return xerrors.Errorf("intersect: %w", err)
}
s, err := o.RunIterator()
if err != nil {
return err
}
bytes, err := rlepluslazy.EncodeRuns(s, []byte{})
if err != nil {
return err
}
fmt.Println(base64.StdEncoding.EncodeToString(bytes))
return nil
},
}
var bitFieldSubCmd = &cli.Command{
Name: "sub",
Description: "subtract 2 bitfields and print the resulting bitfield as base64",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "enc",
Value: "base64",
Usage: "specify input encoding to parse",
},
},
Action: func(cctx *cli.Context) error {
b, err := decode(cctx, 1)
if err != nil {
return err
}
a, err := decode(cctx, 0)
if err != nil {
return err
}
o, err := bitfield.SubtractBitField(a, b)
if err != nil {
return xerrors.Errorf("intersect: %w", err)
}
s, err := o.RunIterator()
if err != nil {
return err
}
bytes, err := rlepluslazy.EncodeRuns(s, []byte{})
if err != nil {
return err
}
fmt.Println(base64.StdEncoding.EncodeToString(bytes))
return nil
},
}
var bitFieldEncodeCmd = &cli.Command{
Name: "encode",
Description: "encode a series of decimal numbers into a bitfield",
ArgsUsage: "[infile]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "enc",
Value: "base64",
Usage: "specify input encoding to parse",
},
},
Action: func(cctx *cli.Context) error {
f, err := os.Open(cctx.Args().First())
if err != nil {
return err
}
defer f.Close() // nolint
out := bitfield.New()
for {
var i uint64
_, err := fmt.Fscan(f, &i)
if err == io.EOF {
break
}
out.Set(i)
}
s, err := out.RunIterator()
if err != nil {
return err
}
bytes, err := rlepluslazy.EncodeRuns(s, []byte{})
if err != nil {
return err
}
fmt.Println(base64.StdEncoding.EncodeToString(bytes))
return nil
},
}
func decode(cctx *cli.Context, a int) (bitfield.BitField, error) {
var val string
if cctx.Args().Present() {
if a >= cctx.NArg() {
return bitfield.BitField{}, xerrors.Errorf("need more than %d args", a)
}
val = cctx.Args().Get(a)
} else {
if a > 0 {
return bitfield.BitField{}, xerrors.Errorf("need more than %d args", a)
}
b, err := ioutil.ReadAll(os.Stdin)
if err != nil {
return bitfield.BitField{}, err
}
val = string(b)
}
var dec []byte
switch cctx.String("enc") {
case "base64":
d, err := base64.StdEncoding.DecodeString(val)
if err != nil {
return bitfield.BitField{}, fmt.Errorf("decoding base64 value: %w", err)
}
dec = d
case "hex":
d, err := hex.DecodeString(val)
if err != nil {
return bitfield.BitField{}, fmt.Errorf("decoding hex value: %w", err)
}
dec = d
default:
return bitfield.BitField{}, fmt.Errorf("unrecognized encoding: %s", cctx.String("enc"))
}
return bitfield.NewFromBytes(dec)
}
+123
View File
@@ -0,0 +1,123 @@
package main
import (
"context"
"fmt"
"os"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/lib/blockstore"
"github.com/filecoin-project/lotus/node/repo"
)
var exportChainCmd = &cli.Command{
Name: "export",
Description: "Export chain from repo (requires node to be offline)",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "repo",
Value: "~/.lotus",
},
&cli.StringFlag{
Name: "tipset",
Usage: "tipset to export from",
},
&cli.Int64Flag{
Name: "recent-stateroots",
},
&cli.BoolFlag{
Name: "full-state",
},
&cli.BoolFlag{
Name: "skip-old-msgs",
},
},
Action: func(cctx *cli.Context) error {
if !cctx.Args().Present() {
return lcli.ShowHelp(cctx, fmt.Errorf("must specify file name to write export to"))
}
ctx := context.TODO()
r, err := repo.NewFS(cctx.String("repo"))
if err != nil {
return xerrors.Errorf("opening fs repo: %w", err)
}
exists, err := r.Exists()
if err != nil {
return err
}
if !exists {
return xerrors.Errorf("lotus repo doesn't exist")
}
lr, err := r.Lock(repo.FullNode)
if err != nil {
return err
}
defer lr.Close() //nolint:errcheck
fi, err := os.Create(cctx.Args().First())
if err != nil {
return xerrors.Errorf("opening the output file: %w", err)
}
defer fi.Close() //nolint:errcheck
ds, err := lr.Datastore("/chain")
if err != nil {
return err
}
mds, err := lr.Datastore("/metadata")
if err != nil {
return err
}
bs := blockstore.NewBlockstore(ds)
cs := store.NewChainStore(bs, mds, nil)
if err := cs.Load(); err != nil {
return err
}
nroots := abi.ChainEpoch(cctx.Int64("recent-stateroots"))
fullstate := cctx.Bool("full-state")
skipoldmsgs := cctx.Bool("skip-old-msgs")
var ts *types.TipSet
if tss := cctx.String("tipset"); tss != "" {
cids, err := lcli.ParseTipSetString(tss)
if err != nil {
return xerrors.Errorf("failed to parse tipset (%q): %w", tss, err)
}
tsk := types.NewTipSetKey(cids...)
selts, err := cs.LoadTipSet(tsk)
if err != nil {
return xerrors.Errorf("loading tipset: %w", err)
}
ts = selts
} else {
ts = cs.GetHeaviestTipSet()
}
if fullstate {
nroots = ts.Height() + 1
}
if err := cs.Export(ctx, ts, nroots, skipoldmsgs, fi); err != nil {
return xerrors.Errorf("export failed: %w", err)
}
return nil
},
}
+2
View File
@@ -33,6 +33,8 @@ func main() {
mpoolCmd,
genesisVerifyCmd,
mathCmd,
mpoolStatsCmd,
exportChainCmd,
}
app := &cli.App{
+273
View File
@@ -0,0 +1,273 @@
package main
import (
"fmt"
"net/http"
"sort"
"time"
"contrib.go.opencensus.io/exporter/prometheus"
"github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log"
"github.com/urfave/cli/v2"
"go.opencensus.io/stats"
"go.opencensus.io/stats/view"
"go.opencensus.io/tag"
"github.com/filecoin-project/go-address"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/specs-actors/actors/builtin"
)
var (
MpoolAge = stats.Float64("mpoolage", "Age of messages in the mempool", stats.UnitSeconds)
MpoolSize = stats.Int64("mpoolsize", "Number of messages in mempool", stats.UnitDimensionless)
MpoolInboundRate = stats.Int64("inbound", "Counter for inbound messages", stats.UnitDimensionless)
BlockInclusionRate = stats.Int64("inclusion", "Counter for message included in blocks", stats.UnitDimensionless)
MsgWaitTime = stats.Float64("msg-wait-time", "Wait time of messages to make it into a block", stats.UnitSeconds)
)
var (
LeTag, _ = tag.NewKey("quantile")
MTTag, _ = tag.NewKey("msg_type")
)
var (
AgeView = &view.View{
Name: "mpool-age",
Measure: MpoolAge,
TagKeys: []tag.Key{LeTag, MTTag},
Aggregation: view.LastValue(),
}
SizeView = &view.View{
Name: "mpool-size",
Measure: MpoolSize,
TagKeys: []tag.Key{MTTag},
Aggregation: view.LastValue(),
}
InboundRate = &view.View{
Name: "msg-inbound",
Measure: MpoolInboundRate,
TagKeys: []tag.Key{MTTag},
Aggregation: view.Count(),
}
InclusionRate = &view.View{
Name: "msg-inclusion",
Measure: BlockInclusionRate,
TagKeys: []tag.Key{MTTag},
Aggregation: view.Count(),
}
MsgWait = &view.View{
Name: "msg-wait",
Measure: MsgWaitTime,
TagKeys: []tag.Key{MTTag},
Aggregation: view.Distribution(10, 30, 60, 120, 240, 600, 1800, 3600),
}
)
type msgInfo struct {
msg *types.SignedMessage
seen time.Time
}
var mpoolStatsCmd = &cli.Command{
Name: "mpool-stats",
Action: func(cctx *cli.Context) error {
logging.SetLogLevel("rpc", "ERROR")
if err := view.Register(AgeView, SizeView, InboundRate, InclusionRate, MsgWait); err != nil {
return err
}
expo, err := prometheus.NewExporter(prometheus.Options{
Namespace: "lotusmpool",
})
if err != nil {
return err
}
http.Handle("/debug/metrics", expo)
go func() {
if err := http.ListenAndServe(":10555", nil); err != nil {
panic(err)
}
}()
api, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := lcli.ReqContext(cctx)
updates, err := api.MpoolSub(ctx)
if err != nil {
return err
}
mcache := make(map[address.Address]bool)
isMiner := func(addr address.Address) (bool, error) {
cache, ok := mcache[addr]
if ok {
return cache, nil
}
act, err := api.StateGetActor(ctx, addr, types.EmptyTSK)
if err != nil {
return false, err
}
ism := act.Code == builtin.StorageMinerActorCodeID
mcache[addr] = ism
return ism, nil
}
wpostTracker := make(map[cid.Cid]*msgInfo)
tracker := make(map[cid.Cid]*msgInfo)
tick := time.Tick(time.Second)
for {
select {
case u, ok := <-updates:
if !ok {
return fmt.Errorf("connection with lotus node broke")
}
switch u.Type {
case lapi.MpoolAdd:
stats.Record(ctx, MpoolInboundRate.M(1))
tracker[u.Message.Cid()] = &msgInfo{
msg: u.Message,
seen: time.Now(),
}
if u.Message.Message.Method == builtin.MethodsMiner.SubmitWindowedPoSt {
miner, err := isMiner(u.Message.Message.To)
if err != nil {
log.Warnf("failed to determine if message target was to a miner: %s", err)
continue
}
if miner {
wpostTracker[u.Message.Cid()] = &msgInfo{
msg: u.Message,
seen: time.Now(),
}
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(MTTag, "wpost")}, MpoolInboundRate.M(1))
}
}
case lapi.MpoolRemove:
mi, ok := tracker[u.Message.Cid()]
if ok {
fmt.Printf("%s was in the mempool for %s (feecap=%s, prem=%s)\n", u.Message.Cid(), time.Since(mi.seen), u.Message.Message.GasFeeCap, u.Message.Message.GasPremium)
stats.Record(ctx, BlockInclusionRate.M(1))
stats.Record(ctx, MsgWaitTime.M(time.Since(mi.seen).Seconds()))
delete(tracker, u.Message.Cid())
}
wm, ok := wpostTracker[u.Message.Cid()]
if ok {
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(MTTag, "wpost")}, BlockInclusionRate.M(1))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(MTTag, "wpost")}, MsgWaitTime.M(time.Since(wm.seen).Seconds()))
delete(wpostTracker, u.Message.Cid())
}
default:
return fmt.Errorf("unrecognized mpool update state: %d", u.Type)
}
case <-tick:
var ages []time.Duration
if len(tracker) > 0 {
for _, v := range tracker {
age := time.Since(v.seen)
ages = append(ages, age)
}
st := ageStats(ages)
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "40")}, MpoolAge.M(st.Perc40.Seconds()))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "50")}, MpoolAge.M(st.Perc50.Seconds()))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "60")}, MpoolAge.M(st.Perc60.Seconds()))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "70")}, MpoolAge.M(st.Perc70.Seconds()))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "80")}, MpoolAge.M(st.Perc80.Seconds()))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "90")}, MpoolAge.M(st.Perc90.Seconds()))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "95")}, MpoolAge.M(st.Perc95.Seconds()))
stats.Record(ctx, MpoolSize.M(int64(len(tracker))))
fmt.Printf("%d messages in mempool for average of %s, (%s / %s / %s)\n", st.Count, st.Average, st.Perc50, st.Perc80, st.Perc95)
}
var wpages []time.Duration
if len(wpostTracker) > 0 {
for _, v := range wpostTracker {
age := time.Since(v.seen)
wpages = append(wpages, age)
}
st := ageStats(wpages)
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "40"), tag.Upsert(MTTag, "wpost")}, MpoolAge.M(st.Perc40.Seconds()))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "50"), tag.Upsert(MTTag, "wpost")}, MpoolAge.M(st.Perc50.Seconds()))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "60"), tag.Upsert(MTTag, "wpost")}, MpoolAge.M(st.Perc60.Seconds()))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "70"), tag.Upsert(MTTag, "wpost")}, MpoolAge.M(st.Perc70.Seconds()))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "80"), tag.Upsert(MTTag, "wpost")}, MpoolAge.M(st.Perc80.Seconds()))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "90"), tag.Upsert(MTTag, "wpost")}, MpoolAge.M(st.Perc90.Seconds()))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(LeTag, "95"), tag.Upsert(MTTag, "wpost")}, MpoolAge.M(st.Perc95.Seconds()))
_ = stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(MTTag, "wpost")}, MpoolSize.M(int64(len(wpostTracker))))
fmt.Printf("%d wpost messages in mempool for average of %s, (%s / %s / %s)\n", st.Count, st.Average, st.Perc50, st.Perc80, st.Perc95)
}
}
}
},
}
type ageStat struct {
Average time.Duration
Max time.Duration
Perc40 time.Duration
Perc50 time.Duration
Perc60 time.Duration
Perc70 time.Duration
Perc80 time.Duration
Perc90 time.Duration
Perc95 time.Duration
Count int
}
func ageStats(ages []time.Duration) *ageStat {
sort.Slice(ages, func(i, j int) bool {
return ages[i] < ages[j]
})
st := ageStat{
Count: len(ages),
}
var sum time.Duration
for _, a := range ages {
sum += a
if a > st.Max {
st.Max = a
}
}
st.Average = sum / time.Duration(len(ages))
p40 := (4 * len(ages)) / 10
p50 := len(ages) / 2
p60 := (6 * len(ages)) / 10
p70 := (7 * len(ages)) / 10
p80 := (4 * len(ages)) / 5
p90 := (9 * len(ages)) / 10
p95 := (19 * len(ages)) / 20
st.Perc40 = ages[p40]
st.Perc50 = ages[p50]
st.Perc60 = ages[p60]
st.Perc70 = ages[p70]
st.Perc80 = ages[p80]
st.Perc90 = ages[p90]
st.Perc95 = ages[p95]
return &st
}
+2 -1
View File
@@ -7,6 +7,7 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/util/adt"
@@ -336,7 +337,7 @@ var verifRegCheckVerifierCmd = &cli.Command{
}
var dcap verifreg.DataCap
if found, err := vh.Get(adt.AddrKey(vaddr), &dcap); err != nil {
if found, err := vh.Get(abi.AddrKey(vaddr), &dcap); err != nil {
return err
} else if !found {
return fmt.Errorf("not found")
+9 -2
View File
@@ -44,6 +44,7 @@ import (
lcli "github.com/filecoin-project/lotus/cli"
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
"github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/journal"
"github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/lotus/node/modules"
"github.com/filecoin-project/lotus/node/modules/dtypes"
@@ -179,8 +180,8 @@ var initCmd = &cli.Command{
return err
}
if !v.APIVersion.EqMajorMinor(build.APIVersion) {
return xerrors.Errorf("Remote API version didn't match (local %s, remote %s)", build.APIVersion, v.APIVersion)
if !v.APIVersion.EqMajorMinor(build.FullAPIVersion) {
return xerrors.Errorf("Remote API version didn't match (expected %s, remote %s)", build.FullAPIVersion, v.APIVersion)
}
log.Info("Initializing repo")
@@ -459,6 +460,12 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode,
return err
}
if jrnl, err := journal.OpenFSJournal(lr, journal.DefaultDisabledEvents); err == nil {
journal.J = jrnl
} else {
return fmt.Errorf("failed to open filesystem journal: %w", err)
}
m := miner.NewMiner(api, epp, a, slashfilter.New(mds))
{
if err := m.Start(ctx); err != nil {
+2
View File
@@ -26,6 +26,8 @@ const FlagMinerRepo = "miner-repo"
const FlagMinerRepoDeprecation = "storagerepo"
func main() {
build.RunningNodeType = build.NodeMiner
lotuslog.SetupLogLevels()
local := []*cli.Command{
+6 -22
View File
@@ -5,16 +5,13 @@ import (
"fmt"
"os"
"text/tabwriter"
"time"
"github.com/fatih/color"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
)
@@ -203,8 +200,8 @@ var provingInfoCmd = &cli.Command{
fmt.Printf("Current Epoch: %d\n", cd.CurrentEpoch)
fmt.Printf("Proving Period Boundary: %d\n", cd.PeriodStart%miner.WPoStProvingPeriod)
fmt.Printf("Proving Period Start: %s\n", epochTime(cd.CurrentEpoch, cd.PeriodStart))
fmt.Printf("Next Period Start: %s\n\n", epochTime(cd.CurrentEpoch, cd.PeriodStart+miner.WPoStProvingPeriod))
fmt.Printf("Proving Period Start: %s\n", lcli.EpochTime(cd.CurrentEpoch, cd.PeriodStart))
fmt.Printf("Next Period Start: %s\n\n", lcli.EpochTime(cd.CurrentEpoch, cd.PeriodStart+miner.WPoStProvingPeriod))
fmt.Printf("Faults: %d (%.2f%%)\n", faults, faultPerc)
fmt.Printf("Recovering: %d\n", recovering)
@@ -224,27 +221,14 @@ var provingInfoCmd = &cli.Command{
fmt.Printf("Deadline Sectors: %d\n", curDeadlineSectors)
}
fmt.Printf("Deadline Open: %s\n", epochTime(cd.CurrentEpoch, cd.Open))
fmt.Printf("Deadline Close: %s\n", epochTime(cd.CurrentEpoch, cd.Close))
fmt.Printf("Deadline Challenge: %s\n", epochTime(cd.CurrentEpoch, cd.Challenge))
fmt.Printf("Deadline FaultCutoff: %s\n", epochTime(cd.CurrentEpoch, cd.FaultCutoff))
fmt.Printf("Deadline Open: %s\n", lcli.EpochTime(cd.CurrentEpoch, cd.Open))
fmt.Printf("Deadline Close: %s\n", lcli.EpochTime(cd.CurrentEpoch, cd.Close))
fmt.Printf("Deadline Challenge: %s\n", lcli.EpochTime(cd.CurrentEpoch, cd.Challenge))
fmt.Printf("Deadline FaultCutoff: %s\n", lcli.EpochTime(cd.CurrentEpoch, cd.FaultCutoff))
return nil
},
}
func epochTime(curr, e abi.ChainEpoch) string {
switch {
case curr > e:
return fmt.Sprintf("%d (%s ago)", e, time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(curr-e)))
case curr == e:
return fmt.Sprintf("%d (now)", e)
case curr < e:
return fmt.Sprintf("%d (in %s)", e, time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(e-curr)))
}
panic("math broke")
}
var provingDeadlinesCmd = &cli.Command{
Name: "deadlines",
Usage: "View the current proving period deadlines information",
+114
View File
@@ -5,9 +5,12 @@ import (
"os"
"text/tabwriter"
"github.com/docker/go-units"
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-state-types/abi"
"github.com/urfave/cli/v2"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
)
@@ -17,6 +20,8 @@ var retrievalDealsCmd = &cli.Command{
Subcommands: []*cli.Command{
retrievalDealSelectionCmd,
retrievalDealsListCmd,
retrievalSetAskCmd,
retrievalGetAskCmd,
},
}
@@ -154,3 +159,112 @@ var retrievalDealsListCmd = &cli.Command{
return w.Flush()
},
}
var retrievalSetAskCmd = &cli.Command{
Name: "set-ask",
Usage: "Configure the provider's retrieval ask",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "price",
Usage: "Set the price of the ask for retrievals (FIL/GiB)",
},
&cli.StringFlag{
Name: "unseal-price",
Usage: "Set the price to unseal",
},
&cli.StringFlag{
Name: "payment-interval",
Usage: "Set the payment interval (in bytes) for retrieval",
DefaultText: "1MiB",
},
&cli.StringFlag{
Name: "payment-interval-increase",
Usage: "Set the payment interval increase (in bytes) for retrieval",
DefaultText: "1MiB",
},
},
Action: func(cctx *cli.Context) error {
ctx := lcli.DaemonContext(cctx)
api, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
return err
}
defer closer()
ask, err := api.MarketGetRetrievalAsk(ctx)
if err != nil {
return err
}
if cctx.IsSet("price") {
v, err := types.ParseFIL(cctx.String("price"))
if err != nil {
return err
}
ask.PricePerByte = types.BigDiv(types.BigInt(v), types.NewInt(1<<30))
}
if cctx.IsSet("unseal-price") {
v, err := types.ParseFIL(cctx.String("unseal-price"))
if err != nil {
return err
}
ask.UnsealPrice = abi.TokenAmount(v)
}
if cctx.IsSet("payment-interval") {
v, err := units.RAMInBytes(cctx.String("payment-interval"))
if err != nil {
return err
}
ask.PaymentInterval = uint64(v)
}
if cctx.IsSet("payment-interval-increase") {
v, err := units.RAMInBytes(cctx.String("payment-interval-increase"))
if err != nil {
return err
}
ask.PaymentIntervalIncrease = uint64(v)
}
return api.MarketSetRetrievalAsk(ctx, ask)
},
}
var retrievalGetAskCmd = &cli.Command{
Name: "get-ask",
Usage: "Get the provider's current retrieval ask",
Flags: []cli.Flag{},
Action: func(cctx *cli.Context) error {
ctx := lcli.DaemonContext(cctx)
api, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
return err
}
defer closer()
ask, err := api.MarketGetRetrievalAsk(ctx)
if err != nil {
return err
}
w := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0)
fmt.Fprintf(w, "Price per Byte\tUnseal Price\tPayment Interval\tPayment Interval Increase\n")
if ask == nil {
fmt.Fprintf(w, "<miner does not have an retrieval ask set>\n")
return w.Flush()
}
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n",
types.FIL(ask.PricePerByte),
types.FIL(ask.UnsealPrice),
units.BytesSize(float64(ask.PaymentInterval)),
units.BytesSize(float64(ask.PaymentIntervalIncrease)),
)
return w.Flush()
},
}
+2 -2
View File
@@ -77,8 +77,8 @@ var runCmd = &cli.Command{
}
}
if v.APIVersion != build.APIVersion {
return xerrors.Errorf("lotus-daemon API version doesn't match: local: %s", api.Version{APIVersion: build.APIVersion})
if v.APIVersion != build.FullAPIVersion {
return xerrors.Errorf("lotus-daemon API version doesn't match: expected: %s", api.Version{APIVersion: build.FullAPIVersion})
}
log.Info("Checking full node sync status")
+1
View File
@@ -46,6 +46,7 @@ func init() {
return xerrors.Errorf("StateMinerWorker: %w", err)
}
// XXX: This can't be right
rand, err := api.ChainGetRandomnessFromTickets(ctx, head.Key(), crypto.DomainSeparationTag_TicketProduction, head.Height(), addr.Bytes())
if err != nil {
return xerrors.Errorf("failed to get randomness: %w", err)
+2
View File
@@ -16,6 +16,8 @@ import (
var AdvanceBlockCmd *cli.Command
func main() {
build.RunningNodeType = build.NodeFull
lotuslog.SetupLogLevels()
local := []*cli.Command{
+62 -16
View File
@@ -6,7 +6,6 @@ import (
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-cid"
typegen "github.com/whyrusleeping/cbor-gen"
@@ -62,6 +61,12 @@ const (
// MethodMutateState is the identifier for the method that attempts to mutate
// a state value in the actor.
MethodMutateState
// MethodAbortWith is the identifier for the method that panics optionally with
// a passed exit code.
MethodAbortWith
// MethodInspectRuntime is the identifier for the method that returns the
// current runtime values.
MethodInspectRuntime
)
// Exports defines the methods this actor exposes publicly.
@@ -74,6 +79,8 @@ func (a Actor) Exports() []interface{} {
MethodDeleteActor: a.DeleteActor,
MethodSend: a.Send,
MethodMutateState: a.MutateState,
MethodAbortWith: a.AbortWith,
MethodInspectRuntime: a.InspectRuntime,
}
}
@@ -97,18 +104,14 @@ type SendReturn struct {
// passed parameters.
func (a Actor) Send(rt runtime.Runtime, args *SendArgs) *SendReturn {
rt.ValidateImmediateCallerAcceptAny()
ret, code := rt.Send(
var out runtime.CBORBytes
code := rt.Send(
args.To,
args.Method,
runtime.CBORBytes(args.Params),
args.Value,
&out,
)
var out runtime.CBORBytes
if ret != nil {
if err := ret.Into(&out); err != nil {
rt.Abortf(exitcode.ErrIllegalState, "failed to unmarshal send return: %v", err)
}
}
return &SendReturn{
Return: out,
Code: code,
@@ -116,7 +119,7 @@ func (a Actor) Send(rt runtime.Runtime, args *SendArgs) *SendReturn {
}
// Constructor will panic because the Chaos actor is a singleton.
func (a Actor) Constructor(_ runtime.Runtime, _ *adt.EmptyValue) *adt.EmptyValue {
func (a Actor) Constructor(_ runtime.Runtime, _ *abi.EmptyValue) *abi.EmptyValue {
panic("constructor should not be called; the Chaos actor is a singleton actor")
}
@@ -127,7 +130,7 @@ func (a Actor) Constructor(_ runtime.Runtime, _ *adt.EmptyValue) *adt.EmptyValue
// CallerValidationBranchAddrNilSet validates against an empty caller
// address set.
// CallerValidationBranchTypeNilSet validates against an empty caller type set.
func (a Actor) CallerValidation(rt runtime.Runtime, branch *typegen.CborInt) *adt.EmptyValue {
func (a Actor) CallerValidation(rt runtime.Runtime, branch *typegen.CborInt) *abi.EmptyValue {
switch CallerValidationBranch(*branch) {
case CallerValidationBranchNone:
case CallerValidationBranchTwice:
@@ -157,7 +160,7 @@ type CreateActorArgs struct {
}
// CreateActor creates an actor with the supplied CID and Address.
func (a Actor) CreateActor(rt runtime.Runtime, args *CreateActorArgs) *adt.EmptyValue {
func (a Actor) CreateActor(rt runtime.Runtime, args *CreateActorArgs) *abi.EmptyValue {
rt.ValidateImmediateCallerAcceptAny()
var (
@@ -195,7 +198,7 @@ func (a Actor) ResolveAddress(rt runtime.Runtime, args *address.Address) *Resolv
// DeleteActor deletes the executing actor from the state tree, transferring any
// balance to beneficiary.
func (a Actor) DeleteActor(rt runtime.Runtime, beneficiary *address.Address) *adt.EmptyValue {
func (a Actor) DeleteActor(rt runtime.Runtime, beneficiary *address.Address) *abi.EmptyValue {
rt.ValidateImmediateCallerAcceptAny()
rt.DeleteActor(*beneficiary)
return nil
@@ -209,19 +212,19 @@ type MutateStateArgs struct {
}
// MutateState attempts to mutate a state value in the actor.
func (a Actor) MutateState(rt runtime.Runtime, args *MutateStateArgs) *adt.EmptyValue {
func (a Actor) MutateState(rt runtime.Runtime, args *MutateStateArgs) *abi.EmptyValue {
rt.ValidateImmediateCallerAcceptAny()
var st State
switch args.Branch {
case MutateInTransaction:
rt.State().Transaction(&st, func() {
rt.StateTransaction(&st, func() {
st.Value = args.Value
})
case MutateReadonly:
rt.State().Readonly(&st)
rt.StateReadonly(&st)
st.Value = args.Value
case MutateAfterTransaction:
rt.State().Transaction(&st, func() {
rt.StateTransaction(&st, func() {
st.Value = args.Value + "-in"
})
st.Value = args.Value
@@ -230,3 +233,46 @@ func (a Actor) MutateState(rt runtime.Runtime, args *MutateStateArgs) *adt.Empty
}
return nil
}
// AbortWithArgs are the arguments to the Actor.AbortWith method, specifying the
// exit code to (optionally) abort with and the message.
type AbortWithArgs struct {
Code exitcode.ExitCode
Message string
Uncontrolled bool
}
// AbortWith simply causes a panic with the passed exit code.
func (a Actor) AbortWith(rt runtime.Runtime, args *AbortWithArgs) *abi.EmptyValue {
if args.Uncontrolled { // uncontrolled abort: directly panic
panic(args.Message)
} else {
rt.Abortf(args.Code, args.Message)
}
return nil
}
// InspectRuntimeReturn is the return value for the Actor.InspectRuntime method.
type InspectRuntimeReturn struct {
Caller address.Address
Receiver address.Address
ValueReceived abi.TokenAmount
CurrEpoch abi.ChainEpoch
CurrentBalance abi.TokenAmount
State State
}
// InspectRuntime returns a copy of the serializable values available in the Runtime.
func (a Actor) InspectRuntime(rt runtime.Runtime, _ *abi.EmptyValue) *InspectRuntimeReturn {
rt.ValidateImmediateCallerAcceptAny()
var st State
rt.StateReadonly(&st)
return &InspectRuntimeReturn{
Caller: rt.Caller(),
Receiver: rt.Receiver(),
ValueReceived: rt.ValueReceived(),
CurrEpoch: rt.CurrEpoch(),
CurrentBalance: rt.CurrentBalance(),
State: st,
}
}
+179
View File
@@ -0,0 +1,179 @@
package chaos
import (
"context"
"testing"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/support/mock"
atesting "github.com/filecoin-project/specs-actors/support/testing"
)
func TestSingleton(t *testing.T) {
receiver := atesting.NewIDAddr(t, 100)
builder := mock.NewBuilder(context.Background(), receiver)
rt := builder.Build(t)
var a Actor
msg := "constructor should not be called; the Chaos actor is a singleton actor"
rt.ExpectAssertionFailure(msg, func() {
rt.Call(a.Constructor, abi.Empty)
})
rt.Verify()
}
func TestDeleteActor(t *testing.T) {
receiver := atesting.NewIDAddr(t, 100)
beneficiary := atesting.NewIDAddr(t, 101)
builder := mock.NewBuilder(context.Background(), receiver)
rt := builder.Build(t)
var a Actor
rt.ExpectValidateCallerAny()
rt.ExpectDeleteActor(beneficiary)
rt.Call(a.DeleteActor, &beneficiary)
rt.Verify()
}
func TestMutateStateInTransaction(t *testing.T) {
receiver := atesting.NewIDAddr(t, 100)
builder := mock.NewBuilder(context.Background(), receiver)
rt := builder.Build(t)
var a Actor
rt.ExpectValidateCallerAny()
rt.StateCreate(&State{})
val := "__mutstat test"
rt.Call(a.MutateState, &MutateStateArgs{
Value: val,
Branch: MutateInTransaction,
})
var st State
rt.GetState(&st)
if st.Value != val {
t.Fatal("state was not updated")
}
rt.Verify()
}
func TestMutateStateAfterTransaction(t *testing.T) {
receiver := atesting.NewIDAddr(t, 100)
builder := mock.NewBuilder(context.Background(), receiver)
rt := builder.Build(t)
var a Actor
rt.ExpectValidateCallerAny()
rt.StateCreate(&State{})
val := "__mutstat test"
rt.Call(a.MutateState, &MutateStateArgs{
Value: val,
Branch: MutateAfterTransaction,
})
var st State
rt.GetState(&st)
// state should be updated successfully _in_ the transaction but not outside
if st.Value != val+"-in" {
t.Fatal("state was not updated")
}
rt.Verify()
}
func TestMutateStateReadonly(t *testing.T) {
receiver := atesting.NewIDAddr(t, 100)
builder := mock.NewBuilder(context.Background(), receiver)
rt := builder.Build(t)
var a Actor
rt.ExpectValidateCallerAny()
rt.StateCreate(&State{})
val := "__mutstat test"
rt.Call(a.MutateState, &MutateStateArgs{
Value: val,
Branch: MutateReadonly,
})
var st State
rt.GetState(&st)
if st.Value != "" {
t.Fatal("state was not expected to be updated")
}
rt.Verify()
}
func TestAbortWith(t *testing.T) {
receiver := atesting.NewIDAddr(t, 100)
builder := mock.NewBuilder(context.Background(), receiver)
rt := builder.Build(t)
var a Actor
msg := "__test forbidden"
rt.ExpectAbortContainsMessage(exitcode.ErrForbidden, msg, func() {
rt.Call(a.AbortWith, &AbortWithArgs{
Code: exitcode.ErrForbidden,
Message: msg,
Uncontrolled: false,
})
})
rt.Verify()
}
func TestAbortWithUncontrolled(t *testing.T) {
receiver := atesting.NewIDAddr(t, 100)
builder := mock.NewBuilder(context.Background(), receiver)
rt := builder.Build(t)
var a Actor
msg := "__test uncontrolled panic"
rt.ExpectAssertionFailure(msg, func() {
rt.Call(a.AbortWith, &AbortWithArgs{
Message: msg,
Uncontrolled: true,
})
})
rt.Verify()
}
func TestInspectRuntime(t *testing.T) {
caller := atesting.NewIDAddr(t, 100)
receiver := atesting.NewIDAddr(t, 101)
builder := mock.NewBuilder(context.Background(), receiver)
rt := builder.Build(t)
rt.SetCaller(caller, builtin.AccountActorCodeID)
rt.StateCreate(&State{})
var a Actor
rt.ExpectValidateCallerAny()
ret := rt.Call(a.InspectRuntime, abi.Empty)
rtr, ok := ret.(*InspectRuntimeReturn)
if !ok {
t.Fatal("invalid return value")
}
if rtr.Caller != caller {
t.Fatal("unexpected runtime caller")
}
if rtr.Receiver != receiver {
t.Fatal("unexpected runtime receiver")
}
rt.Verify()
}
+261 -3
View File
@@ -6,10 +6,10 @@ import (
"fmt"
"io"
abi "github.com/filecoin-project/go-state-types/abi"
exitcode "github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/exitcode"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
"golang.org/x/xerrors"
)
var _ = xerrors.Errorf
@@ -614,3 +614,261 @@ func (t *MutateStateArgs) UnmarshalCBOR(r io.Reader) error {
}
return nil
}
var lengthBufAbortWithArgs = []byte{131}
func (t *AbortWithArgs) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write(lengthBufAbortWithArgs); err != nil {
return err
}
scratch := make([]byte, 9)
// t.Code (exitcode.ExitCode) (int64)
if t.Code >= 0 {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Code)); err != nil {
return err
}
} else {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.Code-1)); err != nil {
return err
}
}
// t.Message (string) (string)
if len(t.Message) > cbg.MaxLength {
return xerrors.Errorf("Value in field t.Message was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len(t.Message))); err != nil {
return err
}
if _, err := io.WriteString(w, string(t.Message)); err != nil {
return err
}
// t.Uncontrolled (bool) (bool)
if err := cbg.WriteBool(w, t.Uncontrolled); err != nil {
return err
}
return nil
}
func (t *AbortWithArgs) UnmarshalCBOR(r io.Reader) error {
*t = AbortWithArgs{}
br := cbg.GetPeeker(r)
scratch := make([]byte, 8)
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 3 {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.Code (exitcode.ExitCode) (int64)
{
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.Code = exitcode.ExitCode(extraI)
}
// t.Message (string) (string)
{
sval, err := cbg.ReadStringBuf(br, scratch)
if err != nil {
return err
}
t.Message = string(sval)
}
// t.Uncontrolled (bool) (bool)
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.Uncontrolled = false
case 21:
t.Uncontrolled = true
default:
return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra)
}
return nil
}
var lengthBufInspectRuntimeReturn = []byte{134}
func (t *InspectRuntimeReturn) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write(lengthBufInspectRuntimeReturn); err != nil {
return err
}
scratch := make([]byte, 9)
// t.Caller (address.Address) (struct)
if err := t.Caller.MarshalCBOR(w); err != nil {
return err
}
// t.Receiver (address.Address) (struct)
if err := t.Receiver.MarshalCBOR(w); err != nil {
return err
}
// t.ValueReceived (big.Int) (struct)
if err := t.ValueReceived.MarshalCBOR(w); err != nil {
return err
}
// t.CurrEpoch (abi.ChainEpoch) (int64)
if t.CurrEpoch >= 0 {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.CurrEpoch)); err != nil {
return err
}
} else {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.CurrEpoch-1)); err != nil {
return err
}
}
// t.CurrentBalance (big.Int) (struct)
if err := t.CurrentBalance.MarshalCBOR(w); err != nil {
return err
}
// t.State (chaos.State) (struct)
if err := t.State.MarshalCBOR(w); err != nil {
return err
}
return nil
}
func (t *InspectRuntimeReturn) UnmarshalCBOR(r io.Reader) error {
*t = InspectRuntimeReturn{}
br := cbg.GetPeeker(r)
scratch := make([]byte, 8)
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 6 {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.Caller (address.Address) (struct)
{
if err := t.Caller.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.Caller: %w", err)
}
}
// t.Receiver (address.Address) (struct)
{
if err := t.Receiver.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.Receiver: %w", err)
}
}
// t.ValueReceived (big.Int) (struct)
{
if err := t.ValueReceived.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.ValueReceived: %w", err)
}
}
// t.CurrEpoch (abi.ChainEpoch) (int64)
{
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.CurrEpoch = abi.ChainEpoch(extraI)
}
// t.CurrentBalance (big.Int) (struct)
{
if err := t.CurrentBalance.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.CurrentBalance: %w", err)
}
}
// t.State (chaos.State) (struct)
{
if err := t.State.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.State: %w", err)
}
}
return nil
}
+2
View File
@@ -14,6 +14,8 @@ func main() {
chaos.SendArgs{},
chaos.SendReturn{},
chaos.MutateStateArgs{},
chaos.AbortWithArgs{},
chaos.InspectRuntimeReturn{},
); err != nil {
panic(err)
}
+173 -6
View File
@@ -75,10 +75,14 @@
* [MpoolSetConfig](#MpoolSetConfig)
* [MpoolSub](#MpoolSub)
* [Msig](#Msig)
* [MsigAddApprove](#MsigAddApprove)
* [MsigAddCancel](#MsigAddCancel)
* [MsigAddPropose](#MsigAddPropose)
* [MsigApprove](#MsigApprove)
* [MsigCancel](#MsigCancel)
* [MsigCreate](#MsigCreate)
* [MsigGetAvailableBalance](#MsigGetAvailableBalance)
* [MsigGetVested](#MsigGetVested)
* [MsigPropose](#MsigPropose)
* [MsigSwapApprove](#MsigSwapApprove)
* [MsigSwapCancel](#MsigSwapCancel)
@@ -144,6 +148,7 @@
* [StateMinerRecoveries](#StateMinerRecoveries)
* [StateMinerSectorCount](#StateMinerSectorCount)
* [StateMinerSectors](#StateMinerSectors)
* [StateMsgGasCost](#StateMsgGasCost)
* [StateNetworkName](#StateNetworkName)
* [StateReadState](#StateReadState)
* [StateReplay](#StateReplay)
@@ -207,7 +212,7 @@ Response:
```json
{
"Version": "string value",
"APIVersion": 3584,
"APIVersion": 3840,
"BlockDelay": 42
}
```
@@ -280,6 +285,7 @@ ChainExport returns a stream of bytes with CAR dump of chain data.
The exported chain data includes the header chain from the given tipset
back to genesis, the entire genesis state, and the most recent 'nroots'
state trees.
If oldmsgskip is set, messages from before the requested roots are also not included.
Perms: read
@@ -288,6 +294,7 @@ Inputs:
```json
[
10101,
true,
[
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
@@ -1839,6 +1846,84 @@ The Msig methods are used to interact with multisig wallets on the
filecoin network
### MsigAddApprove
MsigAddApprove approves a previously proposed AddSigner message
It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
<proposer address>, <new signer>, <whether the number of required signers should be increased>
Perms: sign
Inputs:
```json
[
"t01234",
"t01234",
42,
"t01234",
"t01234",
true
]
```
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
```
### MsigAddCancel
MsigAddCancel cancels a previously proposed AddSigner message
It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
<new signer>, <whether the number of required signers should be increased>
Perms: sign
Inputs:
```json
[
"t01234",
"t01234",
42,
"t01234",
true
]
```
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
```
### MsigAddPropose
MsigAddPropose proposes adding a signer in the multisig
It takes the following params: <multisig address>, <sender address of the propose msg>,
<new signer>, <whether the number of required signers should be increased>
Perms: sign
Inputs:
```json
[
"t01234",
"t01234",
"t01234",
true
]
```
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
```
### MsigApprove
MsigApprove approves a previously-proposed multisig message
It takes the following params: <multisig address>, <proposed message ID>, <proposer address>, <recipient address>, <value to transfer>,
@@ -1946,6 +2031,38 @@ Inputs:
Response: `"0"`
### MsigGetVested
MsigGetVested returns the amount of FIL that vested in a multisig in a certain period.
It takes the following params: <multisig address>, <start epoch>, <end epoch>
Perms: read
Inputs:
```json
[
"t01234",
[
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
{
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
}
],
[
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
{
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
}
]
]
```
Response: `"0"`
### MsigPropose
MsigPropose proposes a multisig message
It takes the following params: <multisig address>, <recipient address>, <value to transfer>,
@@ -1976,7 +2093,7 @@ Response:
### MsigSwapApprove
MsigSwapApprove approves a previously proposed SwapSigner
It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
<proposer address>, <old signer> <new signer>
<proposer address>, <old signer>, <new signer>
Perms: sign
@@ -2003,7 +2120,7 @@ Response:
### MsigSwapCancel
MsigSwapCancel cancels a previously proposed SwapSigner message
It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
<old signer> <new signer>
<old signer>, <new signer>
Perms: sign
@@ -2029,7 +2146,7 @@ Response:
### MsigSwapPropose
MsigSwapPropose proposes swapping 2 signers in the multisig
It takes the following params: <multisig address>, <sender address of the propose msg>,
<old signer> <new signer>
<old signer>, <new signer>
Perms: sign
@@ -2259,7 +2376,12 @@ There are not yet any comments for this method.
Perms: sign
Inputs: `null`
Inputs:
```json
[
"t01234"
]
```
Response:
```json
@@ -2283,6 +2405,7 @@ Perms: sign
Inputs:
```json
[
"t01234",
"t01234"
]
```
@@ -3519,7 +3642,12 @@ Response:
"Open": 10101,
"Close": 10101,
"Challenge": 10101,
"FaultCutoff": 10101
"FaultCutoff": 10101,
"WPoStPeriodDeadlines": 42,
"WPoStProvingPeriod": 10101,
"WPoStChallengeWindow": 10101,
"WPoStChallengeLookback": 10101,
"FaultDeclarationCutoff": 10101
}
```
@@ -3610,6 +3738,45 @@ Inputs:
Response: `null`
### StateMsgGasCost
StateMsgGasCost searches for a message in the chain, and returns details of the messages gas costs, including the penalty and miner tip
Perms: read
Inputs:
```json
[
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
[
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
{
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
}
]
]
```
Response:
```json
{
"Message": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
"GasUsed": "0",
"BaseFeeBurn": "0",
"OverEstimationBurn": "0",
"MinerPenalty": "0",
"MinerTip": "0",
"Refund": "0",
"TotalCost": "0"
}
```
### StateNetworkName
StateNetworkName returns the name of the network the node is synced to
Vendored Submodule
+1
Submodule extern/fil-blst added at 5f93488fc0
Vendored Submodule
+1
Submodule extern/oni added at 8b7e7d438c
+51 -46
View File
@@ -168,50 +168,34 @@ func (s *seal) unseal(t *testing.T, sb *Sealer, sp *basicfs.Provider, si abi.Sec
}
}
func post(t *testing.T, sealer *Sealer, seals ...seal) time.Time {
/*randomness := abi.PoStRandomness{0, 9, 2, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 45, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 7}
func post(t *testing.T, sealer *Sealer, skipped []abi.SectorID, seals ...seal) {
randomness := abi.PoStRandomness{0, 9, 2, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 45, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 7}
sis := make([]abi.SectorInfo, len(seals))
sis := make([]saproof.SectorInfo, len(seals))
for i, s := range seals {
sis[i] = abi.SectorInfo{
RegisteredProof: sealProofType,
SectorNumber: s.id.Number,
SealedCID: s.cids.Sealed,
sis[i] = saproof.SectorInfo{
SealProof: sealProofType,
SectorNumber: s.id.Number,
SealedCID: s.cids.Sealed,
}
}
candidates, err := sealer.GenerateEPostCandidates(context.TODO(), seals[0].id.Miner, sis, randomness, []abi.SectorNumber{})
if err != nil {
t.Fatalf("%+v", err)
}*/
fmt.Println("skipping post")
genCandidates := time.Now()
/*if len(candidates) != 1 {
t.Fatal("expected 1 candidate")
proofs, skp, err := sealer.GenerateWindowPoSt(context.TODO(), seals[0].id.Miner, sis, randomness)
if len(skipped) > 0 {
require.Error(t, err)
require.EqualValues(t, skipped, skp)
return
}
candidatesPrime := make([]abi.PoStCandidate, len(candidates))
for idx := range candidatesPrime {
candidatesPrime[idx] = candidates[idx].Candidate
}
proofs, err := sealer.ComputeElectionPoSt(context.TODO(), seals[0].id.Miner, sis, randomness, candidatesPrime)
if err != nil {
t.Fatalf("%+v", err)
}
ePoStChallengeCount := ElectionPostChallengeCount(uint64(len(sis)), 0)
ok, err := ProofVerifier.VerifyElectionPost(context.TODO(), abi.PoStVerifyInfo{
Randomness: randomness,
Candidates: candidatesPrime,
Proofs: proofs,
EligibleSectors: sis,
Prover: seals[0].id.Miner,
ChallengeCount: ePoStChallengeCount,
ok, err := ProofVerifier.VerifyWindowPoSt(context.TODO(), saproof.WindowPoStVerifyInfo{
Randomness: randomness,
Proofs: proofs,
ChallengedSectors: sis,
Prover: seals[0].id.Miner,
})
if err != nil {
t.Fatalf("%+v", err)
@@ -219,8 +203,21 @@ func post(t *testing.T, sealer *Sealer, seals ...seal) time.Time {
if !ok {
t.Fatal("bad post")
}
*/
return genCandidates
}
func corrupt(t *testing.T, sealer *Sealer, id abi.SectorID) {
paths, done, err := sealer.sectors.AcquireSector(context.Background(), id, stores.FTSealed, 0, stores.PathStorage)
require.NoError(t, err)
defer done()
log.Infof("corrupt %s", paths.Sealed)
f, err := os.OpenFile(paths.Sealed, os.O_RDWR, 0664)
require.NoError(t, err)
_, err = f.WriteAt(bytes.Repeat([]byte{'d'}, 2048), 0)
require.NoError(t, err)
require.NoError(t, f.Close())
}
func getGrothParamFileAndVerifyingKeys(s abi.SectorSize) {
@@ -299,11 +296,11 @@ func TestSealAndVerify(t *testing.T) {
commit := time.Now()
genCandidiates := post(t, sb, s)
post(t, sb, nil, s)
epost := time.Now()
post(t, sb, s)
post(t, sb, nil, s)
if err := sb.FinalizeSector(context.TODO(), si, nil); err != nil {
t.Fatalf("%+v", err)
@@ -313,8 +310,7 @@ func TestSealAndVerify(t *testing.T) {
fmt.Printf("PreCommit: %s\n", precommit.Sub(start).String())
fmt.Printf("Commit: %s\n", commit.Sub(precommit).String())
fmt.Printf("GenCandidates: %s\n", genCandidiates.Sub(commit).String())
fmt.Printf("EPoSt: %s\n", epost.Sub(genCandidiates).String())
fmt.Printf("EPoSt: %s\n", epost.Sub(commit).String())
}
func TestSealPoStNoCommit(t *testing.T) {
@@ -370,16 +366,15 @@ func TestSealPoStNoCommit(t *testing.T) {
t.Fatal(err)
}
genCandidiates := post(t, sb, s)
post(t, sb, nil, s)
epost := time.Now()
fmt.Printf("PreCommit: %s\n", precommit.Sub(start).String())
fmt.Printf("GenCandidates: %s\n", genCandidiates.Sub(precommit).String())
fmt.Printf("EPoSt: %s\n", epost.Sub(genCandidiates).String())
fmt.Printf("EPoSt: %s\n", epost.Sub(precommit).String())
}
func TestSealAndVerify2(t *testing.T) {
func TestSealAndVerify3(t *testing.T) {
defer requireFDsClosed(t, openFDs(t))
if runtime.NumCPU() < 10 && os.Getenv("CI") == "" { // don't bother on slow hardware
@@ -419,22 +414,32 @@ func TestSealAndVerify2(t *testing.T) {
si1 := abi.SectorID{Miner: miner, Number: 1}
si2 := abi.SectorID{Miner: miner, Number: 2}
si3 := abi.SectorID{Miner: miner, Number: 3}
s1 := seal{id: si1}
s2 := seal{id: si2}
s3 := seal{id: si3}
wg.Add(2)
wg.Add(3)
go s1.precommit(t, sb, si1, wg.Done) //nolint: staticcheck
time.Sleep(100 * time.Millisecond)
go s2.precommit(t, sb, si2, wg.Done) //nolint: staticcheck
time.Sleep(100 * time.Millisecond)
go s3.precommit(t, sb, si3, wg.Done) //nolint: staticcheck
wg.Wait()
wg.Add(2)
wg.Add(3)
go s1.commit(t, sb, wg.Done) //nolint: staticcheck
go s2.commit(t, sb, wg.Done) //nolint: staticcheck
go s3.commit(t, sb, wg.Done) //nolint: staticcheck
wg.Wait()
post(t, sb, s1, s2)
post(t, sb, nil, s1, s2, s3)
corrupt(t, sb, si1)
corrupt(t, sb, si2)
post(t, sb, []abi.SectorID{si1, si2}, s1, s2, s3)
}
func BenchmarkWriteWithAlignment(b *testing.B) {
+15 -2
View File
@@ -40,8 +40,21 @@ func (sb *Sealer) GenerateWindowPoSt(ctx context.Context, minerID abi.ActorID, s
}
defer done()
proof, err := ffi.GenerateWindowPoSt(minerID, privsectors, randomness)
return proof, skipped, err
if len(skipped) > 0 {
return nil, skipped, xerrors.Errorf("pubSectorToPriv skipped some sectors")
}
proof, faulty, err := ffi.GenerateWindowPoSt(minerID, privsectors, randomness)
var faultyIDs []abi.SectorID
for _, f := range faulty {
faultyIDs = append(faultyIDs, abi.SectorID{
Miner: minerID,
Number: f,
})
}
return proof, faultyIDs, err
}
func (sb *Sealer) pubSectorToPriv(ctx context.Context, mid abi.ActorID, sectorInfo []proof.SectorInfo, faults []abi.SectorNumber, rpt func(abi.RegisteredSealProof) (abi.RegisteredPoStProof, error)) (ffi.SortedPrivateSectorInfo, []abi.SectorID, func(), error) {
+30 -14
View File
@@ -203,25 +203,26 @@ func schedFetch(sector abi.SectorID, ft stores.SectorFileType, ptype stores.Path
}
}
func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.SectorID, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, ticket abi.SealRandomness, unsealed cid.Cid) error {
func (m *Manager) tryReadUnsealedPiece(ctx context.Context, sink io.Writer, sector abi.SectorID, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (foundUnsealed bool, readOk bool, selector WorkerSelector, returnErr error) {
// acquire a lock purely for reading unsealed sectors
ctx, cancel := context.WithCancel(ctx)
defer cancel()
if err := m.index.StorageLock(ctx, sector, stores.FTSealed|stores.FTCache, stores.FTUnsealed); err != nil {
return xerrors.Errorf("acquiring sector lock: %w", err)
if err := m.index.StorageLock(ctx, sector, stores.FTUnsealed, stores.FTNone); err != nil {
returnErr = xerrors.Errorf("acquiring read sector lock: %w", err)
return
}
// passing 0 spt because we only need it when allowFetch is true
best, err := m.index.StorageFindSector(ctx, sector, stores.FTUnsealed, 0, false)
if err != nil {
return xerrors.Errorf("read piece: checking for already existing unsealed sector: %w", err)
returnErr = xerrors.Errorf("read piece: checking for already existing unsealed sector: %w", err)
return
}
var readOk bool
var selector WorkerSelector
if len(best) == 0 { // new
selector = newAllocSelector(m.index, stores.FTUnsealed, stores.PathSealing)
} else { // append to existing
foundUnsealed = len(best) > 0
if foundUnsealed { // append to existing
// There is unsealed sector, see if we can read from it
selector = newExistingSelector(m.index, sector, stores.FTUnsealed, false)
@@ -231,12 +232,27 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect
return err
})
if err != nil {
return xerrors.Errorf("reading piece from sealed sector: %w", err)
returnErr = xerrors.Errorf("reading piece from sealed sector: %w", err)
}
} else {
selector = newAllocSelector(m.index, stores.FTUnsealed, stores.PathSealing)
}
return
}
if readOk {
return nil
}
func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.SectorID, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, ticket abi.SealRandomness, unsealed cid.Cid) error {
foundUnsealed, readOk, selector, err := m.tryReadUnsealedPiece(ctx, sink, sector, offset, size)
if err != nil {
return err
}
if readOk {
return nil
}
ctx, cancel := context.WithCancel(ctx)
defer cancel()
if err := m.index.StorageLock(ctx, sector, stores.FTSealed|stores.FTCache, stores.FTUnsealed); err != nil {
return xerrors.Errorf("acquiring unseal sector lock: %w", err)
}
unsealFetch := func(ctx context.Context, worker Worker) error {
@@ -244,7 +260,7 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector abi.Sect
return xerrors.Errorf("copy sealed/cache sector data: %w", err)
}
if len(best) > 0 {
if foundUnsealed {
if err := worker.Fetch(ctx, sector, stores.FTUnsealed, stores.PathSealing, stores.AcquireMove); err != nil {
return xerrors.Errorf("copy unsealed sector data: %w", err)
}
+23 -3
View File
@@ -66,8 +66,9 @@ const (
)
type sectorState struct {
pieces []cid.Cid
failed bool
pieces []cid.Cid
failed bool
corrupted bool
state int
@@ -251,6 +252,18 @@ func (mgr *SectorMgr) MarkFailed(sid abi.SectorID, failed bool) error {
return nil
}
func (mgr *SectorMgr) MarkCorrupted(sid abi.SectorID, corrupted bool) error {
mgr.lk.Lock()
defer mgr.lk.Unlock()
ss, ok := mgr.sectors[sid]
if !ok {
return fmt.Errorf("no such sector in storage")
}
ss.corrupted = corrupted
return nil
}
func opFinishWait(ctx context.Context) {
val, ok := ctx.Value("opfinish").(chan struct{})
if !ok {
@@ -275,6 +288,8 @@ func (mgr *SectorMgr) GenerateWindowPoSt(ctx context.Context, minerID abi.ActorI
si := make([]proof.SectorInfo, 0, len(sectorInfo))
var skipped []abi.SectorID
var err error
for _, info := range sectorInfo {
sid := abi.SectorID{
Miner: minerID,
@@ -283,13 +298,18 @@ func (mgr *SectorMgr) GenerateWindowPoSt(ctx context.Context, minerID abi.ActorI
_, found := mgr.sectors[sid]
if found && !mgr.sectors[sid].failed {
if found && !mgr.sectors[sid].failed && !mgr.sectors[sid].corrupted {
si = append(si, info)
} else {
skipped = append(skipped, sid)
err = xerrors.Errorf("skipped some sectors")
}
}
if err != nil {
return nil, skipped, err
}
return generateFakePoSt(si, abi.RegisteredSealProof.RegisteredWindowPoStProof, randomness), skipped, nil
}
+6
View File
@@ -189,6 +189,12 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta
state.Log = append(state.Log, l)
}
if m.notifee != nil {
defer func(before SectorInfo) {
m.notifee(before, *state)
}(*state) // take safe-ish copy of the before state (except for nested pointers)
}
p := fsmPlanners[state.State]
if p == nil {
return nil, 0, xerrors.Errorf("planner for state %s not found", state.State)
+14
View File
@@ -27,6 +27,7 @@ type test struct {
}
func TestHappyPath(t *testing.T) {
var notif []struct{ before, after SectorInfo }
ma, _ := address.NewIDAddress(55151)
m := test{
s: &Sealing{
@@ -34,6 +35,9 @@ func TestHappyPath(t *testing.T) {
stats: SectorStats{
bySector: map[abi.SectorID]statSectorState{},
},
notifee: func(before, after SectorInfo) {
notif = append(notif, struct{ before, after SectorInfo }{before, after})
},
},
t: t,
state: &SectorInfo{State: Packing},
@@ -68,6 +72,16 @@ func TestHappyPath(t *testing.T) {
m.planSingle(SectorFinalized{})
require.Equal(m.t, m.state.State, Proving)
expected := []SectorState{Packing, PreCommit1, PreCommit2, PreCommitting, PreCommitWait, WaitSeed, Committing, SubmitCommit, CommitWait, FinalizeSector, Proving}
for i, n := range notif {
if n.before.State != expected[i] {
t.Fatalf("expected before state: %s, got: %s", expected[i], n.before.State)
}
if n.after.State != expected[i+1] {
t.Fatalf("expected after state: %s, got: %s", expected[i+1], n.after.State)
}
}
}
func TestSeedRevert(t *testing.T) {
+11 -2
View File
@@ -28,6 +28,8 @@ import (
const SectorStorePrefix = "/sectors"
var ErrTooManySectorsSealing = xerrors.New("too many sectors sealing")
var log = logging.Logger("sectors")
type SectorLocation struct {
@@ -59,6 +61,8 @@ type SealingAPI interface {
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
}
type SectorStateNotifee func(before, after SectorInfo)
type Sealing struct {
api SealingAPI
feeCfg FeeConfig
@@ -77,6 +81,8 @@ type Sealing struct {
upgradeLk sync.Mutex
toUpgrade map[abi.SectorNumber]struct{}
notifee SectorStateNotifee
stats SectorStats
getConfig GetSealingConfigFunc
@@ -99,7 +105,7 @@ type UnsealedSectorInfo struct {
pieceSizes []abi.UnpaddedPieceSize
}
func New(api SealingAPI, fc FeeConfig, events Events, maddr address.Address, ds datastore.Batching, sealer sectorstorage.SectorManager, sc SectorIDCounter, verif ffiwrapper.Verifier, pcp PreCommitPolicy, gc GetSealingConfigFunc) *Sealing {
func New(api SealingAPI, fc FeeConfig, events Events, maddr address.Address, ds datastore.Batching, sealer sectorstorage.SectorManager, sc SectorIDCounter, verif ffiwrapper.Verifier, pcp PreCommitPolicy, gc GetSealingConfigFunc, notifee SectorStateNotifee) *Sealing {
s := &Sealing{
api: api,
feeCfg: fc,
@@ -116,6 +122,9 @@ func New(api SealingAPI, fc FeeConfig, events Events, maddr address.Address, ds
},
toUpgrade: map[abi.SectorNumber]struct{}{},
notifee: notifee,
getConfig: gc,
stats: SectorStats{
@@ -280,7 +289,7 @@ func (m *Sealing) newDealSector() (abi.SectorNumber, error) {
if cfg.MaxSealingSectorsForDeals > 0 {
if m.stats.curSealing() > cfg.MaxSealingSectorsForDeals {
return 0, xerrors.Errorf("too many sectors sealing")
return 0, ErrTooManySectorsSealing
}
}
+1 -1
View File
@@ -62,7 +62,7 @@ func (m *Sealing) handleSealPrecommit2Failed(ctx statemachine.Context, sector Se
return err
}
if sector.PreCommit2Fails > 1 {
if sector.PreCommit2Fails > 3 {
return ctx.Send(SectorRetrySealPreCommit1{})
}
+2
View File
@@ -67,6 +67,8 @@ func (m *Sealing) tryUpgradeSector(ctx context.Context, params *miner.SectorPreC
params.ReplaceSectorDeadline = loc.Deadline
params.ReplaceSectorPartition = loc.Partition
log.Infof("replacing sector %d with %d", *replace, params.SectorNumber)
ri, err := m.api.StateSectorGetInfo(ctx, m.maddr, *replace, nil)
if err != nil {
log.Errorf("error calling StateSectorGetInfo for replaced sector: %+v", err)
+12 -12
View File
@@ -2,8 +2,6 @@ module github.com/filecoin-project/lotus
go 1.14
replace github.com/supranational/blst => github.com/supranational/blst v0.1.2-alpha.1
require (
contrib.go.opencensus.io/exporter/jaeger v0.1.0
contrib.go.opencensus.io/exporter/prometheus v0.1.0
@@ -15,10 +13,10 @@ require (
github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129
github.com/coreos/go-systemd/v22 v22.0.0
github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e
github.com/dgraph-io/badger/v2 v2.0.3
github.com/dgraph-io/badger/v2 v2.2007.2
github.com/docker/go-units v0.4.0
github.com/drand/drand v1.0.3-0.20200714175734-29705eaf09d4
github.com/drand/kyber v1.1.1
github.com/drand/drand v1.1.2-0.20200905144319-79c957281b32
github.com/drand/kyber v1.1.2
github.com/dustin/go-humanize v1.0.0
github.com/elastic/go-sysinfo v1.3.0
github.com/fatih/color v1.8.0
@@ -27,18 +25,18 @@ require (
github.com/filecoin-project/go-bitfield v0.2.0
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
github.com/filecoin-project/go-data-transfer v0.6.3
github.com/filecoin-project/go-data-transfer v0.6.4
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f
github.com/filecoin-project/go-fil-markets v0.6.0
github.com/filecoin-project/go-fil-markets v0.6.1
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52
github.com/filecoin-project/go-multistore v0.0.3
github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261
github.com/filecoin-project/go-state-types v0.0.0-20200905071437-95828685f9df
github.com/filecoin-project/go-state-types v0.0.0-20200911004822-964d6c679cfc
github.com/filecoin-project/go-statemachine v0.0.0-20200813232949-df9b130df370
github.com/filecoin-project/go-statestore v0.1.0
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b
github.com/filecoin-project/specs-actors v0.9.7
github.com/filecoin-project/specs-actors v0.9.10
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796
github.com/filecoin-project/test-vectors/schema v0.0.1
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
@@ -92,7 +90,7 @@ require (
github.com/libp2p/go-libp2p-mplex v0.2.4
github.com/libp2p/go-libp2p-noise v0.1.1
github.com/libp2p/go-libp2p-peerstore v0.2.6
github.com/libp2p/go-libp2p-pubsub v0.3.6-0.20200907103802-a3445b756fdb
github.com/libp2p/go-libp2p-pubsub v0.3.6-0.20200910093904-f7f33e10cc18
github.com/libp2p/go-libp2p-quic-transport v0.8.0
github.com/libp2p/go-libp2p-record v0.1.3
github.com/libp2p/go-libp2p-routing-helpers v0.2.3
@@ -135,6 +133,8 @@ replace github.com/golangci/golangci-lint => github.com/golangci/golangci-lint v
replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi
replace github.com/dgraph-io/badger/v2 => github.com/dgraph-io/badger/v2 v2.0.1-rc1.0.20200716180832-3ab515320794
replace github.com/filecoin-project/test-vectors => ./extern/test-vectors
replace github.com/supranational/blst => ./extern/fil-blst/blst
replace github.com/filecoin-project/fil-blst => ./extern/fil-blst
+20 -18
View File
@@ -166,8 +166,10 @@ github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhY
github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
github.com/dgraph-io/badger v1.6.1 h1:w9pSFNSdq/JPM1N12Fz/F/bzo993Is1W+Q7HjPzi7yg=
github.com/dgraph-io/badger v1.6.1/go.mod h1:FRmFw3uxvcpa8zG3Rxs0th+hCLIuaQg8HlNV5bjgnuU=
github.com/dgraph-io/badger/v2 v2.0.1-rc1.0.20200716180832-3ab515320794 h1:PIPH4SLjYXMMlX/cQqV7nIRatv7556yqUfWY+KBjrtQ=
github.com/dgraph-io/badger/v2 v2.0.1-rc1.0.20200716180832-3ab515320794/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE=
github.com/dgraph-io/badger/v2 v2.0.3/go.mod h1:3KY8+bsP8wI0OEnQJAKpd4wIJW/Mm32yw2j/9FUVnIM=
github.com/dgraph-io/badger/v2 v2.2007.2 h1:EjjK0KqwaFMlPin1ajhP943VPENHJdEz1KLIegjaI3k=
github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE=
github.com/dgraph-io/ristretto v0.0.2-0.20200115201040-8f368f2f2ab3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de h1:t0UHb5vdojIDUqktM6+xJAfScFBsVpXZmqC9dsgJmeA=
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
@@ -179,12 +181,12 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/drand/bls12-381 v0.3.2 h1:RImU8Wckmx8XQx1tp1q04OV73J9Tj6mmpQLYDP7V1XE=
github.com/drand/bls12-381 v0.3.2/go.mod h1:dtcLgPtYT38L3NO6mPDYH0nbpc5tjPassDqiniuAt4Y=
github.com/drand/drand v1.0.3-0.20200714175734-29705eaf09d4 h1:+Rov3bfUriGWFR/lUVXnpimx+HMr9BXRC4by0BxuQ8k=
github.com/drand/drand v1.0.3-0.20200714175734-29705eaf09d4/go.mod h1:SnqWL9jksIMK63UKkfmWI6f9PDN8ROoCgg+Z4zWk7hg=
github.com/drand/drand v1.1.2-0.20200905144319-79c957281b32 h1:sU+51aQRaDxg0KnjQg19KuYRIxDBEUHffBAICSnBys8=
github.com/drand/drand v1.1.2-0.20200905144319-79c957281b32/go.mod h1:0sQEVg+ngs1jaDPVIiEgY0lbENWJPaUlWxGHEaSmKVM=
github.com/drand/kyber v1.0.1-0.20200110225416-8de27ed8c0e2/go.mod h1:UpXoA0Upd1N9l4TvRPHr1qAUBBERj6JQ/mnKI3BPEmw=
github.com/drand/kyber v1.0.2/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw=
github.com/drand/kyber v1.1.1 h1:mwCY2XGRB+Qc1MPfrnRuVuXELkPhcq/r9yMoJIcDhHI=
github.com/drand/kyber v1.1.1/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw=
github.com/drand/kyber v1.1.2 h1:faemqlaFyLrbBSjZGRzzu5SG/do+uTYpHlnrJIHbAhQ=
github.com/drand/kyber v1.1.2/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw=
github.com/drand/kyber-bls12381 v0.1.0 h1:/P4C65VnyEwxzR5ZYYVMNzY1If+aYBrdUU5ukwh7LQw=
github.com/drand/kyber-bls12381 v0.1.0/go.mod h1:N1emiHpm+jj7kMlxEbu3MUyOiooTgNySln564cgD9mk=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@@ -220,12 +222,14 @@ github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:a
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg=
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus=
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ=
github.com/filecoin-project/go-data-transfer v0.6.3 h1:7TLwm8nuodHYD/uiwJjKc/PGRR+LwqM8jmlZqgWuUfY=
github.com/filecoin-project/go-data-transfer v0.6.3/go.mod h1:PmBKVXkhh67/tnEdJXQwDHl5mT+7Tbcwe1NPninqhnM=
github.com/filecoin-project/go-data-transfer v0.6.4 h1:Q08ABa+cOTOLoAyHeA94fPLcwu53p6eeAaxMxQb0m0A=
github.com/filecoin-project/go-data-transfer v0.6.4/go.mod h1:PmBKVXkhh67/tnEdJXQwDHl5mT+7Tbcwe1NPninqhnM=
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s=
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ=
github.com/filecoin-project/go-fil-markets v0.6.0 h1:gfxMweUHo4u+2BZh2Q7/7+cV0/ttikuJfhkkxLRsE2Q=
github.com/filecoin-project/go-fil-markets v0.6.0/go.mod h1:LhSFYLkjaoe0vFRKABGYyw1Jz+9jCpF1sPA7yOftLTw=
github.com/filecoin-project/go-fil-markets v0.6.1 h1:qCFLcVkUCbxwEfH/6EcqTuQvibXt/TXZr+vh8tWv/BQ=
github.com/filecoin-project/go-fil-markets v0.6.1/go.mod h1:dBJl59dAyl8+cGVb/ONPlEQW4+YzhjI3d6bxLfHVpX0=
github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM=
github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24=
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52 h1:FXtCp0ybqdQL9knb3OGDpkNTaBbPxgkqPeWKotUwkH0=
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4=
github.com/filecoin-project/go-multistore v0.0.3 h1:vaRBY4YiA2UZFPK57RNuewypB8u0DzzQwqsL0XarpnI=
@@ -236,8 +240,9 @@ github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261 h
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261/go.mod h1:fZzmf4tftbwf9S37XRifoJlz7nCjRdIrMGLR07dKLCc=
github.com/filecoin-project/go-state-types v0.0.0-20200903145444-247639ffa6ad/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I=
github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I=
github.com/filecoin-project/go-state-types v0.0.0-20200905071437-95828685f9df h1:m2esXSuGBkuXlRyCsl1a/7/FkFam63o1OzIgzaHtOfI=
github.com/filecoin-project/go-state-types v0.0.0-20200905071437-95828685f9df/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I=
github.com/filecoin-project/go-state-types v0.0.0-20200911004822-964d6c679cfc h1:1vr/LoqGq5m5g37Q3sNSAjfwF1uJY0zmiHcvnxY6hik=
github.com/filecoin-project/go-state-types v0.0.0-20200911004822-964d6c679cfc/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g=
github.com/filecoin-project/go-statemachine v0.0.0-20200714194326-a77c3ae20989/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
github.com/filecoin-project/go-statemachine v0.0.0-20200813232949-df9b130df370 h1:Jbburj7Ih2iaJ/o5Q9A+EAeTabME6YII7FLi9SKUf5c=
github.com/filecoin-project/go-statemachine v0.0.0-20200813232949-df9b130df370/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
@@ -246,8 +251,9 @@ github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZO
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b h1:fkRZSPrYpk42PV3/lIXiL0LHetxde7vyYYvSsttQtfg=
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/go.mod h1:Q0GQOBtKf1oE10eSXSlhN45kDBdGvEcVOqMiffqX+N8=
github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07U6cPKol6fd3w9KjMPZ6Z4=
github.com/filecoin-project/specs-actors v0.9.7 h1:7PAZ8kdqwBdmgf/23FCkQZLCXcVu02XJrkpkhBikiA8=
github.com/filecoin-project/specs-actors v0.9.7/go.mod h1:wM2z+kwqYgXn5Z7scV1YHLyd1Q1cy0R8HfTIWQ0BFGU=
github.com/filecoin-project/specs-actors v0.9.10 h1:gU0TrRhgkCsBEOP42sGDE7RQuR0Cov9hJhBqq+RJmjU=
github.com/filecoin-project/specs-actors v0.9.10/go.mod h1:czlvLQGEX0fjLLfdNHD7xLymy6L3n7aQzRWzsYGf+ys=
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 h1:dJsTPWpG2pcTeojO2pyn0c6l+x/3MZYCBgo/9d11JEk=
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g=
github.com/filecoin-project/test-vectors/schema v0.0.1 h1:5fNF76nl4qolEvcIsjc0kUADlTMVHO73tW4kXXPnsus=
@@ -497,7 +503,6 @@ github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28
github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE=
github.com/ipfs/go-graphsync v0.1.2 h1:25Ll9kIXCE+DY0dicvfS3KMw+U5sd01b/FJbA7KAbhg=
github.com/ipfs/go-graphsync v0.1.2/go.mod h1:sLXVXm1OxtE2XYPw62MuXCdAuNwkAdsbnfrmos5odbA=
github.com/ipfs/go-hamt-ipld v0.1.1 h1:0IQdvwnAAUKmDE+PMJa5y1QiwOPHpI9+eAbQEEEYthk=
github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk=
github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08=
github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw=
@@ -843,8 +848,8 @@ github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1
github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk=
github.com/libp2p/go-libp2p-pubsub v0.1.1/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q=
github.com/libp2p/go-libp2p-pubsub v0.3.2-0.20200527132641-c0712c6e92cf/go.mod h1:TxPOBuo1FPdsTjFnv+FGZbNbWYsp74Culx+4ViQpato=
github.com/libp2p/go-libp2p-pubsub v0.3.6-0.20200907103802-a3445b756fdb h1:0jm9ZSDkteX9XRjZqZwG5X0wuR+e0zAJ6ZEnqo2vcb0=
github.com/libp2p/go-libp2p-pubsub v0.3.6-0.20200907103802-a3445b756fdb/go.mod h1:DTMSVmZZfXodB/pvdTGrY2eHPZ9W2ev7hzTH83OKHrI=
github.com/libp2p/go-libp2p-pubsub v0.3.6-0.20200910093904-f7f33e10cc18 h1:+ae7vHSv/PJ4xGXwLV6LKGj32zjyB8ttJHtyV4TXal0=
github.com/libp2p/go-libp2p-pubsub v0.3.6-0.20200910093904-f7f33e10cc18/go.mod h1:DTMSVmZZfXodB/pvdTGrY2eHPZ9W2ev7hzTH83OKHrI=
github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU=
github.com/libp2p/go-libp2p-quic-transport v0.5.0/go.mod h1:IEcuC5MLxvZ5KuHKjRu+dr3LjCT1Be3rcD/4d8JrX8M=
github.com/libp2p/go-libp2p-quic-transport v0.8.0 h1:mHA94K2+TD0e9XtjWx/P5jGGZn0GdQ4OFYwNllagv4E=
@@ -1316,8 +1321,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/supranational/blst v0.1.2-alpha.1 h1:v0UqVlvbRNZIaSeMPr+T01kvTUq1h0EZuZ6gnDR1Mlg=
github.com/supranational/blst v0.1.2-alpha.1/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
@@ -1747,7 +1750,6 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200617041141-9a465503579e/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+136
View File
@@ -0,0 +1,136 @@
package journal
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/node/repo"
)
const RFC3339nocolon = "2006-01-02T150405Z0700"
// fsJournal is a basic journal backed by files on a filesystem.
type fsJournal struct {
EventTypeRegistry
dir string
sizeLimit int64
fi *os.File
fSize int64
incoming chan *Event
closing chan struct{}
closed chan struct{}
}
// OpenFSJournal constructs a rolling filesystem journal, with a default
// per-file size limit of 1GiB.
func OpenFSJournal(lr repo.LockedRepo, disabled DisabledEvents) (Journal, error) {
dir := filepath.Join(lr.Path(), "journal")
if err := os.MkdirAll(dir, 0755); err != nil {
return nil, fmt.Errorf("failed to mk directory %s for file journal: %w", dir, err)
}
f := &fsJournal{
EventTypeRegistry: NewEventTypeRegistry(disabled),
dir: dir,
sizeLimit: 1 << 30,
incoming: make(chan *Event, 32),
closing: make(chan struct{}),
closed: make(chan struct{}),
}
if err := f.rollJournalFile(); err != nil {
return nil, err
}
go f.runLoop()
return f, nil
}
func (f *fsJournal) RecordEvent(evtType EventType, supplier func() interface{}) {
defer func() {
if r := recover(); r != nil {
log.Warnf("recovered from panic while recording journal event; type=%s, err=%v", evtType, r)
}
}()
if !evtType.Enabled() {
return
}
je := &Event{
EventType: evtType,
Timestamp: build.Clock.Now(),
Data: supplier(),
}
select {
case f.incoming <- je:
case <-f.closing:
log.Warnw("journal closed but tried to log event", "event", je)
}
}
func (f *fsJournal) Close() error {
close(f.closing)
<-f.closed
return nil
}
func (f *fsJournal) putEvent(evt *Event) error {
b, err := json.Marshal(evt)
if err != nil {
return err
}
n, err := f.fi.Write(append(b, '\n'))
if err != nil {
return err
}
f.fSize += int64(n)
if f.fSize >= f.sizeLimit {
_ = f.rollJournalFile()
}
return nil
}
func (f *fsJournal) rollJournalFile() error {
if f.fi != nil {
_ = f.fi.Close()
}
nfi, err := os.Create(filepath.Join(f.dir, fmt.Sprintf("lotus-journal-%s.ndjson", build.Clock.Now().Format(RFC3339nocolon))))
if err != nil {
return xerrors.Errorf("failed to open journal file: %w", err)
}
f.fi = nfi
f.fSize = 0
return nil
}
func (f *fsJournal) runLoop() {
defer close(f.closed)
for {
select {
case je := <-f.incoming:
if err := f.putEvent(je); err != nil {
log.Errorw("failed to write out journal event", "event", je, "err", err)
}
case <-f.closing:
_ = f.fi.Close()
return
}
}
}
+9
View File
@@ -0,0 +1,9 @@
package journal
var (
// J is a globally accessible Journal. It starts being NilJournal, and early
// during the Lotus initialization routine, it is reset to whichever Journal
// is configured (by default, the filesystem journal). Components can safely
// record in the journal by calling: journal.J.RecordEvent(...).
J Journal = NilJournal() // nolint
)
-152
View File
@@ -1,152 +0,0 @@
package journal
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"time"
logging "github.com/ipfs/go-log"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/build"
)
func InitializeSystemJournal(dir string) error {
if err := os.MkdirAll(dir, 0755); err != nil {
return err
}
j, err := OpenFSJournal(dir)
if err != nil {
return err
}
currentJournal = j
return nil
}
func Add(sys string, val interface{}) {
if currentJournal == nil {
log.Warn("no journal configured")
return
}
currentJournal.AddEntry(sys, val)
}
var log = logging.Logger("journal")
var currentJournal Journal
type Journal interface {
AddEntry(system string, obj interface{})
Close() error
}
// fsJournal is a basic journal backed by files on a filesystem
type fsJournal struct {
fi *os.File
fSize int64
journalDir string
incoming chan *JournalEntry
journalSizeLimit int64
closing chan struct{}
}
func OpenFSJournal(dir string) (Journal, error) {
fsj := &fsJournal{
journalDir: dir,
incoming: make(chan *JournalEntry, 32),
journalSizeLimit: 1 << 30,
closing: make(chan struct{}),
}
if err := fsj.rollJournalFile(); err != nil {
return nil, err
}
go fsj.runLoop()
return fsj, nil
}
type JournalEntry struct {
System string
Timestamp time.Time
Val interface{}
}
func (fsj *fsJournal) putEntry(je *JournalEntry) error {
b, err := json.Marshal(je)
if err != nil {
return err
}
n, err := fsj.fi.Write(append(b, '\n'))
if err != nil {
return err
}
fsj.fSize += int64(n)
if fsj.fSize >= fsj.journalSizeLimit {
return fsj.rollJournalFile()
}
return nil
}
const RFC3339nocolon = "2006-01-02T150405Z0700"
func (fsj *fsJournal) rollJournalFile() error {
if fsj.fi != nil {
err := fsj.fi.Close()
if err != nil {
return err
}
}
nfi, err := os.Create(filepath.Join(fsj.journalDir, fmt.Sprintf("lotus-journal-%s.ndjson", build.Clock.Now().Format(RFC3339nocolon))))
if err != nil {
return xerrors.Errorf("failed to open journal file: %w", err)
}
fsj.fi = nfi
fsj.fSize = 0
return nil
}
func (fsj *fsJournal) runLoop() {
for {
select {
case je := <-fsj.incoming:
if err := fsj.putEntry(je); err != nil {
log.Errorw("failed to write out journal entry", "entry", je, "err", err)
}
case <-fsj.closing:
if err := fsj.fi.Close(); err != nil {
log.Errorw("failed to close journal", "err", err)
}
return
}
}
}
func (fsj *fsJournal) AddEntry(system string, obj interface{}) {
je := &JournalEntry{
System: system,
Timestamp: build.Clock.Now(),
Val: obj,
}
select {
case fsj.incoming <- je:
case <-fsj.closing:
log.Warnw("journal closed but tried to log event", "entry", je)
}
}
func (fsj *fsJournal) Close() error {
close(fsj.closing)
return nil
}
+16
View File
@@ -0,0 +1,16 @@
package journal
type nilJournal struct{}
// nilj is a singleton nil journal.
var nilj Journal = &nilJournal{}
func NilJournal() Journal {
return nilj
}
func (n *nilJournal) RegisterEventType(_, _ string) EventType { return EventType{} }
func (n *nilJournal) RecordEvent(_ EventType, _ func() interface{}) {}
func (n *nilJournal) Close() error { return nil }

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