Compare commits

...
598 Commits
Author SHA1 Message Date
Aayush Rajasekaran a6b2180756 Merge pull request #4323 from filecoin-project/asr/changelog
Lotus version 0.10.0
2020-10-12 02:27:55 -04:00
Aayush Rajasekaran 160f209f6a Lotus version 0.10.0 2020-10-12 02:14:36 -04:00
Aayush Rajasekaran a9d8bc7c45 Merge pull request #4322 from filecoin-project/steb/tape-upgrade
implement tape upgrade
2020-10-12 02:14:13 -04:00
Steven Allen 92177b5738 implement tape upgrade
Upgrade to specs-actors v2.1 and network version 5. This fixes the bug where
prove commits were not accepted.
2020-10-12 02:00:27 -04:00
Łukasz Magiera 8fd9b5f235 Merge pull request #4315 from filecoin-project/feat/stats-ops
lotus-stats: optmize getting miner power
2020-10-12 06:01:52 +02:00
Jakub Sztandera a95e343dee Merge pull request #4321 from filecoin-project/feat/love
Chain is love
2020-10-12 05:44:34 +02:00
Steven Allen c296e1bbca use actor abstraction in metrics command 2020-10-11 20:31:20 -07:00
Jakub Sztandera ae366972a9 Chain is love
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-12 05:11:04 +02:00
Travis Person 23470bc38f lotus-stats: optmize getting miner power 2020-10-11 20:27:36 +00:00
Whyrusleeping 40b2e2d0c1 Merge pull request #4312 from filecoin-project/feat/msig-inspect-decode
decode parameters for multisig transactions in inspect
2020-10-11 11:51:32 -05:00
Łukasz Magiera 00620aac57 Merge pull request #4296 from filecoin-project/feat/sync-unmarkbad-all
sync unmark-bad --all
2020-10-10 22:35:56 +02:00
Łukasz Magiera 32d95fc97a docsgen, gofmt 2020-10-10 20:46:06 +02:00
Łukasz Magiera a491fc97b9 Merge pull request #4301 from filecoin-project/steb/fix-two-races
Fix two races
2020-10-10 20:37:13 +02:00
Łukasz Magiera 151577f04e Merge pull request #4287 from filecoin-project/feat/flush_validation_cache_on_chain_import
Dump the block validation cache whenever we perform an import
2020-10-10 20:33:17 +02:00
Steven Allen c463582528 fix a race and optimize hello messages
LifecycleCtx can _only_ be called during startup as it appends an fx hook.
Worse, this was causing us to append an fx hook on every single hello message,
leaking memory (and probably causing other shutdown issues...).
2020-10-10 08:33:06 -07:00
Steven Allen 7245ac2b69 fix a race in the sync manager
1. SyncerState contains a mutex and should never be copied. Honestly, this case
was probably fine but it's just as easy to create a separate snapshot type and
easier to reason about.

2. We need to initialize the syncStates array once at start, before accessing
it. By each syncer state inside each worker, we were racing with calls to
`State()`. Again, this was probably benign, but I don't trust optimizing
compilers.
2020-10-10 08:31:04 -07:00
Łukasz Magiera 58f13a7d5a Merge pull request #4299 from filecoin-project/fix/wallet-export-panic
Fix panic in wallet export when key is not found
2020-10-10 16:25:40 +02:00
Peter Rabbitson e7d3b2503e Merge tag 'v0.9.1' 2020-10-10 15:54:51 +02:00
Łukasz Magiera ee8b8b8174 Merge pull request #4298 from filecoin-project/fix/cli-stderr-errors
cli: Don't output errors to stdout
2020-10-10 15:52:43 +02:00
Łukasz Magiera 4fa6afad13 Fix panic in wallet export when key is not found 2020-10-10 15:44:22 +02:00
Łukasz Magiera a80e98dc05 cli: Don't output errors to stdout 2020-10-10 15:38:14 +02:00
Peter Rabbitson 23f5a99117 Add comment clarifying current codepath 2020-10-10 15:36:32 +02:00
Łukasz Magiera 651522cbaa Merge pull request #4274 from filecoin-project/feat/msig-remove-api
add an api for removing multisig signers
2020-10-10 12:56:07 +02:00
Łukasz Magiera 388c9afce0 docsgen 2020-10-10 12:28:59 +02:00
Łukasz Magiera 9a26896c69 Merge pull request #4282 from filecoin-project/steb/fix-tipset-cache-race
fix a race in tipset cache usage
2020-10-10 12:27:15 +02:00
Łukasz Magiera 2db8b7efa7 Merge pull request #4291 from filecoin-project/steb/node-test-races
make pledge test pass with the race detector
2020-10-10 11:54:25 +02:00
Łukasz Magiera 18e58467f8 sync unmark-bad --all 2020-10-10 10:26:42 +02:00
Łukasz Magiera 1401efb115 Merge pull request #4294 from filecoin-project/feat/v0.9.1
Bump the version to 0.9.1
2020-10-10 09:15:04 +02:00
Łukasz Magiera f417d39a08 Bump the version to 0.9.1 2020-10-10 09:13:52 +02:00
Łukasz Magiera 11e35cf911 Merge pull request #4293 from filecoin-project/steb/actors-fixes
upgrade specs-actors
2020-10-10 08:53:20 +02:00
Steven Allen 10d464a1eb upgrade to specs-actors v2.0.3 2020-10-09 21:52:01 -07:00
Steven Allen d84f5dabab remove upgrade invariant checks
These checks may be _too_ strict and could cause the upgrade to fail unnecessarily.
2020-10-09 21:51:58 -07:00
Steven Allen f3abd1ae82 make pledge test pass with the race detector 2020-10-09 20:32:09 -07:00
Peter Rabbitson 85abca4b16 Delint 2020-10-10 04:00:12 +02:00
Peter Rabbitson 6610a247cf Dump the block validation cache whenever we perform an import
This solves a problem with folks resurrecting long-out-of-sync nodes via
snapshot imports.

The interface switch to Batching is necessary: startup is too long otherwise
( 8 minutes just to clear everything on a relatively old node )
2020-10-10 03:41:04 +02:00
Łukasz Magiera a6d9b302fa Merge pull request #3583 from filecoin-project/feat/signing-backends
Remote wallet backends
2020-10-10 02:58:02 +02:00
Steven Allen f32b3bf99b fix a race in tipset cache usage
This tipset cache is shared between multiple services and is called from
multiple places.
2020-10-09 17:32:45 -07:00
Łukasz Magiera 114a1aaffd Merge pull request #4281 from filecoin-project/steb/seal-race
fix race in unseal
2020-10-10 02:23:02 +02:00
Łukasz Magiera 83ba7ec8cc Merge pull request #4280 from filecoin-project/fix/market-deal-race
fix a race when retrieving pieces
2020-10-10 02:15:47 +02:00
Steven Allen 83dfc460d4 fix race in unseal
1. Remove an invalid error check.
2. Make sure to shadow the outer error type from within the goroutine instead or
reading the outer type.

This may have been causing test issues (caught in TestMinerAllInfo with the race
detector).
2020-10-09 15:39:41 -07:00
Steven Allen 283fd054e8 fix a race when retrieving pieces
We'd read the deal ID without synchronizing. This could (and probably did given
the history of flaky deal tests) cause us to miss events.

This patch also makes sure to always unsubscribe from events, even on error.
2020-10-09 15:35:44 -07:00
Łukasz Magiera 09bff14d85 Merge pull request #4269 from filecoin-project/steb/simplify-sync
simplify message syncing logic
2020-10-10 00:00:26 +02:00
Łukasz Magiera 3cb1abba4f Merge pull request #4276 from filecoin-project/steb/fix-bad-error
return the correct err from iterFullTipset
2020-10-09 23:26:54 +02:00
Łukasz Magiera d4c92942e7 Merge pull request #4275 from filecoin-project/steb/unshare-journal
unshare the journal
2020-10-09 23:16:27 +02:00
Aayush Rajasekaran f773ab4b28 Correct docs 2020-10-09 17:14:21 -04:00
Steven Allen c0182f8301 return the correct err from iterFullTipset 2020-10-09 13:59:56 -07:00
Łukasz Magiera c06f394b81 Merge pull request #4273 from filecoin-project/fix/fundsmgr-incorrect-cached-value
Revert cached "available" amount if the AddFunds message send fails
2020-10-09 22:52:40 +02:00
Steven Allen 748d2e82a7 unshare the journal
Motivation:

* Run lotus with the race detector enabled (primary motivation).
* Allow multiple lotus nodes in a process (not a high priority).

Previously, the journal was shared between all lotus instances, but it was
initialized for every new node. This caused safety problems in tests (at a
minimum).

This patch explicitly passes the journal to all services that need it.
2020-10-09 13:23:07 -07:00
Steven Allen a5c78371fd Merge pull request #4270 from filecoin-project/steb/test-fix-paychstatus-race
fix a race in the payment channel status test
2020-10-09 13:22:16 -07:00
Ingar Shu d80e7eda93 Revert cached "available" amount if the AddFunds message send fails 2020-10-09 13:18:43 -07:00
Steven Allen 9f9d5cb2a5 fix a race in the payment channel status test
We should not be clobbering the cmd variable.
2020-10-09 11:50:16 -07:00
Łukasz Magiera fdaa9c14ad Merge remote-tracking branch 'origin/master' into feat/signing-backends 2020-10-09 20:36:51 +02:00
Łukasz Magiera 9d8932d395 Merge pull request #4268 from iand/fix/rewardv2-cumsumrealized
fix: spec actors 2 reward shim uses correct field for CumsumRealized
2020-10-09 20:32:14 +02:00
Steven Allen 105aa40007 simplify message syncing logic
1. Allow duplicate blocks from bitswap. This shouldn't happen, but there's no
reason to bail (just log loudly).
2. Simplify logic to very explicitly check to make sure we're fetching every
block.
2020-10-09 11:06:49 -07:00
Łukasz Magiera 110f033c83 Merge pull request #4095 from filecoin-project/feat/daemon-lite
lotus-lite: replace wallet / msig calls with thin client to gateway
2020-10-09 19:22:43 +02:00
Ian Davis f87d325b6f fix: spec actors 2 reward shim uses correct field for CumsumRealized 2020-10-09 17:48:20 +01:00
Łukasz Magiera ab8286fa38 Fix docsgen, lotus-soup build 2020-10-09 18:43:22 +02:00
whyrusleeping 4cca3f19a3 add an api for removing multisig signers 2020-10-09 09:40:25 -07:00
Łukasz Magiera feb4b3c8b4 Merge remote-tracking branch 'origin/master' into feat/signing-backends 2020-10-09 15:51:25 +02:00
Dirk McCormick 7f7c9e978f feat: hide lite mode flag 2020-10-09 11:56:25 +02:00
Dirk McCormick 200a95f824 refactor: unify test builder full node options 2020-10-09 11:56:25 +02:00
Dirk McCormick d69e4c7cf2 refactor: lite-mode - simplify organization of dep injection 2020-10-09 11:54:42 +02:00
Dirk McCormick b2834baa4b feat: add msig available balance and vested to lite mode 2020-10-09 11:51:20 +02:00
Dirk McCormick e9e27cbbb0 feat: put gateway in middle of end-to-end test for lite mode 2020-10-09 11:48:35 +02:00
Dirk McCormick ef73b964fb feat: add end-to-end test for lite mode 2020-10-09 11:48:35 +02:00
Dirk McCormick 7b1bec91ed feat: add tests for gateway ChainGetTipsetByHeight 2020-10-09 11:45:16 +02:00
Dirk McCormick b32d25c562 feat: add RPC for GasEstimateMessageGas 2020-10-09 11:45:16 +02:00
Dirk McCormick 767611247c feat: add RPC for StateWaitMsg 2020-10-09 11:45:16 +02:00
Dirk McCormick be09a8a00a feat: lite-mode - check that gateway API implements required chain, mpool, state methods 2020-10-09 11:43:03 +02:00
Dirk McCormick 2719adc1b1 feat: lite-mode - thin client for chan & state 2020-10-09 11:43:03 +02:00
Dirk McCormick f1b1d8cec6 fix: MpoolAPI DI 2020-10-09 11:43:03 +02:00
Dirk McCormick 8fa4c0a970 feat: gateway - MpoolPush 2020-10-09 11:43:03 +02:00
Dirk McCormick 00a14de094 feat: gateway - StateLookupID 2020-10-09 11:43:03 +02:00
Dirk McCormick eec13ff8dc refactor: daemon - simplify gateway cleanup 2020-10-09 11:43:03 +02:00
Dirk McCormick 1ffdd7d5b3 fix: gateway - remove tracing (JsonRPC automatically traces all calls) 2020-10-09 11:43:03 +02:00
Dirk McCormick e19cd9ed01 feat: lotus-lite - replace wallet StateManager with thin client to gateway 2020-10-09 11:43:03 +02:00
Łukasz Magiera bacac245c7 Merge pull request #4256 from filecoin-project/steb/call-stop
cleanup tests on finish
2020-10-09 10:20:33 +02:00
Łukasz Magiera e1792ffe4d Merge pull request #4260 from filecoin-project/asr/wallet-abstract
Fix deletion of addresses from wallet
2020-10-09 09:55:25 +02:00
Aayush Rajasekaran 9c35762966 Fix deletion of addresses from wallet 2020-10-09 03:26:51 -04:00
Łukasz Magiera 356137439f apistruct: Drop unused WalletSignMessage 2020-10-09 03:12:33 +02:00
Łukasz Magiera 6cc7559b04 Fix APIInfo import cycle in tests 2020-10-09 02:58:12 +02:00
Łukasz Magiera 3cd53ad9d9 Use APIInfo parser for RemoteBacked wallet config 2020-10-09 02:21:37 +02:00
Łukasz Magiera 6c54d2445d Appease the linter 2020-10-09 01:53:12 +02:00
Łukasz Magiera 6a10af626c Nicer message logging in lotus-wallet 2020-10-09 01:50:46 +02:00
Łukasz Magiera 597d065e05 Update go-jsonrpc with http(s) client support 2020-10-09 01:39:06 +02:00
Łukasz Magiera 791aa5c6c8 Add lotus-wallet to Makefile 2020-10-09 01:37:17 +02:00
Steven Allen 82b15d2637 cleanup tests on finish 2020-10-08 16:36:02 -07:00
Łukasz Magiera 7d2f06cfbd Fix WalletSign in tests 2020-10-09 01:34:48 +02:00
Łukasz Magiera 6e8efb9d2c gofmt 2020-10-09 01:27:49 +02:00
Łukasz Magiera f3dc730b05 wallet: Add metadata to WalletAPI.WalletSign 2020-10-09 01:27:38 +02:00
Łukasz Magiera 114776f2c5 wallet: Drop WalletSignMessage from WalletAPI 2020-10-09 01:04:59 +02:00
Łukasz Magiera 4835109470 wallet: Post-merge fixes 2020-10-09 00:51:04 +02:00
Łukasz Magiera 8783c7434e Merge remote-tracking branch 'origin/master' into feat/signing-backends 2020-10-09 00:50:41 +02:00
Łukasz Magiera 2d3b61675b Merge pull request #3444 from IPFSMain-Official/fix-GetBestMiningCandidate-bug
fix GetBestMiningCandidate bug
2020-10-08 23:55:19 +02:00
刘林欣 a23ab123d7 fix GetBestMiningCandidate bug
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-08 23:39:33 +02:00
Łukasz Magiera 26ed6af040 Merge pull request #4227 from filecoin-project/par-upper-bounds
Increase the message fee cap upper bounds in PCR.
2020-10-08 23:34:32 +02:00
Łukasz Magiera 82bd7bd2ec Merge pull request #4224 from filecoin-project/fix/repub-journal
Fix Messages field in MessagePoolEvtMessage journal entry
2020-10-08 23:33:57 +02:00
Łukasz Magiera cd0a43b7f4 Merge pull request #4253 from filecoin-project/fix/syncwait-applied-offset
sync wait: Handle processed message offset
2020-10-08 23:30:55 +02:00
Łukasz Magiera b14632b750 Merge pull request #4250 from filecoin-project/asr/vesting-params-api
Add some new endpoints for querying Msig info
2020-10-08 23:25:23 +02:00
Łukasz Magiera ebcf77e830 Merge pull request #4254 from filecoin-project/feat/update-markets-0.7.1
Update markets v0.7.1
2020-10-08 23:24:08 +02:00
Łukasz Magiera 344d30e960 Merge pull request #4252 from filecoin-project/devnet-jennijuju
Update address prefix in client cli.
2020-10-08 23:23:40 +02:00
Łukasz Magiera efb13a0d9b Merge pull request #4246 from filecoin-project/feat/optim-search-msg
Optimize SearchForMessage and GetReceipt
2020-10-08 23:22:49 +02:00
Łukasz Magiera 0223582d41 sync wait: Handle processed message offset 2020-10-08 23:14:12 +02:00
Jakub Sztandera 973f61bc10 Optimize chain and message sync
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-08 23:10:07 +02:00
Jakub Sztandera 60768f4863 Optimize SearchForMessage and GetReceipt
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-08 23:10:06 +02:00
hannahhoward c60d13ee56 feat(markets): update markets v0.7.1 2020-10-08 13:52:39 -07:00
jennijuju 0f8fc119f3 Update address prefix in client cli. 2020-10-08 16:45:24 -04:00
Łukasz Magiera e4d2e6e01d Merge pull request #4249 from filecoin-project/feat/ux-enhancements
Feat/ux enhancements
2020-10-08 22:30:20 +02:00
Łukasz Magiera d55f10bed6 Merge pull request #4251 from filecoin-project/upgrade/noise
upgrade go-libp2p-noise to v0.1.2.
2020-10-08 22:26:46 +02:00
Raúl Kripalani 21de538d09 upgrade go-libp2p-noise to v0.1.2.
Improves throughput in large and/or fast transfers
and reduces syscalls when data is queued in receive
buffer, by using bufio.Reader.
2020-10-08 21:19:09 +01:00
Aayush Rajasekaran fe5b32026a Add some new endpoints for querying Msig info 2020-10-08 15:51:21 -04:00
Łukasz Magiera 91c10c2df5 Merge pull request #4248 from filecoin-project/feat/update-libp2p
Update libp2p things
2020-10-08 21:08:38 +02:00
Ingar Shu c3420c0ceb Display price, verified-price with units in lotus-miner storage-deals get-ask 2020-10-08 12:08:01 -07:00
vyzo 7933cf094f allow all drand topics 2020-10-08 21:48:55 +03:00
vyzo 4cd73f1560 use subscription filter in pubsub 2020-10-08 21:40:36 +03:00
vyzo 8a175a7465 update go-libp2p-pubsub and go-libp2p-quic-transport 2020-10-08 21:32:10 +03:00
Ingar Shu f7f229ae54 Show verified status in client list-deals 2020-10-08 11:31:33 -07:00
Ingar Shu 1323e07a2c Don't show failed deals by default in client list-deals, add option to to show failed deals. 2020-10-08 11:31:33 -07:00
Ingar Shu 2ad671649c Use FIL units for miner set-ask 2020-10-08 11:31:32 -07:00
Łukasz Magiera d26ece10b8 Merge pull request #4241 from filecoin-project/fix/daemon-flag-clash
fix: clash between daemon --api flag and cli tests
2020-10-08 18:30:47 +02:00
Raúl Kripalani 4c8084dcb0 Merge pull request #4243 from filecoin-project/conformance/rm-faked-syscalls 2020-10-08 17:06:25 +01:00
Raúl Kripalani 98d702fb5a add signature imports. 2020-10-08 16:44:20 +01:00
Łukasz Magiera 17f61ac212 Merge pull request #4245 from filecoin-project/debug/chain-sync-lookback
add more info to chain sync lookback failure
2020-10-08 17:05:08 +02:00
Łukasz Magiera df67576b89 Merge pull request #4233 from filecoin-project/fix/balances-audit-no-suffix
Some improvements to the lotus-shed balance audit commands
2020-10-08 17:02:21 +02:00
whyrusleeping cdc2f86f5a add more info to chain sync lookback failure 2020-10-08 09:45:07 -05:00
Raúl Kripalani 67b3a55e30 update test-vectors submodule. 2020-10-08 15:44:11 +01:00
Raúl Kripalani 3201e0eb8f Merge branch 'master' into conformance/rm-faked-syscalls 2020-10-08 15:17:26 +01:00
Raúl Kripalani 8d2d74438b Merge pull request #4221 from filecoin-project/conformance/randomness 2020-10-08 15:16:32 +01:00
Raúl Kripalani 1f9446f91f upgrade to test vectors schema v0.0.4. 2020-10-08 15:00:35 +01:00
Raúl Kripalani 4937ca1a96 conformance: remove usage of fake syscalls. 2020-10-08 14:55:03 +01:00
Łukasz Magiera 264fe4edb9 Merge pull request #4230 from filecoin-project/feat/inspect-counts
Add message counts to inspect chain output
2020-10-08 15:12:28 +02:00
Dirk McCormick cb7d99fcc7 fix: clash between daemon --api flag and cli tests 2020-10-08 14:24:50 +02:00
Łukasz Magiera 7332a39f00 Merge remote-tracking branch 'origin/master' into fix/balances-audit-no-suffix 2020-10-08 13:58:40 +02:00
Aayush Rajasekaran 8f35a5c036 Merge pull request #4238 from filecoin-project/asr/changelog
Lotus version 0.9.0
2020-10-07 23:25:02 -04:00
Aayush Rajasekaran dea7042668 Lotus version 0.9.0 2020-10-07 23:09:08 -04:00
Aayush Rajasekaran bd8f3f05be Merge pull request #4237 from filecoin-project/next
Merge next into master
2020-10-07 23:08:48 -04:00
Aayush Rajasekaran 304d835739 Merge branch 'master' into next 2020-10-07 23:03:59 -04:00
Łukasz Magiera cb8678e4c2 Merge pull request #4235 from filecoin-project/asr/set-head-unmark-valid
Set head should unmark blocks as valid
2020-10-08 03:58:05 +02:00
Aayush Rajasekaran da34548a05 Set head should unmark blocks as valid 2020-10-07 21:52:29 -04:00
whyrusleeping cd9af278b4 more info in audit outputs 2020-10-07 17:01:01 -07:00
Łukasz Magiera b1fe92f8ff Merge pull request #4201 from filecoin-project/feat/faster-v2-upgrade
stmgr: Make v2 upgrade faster
2020-10-08 01:56:05 +02:00
Łukasz Magiera 8dd8892b81 Merge remote-tracking branch 'origin/next' into feat/faster-v2-upgrade 2020-10-08 01:54:29 +02:00
Łukasz Magiera 79dba816c7 Merge pull request #4232 from filecoin-project/steb/fix-v2-actor-error
return an illegal actor error when we see an unsupported actor version
2020-10-08 01:47:10 +02:00
Aayush Rajasekaran 14bb4c9a0b Merge pull request #4196 from filecoin-project/asr/update-epoch
Set actorsv2 upgrade epoch
2020-10-07 19:45:56 -04:00
Łukasz Magiera f9f54819d4 Env var to control v2 actor migration
Env var to control v2 actor migration
2020-10-07 19:41:36 -04:00
Aayush Rajasekaran d1555106a4 Set actorsv2 upgrade epoch 2020-10-07 19:41:36 -04:00
Steven Allen 413c357361 Merge pull request #4231 from filecoin-project/steb/call-at-upgrade
reject explicit "calls" at the upgrade height
2020-10-07 16:33:51 -07:00
Steven Allen d97eb10349 fix spelling nit 2020-10-07 16:32:54 -07:00
Steven Allen e8253d22c6 only forbid Call* at expensive forks 2020-10-07 16:14:11 -07:00
Steven Allen a4e954197c retry StateCall at different height if we're at an expensive fork height 2020-10-07 16:03:42 -07:00
whyrusleeping 8f4911ac0d dont print fil suffix in lotus shed audit balances 2020-10-07 16:00:52 -07:00
Steven Allen b0bea5f145 return an illegal actor error when we see an unsupported actor version
As far as the chain is concerned, this actor does not exist.
2020-10-07 15:46:56 -07:00
Travis Person 7c7e0d73d5 Merge pull request #4229 from filecoin-project/fix/lotus-pcr-zero-refund
lotus-pcr: zero refund
2020-10-07 15:33:28 -07:00
Steven Allen 1fea550ce5 test that we refuse explicit calls at the migration epochs 2020-10-07 15:33:14 -07:00
Steven Allen 9b7b6146eb construct the new vm with the state manager's vm constructor 2020-10-07 15:31:14 -07:00
Steven Allen dab1107f5b avoid estimating gas and explicitly calling blocks on fork tipsets
These tipsets can be slow.
2020-10-07 15:31:14 -07:00
Steven Allen fe912223bd pass an explicit upgrade height to migrations
The tipset height may not be the correct one, given null blocks.
2020-10-07 15:31:12 -07:00
whyrusleeping 12cd478e11 Add message counts to inspect chain output 2020-10-07 15:14:46 -07:00
Travis Person ae3691e0a2 lotus-pcr: zero refund 2020-10-07 21:53:56 +00:00
Jennifer e55b00f358 Increase the message fee cap upper bounds in PCR. 2020-10-07 17:07:19 -04:00
Steven Allen de3f4111f4 Merge pull request #4197 from filecoin-project/steb/state-tree-version
introduce separate state-tree versions
2020-10-07 12:29:14 -07:00
Steven Allen 767c346cf8 update test-vectors 2020-10-07 12:17:32 -07:00
Jakub Sztandera 6f4a762664 Fix Messages field in MessagePoolEvtMessage journal entry
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-07 21:13:04 +02:00
Raúl Kripalani c02daca9e9 work around #4223. 2020-10-07 20:12:35 +01:00
Steven Allen cca17f6078 fix state tree version in v2 upgrade 2020-10-07 12:04:32 -07:00
Steven Allen c17fa4bc35 update test-vectors for StateManager constructor change 2020-10-07 12:04:32 -07:00
Steven Allen e803cf151f introduce separate state-tree versions
Instead of versioning the state tree along with the actors, version it
separately. This structure may not upgrade every time we update actors.
2020-10-07 12:04:32 -07:00
Łukasz Magiera 1268cfbfcd Merge pull request #4218 from filecoin-project/fix/lotus-pcr-ignore-other-messages
lotus-pcr: ignore all other messages
2020-10-07 21:03:53 +02:00
Łukasz Magiera 5ef929f130 Merge pull request #4219 from filecoin-project/merge-master-to-next
Merge branch 'master' into merge-master-to-next
2020-10-07 21:02:57 +02:00
Raúl Kripalani 5bd6a3cdad conformance: record randomness in tvx; replay in driver. 2020-10-07 19:57:42 +01:00
Steven Allen df4b068d0e Merge branch 'master' into next 2020-10-07 11:55:00 -07:00
Travis Person 0d34881a0c lotus-pcr: ignore all other messages 2020-10-07 18:50:50 +00:00
Steven Allen 6eb49b717f Merge pull request #4214 from filecoin-project/gas-tracing-public
make vm.EnableGasTracing public.
2020-10-07 11:12:55 -07:00
Whyrusleeping 099b982ea8 Merge pull request #4178 from filecoin-project/frrist/miner-diff-deadlines
feat(miner): add miner deadline diffing logic.
2020-10-07 12:00:31 -05:00
Łukasz Magiera 10c120bd3c Merge pull request #4213 from filecoin-project/feat/test-addrs-envvar
build: Env var to keep test address output
2020-10-07 18:49:55 +02:00
Raúl Kripalani 7cd1330acd make vm.EnableGasTracing public. 2020-10-07 15:52:03 +01:00
Łukasz Magiera 39bc816a79 build: Env var to keep test address output 2020-10-07 15:01:30 +02:00
Łukasz Magiera 81fb552e1d Merge pull request #4211 from filecoin-project/conformance/minor-refactors
conformance: minor driver refactors.
2020-10-07 14:57:00 +02:00
Łukasz Magiera cfd126ee9f Merge pull request #3961 from filecoin-project/docs/miner-storage
lotus-miner: add more help text to storage / attach
2020-10-07 14:55:42 +02:00
Łukasz Magiera d6fa644974 Fix lint 2020-10-07 14:19:04 +02:00
Raúl Kripalani d3dc560f53 conformance: minor refactors. 2020-10-07 13:01:08 +01:00
Łukasz Magiera 25bc00eec8 Merge pull request #4200 from filecoin-project/feat/state-exec-trace
implement command to get execution traces of any message
2020-10-07 08:14:08 +02:00
whyrusleeping 3b12a9f425 Add flag to accept previous output of compute-state as input 2020-10-07 08:12:39 +02:00
Łukasz Magiera b7c8f65af5 stmgr: Make v2 upgrade faster 2020-10-07 08:12:05 +02:00
Łukasz Magiera c6e0cb4ff2 Merge pull request #4205 from filecoin-project/feat/noncefix-manual-fee-cap
allow manual setting of noncefix fee cap
2020-10-07 08:08:52 +02:00
Łukasz Magiera f6eb530cba Merge pull request #4203 from filecoin-project/fix/pond-actorsv2
Fix pond
2020-10-07 07:55:38 +02:00
Travis Person f4991e868e Merge pull request #4198 from filecoin-project/feat/lotus-pcr-cap-limit
Limit the fee cap of messages we will process, refund gas fees for windowed post and storage deals
2020-10-06 21:03:43 -07:00
Aayush Rajasekaran 0ec2a10ebc Merge branch 'master' into next 2020-10-06 21:09:20 -04:00
whyrusleeping be92dd9e63 allow manual setting of noncefix fee cap 2020-10-06 18:07:34 -07:00
Aayush Rajasekaran e90ca96289 Merge pull request #4199 from filecoin-project/asr/specs-update
Update to actors v2.0.1
2020-10-06 21:06:20 -04:00
Aayush Rajasekaran c23f1623a1 Fix test 2020-10-06 20:48:00 -04:00
Aayush Rajasekaran 839d1121ce Update to actors v2.0.1 2020-10-06 20:37:54 -04:00
Łukasz Magiera a98b0f18fc Merge pull request #4202 from filecoin-project/fix/nonce-gap-fixer
fix noncefix
2020-10-07 01:58:29 +02:00
Łukasz Magiera 15670942c3 Fix pond 2020-10-07 01:50:11 +02:00
whyrusleeping 74016ab1cc fix noncefix 2020-10-06 16:46:47 -07:00
whyrusleeping bd474617ed implement command to get execution traces of any message 2020-10-06 16:06:24 -07:00
Travis Person 087030fe37 lotus-pcr: refund windowed post and storage deal gas fees 2020-10-06 22:35:04 +00:00
Łukasz Magiera 2f70a91665 Merge remote-tracking branch 'origin/master' into next 2020-10-06 23:54:59 +02:00
Aayush Rajasekaran 60ad339033 Merge pull request #4194 from filecoin-project/steb/test-amt-update
update the AMT implementation
2020-10-06 17:44:08 -04:00
Steven Allen 00187d4aa8 update the AMT implementation
This change ensures the bitmap is reset on flush.
2020-10-06 17:43:45 -04:00
Aayush Rajasekaran dfaabb4596 Merge pull request #3697 from filecoin-project/fix/actor-panic-fatal
fix: error when actor panics directly
2020-10-06 17:41:31 -04:00
Aayush Rajasekaran 0edecbd043 Merge pull request #4190 from filecoin-project/asr/post-lookback-finality
Set WinningPoStSectorSetLookback to finality post-v2 actors
2020-10-06 17:41:08 -04:00
Aayush Rajasekaran 4d6a0f7b8c Set WinningPoStSectorSetLookback to finality post-v2 actors 2020-10-06 17:40:37 -04:00
Aayush Rajasekaran 5043247958 Merge pull request #4189 from filecoin-project/asr/cli-change-owner
Add a CLI command to set a miner's owner address
2020-10-06 17:39:31 -04:00
Aayush Rajasekaran 282c99bdbd Merge pull request #4160 from filecoin-project/asr/reserve-funds-cric-supply
Add funds that have left FilReserve to circ supply
2020-10-06 17:39:05 -04:00
Aayush Rajasekaran 9857e42206 Merge pull request #4188 from filecoin-project/asr/miner-eligible
Update miner eligibility checks for v2 actors
2020-10-06 17:38:46 -04:00
Aayush Rajasekaran 6919ff3881 Merge pull request #3589 from filecoin-project/asr/rt-fix
Bugfix: Runtime's Receiver() should only return ID addresses
2020-10-06 17:38:20 -04:00
Aayush Rajasekaran d9fad5fad0 Move rt.Message fixes behind fork logic 2020-10-06 17:37:50 -04:00
Aayush Rajasekaran 757aa1039f Panic if runtime's Message has non-ID caller or receiver 2020-10-06 17:37:50 -04:00
Aayush Rajasekaran b71b743420 Bugfix: Runtime's Receiver() should only return ID addresses 2020-10-06 17:37:50 -04:00
Aayush Rajasekaran 8739b938db Merge pull request #3936 from filecoin-project/asr/spec-v1
Introduce v2 actors
2020-10-06 17:34:28 -04:00
Travis Person 4a3081c77a lotus-pcr: limit refunds to properly priced messages 2020-10-06 20:13:48 +00:00
Steven Allen b1818a1055 fix base fee tests for different smoke heights 2020-10-06 13:12:16 -07:00
Steven Allen 256be285ba only enable gas tampering if the breeze upgrade is enabled 2020-10-06 13:00:06 -07:00
Steven Allen 4a6e9c920d set genesis name in test 2020-10-06 11:42:04 -07:00
frrist d4cbd4fb55 feat(miner): add miner deadline diffing
- logic gathering all removed, faulted, recovered, and recovering
sectors for a miner.
2020-10-06 11:39:38 -07:00
Łukasz Magiera 15330396bb Fix circ supply before v2 upgrade epoch 2020-10-06 16:53:49 +02:00
Łukasz Magiera 2bf42d5318 Merge pull request #4186 from filecoin-project/asr/default-address
Support addresses with mainnet prefixes
2020-10-06 13:59:13 +02:00
Łukasz Magiera a179cadf0e wallet: Don't output duplicate keys from WalletList 2020-10-06 13:35:31 +02:00
Jakub Sztandera 405aba4d8f Merge pull request #4179 from filecoin-project/fix/export-unclean-exit
chain export: Error with unfinished exports
2020-10-06 13:30:53 +02:00
Aayush Rajasekaran 7b556252db Use SysErrReserved1 in the event of an actors panic 2020-10-06 05:34:53 -04:00
Aayush Rajasekaran 7a80e356de Add a CLI command to set a miner's owner address 2020-10-06 05:11:52 -04:00
Aayush Rajasekaran c53cef1526 Update docs 2020-10-06 04:47:00 -04:00
Aayush Rajasekaran 4a9155ba85 Use new MinerEligibleToMine method post-v2 actors 2020-10-06 04:43:55 -04:00
Łukasz Magiera 1a170e18ad Merge pull request #4183 from filecoin-project/fix/relax-colocation-factor
relax pubsub IPColocationFactorThreshold to 5
2020-10-06 10:37:25 +02:00
Aayush Rajasekaran f8c886a611 Rename MiningBaseInfo.HasMinPower to EligibleForMining 2020-10-06 03:49:11 -04:00
Aayush Rajasekaran b5907c665b Fix test 2020-10-06 03:43:20 -04:00
Aayush Rajasekaran ba25806fbd Update docs 2020-10-06 03:30:40 -04:00
Aayush Rajasekaran d02fc08ca4 Support both testnet and mainnet addresses in the internal wallet 2020-10-06 03:27:46 -04:00
vyzo de390749fc set pubsub IPColocationFactor to 5 2020-10-06 09:11:44 +03:00
Aayush Rajasekaran 3672f2cc44 Set default address type to mainnet 2020-10-06 01:59:15 -04:00
Aayush Rajasekaran 14ad91c53f Add type assertion for v2 runtime 2020-10-06 01:27:45 -04:00
Aayush Rajasekaran f55b18eabe Add funds that have left FilReserve to circ supply 2020-10-05 23:54:57 -04:00
Łukasz Magiera c920257a33 chain export: Error with unfinished exports 2020-10-06 02:59:19 +02:00
Łukasz Magiera 0e2f697217 Merge pull request #4133 from filecoin-project/feat/backup
Miner backup/restore commands
2020-10-06 02:05:03 +02:00
Steven Allen 16243b97aa make state diffing work with partial state trees 2020-10-05 17:03:28 -07:00
Steven Allen 89b88c1e0d fix conformance tests 2020-10-05 17:03:28 -07:00
Łukasz Magiera 8cdf078999 backup: append checksum 2020-10-06 01:50:54 +02:00
Łukasz Magiera 70d88f226e Add usage to repo-type in shed datastore 2020-10-06 01:33:51 +02:00
Łukasz Magiera 937d7fcca9 Merge pull request #4170 from filecoin-project/feat/mstat-base
Add mpool stats for base fee
2020-10-06 01:28:14 +02:00
Łukasz Magiera c8822fc9b6 Merge pull request #4177 from filecoin-project/feat/chain-usage-cmd
allow usage inspection on a chain segment
2020-10-06 01:21:01 +02:00
Łukasz Magiera dd1661c0b1 Merge pull request #4173 from filecoin-project/feat/basic-filter-on-start-epoch
Reject deals that are > 90 days in the future in the BasicDealFilter
2020-10-06 00:57:08 +02:00
whyrusleeping e9417562e0 allow usage inspection on a chain segment 2020-10-05 15:53:43 -07:00
Łukasz Magiera 40f4266070 Merge pull request #4176 from filecoin-project/feat/chain-usage-cmd
add a command to view block space utilization
2020-10-06 00:52:55 +02:00
Aayush Rajasekaran 6d25f3d2ae Add some comments 2020-10-05 18:39:39 -04:00
Steven Allen 1e78cd21ec fix lotus soup build 2020-10-05 14:37:08 -07:00
Steven Allen 17846aad2f add some more policy toggles for testground 2020-10-05 14:28:47 -07:00
whyrusleeping bd0633ff90 add a command to view block space utilization 2020-10-05 14:06:03 -07:00
Steven Allen 9621dbb4f1 fix tests to use v2 types 2020-10-05 13:27:34 -07:00
Łukasz Magiera c55b9baf37 Merge pull request #4166 from filecoin-project/test/miner-allinfo
Test lotus-miner info all
2020-10-05 22:04:12 +02:00
Ingar Shu 1227bf2893 Change max time in future for StartEpoch to 7 days 2020-10-05 12:35:58 -07:00
Ingar Shu 550f3771ea Reject deals that are > 90 days in the future in the BasicDealFilter 2020-10-05 11:39:02 -07:00
Steven Allen f8b2022f82 fix linters 2020-10-05 11:14:05 -07:00
Steven Allen 5a08b881d6 Test upgrade before/during/after cc upgrade 2020-10-05 11:05:00 -07:00
Steven Allen 8bcc201fc0 fix v2 GetSectorExpiration 2020-10-05 10:54:22 -07:00
Steven Allen 420c44ed2c fix msig start height 2020-10-05 10:35:21 -07:00
Steven Allen b6500beaab Merge branch 'master' into asr/spec-v1 2020-10-05 10:29:09 -07:00
Steven Allen d0c52535a6 Merge pull request #4171 from filecoin-project/upd/bitfield
Update go-bitfield
2020-10-05 10:27:55 -07:00
Jakub Sztandera 4be8964062 Add stats for base fee
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-05 19:15:51 +02:00
Jakub Sztandera feb85a272c Update go-bitfield
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-05 19:14:21 +02:00
Łukasz Magiera fee84c4b44 Merge pull request #4165 from filecoin-project/fix/message-signer-nonce-generation
fix: make message signer nonce generation transactional
2020-10-05 18:56:35 +02:00
Steven AllenandŁukasz Magiera b9f8831aaf fix specs-actors import in payment channel abstraction
Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com>
2020-10-05 09:51:04 -07:00
Dirk McCormick 7c3f622fae refactor: message signer - always store *next* nonce in datastore 2020-10-05 14:54:22 +02:00
Dirk McCormick 140671599c fix: make message signer nonce generation transactional 2020-10-05 14:19:31 +02:00
Łukasz Magiera ed03202c1d Test lotus-miner info all 2020-10-05 14:15:14 +02:00
Łukasz Magiera 0162a485d8 Merge pull request #4142 from filecoin-project/steb/bs-sessions
use bitswap sessions when fetching messages, and cancel them
2020-10-05 11:33:21 +02:00
Łukasz Magiera 97087fe576 Merge pull request #4122 from filecoin-project/asr/client-wallet
Convert ID addresses to key addresses before checking wallet
2020-10-04 17:20:04 +02:00
Łukasz Magiera e3269770d8 Merge pull request #4153 from filecoin-project/asr/verbose-verification
Add verified status to api.DealInfo
2020-10-04 17:13:49 +02:00
Łukasz Magiera 0fee5dab8a Merge pull request #4077 from filecoin-project/4076-remove-ask-duration
Always use default 720h for setask duration and hide the duration param option
2020-10-04 13:59:41 +02:00
Łukasz Magiera 1fc23fb466 lotus-miner: Cleanup storage attach helptext a bit 2020-10-03 11:30:22 +02:00
Aayush Rajasekaran 306dfaa11f Update docs 2020-10-03 03:41:01 -04:00
Aayush Rajasekaran 8fe8da6f4c Add verified status to api.DealInfo 2020-10-03 03:39:59 -04:00
Aayush Rajasekaran 4631cee564 Merge pull request #4114 from filecoin-project/fix/fork-after-cron
Run fork function after cron for null block safety
2020-10-02 23:05:36 -04:00
Steven Allen 8292d60196 Merge branch 'master' into asr/spec-v1 2020-10-02 18:03:03 -07:00
Steven Allen f6ccab1c6c ignore context canceled error in window post test 2020-10-02 17:47:01 -07:00
Steven Allen 6aba3e3b94 fix deal error message logging 2020-10-02 17:45:15 -07:00
Steven Allen 863a6ed38c fix lints 2020-10-02 17:45:01 -07:00
Steven Allen f1e5e9fe72 better upgrade test times 2020-10-02 17:31:26 -07:00
Steven Allen a57288a4b9 run post before, while, and after upgrading 2020-10-02 17:27:44 -07:00
Steven Allen c5de617af6 decouple network version and upgrades
Not all upgrades require network version bumps.
2020-10-02 17:10:57 -07:00
Łukasz Magiera bd964b4c3e Merge pull request #4124 from filecoin-project/asr/verifreg
Some helpers for verifreg work
2020-10-03 00:20:45 +02:00
Łukasz Magiera 5e256be81e Merge pull request #4141 from filecoin-project/feat/cap-market-provider-msgs
Cap market provider messages
2020-10-03 00:15:08 +02:00
Łukasz Magiera 04db9ea72d Merge pull request #3743 from filecoin-project/3692-config-default-update
Increased ExpectedSealDuration and and WaitDealsDelay.
2020-10-03 00:14:48 +02:00
Łukasz Magiera 6f33706025 Merge remote-tracking branch 'origin/master' into feat/backup 2020-10-03 00:08:23 +02:00
Łukasz Magiera 44e352cd8e Merge pull request #3876 from filecoin-project/feat/pruning-command
add command to (slowly) prune lotus chain datastore
2020-10-03 00:04:08 +02:00
Łukasz Magiera 1319d7072e shed: Fix lint 2020-10-02 23:54:03 +02:00
whyrusleeping ef3987e2ab decode parameters for multisig transactions in inspect 2020-10-02 14:51:32 -07:00
Łukasz Magiera f147072284 Merge remote-tracking branch 'origin/master' into feat/pruning-command 2020-10-02 23:37:25 +02:00
Łukasz Magiera 43bd7cb055 Merge pull request #4145 from filecoin-project/feat/cli-interactive-verified-deal
Add verified flag to interactive deal creation
2020-10-02 23:32:01 +02:00
Łukasz Magiera a3a3df9b30 Merge pull request #3915 from filecoin-project/feat/mpool-gateway-api
MpoolPushUntrusted API for gateway
2020-10-02 23:30:25 +02:00
Łukasz Magiera d3effe52a5 Merge pull request #3821 from filecoin-project/fix/paych-voucher-verify
paych: fix voucher amount verification
2020-10-02 23:27:18 +02:00
Łukasz Magieraanddirkmc 0591bac768 Compare more accurately
Co-authored-by: dirkmc <dirkmdev@gmail.com>
2020-10-02 23:18:37 +02:00
Łukasz Magiera db91d22a8a docsgen 2020-10-02 23:14:47 +02:00
ZenGround0 fecc1ee0ef Review cleanup 2020-10-02 17:12:12 -04:00
Łukasz Magiera 3bebdb3882 Merge remote-tracking branch 'origin/master' into feat/mpool-gateway-api 2020-10-02 23:09:55 +02:00
Ingar Shu 73b9fe36e3 Use verified price for verified deals 2020-10-02 13:07:40 -07:00
Ingar Shu 2c1ef3708e Add verified flag to interactive deal creation 2020-10-02 12:41:27 -07:00
Steven Allen 53cc1f18d0 use bitswap sessions when fetching messages, and cancel them
1. Explicitly use a session when fetching messages for a block. Technically,
GetBlocks would use an internal session so we'd only end up with two, but one
per block is even better.
2. Actually cancel sessions after a timeout (threading through the context).

NOTE: We should seriously consider having a single session for all blocks, but
we can do that in a followup as it may have unintended consequences (e.g., leaks).
2020-10-02 10:49:35 -07:00
Łukasz Magiera e848c13ff1 client: bump default deal start buffer 2020-10-02 19:39:34 +02:00
Łukasz Magiera 8fe8a5df45 Cap market provider messages 2020-10-02 18:35:52 +02:00
Łukasz Magiera a572bef8b2 Merge remote-tracking branch 'origin/master' into 3692-config-default-update 2020-10-02 13:33:17 +02:00
Steven Allen ed86ac14a1 use upgrade epochs from upgrade schedule 2020-10-01 20:37:14 -07:00
Steven Allen 101d07f704 fix version off by one error 2020-10-01 15:33:32 -07:00
Steven Allen 8ad8a945fb make it possible to override options when testing 2020-10-01 15:26:00 -07:00
Steven Allen e865ba0c64 improve upgrade schedule configurable
Unfortunately, it looks like functional ops cannot be passed in via lotus's
di system.
2020-10-01 15:18:59 -07:00
Steven Allen 1cc0f74744 make the upgrade schedule fully configurable
This should help with testing.
2020-10-01 15:02:40 -07:00
Łukasz Magiera efc1b24f4e Merge pull request #3714 from filecoin-project/feat/lotus-pcr-miner-recovery
lotus-pcr: add recover-miners command
2020-10-01 21:27:42 +02:00
Łukasz Magiera 078044153f pcr: Appease the linter 2020-10-01 21:07:39 +02:00
Łukasz Magiera 9b4274638c pcr: fix build 2020-10-01 20:51:36 +02:00
Łukasz Magiera 1253a5600e Merge remote-tracking branch 'origin/master' into feat/lotus-pcr-miner-recovery 2020-10-01 20:41:30 +02:00
Łukasz Magiera bceb880ee2 Merge pull request #4134 from filecoin-project/feat/better-replace-ux
improve the UX for replacing messages
2020-10-01 18:05:25 +02:00
Łukasz Magiera 15885ad535 docsgen 2020-10-01 18:00:24 +02:00
Łukasz Magiera ec7282ff09 miner restore: Resolve worker key for wallet check 2020-10-01 17:55:48 +02:00
Łukasz Magiera 738efe3f9a miner restore: Add progerss bar for metadata import 2020-10-01 17:55:48 +02:00
Łukasz Magiera e444977891 Full node metadata backup 2020-10-01 17:55:48 +02:00
Łukasz Magiera 5c33982f72 miner restore: storage config flag 2020-10-01 17:55:48 +02:00
Łukasz Magiera 44747446a9 miner restore: config flag 2020-10-01 17:55:48 +02:00
Łukasz Magiera d7ec5e3618 lotus-miner init restore 2020-10-01 17:55:48 +02:00
Łukasz Magiera 9b5a0815fc backup: open datastores in readonly in offline mode 2020-10-01 17:55:47 +02:00
Łukasz Magiera deac7166b5 Support offline backups 2020-10-01 17:55:47 +02:00
Łukasz Magiera c8a3269c4b shed: utils to read datastore backups 2020-10-01 17:55:47 +02:00
Łukasz Magiera 2dc9a1ee4e lotus-miner backup command 2020-10-01 17:55:47 +02:00
Łukasz Magiera d20ebe93b9 shed: gofmt 2020-10-01 17:55:47 +02:00
Łukasz Magiera 6875527224 shed: Datastore utils 2020-10-01 17:55:46 +02:00
whyrusleeping 889dd3cb3f improve the UX for replacing messages 2020-10-01 08:51:01 -07:00
Dirk McCormick 594ec8855c fix: read lane state from chain as well as datastore 2020-10-01 12:08:11 +02:00
Dirk McCormick e2ecc35dff test: add test for voucher after add-funds 2020-10-01 11:35:41 +02:00
Dirk McCormick 9dc75a7bc4 fix: verify voucher amount check 2020-10-01 11:35:41 +02:00
Aayush Rajasekaran 3d91633699 Update to v2/actors master 2020-10-01 05:07:00 -04:00
Aayush Rajasekaran 93e4eae94c Some helpers for verifreg work 2020-10-01 04:49:38 -04:00
Aayush Rajasekaran 6f0453c581 Convert ID addresses to key addresses before checking wallet 2020-10-01 04:41:24 -04:00
Aayush Rajasekaran 60d442e36a Slash filter shouldn't be trigerred if the same block is submitted multiple times 2020-09-30 22:05:16 -04:00
Aayush Rajasekaran 1ebad94da9 Merge pull request #4117 from filecoin-project/asr/changelog
Lotus version 0.8.1
2020-09-30 21:40:08 -04:00
Aayush Rajasekaran 636810daa5 Lotus version 0.8.1 2020-09-30 21:30:52 -04:00
Steven Allen 196bf39574 use non-faulty sectors, instead of active, in post proof
In actors v2, active doesn't include "new" (unproven) sectors.
2020-09-30 17:35:14 -07:00
Łukasz Magiera 954d806367 Merge pull request #4116 from filecoin-project/feat/sched-par-pcc2
sched: Allow some single-thread tasks to run in parallel with PC2/C2
2020-10-01 01:35:05 +02:00
Aayush Rajasekaran 7699f195f1 Merge pull request #4108 from filecoin-project/feat/nice-sectorslist
Improve miner sectors list UX
2020-09-30 19:07:23 -04:00
Łukasz Magiera 6981f776f4 Lower PC2 memory requirements 2020-10-01 00:54:53 +02:00
Łukasz Magiera 1b7cdb9341 Fix storage manager tests 2020-10-01 00:54:34 +02:00
Steven Allen 47a83b422e handle state forks in gas estimation 2020-09-30 15:52:32 -07:00
Łukasz Magiera 5e08d56630 sched: Allow some single-thread tasks to run in parallel with PC2/C2 2020-10-01 00:28:44 +02:00
Steven Allen 9705b25bbd fix testground actor versions 2020-09-30 15:15:34 -07:00
Steven Allen 9d59635b42 fix error messages 2020-09-30 15:04:16 -07:00
Steven Allen 42d5d8d784 run upgrade logic on stmgr.Call 2020-09-30 14:56:16 -07:00
Steven Allen 486812e082 name test networks
Necessary to get upgrades to run.
2020-09-30 14:55:50 -07:00
Steven Allen 6825a485eb update message extraction tool for specs-actors update 2020-09-30 14:28:25 -07:00
ZenGround0 8091bb3117 Run fork function after cron 2020-09-30 17:19:58 -04:00
Steven Allen 8dcbd525da abstract over deal collateral 2020-09-30 13:30:24 -07:00
Steven Allen 35e606d397 remove direct specs-actors miner access from expiration calculation 2020-09-30 13:17:56 -07:00
Steven Allen 99fe63716b regen lotuspond info 2020-09-30 13:12:17 -07:00
Steven Allen 941c1947be Merge branch 'master' into asr/spec-v1 2020-09-30 13:03:58 -07:00
Łukasz Magiera feecee310d Merge pull request #4089 from filecoin-project/feat/update-markets-0.7.0
Markets 0.7.0 with updated data stores
2020-09-30 21:49:14 +02:00
Steven Allen b01a1d457a abstract multisig calls 2020-09-30 12:30:02 -07:00
Steven Allen 2e9915ac28 move common from message param into message builder constructor 2020-09-30 10:58:34 -07:00
hannahhoward be884e27be feat(markets): update markets 0.7.0 2020-09-30 10:26:50 -07:00
Steven Allen 5253c0d959 fix: import the correct v2 methods 2020-09-30 10:11:48 -07:00
Steven Allen 4c60d7b5ce abstract over paych messages 2020-09-30 10:04:10 -07:00
Steven Allen 23b729a056 remove proof parameter from payment channels
It never worked properly, and will be removed in actors v2.
2020-09-30 09:35:42 -07:00
Steven Allen 724306c110 update specs-actors 2020-09-30 09:23:04 -07:00
Steven Allen 4989b1cc90 Merge branch 'master' into asr/spec-v1 2020-09-30 09:19:12 -07:00
Łukasz Magiera 5bffea6f54 Merge pull request #4064 from filecoin-project/tvx
tvx: a test vector extraction and execution tool
2020-09-30 17:22:42 +02:00
Raúl Kripalani 1c4f8e83d7 tvx/extract-many: add batch id, change generated filename. 2020-09-30 16:11:44 +01:00
Raúl Kripalani ff8663faa0 update test-vectors submodule. 2020-09-30 14:58:22 +01:00
Raúl Kripalani f58881e966 minor fixes. 2020-09-30 14:57:24 +01:00
Łukasz Magiera d2f279c3de Print heman-readable transferred bytes in client list-transfers 2020-09-30 13:51:52 +02:00
Łukasz Magiera 4d4bab12eb Improve miner sectors list UX 2020-09-30 13:34:05 +02:00
Raúl Kripalani eb6191d0ff tvx: precursor selection modes; canonical message fetching; basefee. 2020-09-30 11:02:10 +01:00
Łukasz Magiera 54dfeb1fd9 Merge pull request #4043 from zgfzgf/test-post
add printf in TestWindowPost
2020-09-30 10:53:16 +02:00
Łukasz Magiera c2c64caefe Merge pull request #4020 from zgfzgf/post-trace
add trace wdpost
2020-09-30 10:46:05 +02:00
Łukasz Magiera 90be8d801b Merge branch 'master' into post-trace 2020-09-30 10:03:54 +02:00
Łukasz Magiera 430897c9ac Merge pull request #3445 from filecoin-project/asr/precommit-failed-fix
Fix some failed precommit handling
2020-09-30 09:35:41 +02:00
Aayush Rajasekaran c77ab47cb5 Merge pull request #4103 from filecoin-project/asr/config
Add an option to set config
2020-09-30 03:33:52 -04:00
Łukasz Magiera bc85e3ce50 Merge pull request #4107 from shaodan/worker-no-swap
Add --no-swap flag for worker
2020-09-30 09:25:57 +02:00
Łukasz Magiera 76b1ec1de0 Merge pull request #4065 from filecoin-project/asr/sync-validate
Add lotus shed util to validate a tipset
2020-09-30 09:24:47 +02:00
Aayush Rajasekaran 6abccc4d5e Add an option to set config 2020-09-30 03:19:04 -04:00
Łukasz Magiera 7a3a2f8db9 Merge pull request #3924 from filecoin-project/feat/dont-recompute-PoST-redux
Dont recompute post on revert <<redux>>
2020-09-30 09:18:46 +02:00
Łukasz Magiera 4e8ccb2158 Merge pull request #4092 from filecoin-project/fix/finalize-uns-panic
sectorstorage: Fix potential panic in FinalizeSector
2020-09-30 09:18:01 +02:00
Dan Shao 1affd498c1 Add --no-swap flag for worker 2020-09-30 14:23:35 +08:00
Aayush Rajasekaran e250429f56 Merge pull request #4106 from filecoin-project/asr/validate-address
Add an endpoint to validate whether a string is a well-formed address
2020-09-30 01:58:29 -04:00
Aayush Rajasekaran bc4cbdc895 Update docs 2020-09-30 01:45:03 -04:00
Aayush Rajasekaran a388bcfad6 Add an endpoint to validate whether a string is a well-formed address 2020-09-30 01:43:10 -04:00
Łukasz Magiera e39c5dc372 Merge pull request #4104 from filecoin-project/asr/wallet-fix
Fix wallet list
2020-09-30 07:41:10 +02:00
Aayush Rajasekaran c45c8f34a1 Parametrise whether sync validators should use cache 2020-09-30 01:39:06 -04:00
Aayush Rajasekaran 73d193bd9c Update docs 2020-09-30 01:29:04 -04:00
Aayush Rajasekaran a4e7117429 Add lotus shed util to validate a tipset 2020-09-30 01:29:04 -04:00
Aayush Rajasekaran 9fe32b7777 Fix wallet list 2020-09-30 01:25:47 -04:00
Łukasz Magiera 6025bceaa1 Merge pull request #3431 from filecoin-project/feat/docs-reorg
Docs review and re-organization
2020-09-29 22:29:58 +02:00
Łukasz Magiera 91d04ede0f Merge pull request #4051 from filecoin-project/chore/final-dealstat-version
Chore/final dealstat version
2020-09-29 19:39:16 +02:00
Łukasz Magiera 237c8c4deb Merge pull request #3868 from austinabell/async/stransition
Make state transition in validation async
2020-09-29 16:50:52 +02:00
Łukasz Magiera 0ba911279a Merge pull request #3888 from filecoin-project/feat/bench-cache
Implement caching syscalls for import-bench
2020-09-29 16:38:05 +02:00
Łukasz Magiera baef3c8dd2 sectorstorage: Fix potential panic in FinalizeSector 2020-09-29 15:22:46 +02:00
Łukasz Magiera 867ca2f25d Merge pull request #3434 from filecoin-project/feat/shed-import-object-cmd
add a command to import an ipld object into the chainstore
2020-09-29 15:02:31 +02:00
Jakub Sztandera 247a5e2c49 Go mod tidy
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:50:08 +02:00
Jakub Sztandera 7e8c6e5070 Remove statediff, fix lint, go mod tidy
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:47 +02:00
Jakub Sztandera 0d914ac1d4 Switch to badger
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:47 +02:00
Jakub Sztandera 76db65b1af Update pebble
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:47 +02:00
Jakub Sztandera ff8c0af8c8 Add only-import option
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:47 +02:00
Jakub Sztandera 55c6b88537 Add toggle for badger, flag out gas tracing
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:46 +02:00
Jakub Sztandera 0771c23fb0 Use pebble
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:46 +02:00
Jakub Sztandera 1c6214b76d Usage go-bitfield with buffer pool
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:45 +02:00
Jakub Sztandera b7f18b4601 Disable callers
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:18 +02:00
Jakub Sztandera 242a77b391 go mod tidy
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:18 +02:00
Jakub Sztandera 35cf69ae64 Disable bloomcache
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:18 +02:00
Jakub Sztandera ebc8489ff1 Add global-profile option
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:18 +02:00
Jakub Sztandera f21c5cbbe2 Add start-at
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:18 +02:00
Jakub Sztandera 01386a206c Update options
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:18 +02:00
Jakub Sztandera 3858309368 Add http to import bench
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:17 +02:00
Jakub Sztandera 782717948a Add logs
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:17 +02:00
Jakub Sztandera 108fe7823c Add command to trigger gc
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:17 +02:00
Jakub Sztandera 12a0dd3d0a <3 to linter
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:17 +02:00
Jakub Sztandera 1f4d1dcc58 Do not sync
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:17 +02:00
Jakub Sztandera 53ab17cf50 Add no import to import-bench
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:17 +02:00
Jakub Sztandera 79ba4598d6 Implement cache
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:17 +02:00
Jakub Sztandera 96193c2044 Implement bench-cache
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-29 14:49:11 +02:00
Hector Sanjuan 09e5cc90a4 Add README to documentation/en with explanations 2020-09-29 14:45:55 +02:00
Łukasz Magiera edf1875e88 Merge pull request #4003 from filecoin-project/option-to-hide-sectors
Added an option to show or not show sector info for `lotus-miner info`
2020-09-29 14:26:23 +02:00
Łukasz Magiera 1479142047 Merge pull request #3970 from filecoin-project/feat/mpool-to-wallet
refactor: move nonce generation out of mpool
2020-09-29 13:24:35 +02:00
Dirk McCormick d1c10a61dd fix: message signer - always compare with mpool nonce 2020-09-29 12:20:09 +02:00
Łukasz Magiera 8205149675 Merge pull request #4088 from filecoin-project/feat/walletlist-ux
wallet list cli: Print balances/nonces
2020-09-29 11:33:29 +02:00
Łukasz Magiera eaece306b6 wallet list cli: Print balances/nonces 2020-09-29 11:21:08 +02:00
Aayush Rajasekaran be9d23b329 Centralize some params in builtin 2020-09-29 02:25:43 -04:00
Steven Allen dd65e57d4b set policy correctly from test vectors 2020-09-28 17:53:11 -07:00
Steven Allen e658ab3287 fix policy test 2020-09-28 17:44:34 -07:00
Steven Allen c0e190344d check state invariants after upgrade 2020-09-28 17:42:29 -07:00
Steven Allen 1c03862854 fix policy for specs-actors update 2020-09-28 17:28:16 -07:00
Steven Allen 2315db161b cleanup state-tree loading
And remove incorrect comment.
2020-09-28 16:46:29 -07:00
Steven Allen 9344bc4e9b update api docs for new network version 2020-09-28 16:27:47 -07:00
Steven Allen 01272f850d fix state test 2020-09-28 16:23:46 -07:00
Steven Allen b95b871943 actually upgrade to actors v2 2020-09-28 16:14:51 -07:00
Steven Allen a314cfd237 process error when setting network name 2020-09-28 15:59:11 -07:00
Steven Allen c0b316fd9c finish wiring up actors v2 2020-09-28 15:58:07 -07:00
Steven Allen 3e6323a503 make setNetworkName work with any actors version 2020-09-28 15:54:48 -07:00
Steven Allen d1000e38d7 wire up network upgrade logic for v2 actors upgrade 2020-09-28 15:50:54 -07:00
Raúl Kripalani 044674487e fix double mutex. 2020-09-28 23:14:37 +01:00
Raúl Kripalani 0070d2716c Merge pull request #4078 from filecoin-project/tvx-circsupply 2020-09-28 23:12:43 +01:00
Raúl Kripalani 9b403e26e5 fix lint. 2020-09-28 23:07:45 +01:00
Raúl Kripalani 4b3b35c9de conformance: record and feed circulating supply. 2020-09-28 23:04:52 +01:00
Steven Allen c88d124954 use built-in actor ID
The init actor will not allow the account actor to exec an arbitrary actor.
2020-09-28 14:43:55 -07:00
Steven Allen 233d8a9b72 update even more imports 2020-09-28 14:25:58 -07:00
Steven Allen 52e064dabb add gas numbers for v2 2020-09-28 14:09:46 -07:00
Steven Allen 1a7fb06dd9 improve lotuspond
There's still some work to do here, but it should now work better with the
network upgrade.
2020-09-28 14:09:04 -07:00
Steven Allen 6fcf57ed1f use actor state abstraction in payment channel test 2020-09-28 13:34:14 -07:00
Steven Allen ca9448bc11 rename actors v1 -> actors v2
The actual actors version is v2, not v1. Using Version1 internally was really confusing.
2020-09-28 13:13:18 -07:00
Steven Allen 2049daa008 fix actor imports 2020-09-28 13:12:41 -07:00
Steven Allen 947d1e2902 Merge branch 'master' into asr/spec-v1 2020-09-28 12:53:40 -07:00
Steven Allen 5f3160cf5b continue expanding vm abstraction layer 2020-09-28 12:48:08 -07:00
jennijuju 64f24fd276 Added an option to hide sector info for lotus-miner info 2020-09-28 15:42:50 -04:00
jennijuju 124bd0c765 Always use default 720h for setask duration and hide the duration param option. 2020-09-28 14:58:46 -04:00
Łukasz Magiera 4b61f1756e Merge pull request #4070 from filecoin-project/feat/import-ux
snapshot import progress bar, http support
2020-09-28 20:25:53 +02:00
Jakub Sztandera 2633198e6c Merge pull request #4056 from zgfzgf/tipset-equals
optimize Tipset equals
2020-09-28 20:15:54 +02:00
Łukasz Magiera b84cc46c3d Merge pull request #4074 from filecoin-project/refactor/chain-store-ts-parallel
fetch tipset blocks in parallel
2020-09-28 18:43:43 +02:00
Raúl Kripalani 96f882860f add extract-many command. 2020-09-28 17:02:56 +01:00
Dirk McCormick cfe6f595b0 fix: unsafe append in LoadTipSet 2020-09-28 16:54:18 +02:00
Dirk McCormick 6b16d48bad refactor: fetch tipset blocks in parallel 2020-09-28 15:56:44 +02:00
Raúl Kripalani 9f6862a456 fix lint. 2020-09-28 13:22:56 +01:00
Raúl Kripalani 4c9717187f tvx/extract: small refactor. 2020-09-28 13:19:45 +01:00
Raúl Kripalani a0dffb44d3 tvx/extract: perform sanity check on receipt. 2020-09-28 13:11:34 +01:00
Raúl Kripalani 8f3be78667 tvx/extract: allow passing in block to speed things up. 2020-09-28 13:00:07 +01:00
Raúl Kripalani dfdcbd184d add --repo flag. 2020-09-28 12:35:01 +01:00
Raúl Kripalani f05a40feed use lotus CLI package; document API endpoint setting in usage. 2020-09-28 12:27:42 +01:00
Łukasz Magiera f809529699 daemon cmd: Support imports straight from http 2020-09-28 12:30:12 +02:00
Łukasz Magiera a3145bae07 daemon cmd: Add progress bar to chain import 2020-09-28 12:17:54 +02:00
Łukasz Magiera b14afba859 Merge pull request #4058 from zgfzgf/miner-debug
miner debug where injectNulls != 0
2020-09-28 11:52:42 +02:00
Łukasz Magiera c33b3dfa55 Merge pull request #4022 from filecoin-project/feat/dont-recompute-PoST-abstract
Use abstract types for Dont recompute post on revert
2020-09-28 11:44:38 +02:00
Łukasz Magiera c448d85cf5 Merge pull request #4050 from filecoin-project/fix/stats-network-power
Add back network power to stats
2020-09-28 11:33:03 +02:00
Łukasz Magiera bc495a5c8c Merge pull request #4049 from filecoin-project/fix/miner-power-cli
fix GetPower with no miner address
2020-09-28 11:30:54 +02:00
Łukasz Magiera 18dac6d415 Merge pull request #4067 from IPFSMain-Official/master
add ipfsmain bootstrapper
2020-09-28 09:35:23 +02:00
Łukasz Magiera 5a72662d26 Merge branch 'master' into master 2020-09-28 09:22:21 +02:00
Łukasz Magiera b479988044 Merge pull request #4061 from filecoin-project/dev
Post-upgrade staging branch
2020-09-28 09:20:47 +02:00
刘林欣 a2d24b5b33 add ipfsmain bootstrapper 2020-09-28 13:53:29 +08:00
Raúl Kripalani 9a355c4bc5 fix lint errors. 2020-09-27 21:11:32 +01:00
Raúl Kripalani fe869c9c22 address review comments; lint. 2020-09-27 21:06:07 +01:00
Raúl Kripalani f5f23f7291 driver: option for VM flushing. 2020-09-27 20:55:09 +01:00
Raúl Kripalani a712c109d8 tvx/extract: print confirmation. 2020-09-27 20:30:32 +01:00
Raúl Kripalani e5c56da321 move conformance tvx tool to lotus. 2020-09-27 20:10:05 +01:00
Peter Rabbitson be5dc2c57f Walk back 10 epochs for stat generation 2020-09-27 20:45:45 +02:00
Peter Rabbitson e4c1f090af Disable exclusion of miner-associated addresses 2020-09-27 20:44:50 +02:00
zgfzgf 7a14455ac8 miner debug where injectNulls != 0 2020-09-27 15:01:42 +08:00
zgfzgf 04876c663e modify tipset Equals 2020-09-27 10:17:06 +08:00
zgfzgf 70071e273d optimize tipset Equals func 2020-09-27 09:58:37 +08:00
Peter Rabbitson fb3bcc4ce5 Add startup warning 2020-09-26 21:49:05 +02:00
Peter Rabbitson 1483f1e59a Add filtering of addresses associated with miners 2020-09-26 21:45:34 +02:00
Peter Rabbitson 10cdbadd82 Arrange json as the frontend expects it 2020-09-26 21:44:40 +02:00
Peter Rabbitson 8955b8d8a7 Centralize filtering, output wallet addresses 2020-09-26 21:44:36 +02:00
Travis Person 1c5cb50da3 Add back network power to stats 2020-09-26 17:09:16 +00:00
whyrusleeping bddd6dd8a8 fix GetPower with no miner address 2020-09-26 11:06:16 -05:00
zgfzgf 650725d71e add printf 2020-09-26 17:30:58 +08:00
Łukasz Magiera c243378cab Merge pull request #4032 from filecoin-project/fix/bench-2k
Move policy change to seal bench
2020-09-26 10:27:03 +02:00
Łukasz Magiera e15065b142 Merge pull request #4038 from filecoin-project/feat/state-compute-json
add json output to state compute
2020-09-26 10:20:30 +02:00
Łukasz Magiera 71fa198eee Merge pull request #4004 from ArseniiPetrovich/patch-1
Add glif node to bootstrap peers
2020-09-26 10:19:02 +02:00
Łukasz Magiera ca1715616f Merge branch 'dev' into patch-1 2020-09-26 10:18:47 +02:00
Łukasz Magiera b12bade989 Merge pull request #4007 from maobisheng/master
Add new booststrappers
2020-09-26 10:18:04 +02:00
Łukasz Magiera 28566b4d64 Merge branch 'dev' into master 2020-09-26 10:17:45 +02:00
Łukasz Magiera dfd1473384 Merge pull request #4041 from ipfs-force-community/master
Add one more node located in China
2020-09-26 10:16:01 +02:00
Łukasz Magiera 3fe0aa5026 Merge pull request #4030 from filecoin-project/feat/export-logging
add logging to chain export
2020-09-26 10:14:32 +02:00
Łukasz Magiera 6a502090f4 Merge pull request #4028 from filecoin-project/asr/address-update
Add an envvar to set address network version
2020-09-26 10:14:10 +02:00
Łukasz Magiera 3d40fb294e Merge pull request #3998 from filecoin-project/deps/update-ffi-blst-fix
update ffi to code with blst fixes
2020-09-26 10:12:34 +02:00
Steven Li 81a30cbf06 Add one more node located in China 2020-09-26 16:01:10 +08:00
Łukasz Magiera 2c1d96bcaa Merge pull request #4040 from filecoin-project/asr/changelog
Lotus version 0.8.0
2020-09-26 09:16:49 +02:00
Aayush Rajasekaran 45eadc1b3a Lotus version 0.8.0 2020-09-26 03:13:20 -04:00
Łukasz Magiera b453b8da99 Merge pull request #4039 from filecoin-project/feat/v0.8-actors
Ignition upgrades, for release v0.8.0
2020-09-26 09:13:07 +02:00
whyrusleeping 567261e2c7 set upgrade heights for testground builds 2020-09-26 00:03:03 -07:00
Aayush Rajasekaran 12e97dbea7 Fix docs and linter 2020-09-26 02:59:24 -04:00
Łukasz Magiera ef28ebb14a Ignition upgrades, much excite. 2020-09-25 23:55:37 -07:00
whyrusleeping 8545c08f30 add json output to state compute 2020-09-25 23:47:59 -07:00
Jakub Sztandera eaf3424938 Merge pull request #4033 from filecoin-project/asr/add-supported-proof
Fix AddSupportedProofTypes
2020-09-26 00:13:53 +02:00
Steven Allen a5f13a5b31 Test supported proof types. 2020-09-25 14:36:36 -07:00
Aayush Rajasekaran d8431ff611 Fix AddSupportedProofTypes 2020-09-25 17:33:25 -04:00
Jakub Sztandera 4eec4a0141 Move policy change to seal bench
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-09-25 23:28:12 +02:00
Steven Allen 6db6a90b1e Merge pull request #4026 from filecoin-project/steb/fix-status-inactive
return an error when we fail to find a sector when checking sector expiration
2020-09-25 13:28:27 -07:00
Travis Person a13d10e42d add logging to chain export 2020-09-25 20:20:18 +00:00
Steven Allen 271ceb968a add v1 support to the state tree 2020-09-25 12:55:10 -07:00
Steven Allen b8d9d7894f fix vm version 2020-09-25 12:52:16 -07:00
Steven Allen 7d3bd146e6 rebase fixup 2020-09-25 12:51:02 -07:00
Steven Allen 8b35f480c4 initial vm conversion
We're probably going to want to change some of these design decisions down the
road, but this is a good starting point.

* We may want to use a more general test for "is actor valid at epoch". Maybe
just a function?
* I'd like to push some of the actor metadata down into the actor types
themselves. Ideally, we'd be able to register actors with a simple
`Register(validation, manyActors...)` call.
2020-09-25 12:49:39 -07:00
Steven Allen d9656f5220 add a generic load method for actor state
This will make it easier to load arbitrary actors. We can:

* Type switch (sort of unsafe, may want marker methods?)
* Use this with `vm.MutateActorState`.
2020-09-25 12:49:39 -07:00
Steven Allen 87351fa35c move version to actors, from builtin
Otherwise, we're going to end up with an import cycle between the adt and this
version.
2020-09-25 12:49:39 -07:00
Steven Allen edb31e606a correctly load new actors 2020-09-25 12:49:39 -07:00
Steven Allen 8806f27220 fix runtime reflection for upgrade 2020-09-25 12:49:39 -07:00
Steven Allen 858f11992f compile fix 2020-09-25 12:49:39 -07:00
Steven Allen 35562bd2f9 fixup v1 actors for new methods
Also, correctly handle multiple ADT versions.
2020-09-25 12:49:39 -07:00
Aayush Rajasekaran ebad0ded3d Introduce v1 actors 2020-09-25 12:49:39 -07:00
Aayush Rajasekaran 60e43ccbb1 Add an envvar to set address network version 2020-09-25 15:45:27 -04:00
Steven Allen ddcbcdea48 test sector status on expiring sectors 2020-09-25 12:16:35 -07:00
Łukasz Magiera 3491e7b707 Merge pull request #4013 from filecoin-project/feat/update-markets-0.6.3
Update markets to 0.6.3
2020-09-25 20:42:04 +02:00
Steven Allen bdc782617f return an error when we fail to find a sector when checking sector expiration
Returning nil, nil is a footgun.

fix: https://github.com/filecoin-project/lotus/issues/3984
2020-09-25 11:28:38 -07:00
Dirk McCormick 80a7ed8116 refactor: use abstract types instead of specs-actors 2020-09-25 15:54:27 +02:00
zgfzgf 13b38815c2 add trace wdpost 2020-09-25 20:31:07 +08:00
MaoBisheng-IPFSUNION 9dfce400a7 delate 2020-09-25 17:36:57 +08:00
hannahhoward 4ff38aa856 feat(markets): update to 0.6.3 2020-09-25 02:35:34 -07:00
Łukasz Magiera e5873d5dea Merge pull request #4009 from filecoin-project/asr/fractional-asks
Correct helptext
2020-09-25 09:00:02 +02:00
Aayush Rajasekaran 8fbbebbaf1 Correct helptext around set ask 2020-09-25 00:11:10 -04:00
MaoBisheng-IPFSUNION 89bfe84f36 add new booststrappers
we hope to add two booststrappers for the filecoin network to improve the network synchronization
2020-09-25 10:18:12 +08:00
Arsenii Petrovich 585b8cc51d Add glif node to bootstrap peers 2020-09-25 03:54:29 +03:00
whyrusleeping 306c098d30 also update our vendored blst repo 2020-09-24 11:32:38 -07:00
whyrusleeping 6db37b72a8 update ffi to code with blst fixes 2020-09-24 11:05:21 -07:00
Łukasz Magiera 80ee3be4d0 Merge pull request #3870 from filecoin-project/asr/msig-set-locked
Add CLIs for new multisig LockBalance method
2020-09-24 19:42:47 +02:00
Hector Sanjuan e48c525053 Re-add jaeger-tracing 2020-09-24 19:41:14 +02:00
Łukasz Magiera cf9dfdb972 Multisig: fix build 2020-09-24 19:26:32 +02:00
Łukasz Magiera 6ca5308c82 Merge pull request #3996 from filecoin-project/conformance-ntwork-upgrade-adjustments
small adjustments following network upgradability changes
2020-09-24 19:24:45 +02:00
Raúl Kripalani 68663060dc add state.StateTree#Version() accessor. 2020-09-24 17:58:49 +01:00
Raúl Kripalani 87b48c94a6 conformance: supply network version to driver. 2020-09-24 17:58:34 +01:00
Jakub Sztandera 45d8cb08ba Merge pull request #3995 from filecoin-project/feat/more-stateroot-stats
add some more big pictures stats to stateroot stat
2020-09-24 18:57:05 +02:00
Łukasz Magiera 130ae3ccb3 Multisig: Fix from flag descriptions 2020-09-24 18:46:21 +02:00
whyrusleeping 4eaa05db52 add some more big pictures stats to stateroot stat 2020-09-24 09:40:49 -07:00
Łukasz Magiera a19023fada Merge remote-tracking branch 'origin/master' into asr/msig-set-locked 2020-09-24 18:38:02 +02:00
Łukasz Magiera 85caa48814 Merge pull request #3991 from filecoin-project/feat/nicer-syncwait
Make sync wait nicer
2020-09-24 17:03:21 +02:00
Łukasz Magiera cdda66a154 Merge pull request #3942 from filecoin-project/3941-deadline-info
3941: Added cmd `lotus-miner proving deadline <deadline index>`
2020-09-24 16:25:45 +02:00
jennijuju f8f335df55 3941: Added cmd `lotus-miner proving deadline <deadline index>"
- To show the current proving period deadline information of given deadline index.
- It outputs the following:
        - number of partitions in this deadline
        - partitions numbers has submitted PoSt since the current proving period started
        - if the deadline is the current proving deadline
        - for each patition, shows the amount of the sectors in this partition, and their numbers. Also, shows the number of fault sectors and corresponding sector numbers.
2020-09-24 16:23:12 +02:00
Łukasz Magiera 28b46ad08c Merge branch 'zgfzgf-miner-break' into master 2020-09-24 16:03:47 +02:00
Łukasz Magiera 43323b2188 Use continue instead of goto 2020-09-24 16:03:24 +02:00
Łukasz Magiera 17a84c9a2c Merge pull request #3975 from filecoin-project/steb/abstract-actor-policy
Add some actors policy setters for testing
2020-09-24 15:51:41 +02:00
Dirk McCormick 7eb9bec13f feat: dont recompute post on submit redux 2020-09-24 14:38:33 +02:00
Łukasz Magiera 2867b31d2b Merge pull request #3208 from austinabell/extratsload
Update beacon entry load error message
2020-09-24 14:19:00 +02:00
Dirk McCormick 3c524ac0e0 refactor: move nonce generation from mpool to wallet 2020-09-24 14:09:42 +02:00
Łukasz Magiera 1a70dd4fb4 Merge pull request #3977 from filecoin-project/steb/remove-cbor-abstraction
Remove a misleading miner actor abstraction
2020-09-24 14:02:59 +02:00
Łukasz Magiera 15eddf0c96 Make sync wait nicer 2020-09-24 13:39:49 +02:00
Łukasz Magiera bbcad52ce0 Merge pull request #3980 from filecoin-project/feat/batch-blockstore-copy
batch blockstore copies after block validation
2020-09-24 13:07:16 +02:00
Łukasz Magiera ded3a30f55 fix lint 2020-09-24 11:56:54 +02:00
whyrusleeping 38e256cece add some tracing to the vm's blockstore copy 2020-09-23 20:19:20 -07:00
whyrusleeping b4e03d1759 batch blockstore copies after block validation 2020-09-23 18:53:28 -07:00
Steven Allen 32a699d6a3 Add some actors policy setters for testing
Addresses:
* https://github.com/filecoin-project/lotus/pull/3781/files/a307e4593a005888395db34e5af4691ee50d765d#r491966115
* https://github.com/filecoin-project/lotus/pull/3781/files/a307e4593a005888395db34e5af4691ee50d765d#r491966634

Note: This puts everything into a policy package to avoid a dependency cycle
between the build package, the miner package, and the types package. This is
also why I introduced a GetPreCommitChallengeDelay function and removed the
variable.
2020-09-23 15:00:52 -07:00
Steven Allen 46f5b62a76 Remove a misleading miner actor abstraction
We shouldn't implement CBOR functions on the "abstract" miner info. Otherwise,
we could end up trying to actually _use_ this "abstract" info when decoding
state (which won't work across version).

Also remove the use of these CBOR functions, and instead explicitly use miner0
types. We'll have to abstract over versions eventually, but we'll probably need
some form of abstract miner builder (or maybe even adding some "add sector",
etc. functions to the current miner abstraction?
2020-09-23 14:49:53 -07:00
zgfzgf a4ade158f4 change minerStop to minerLoop 2020-09-23 20:24:19 +08:00
Travis Person c66f087f4c lotus-miner: add more help text to storage / attach 2020-09-22 18:15:42 +00:00
zgfzgf 001ba17d37 break error 2020-09-22 15:21:35 +08:00
Hector Sanjuan ad3db0e83c Move unclassified docs back to the docs root 2020-09-21 19:05:49 +02:00
Hector Sanjuan a5e7fd8f5c Re-add docs-check step to circle 2020-09-21 18:43:57 +02:00
Travis Person e6bbc03ca8 lotus-pcr: update miner recovery 2020-09-19 02:09:05 +00:00
Travis Person e39036dd49 lotus-pcr: find miners command 2020-09-18 23:17:04 +00:00
Travis Person 26de0db757 lotus-pcr: add recover-miners command 2020-09-18 23:17:04 +00:00
Hector Sanjuan 9e2df907f8 Merge remote-tracking branch 'origin/master' into feat/docs-reorg 2020-09-18 15:23:42 +02:00
vyzo 3c72461969 MpoolPushUntrusted API for gateway 2020-09-18 09:40:43 +03:00
Hector Sanjuan dfd28ab0c4 Fix links in READMEs. 2020-09-17 20:56:43 +02:00
Hector Sanjuan 784399738a Keep api-methods.md even if not part of the docs 2020-09-17 20:50:37 +02:00
Hector Sanjuan bc9232544c Remove faqs too 2020-09-17 20:48:09 +02:00
Hector Sanjuan 591e32af48 Remove circle_ci docs-check. 2020-09-17 20:46:14 +02:00
Hector Sanjuan a4fd356fcb Delete most docs. Update about page with links to docs.filecoin.io 2020-09-17 20:35:19 +02:00
Hector Sanjuan 6849d18b03 Merge branch 'master' into feat/docs-reorg 2020-09-17 19:28:54 +02:00
austinabell ca956ca57e Merge branch 'master' of github.com:filecoin-project/lotus into async/stransition 2020-09-16 11:23:55 -04:00
whyrusleeping 6670d22fb5 add command to (slowly) prune lotus chain datastore 2020-09-15 20:20:48 -07:00
Aayush Rajasekaran 2ca1d111c5 Multisig: Add a CLI command to cancel locking some balance 2020-09-15 19:52:58 -04:00
Aayush Rajasekaran b20f558abb Multisig: Add a CLI command to approve locking some balance 2020-09-15 19:51:18 -04:00
Aayush Rajasekaran c2148ba106 Multisig: Add a CLI command to propose locking some balance 2020-09-15 19:27:36 -04:00
austinabell e53aee26a3 Make state transition in validation async 2020-09-15 18:36:06 -04:00
jennijuju c610bd818e Increased ExpectedSealDuration and and WaitDealsDelay. 2020-09-10 14:34:18 -04:00
Łukasz Magiera 780f6dba34 Remote wallet backends 2020-09-05 21:39:09 +02:00
Łukasz Magiera f90cfda2e6 wallet: Add interface layer 2020-09-04 22:18:03 +02:00
Hector Sanjuan bd0c6a4ccc Fix filename 2020-09-03 16:35:55 +02:00
Hector Sanjuan af38c902f8 Fix architecture entry 2020-09-03 16:35:18 +02:00
Hector Sanjuan a153e1d586 Fix #2334: Specify seal options to disable with co-located storage worker 2020-09-03 16:35:18 +02:00
Hector Sanjuan fe52c47570 Docs review and re-organization
This:

* Re-organizes the docs into sections that align with what docs.filecoin.io becoming:
  * An installation section
  * A "getting started" section (lotus client focused)
  * A "storing" section (lotus client focused)
  * A "mining" section (miner focused)
  * A "build" section (developer focused)
  * An legacy "architecture" section is left in the last place.

A few high-value documentation pages have been reviewed and updated with the latest recommendations:

* Installation section and lotus setup
* Miner setup
* etc.
...

Other pages have been correctly merged into the new relevant sections. Some pages have not been touched. The filesystem layout of the documentation has been changed into folders corresponding to the sections (as requested by @cw). Some pages that were not linked at all and/or where hidden, have been moved to "unclassified".

This should make the porting of the Lotus documentation to docs.filecoin.io much easier, while ensuring it is more up to date than it was before.

For the moment, this breaks most links as link-aliasing is not supported in lotus-docs.
2020-09-03 16:35:16 +02:00
austinabell 6b63fa379f format 2020-09-02 16:45:50 -04:00
austinabell 485f13de12 Remove load check 2020-09-02 16:45:23 -04:00
austinabell 7f3ba0e6eb Merge branch 'master' of github.com:filecoin-project/lotus into extratsload 2020-09-02 16:44:06 -04:00
Aayush Rajasekaran f58e8bc9a3 Fix some failed precommit handling 2020-09-01 02:18:02 -04:00
whyrusleeping cac848c106 add a command to import an ipld object into the chainstore 2020-08-31 14:24:23 -07:00
austinabell e4daadbfcf Remove extra tipset load from checking beacon entries 2020-08-20 17:54:59 -04:00
318 changed files with 18265 additions and 6622 deletions
+1
View File
@@ -13,3 +13,4 @@
### Conformance testing.
conformance/ @raulk
extern/test-vectors @raulk
cmd/tvx @raulk
+1
View File
@@ -12,6 +12,7 @@
/lotus-bench
/lotus-gateway
/lotus-pcr
/lotus-wallet
/bench.json
/lotuspond/front/node_modules
/lotuspond/front/build
+255
View File
@@ -1,5 +1,260 @@
# Lotus changelog
# 0.10.0 / 2020-10-12
This is a consensus-breaking hotfix that addresses an issue in specs-actors v2.0.3 that made it impossible to pledge new 32GiB sectors. The change in Lotus is to update to actors v2.1.0, behind the new network version 5.
## Changes
- make pledge test pass with the race detector (https://github.com/filecoin-project/lotus/pull/4291)
- fix a race in tipset cache usage (https://github.com/filecoin-project/lotus/pull/4282)
- add an api for removing multisig signers (https://github.com/filecoin-project/lotus/pull/4274)
- cli: Don't output errors to stdout (https://github.com/filecoin-project/lotus/pull/4298)
- Fix panic in wallet export when key is not found (https://github.com/filecoin-project/lotus/pull/4299)
- Dump the block validation cache whenever we perform an import (https://github.com/filecoin-project/lotus/pull/4287)
- Fix two races (https://github.com/filecoin-project/lotus/pull/4301)
- sync unmark-bad --all (https://github.com/filecoin-project/lotus/pull/4296)
- decode parameters for multisig transactions in inspect (https://github.com/filecoin-project/lotus/pull/4312)
- Chain is love (https://github.com/filecoin-project/lotus/pull/4321)
- lotus-stats: optmize getting miner power (https://github.com/filecoin-project/lotus/pull/4315)
- implement tape upgrade (https://github.com/filecoin-project/lotus/pull/4322)
# 0.9.1 / 2020-10-10
This release fixes an issue which may cause the actors v2 migration to compute the state incorrectly when more than one migration is running in parallel.
## Changes
- Make concurrent actor migrations safe (https://github.com/filecoin-project/lotus/pull/4293)
- Remote wallet backends (https://github.com/filecoin-project/lotus/pull/3583)
- Track funds in FundMgr correctly in case of AddFunds failing (https://github.com/filecoin-project/lotus/pull/4273)
- Partial lite-node mode (https://github.com/filecoin-project/lotus/pull/4095)
- Fix potential infinite loop in GetBestMiningCandidate (https://github.com/filecoin-project/lotus/pull/3444)
- sync wait: Handle processed message offset (https://github.com/filecoin-project/lotus/pull/4253)
- Add some new endpoints for querying Msig info (https://github.com/filecoin-project/lotus/pull/4250)
- Update markets v0.7.1 (https://github.com/filecoin-project/lotus/pull/4254)
- Optimize SearchForMessage and GetReceipt (https://github.com/filecoin-project/lotus/pull/4246)
- Use FIL instead of attoFIL in CLI more consistently (https://github.com/filecoin-project/lotus/pull/4249)
- fix: clash between daemon --api flag and cli tests (https://github.com/filecoin-project/lotus/pull/4241)
- add more info to chain sync lookback failure (https://github.com/filecoin-project/lotus/pull/4245)
- Add message counts to inspect chain output (https://github.com/filecoin-project/lotus/pull/4230)
# 0.9.0 / 2020-10-07
This consensus-breaking release of Lotus upgrades the actors version to v2.0.0. This requires migrating actor state from v0 to v2. The changes that break consensus are:
- Introducing v2 actors and its migration (https://github.com/filecoin-project/lotus/pull/3936)
- Runtime's Receiver() should only return ID addresses (https://github.com/filecoin-project/lotus/pull/3589)
- Update miner eligibility checks for v2 actors (https://github.com/filecoin-project/lotus/pull/4188)
- Add funds that have left FilReserve to circ supply (https://github.com/filecoin-project/lotus/pull/4160)
- Set WinningPoStSectorSetLookback to finality post-v2 actors (https://github.com/filecoin-project/lotus/pull/4190)
- fix: error when actor panics directly (https://github.com/filecoin-project/lotus/pull/3697)
## Changes
#### Dependencies
- Update go-bitfield (https://github.com/filecoin-project/lotus/pull/4171)
- update the AMT implementation (https://github.com/filecoin-project/lotus/pull/4194)
- Update to actors v0.2.1 (https://github.com/filecoin-project/lotus/pull/4199)
#### Core Lotus
- Paych: fix voucher amount verification (https://github.com/filecoin-project/lotus/pull/3821)
- Cap market provider messages (https://github.com/filecoin-project/lotus/pull/4141)
- Run fork function after cron for null block safety (https://github.com/filecoin-project/lotus/pull/4114)
- use bitswap sessions when fetching messages, and cancel them (https://github.com/filecoin-project/lotus/pull/4142)
- relax pubsub IPColocationFactorThreshold to 5 (https://github.com/filecoin-project/lotus/pull/4183)
- Support addresses with mainnet prefixes (https://github.com/filecoin-project/lotus/pull/4186)
- fix: make message signer nonce generation transactional (https://github.com/filecoin-project/lotus/pull/4165)
- build: Env var to keep test address output (https://github.com/filecoin-project/lotus/pull/4213)
- make vm.EnableGasTracing public (https://github.com/filecoin-project/lotus/pull/4214)
- introduce separate state-tree versions (https://github.com/filecoin-project/lotus/pull/4197)
- reject explicit "calls" at the upgrade height (https://github.com/filecoin-project/lotus/pull/4231)
- return an illegal actor error when we see an unsupported actor version (https://github.com/filecoin-project/lotus/pull/4232)
- Set head should unmark blocks as valid (https://gist.github.com/travisperson/3c7cddd77a33979a519ccef4e6515f20)
#### Mining
- Increased ExpectedSealDuration and and WaitDealsDelay (https://github.com/filecoin-project/lotus/pull/3743)
- Miner backup/restore commands (https://github.com/filecoin-project/lotus/pull/4133)
- lotus-miner: add more help text to storage / attach (https://github.com/filecoin-project/lotus/pull/3961)
- Reject deals that are > 7 days in the future in the BasicDealFilter (https://github.com/filecoin-project/lotus/pull/4173)
- feat(miner): add miner deadline diffing logic (https://github.com/filecoin-project/lotus/pull/4178)
#### UX
- Improve the UX for replacing messages (https://github.com/filecoin-project/lotus/pull/4134)
- Add verified flag to interactive deal creation (https://github.com/filecoin-project/lotus/pull/4145)
- Add command to (slowly) prune lotus chain datastore (https://github.com/filecoin-project/lotus/pull/3876)
- Some helpers for verifreg work (https://github.com/filecoin-project/lotus/pull/4124)
- Always use default 720h for setask duration and hide the duration param option (https://github.com/filecoin-project/lotus/pull/4077)
- Convert ID addresses to key addresses before checking wallet (https://github.com/filecoin-project/lotus/pull/4122)
- add a command to view block space utilization (https://github.com/filecoin-project/lotus/pull/4176)
- allow usage inspection on a chain segment (https://github.com/filecoin-project/lotus/pull/4177)
- Add mpool stats for base fee (https://github.com/filecoin-project/lotus/pull/4170)
- Add verified status to api.DealInfo (https://github.com/filecoin-project/lotus/pull/4153)
- Add a CLI command to set a miner's owner address (https://github.com/filecoin-project/lotus/pull/4189)
#### Tooling and validation
- Lotus-pcr: add recover-miners command (https://github.com/filecoin-project/lotus/pull/3714)
- MpoolPushUntrusted API for gateway (https://github.com/filecoin-project/lotus/pull/3915)
- Test lotus-miner info all (https://github.com/filecoin-project/lotus/pull/4166)
- chain export: Error with unfinished exports (https://github.com/filecoin-project/lotus/pull/4179)
- add printf in TestWindowPost (https://github.com/filecoin-project/lotus/pull/4043)
- add trace wdpost (https://github.com/filecoin-project/lotus/pull/4020)
- Fix noncefix (https://github.com/filecoin-project/lotus/pull/4202)
- Lotus-pcr: Limit the fee cap of messages we will process, refund gas fees for windowed post and storage deals (https://github.com/filecoin-project/lotus/pull/4198)
- Fix pond (https://github.com/filecoin-project/lotus/pull/4203)
- allow manual setting of noncefix fee cap (https://github.com/filecoin-project/lotus/pull/4205)
- implement command to get execution traces of any message (https://github.com/filecoin-project/lotus/pull/4200)
- conformance: minor driver refactors (https://github.com/filecoin-project/lotus/pull/4211)
- lotus-pcr: ignore all other messages (https://github.com/filecoin-project/lotus/pull/4218)
- lotus-pcr: zero refund (https://github.com/filecoin-project/lotus/pull/4229)
## Contributors
The following contributors had 5 or more commits go into this release.
We are grateful for every contribution!
| Contributor | Commits | Lines ± |
|--------------------|---------|---------------|
| Stebalien | 84 | +3425/-2287 |
| magik6k | 41 | +2121/-506 |
| arajasek | 39 | +2467/-424 |
| Kubuxu | 25 | +2344/-775 |
| raulk | 21 | +287/-196 |
| whyrusleeping | 13 | +727/-71 |
| hsanjuan | 13 | +5886/-7956 |
| dirkmc | 11 | +2634/-576 |
| travisperson | 8 | +923/-202 |
| ribasushi | 6 | +188/-128 |
| zgfzgf | 5 | +21/-17 |
# 0.8.1 / 2020-09-30
This optional release of Lotus introduces a new version of markets which switches to CBOR-map encodings, and allows datastore migrations. The release also introduces several improvements to the mining process, a few performance optimizations, and a battery of UX additions and enhancements.
## Changes
#### Dependencies
- Markets 0.7.0 with updated data stores (https://github.com/filecoin-project/lotus/pull/4089)
- Update ffi to code with blst fixes (https://github.com/filecoin-project/lotus/pull/3998)
#### Core Lotus
- Fix GetPower with no miner address (https://github.com/filecoin-project/lotus/pull/4049)
- Refactor: Move nonce generation out of mpool (https://github.com/filecoin-project/lotus/pull/3970)
#### Performance
- Implement caching syscalls for import-bench (https://github.com/filecoin-project/lotus/pull/3888)
- Fetch tipset blocks in parallel (https://github.com/filecoin-project/lotus/pull/4074)
- Optimize Tipset equals() (https://github.com/filecoin-project/lotus/pull/4056)
- Make state transition in validation async (https://github.com/filecoin-project/lotus/pull/3868)
#### Mining
- Add trace window post (https://github.com/filecoin-project/lotus/pull/4020)
- Use abstract types for Dont recompute post on revert (https://github.com/filecoin-project/lotus/pull/4022)
- Fix injectNulls logic in test miner (https://github.com/filecoin-project/lotus/pull/4058)
- Fix potential panic in FinalizeSector (https://github.com/filecoin-project/lotus/pull/4092)
- Don't recompute post on revert (https://github.com/filecoin-project/lotus/pull/3924)
- Fix some failed precommit handling (https://github.com/filecoin-project/lotus/pull/3445)
- Add --no-swap flag for worker (https://github.com/filecoin-project/lotus/pull/4107)
- Allow some single-thread tasks to run in parallel with PC2/C2 (https://github.com/filecoin-project/lotus/pull/4116)
#### UX
- Add an envvar to set address network version (https://github.com/filecoin-project/lotus/pull/4028)
- Add logging to chain export (https://github.com/filecoin-project/lotus/pull/4030)
- Add JSON output to state compute (https://github.com/filecoin-project/lotus/pull/4038)
- Wallet list CLI: Print balances/nonces (https://github.com/filecoin-project/lotus/pull/4088)
- Added an option to show or not show sector info for `lotus-miner info` (https://github.com/filecoin-project/lotus/pull/4003)
- Add a command to import an ipld object into the chainstore (https://github.com/filecoin-project/lotus/pull/3434)
- Improve the lotus-shed dealtracker (https://github.com/filecoin-project/lotus/pull/4051)
- Docs review and re-organization (https://github.com/filecoin-project/lotus/pull/3431)
- Fix wallet list (https://github.com/filecoin-project/lotus/pull/4104)
- Add an endpoint to validate whether a string is a well-formed address (https://github.com/filecoin-project/lotus/pull/4106)
- Add an option to set config path (https://github.com/filecoin-project/lotus/pull/4103)
- Add printf in TestWindowPost (https://github.com/filecoin-project/lotus/pull/4043)
- Improve miner sectors list UX (https://github.com/filecoin-project/lotus/pull/4108)
#### Tooling
- Move policy change to seal bench (https://github.com/filecoin-project/lotus/pull/4032)
- Add back network power to stats (https://github.com/filecoin-project/lotus/pull/4050)
- Conformance: Record and feed circulating supply (https://github.com/filecoin-project/lotus/pull/4078)
- Snapshot import progress bar, add HTTP support (https://github.com/filecoin-project/lotus/pull/4070)
- Add lotus shed util to validate a tipset (https://github.com/filecoin-project/lotus/pull/4065)
- tvx: a test vector extraction and execution tool (https://github.com/filecoin-project/lotus/pull/4064)
#### Bootstrap
- Add new bootstrappers (https://github.com/filecoin-project/lotus/pull/4007)
- Add Glif node to bootstrap peers (https://github.com/filecoin-project/lotus/pull/4004)
- Add one more node located in China (https://github.com/filecoin-project/lotus/pull/4041)
- Add ipfsmain bootstrapper (https://github.com/filecoin-project/lotus/pull/4067)
# 0.8.0 / 2020-09-26
This consensus-breaking release of Lotus introduces an upgrade to the network. The changes that break consensus are:
- Upgrading to specs-actors v0.9.11, which reduces WindowPoSt faults per [FIP 0002](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0002.md) to reduce cost for honest miners with occasional faults (see https://github.com/filecoin-project/specs-actors/pull/1181)
- Revisions to some cryptoeconomics and network params
This release also updates go-fil-markets to fix an incompatibility issue between v0.7.2 and earlier versions.
## Changes
#### Dependencies
- Update spec actors to 0.9.11 (https://github.com/filecoin-project/lotus/pull/4039)
- Update markets to 0.6.3 (https://github.com/filecoin-project/lotus/pull/4013)
#### Core Lotus
- Network upgrade (https://github.com/filecoin-project/lotus/pull/4039)
- Fix AddSupportedProofTypes (https://github.com/filecoin-project/lotus/pull/4033)
- Return an error when we fail to find a sector when checking sector expiration (https://github.com/filecoin-project/lotus/pull/4026)
- Batch blockstore copies after block validation (https://github.com/filecoin-project/lotus/pull/3980)
- Remove a misleading miner actor abstraction (https://github.com/filecoin-project/lotus/pull/3977)
- Fix out-of-bounds when loading all sector infos (https://github.com/filecoin-project/lotus/pull/3976)
- Fix break condition in the miner (https://github.com/filecoin-project/lotus/pull/3953)
#### UX
- Correct helptext around miners setting ask (https://github.com/filecoin-project/lotus/pull/4009)
- Make sync wait nicer (https://github.com/filecoin-project/lotus/pull/3991)
#### Tooling and validation
- Small adjustments following network upgradability changes (https://github.com/filecoin-project/lotus/pull/3996)
- Add some more big pictures stats to stateroot stat (https://github.com/filecoin-project/lotus/pull/3995)
- Add some actors policy setters for testing (https://github.com/filecoin-project/lotus/pull/3975)
## Contributors
The following contributors had 5 or more commits go into this release.
We are grateful for every contribution!
| Contributor | Commits | Lines ± |
|--------------------|---------|---------------|
| arajasek | 66 | +3140/-1261 |
| Stebalien | 64 | +3797/-3434 |
| magik6k | 48 | +1892/-976 |
| raulk | 40 | +2412/-1549 |
| vyzo | 22 | +287/-196 |
| alanshaw | 15 | +761/-146 |
| whyrusleeping | 15 | +736/-52 |
| hannahhoward | 14 | +1237/-837 |
| anton | 6 | +32/-8 |
| travisperson | 5 | +502/-6 |
| Frank | 5 | +78/-39 |
| Jennifer | 5 | +148/-41 |
# 0.7.2 / 2020-09-23
This optional release of Lotus introduces a major refactor around how a Lotus node interacts with code from the specs-actors repo. We now use interfaces to read the state of actors, which is required to be able to reason about different versions of actors code at the same time.
+6
View File
@@ -186,6 +186,12 @@ lotus-health:
.PHONY: lotus-health
BINS+=lotus-health
lotus-wallet:
rm -f lotus-wallet
go build -o lotus-wallet ./cmd/lotus-wallet
.PHONY: lotus-wallet
BINS+=lotus-wallet
testground:
go build -tags testground -o /dev/null ./cmd/lotus
.PHONY: testground
+2 -2
View File
@@ -1,5 +1,5 @@
<p align="center">
<a href="https://lotu.sh/" title="Lotus Docs">
<a href="https://docs.filecoin.io/" title="Filecoin Docs">
<img src="documentation/images/lotus_logo_h.png" alt="Project Lotus Logo" width="244" />
</a>
</p>
@@ -18,7 +18,7 @@ Lotus is an implementation of the Filecoin Distributed Storage Network. For more
## Building & Documentation
For instructions on how to build lotus from source, please visit [Lotus build and setup instruction](https://docs.filecoin.io/get-started/lotus/installation/#minimal-requirements) or read the source [here](https://github.com/filecoin-project/lotus/tree/master/documentation).
For instructions on how to build, install and setup lotus, please visit [https://docs.filecoin.io/get-started/lotus](https://docs.filecoin.io/get-started/lotus/).
## Reporting a Vulnerability
+72 -12
View File
@@ -172,10 +172,16 @@ type FullNode interface {
// SyncUnmarkBad unmarks a blocks as bad, making it possible to be validated and synced again.
SyncUnmarkBad(ctx context.Context, bcid cid.Cid) error
// SyncUnmarkAllBad purges bad block cache, making it possible to sync to chains previously marked as bad
SyncUnmarkAllBad(ctx context.Context) error
// SyncCheckBad checks if a block was marked as bad, and if it was, returns
// the reason.
SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error)
// SyncValidateTipset indicates whether the provided tipset is valid or not
SyncValidateTipset(ctx context.Context, tsk types.TipSetKey) (bool, error)
// MethodGroup: Mpool
// The Mpool methods are for interacting with the message pool. The message pool
// manages all incoming and outgoing 'messages' going over the network.
@@ -189,6 +195,9 @@ type FullNode interface {
// MpoolPush pushes a signed message to mempool.
MpoolPush(context.Context, *types.SignedMessage) (cid.Cid, error)
// MpoolPushUntrusted pushes a signed message to mempool from untrusted sources.
MpoolPushUntrusted(context.Context, *types.SignedMessage) (cid.Cid, error)
// MpoolPushMessage atomically assigns a nonce, signs, and pushes a message
// to mempool.
// maxFee is only used when GasFeeCap/GasPremium fields aren't specified
@@ -244,6 +253,8 @@ type FullNode interface {
WalletImport(context.Context, *types.KeyInfo) (address.Address, error)
// WalletDelete deletes an address from the wallet.
WalletDelete(context.Context, address.Address) error
// WalletValidateAddress validates whether a given string can be decoded as a well-formed address
WalletValidateAddress(context.Context, string) (address.Address, error)
// Other
@@ -275,7 +286,7 @@ type FullNode interface {
// of status updates.
ClientRetrieveWithEvents(ctx context.Context, order RetrievalOrder, ref *FileRef) (<-chan marketevents.RetrievalEvent, error)
// ClientQueryAsk returns a signed StorageAsk from the specified miner.
ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error)
ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error)
// ClientCalcCommP calculates the CommP for a specified file
ClientCalcCommP(ctx context.Context, inpath string) (*CommPRet, error)
// ClientGenCar generates a CAR file for the specified file.
@@ -359,6 +370,10 @@ type FullNode interface {
// 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)
// StateWaitMsgLimited looks back up to limit epochs in the chain for a message.
// If not found, it blocks until the message arrives on chain, and gets to the
// indicated confidence depth.
StateWaitMsgLimited(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch) (*MsgLookup, error)
// StateListMiners returns the addresses of every miner that has claimed power in the Power Actor
StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error)
// StateListActors returns the addresses of every actor in the state
@@ -385,10 +400,16 @@ type FullNode interface {
// StateCompute is a flexible command that applies the given messages on the given tipset.
// The messages are run as though the VM were at the provided height.
StateCompute(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*ComputeStateOutput, error)
// StateVerifierStatus returns the data cap for the given address.
// Returns nil if there is no entry in the data cap table for the
// address.
StateVerifierStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
// StateVerifiedClientStatus returns the data cap for the given address.
// Returns nil if there is no entry in the data cap table for the
// address.
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
// StateVerifiedClientStatus returns the address of the Verified Registry's root key
StateVerifiedRegistryRootKey(ctx context.Context, tsk types.TipSetKey) (address.Address, error)
// StateDealProviderCollateralBounds returns the min and max collateral a storage provider
// can issue. It takes the deal size and verified status as parameters.
StateDealProviderCollateralBounds(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (DealCollateralBounds, error)
@@ -404,6 +425,8 @@ 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)
// MsigGetVestingSchedule returns the vesting details of a given multisig.
MsigGetVestingSchedule(context.Context, address.Address, types.TipSetKey) (MsigVesting, 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)
@@ -415,12 +438,21 @@ type FullNode interface {
// It takes the following params: <multisig address>, <recipient address>, <value to transfer>,
// <sender address of the propose msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigPropose(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
// MsigApprove approves a previously-proposed multisig message
// MsigApprove approves a previously-proposed multisig message by transaction ID
// It takes the following params: <multisig address>, <proposed transaction ID> <signer address>
MsigApprove(context.Context, address.Address, uint64, address.Address) (cid.Cid, error)
// MsigApproveTxnHash approves a previously-proposed multisig message, specified
// using both transaction ID and a hash of the parameters used in the
// proposal. This method of approval can be used to ensure you only approve
// exactly the transaction you think you are.
// It takes the following params: <multisig address>, <proposed message ID>, <proposer address>, <recipient address>, <value to transfer>,
// <sender address of the approve msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigApprove(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
MsigApproveTxnHash(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
// MsigCancel cancels a previously-proposed multisig message
// It takes the following params: <multisig address>, <proposed message ID>, <recipient address>, <value to transfer>,
// It takes the following params: <multisig address>, <proposed transaction 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
@@ -448,6 +480,13 @@ type FullNode interface {
// <old signer>, <new signer>
MsigSwapCancel(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error)
// MsigRemoveSigner proposes the removal of a signer from the multisig.
// It accepts the multisig to make the change on, the proposer address to
// send the message from, the address to be removed, and a boolean
// indicating whether or not the signing threshold should be lowered by one
// along with the address removal.
MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error)
MarketEnsureAvailable(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error)
// MarketFreeBalance
@@ -470,6 +509,12 @@ type FullNode interface {
PaychVoucherAdd(context.Context, address.Address, *paych.SignedVoucher, []byte, types.BigInt) (types.BigInt, error)
PaychVoucherList(context.Context, address.Address) ([]*paych.SignedVoucher, error)
PaychVoucherSubmit(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (cid.Cid, error)
// CreateBackup creates node backup onder the specified file name. The
// method requires that the lotus daemon is running with the
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
// the path specified when calling CreateBackup is within the base path
CreateBackup(ctx context.Context, fpath string) error
}
type FileRef struct {
@@ -516,6 +561,7 @@ type DealInfo struct {
DealID abi.DealID
CreationTime time.Time
Verified bool
}
type MsgLookup struct {
@@ -725,6 +771,8 @@ type ActiveSync struct {
type SyncState struct {
ActiveSyncs []ActiveSync
VMApplied uint64
}
type SyncStateStage int
@@ -789,14 +837,14 @@ type CirculatingSupply struct {
}
type MiningBaseInfo struct {
MinerPower types.BigInt
NetworkPower types.BigInt
Sectors []builtin.SectorInfo
WorkerKey address.Address
SectorSize abi.SectorSize
PrevBeaconEntry types.BeaconEntry
BeaconEntries []types.BeaconEntry
HasMinPower bool
MinerPower types.BigInt
NetworkPower types.BigInt
Sectors []builtin.SectorInfo
WorkerKey address.Address
SectorSize abi.SectorSize
PrevBeaconEntry types.BeaconEntry
BeaconEntries []types.BeaconEntry
EligibleForMining bool
}
type BlockTemplate struct {
@@ -848,3 +896,15 @@ type Fault struct {
Miner address.Address
Epoch abi.ChainEpoch
}
var EmptyVesting = MsigVesting{
InitialBalance: types.EmptyInt,
StartEpoch: -1,
UnlockDuration: -1,
}
type MsigVesting struct {
InitialBalance abi.TokenAmount
StartEpoch abi.ChainEpoch
UnlockDuration abi.ChainEpoch
}
+24
View File
@@ -0,0 +1,24 @@
package api
import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
)
type GatewayAPI interface {
ChainHead(ctx context.Context) (*types.TipSet, error)
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*MsgLookup, error)
}
+6
View File
@@ -101,6 +101,12 @@ type StorageMiner interface {
PiecesListCidInfos(ctx context.Context) ([]cid.Cid, error)
PiecesGetPieceInfo(ctx context.Context, pieceCid cid.Cid) (*piecestore.PieceInfo, error)
PiecesGetCIDInfo(ctx context.Context, payloadCid cid.Cid) (*piecestore.CIDInfo, error)
// CreateBackup creates node backup onder the specified file name. The
// method requires that the lotus-miner is running with the
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
// the path specified when calling CreateBackup is within the base path
CreateBackup(ctx context.Context, fpath string) error
}
type SealRes struct {
+47
View File
@@ -0,0 +1,47 @@
package api
import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/chain/types"
)
type MsgType string
const (
MTUnknown = "unknown"
// Signing message CID. MsgMeta.Extra contains raw cbor message bytes
MTChainMsg = "message"
// Signing a blockheader. signing raw cbor block bytes (MsgMeta.Extra is empty)
MTBlock = "block"
// Signing a deal proposal. signing raw cbor proposal bytes (MsgMeta.Extra is empty)
MTDealProposal = "dealproposal"
// TODO: Deals, Vouchers, VRF
)
type MsgMeta struct {
Type MsgType
// Additional data related to what is signed. Should be verifiable with the
// signed bytes (e.g. CID(Extra).Bytes() == toSign)
Extra []byte
}
type WalletAPI interface {
WalletNew(context.Context, crypto.SigType) (address.Address, error)
WalletHas(context.Context, address.Address) (bool, error)
WalletList(context.Context) ([]address.Address, error)
WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta MsgMeta) (*crypto.Signature, error)
WalletExport(context.Context, address.Address) (*types.KeyInfo, error)
WalletImport(context.Context, *types.KeyInfo) (address.Address, error)
WalletDelete(context.Context, address.Address) error
}
+6
View File
@@ -36,3 +36,9 @@ func PermissionedWorkerAPI(a api.WorkerAPI) api.WorkerAPI {
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
return &out
}
func PermissionedWalletAPI(a api.WalletAPI) api.WalletAPI {
var out WalletStruct
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
return &out
}
+184 -18
View File
@@ -111,7 +111,9 @@ type FullNodeStruct struct {
SyncCheckpoint func(ctx context.Context, key types.TipSetKey) error `perm:"admin"`
SyncMarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"`
SyncUnmarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"`
SyncUnmarkAllBad func(ctx context.Context) error `perm:"admin"`
SyncCheckBad func(ctx context.Context, bcid cid.Cid) (string, error) `perm:"read"`
SyncValidateTipset func(ctx context.Context, tsk types.TipSetKey) (bool, error) `perm:"read"`
MpoolGetConfig func(context.Context) (*types.MpoolConfig, error) `perm:"read"`
MpoolSetConfig func(context.Context, *types.MpoolConfig) error `perm:"write"`
@@ -121,7 +123,9 @@ type FullNodeStruct struct {
MpoolPending func(context.Context, types.TipSetKey) ([]*types.SignedMessage, error) `perm:"read"`
MpoolClear func(context.Context, bool) error `perm:"write"`
MpoolPush func(context.Context, *types.SignedMessage) (cid.Cid, error) `perm:"write"`
MpoolPush func(context.Context, *types.SignedMessage) (cid.Cid, error) `perm:"write"`
MpoolPushUntrusted func(context.Context, *types.SignedMessage) (cid.Cid, error) `perm:"write"`
MpoolPushMessage func(context.Context, *types.Message, *api.MessageSendSpec) (*types.SignedMessage, error) `perm:"sign"`
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"`
@@ -129,18 +133,19 @@ type FullNodeStruct struct {
MinerGetBaseInfo func(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"`
MinerCreateBlock func(context.Context, *api.BlockTemplate) (*types.BlockMsg, error) `perm:"write"`
WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"`
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
WalletList func(context.Context) ([]address.Address, error) `perm:"write"`
WalletBalance func(context.Context, address.Address) (types.BigInt, error) `perm:"read"`
WalletSign func(context.Context, address.Address, []byte) (*crypto.Signature, error) `perm:"sign"`
WalletSignMessage func(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
WalletVerify func(context.Context, address.Address, []byte, *crypto.Signature) (bool, error) `perm:"read"`
WalletDefaultAddress func(context.Context) (address.Address, error) `perm:"write"`
WalletSetDefault func(context.Context, address.Address) error `perm:"admin"`
WalletExport func(context.Context, address.Address) (*types.KeyInfo, error) `perm:"admin"`
WalletImport func(context.Context, *types.KeyInfo) (address.Address, error) `perm:"admin"`
WalletDelete func(context.Context, address.Address) error `perm:"write"`
WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"`
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
WalletList func(context.Context) ([]address.Address, error) `perm:"write"`
WalletBalance func(context.Context, address.Address) (types.BigInt, error) `perm:"read"`
WalletSign func(context.Context, address.Address, []byte) (*crypto.Signature, error) `perm:"sign"`
WalletSignMessage func(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
WalletVerify func(context.Context, address.Address, []byte, *crypto.Signature) (bool, error) `perm:"read"`
WalletDefaultAddress func(context.Context) (address.Address, error) `perm:"write"`
WalletSetDefault func(context.Context, address.Address) error `perm:"admin"`
WalletExport func(context.Context, address.Address) (*types.KeyInfo, error) `perm:"admin"`
WalletImport func(context.Context, *types.KeyInfo) (address.Address, error) `perm:"admin"`
WalletDelete func(context.Context, address.Address) error `perm:"write"`
WalletValidateAddress func(context.Context, string) (address.Address, error) `perm:"read"`
ClientImport func(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) `perm:"admin"`
ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"`
@@ -154,7 +159,7 @@ type FullNodeStruct struct {
ClientGetDealUpdates func(ctx context.Context) (<-chan api.DealInfo, error) `perm:"read"`
ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error `perm:"admin"`
ClientRetrieveWithEvents func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) (<-chan marketevents.RetrievalEvent, error) `perm:"admin"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) `perm:"read"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error) `perm:"read"`
ClientCalcCommP func(ctx context.Context, inpath string) (*api.CommPRet, error) `perm:"read"`
ClientGenCar func(ctx context.Context, ref api.FileRef, outpath string) error `perm:"write"`
ClientDealSize func(ctx context.Context, root cid.Cid) (api.DataSize, error) `perm:"read"`
@@ -186,6 +191,7 @@ type FullNodeStruct struct {
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"`
StateWaitMsgLimited func(context.Context, cid.Cid, uint64, abi.ChainEpoch) (*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"`
StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
@@ -200,16 +206,20 @@ type FullNodeStruct struct {
StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"`
StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"`
StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"`
StateVerifierStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"`
StateVerifiedClientStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"`
StateVerifiedRegistryRootKey func(ctx context.Context, tsk types.TipSetKey) (address.Address, error) `perm:"read"`
StateDealProviderCollateralBounds func(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (api.DealCollateralBounds, error) `perm:"read"`
StateCirculatingSupply func(context.Context, types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"`
StateNetworkVersion func(context.Context, types.TipSetKey) (stnetwork.Version, error) `perm:"read"`
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
MsigGetVestingSchedule func(context.Context, address.Address, types.TipSetKey) (api.MsigVesting, 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"`
MsigApprove func(context.Context, address.Address, uint64, address.Address) (cid.Cid, error) `perm:"sign"`
MsigApproveTxnHash 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"`
@@ -217,6 +227,7 @@ type FullNodeStruct struct {
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"`
MsigRemoveSigner func(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error) `perm:"sign"`
MarketEnsureAvailable func(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
@@ -237,6 +248,8 @@ type FullNodeStruct struct {
PaychVoucherCreate func(context.Context, address.Address, big.Int, uint64) (*api.VoucherCreateResult, error) `perm:"sign"`
PaychVoucherList func(context.Context, address.Address) ([]*paych.SignedVoucher, error) `perm:"write"`
PaychVoucherSubmit func(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (cid.Cid, error) `perm:"sign"`
CreateBackup func(ctx context.Context, fpath string) error `perm:"admin"`
}
}
@@ -317,6 +330,8 @@ type StorageMinerStruct struct {
PiecesListCidInfos func(ctx context.Context) ([]cid.Cid, error) `perm:"read"`
PiecesGetPieceInfo func(ctx context.Context, pieceCid cid.Cid) (*piecestore.PieceInfo, error) `perm:"read"`
PiecesGetCIDInfo func(ctx context.Context, payloadCid cid.Cid) (*piecestore.CIDInfo, error) `perm:"read"`
CreateBackup func(ctx context.Context, fpath string) error `perm:"admin"`
}
}
@@ -350,6 +365,35 @@ type WorkerStruct struct {
}
}
type GatewayStruct struct {
Internal struct {
// TODO: does the gateway need perms?
ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
ChainHead func(ctx context.Context) (*types.TipSet, error)
GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
MsigGetVested func(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateWaitMsg func(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
}
}
type WalletStruct struct {
Internal struct {
WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"`
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
WalletList func(context.Context) ([]address.Address, error) `perm:"write"`
WalletSign func(context.Context, address.Address, []byte, api.MsgMeta) (*crypto.Signature, error) `perm:"sign"`
WalletExport func(context.Context, address.Address) (*types.KeyInfo, error) `perm:"admin"`
WalletImport func(context.Context, *types.KeyInfo) (address.Address, error) `perm:"admin"`
WalletDelete func(context.Context, address.Address) error `perm:"write"`
}
}
// CommonStruct
func (c *CommonStruct) AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) {
@@ -484,7 +528,7 @@ func (c *FullNodeStruct) ClientRetrieveWithEvents(ctx context.Context, order api
return c.Internal.ClientRetrieveWithEvents(ctx, order, ref)
}
func (c *FullNodeStruct) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) {
func (c *FullNodeStruct) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error) {
return c.Internal.ClientQueryAsk(ctx, p, miner)
}
func (c *FullNodeStruct) ClientCalcCommP(ctx context.Context, inpath string) (*api.CommPRet, error) {
@@ -551,6 +595,10 @@ func (c *FullNodeStruct) MpoolPush(ctx context.Context, smsg *types.SignedMessag
return c.Internal.MpoolPush(ctx, smsg)
}
func (c *FullNodeStruct) MpoolPushUntrusted(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) {
return c.Internal.MpoolPushUntrusted(ctx, smsg)
}
func (c *FullNodeStruct) MpoolPushMessage(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec) (*types.SignedMessage, error) {
return c.Internal.MpoolPushMessage(ctx, msg, spec)
}
@@ -631,6 +679,10 @@ func (c *FullNodeStruct) WalletDelete(ctx context.Context, addr address.Address)
return c.Internal.WalletDelete(ctx, addr)
}
func (c *FullNodeStruct) WalletValidateAddress(ctx context.Context, str string) (address.Address, error) {
return c.Internal.WalletValidateAddress(ctx, str)
}
func (c *FullNodeStruct) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) {
return c.Internal.MpoolGetNonce(ctx, addr)
}
@@ -731,10 +783,18 @@ func (c *FullNodeStruct) SyncUnmarkBad(ctx context.Context, bcid cid.Cid) error
return c.Internal.SyncUnmarkBad(ctx, bcid)
}
func (c *FullNodeStruct) SyncUnmarkAllBad(ctx context.Context) error {
return c.Internal.SyncUnmarkAllBad(ctx)
}
func (c *FullNodeStruct) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) {
return c.Internal.SyncCheckBad(ctx, bcid)
}
func (c *FullNodeStruct) SyncValidateTipset(ctx context.Context, tsk types.TipSetKey) (bool, error) {
return c.Internal.SyncValidateTipset(ctx, tsk)
}
func (c *FullNodeStruct) StateNetworkName(ctx context.Context) (dtypes.NetworkName, error) {
return c.Internal.StateNetworkName(ctx)
}
@@ -831,6 +891,10 @@ func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid, confide
return c.Internal.StateWaitMsg(ctx, msgc, confidence)
}
func (c *FullNodeStruct) StateWaitMsgLimited(ctx context.Context, msgc cid.Cid, confidence uint64, limit abi.ChainEpoch) (*api.MsgLookup, error) {
return c.Internal.StateWaitMsgLimited(ctx, msgc, confidence, limit)
}
func (c *FullNodeStruct) StateSearchMsg(ctx context.Context, msgc cid.Cid) (*api.MsgLookup, error) {
return c.Internal.StateSearchMsg(ctx, msgc)
}
@@ -883,10 +947,18 @@ func (c *FullNodeStruct) StateCompute(ctx context.Context, height abi.ChainEpoch
return c.Internal.StateCompute(ctx, height, msgs, tsk)
}
func (c *FullNodeStruct) StateVerifierStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
return c.Internal.StateVerifierStatus(ctx, addr, tsk)
}
func (c *FullNodeStruct) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
return c.Internal.StateVerifiedClientStatus(ctx, addr, tsk)
}
func (c *FullNodeStruct) StateVerifiedRegistryRootKey(ctx context.Context, tsk types.TipSetKey) (address.Address, error) {
return c.Internal.StateVerifiedRegistryRootKey(ctx, tsk)
}
func (c *FullNodeStruct) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
return c.Internal.StateDealProviderCollateralBounds(ctx, size, verified, tsk)
}
@@ -903,6 +975,10 @@ func (c *FullNodeStruct) MsigGetAvailableBalance(ctx context.Context, a address.
return c.Internal.MsigGetAvailableBalance(ctx, a, tsk)
}
func (c *FullNodeStruct) MsigGetVestingSchedule(ctx context.Context, a address.Address, tsk types.TipSetKey) (api.MsigVesting, error) {
return c.Internal.MsigGetVestingSchedule(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)
}
@@ -915,8 +991,12 @@ func (c *FullNodeStruct) MsigPropose(ctx context.Context, msig address.Address,
return c.Internal.MsigPropose(ctx, msig, to, amt, src, method, params)
}
func (c *FullNodeStruct) MsigApprove(ctx context.Context, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
return c.Internal.MsigApprove(ctx, msig, txID, proposer, to, amt, src, method, params)
func (c *FullNodeStruct) MsigApprove(ctx context.Context, msig address.Address, txID uint64, signer address.Address) (cid.Cid, error) {
return c.Internal.MsigApprove(ctx, msig, txID, signer)
}
func (c *FullNodeStruct) MsigApproveTxnHash(ctx context.Context, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
return c.Internal.MsigApproveTxnHash(ctx, msig, txID, proposer, to, amt, src, method, params)
}
func (c *FullNodeStruct) MsigCancel(ctx context.Context, msig address.Address, txID uint64, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
@@ -947,6 +1027,10 @@ func (c *FullNodeStruct) MsigSwapCancel(ctx context.Context, msig address.Addres
return c.Internal.MsigSwapCancel(ctx, msig, src, txID, oldAdd, newAdd)
}
func (c *FullNodeStruct) MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error) {
return c.Internal.MsigRemoveSigner(ctx, msig, proposer, toRemove, decrease)
}
func (c *FullNodeStruct) MarketEnsureAvailable(ctx context.Context, addr, wallet address.Address, amt types.BigInt) (cid.Cid, error) {
return c.Internal.MarketEnsureAvailable(ctx, addr, wallet, amt)
}
@@ -1015,6 +1099,10 @@ func (c *FullNodeStruct) PaychVoucherSubmit(ctx context.Context, ch address.Addr
return c.Internal.PaychVoucherSubmit(ctx, ch, sv, secret, proof)
}
func (c *FullNodeStruct) CreateBackup(ctx context.Context, fpath string) error {
return c.Internal.CreateBackup(ctx, fpath)
}
// StorageMinerStruct
func (c *StorageMinerStruct) ActorAddress(ctx context.Context) (address.Address, error) {
@@ -1255,6 +1343,10 @@ func (c *StorageMinerStruct) PiecesGetCIDInfo(ctx context.Context, payloadCid ci
return c.Internal.PiecesGetCIDInfo(ctx, payloadCid)
}
func (c *StorageMinerStruct) CreateBackup(ctx context.Context, fpath string) error {
return c.Internal.CreateBackup(ctx, fpath)
}
// WorkerStruct
func (w *WorkerStruct) Version(ctx context.Context) (build.Version, error) {
@@ -1329,7 +1421,81 @@ func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
return w.Internal.Closing(ctx)
}
func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
return g.Internal.ChainHead(ctx)
}
func (g GatewayStruct) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
return g.Internal.ChainGetTipSet(ctx, tsk)
}
func (g GatewayStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
}
func (g GatewayStruct) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
return g.Internal.GasEstimateMessageGas(ctx, msg, spec, tsk)
}
func (g GatewayStruct) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
return g.Internal.MpoolPush(ctx, sm)
}
func (g GatewayStruct) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
return g.Internal.MsigGetAvailableBalance(ctx, addr, tsk)
}
func (g GatewayStruct) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
return g.Internal.MsigGetVested(ctx, addr, start, end)
}
func (g GatewayStruct) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
return g.Internal.StateAccountKey(ctx, addr, tsk)
}
func (g GatewayStruct) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
return g.Internal.StateGetActor(ctx, actor, ts)
}
func (g GatewayStruct) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
return g.Internal.StateLookupID(ctx, addr, tsk)
}
func (g GatewayStruct) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
return g.Internal.StateWaitMsg(ctx, msg, confidence)
}
func (c *WalletStruct) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
return c.Internal.WalletNew(ctx, typ)
}
func (c *WalletStruct) WalletHas(ctx context.Context, addr address.Address) (bool, error) {
return c.Internal.WalletHas(ctx, addr)
}
func (c *WalletStruct) WalletList(ctx context.Context) ([]address.Address, error) {
return c.Internal.WalletList(ctx)
}
func (c *WalletStruct) WalletSign(ctx context.Context, k address.Address, msg []byte, meta api.MsgMeta) (*crypto.Signature, error) {
return c.Internal.WalletSign(ctx, k, msg, meta)
}
func (c *WalletStruct) WalletExport(ctx context.Context, a address.Address) (*types.KeyInfo, error) {
return c.Internal.WalletExport(ctx, a)
}
func (c *WalletStruct) WalletImport(ctx context.Context, ki *types.KeyInfo) (address.Address, error) {
return c.Internal.WalletImport(ctx, ki)
}
func (c *WalletStruct) WalletDelete(ctx context.Context, addr address.Address) error {
return c.Internal.WalletDelete(ctx, addr)
}
var _ api.Common = &CommonStruct{}
var _ api.FullNode = &FullNodeStruct{}
var _ api.StorageMiner = &StorageMinerStruct{}
var _ api.WorkerAPI = &WorkerStruct{}
var _ api.GatewayAPI = &GatewayStruct{}
var _ api.WalletAPI = &WalletStruct{}
+26
View File
@@ -82,3 +82,29 @@ func NewWorkerRPC(ctx context.Context, addr string, requestHeader http.Header) (
return &res, closer, err
}
// NewGatewayRPC creates a new http jsonrpc client for a gateway node.
func NewGatewayRPC(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (api.GatewayAPI, jsonrpc.ClientCloser, error) {
var res apistruct.GatewayStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
&res.Internal,
},
requestHeader,
opts...,
)
return &res, closer, err
}
func NewWalletRPC(ctx context.Context, addr string, requestHeader http.Header) (api.WalletAPI, jsonrpc.ClientCloser, error) {
var res apistruct.WalletStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
&res.Internal,
},
requestHeader,
)
return &res, closer, err
}
+31 -1
View File
@@ -19,8 +19,22 @@ import (
func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
for _, height := range []abi.ChainEpoch{
1, // before
162, // while sealing
520, // after upgrade deal
5000, // after
} {
height := height // make linters happy by copying
t.Run(fmt.Sprintf("upgrade-%d", height), func(t *testing.T) {
testCCUpgrade(t, b, blocktime, height)
})
}
}
func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeHeight abi.ChainEpoch) {
ctx := context.Background()
n, sn := b(t, 1, OneMiner)
n, sn := b(t, []FullNodeOpts{FullNodeWithUpgradeAt(upgradeHeight)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@@ -94,6 +108,22 @@ func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
require.Less(t, 50000, int(exp.OnTime))
}
dlInfo, err := client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
// Sector should expire.
for {
// Wait for the sector to expire.
status, err := miner.SectorsStatus(ctx, CC, true)
require.NoError(t, err)
if status.OnTime == 0 && status.Early == 0 {
break
}
t.Log("waiting for sector to expire")
// wait one deadline per loop.
time.Sleep(time.Duration(dlInfo.WPoStChallengeWindow) * blocktime)
}
fmt.Println("shutting down mining")
atomic.AddInt64(&mine, -1)
<-done
+8 -5
View File
@@ -48,7 +48,7 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, OneMiner)
n, sn := b(t, OneFull, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@@ -85,7 +85,7 @@ func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, OneMiner)
n, sn := b(t, OneFull, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@@ -149,7 +149,7 @@ func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Durati
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, OneMiner)
n, sn := b(t, OneFull, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@@ -204,7 +204,7 @@ func TestSenondDealRetrieval(t *testing.T, b APIBuilder, blocktime time.Duration
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, OneMiner)
n, sn := b(t, OneFull, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@@ -402,9 +402,12 @@ func testRetrieval(t *testing.T, ctx context.Context, client *impl.FullNodeAPI,
IsCAR: carExport,
}
updates, err := client.ClientRetrieveWithEvents(ctx, offers[0].Order(caddr), ref)
if err != nil {
t.Fatal(err)
}
for update := range updates {
if update.Err != "" {
t.Fatalf("%v", err)
t.Fatalf("retrieval failed: %s", update.Err)
}
}
+3 -3
View File
@@ -25,7 +25,7 @@ var log = logging.Logger("apitest")
func (ts *testSuite) testMining(t *testing.T) {
ctx := context.Background()
apis, sn := ts.makeNodes(t, 1, OneMiner)
apis, sn := ts.makeNodes(t, OneFull, OneMiner)
api := apis[0]
newHeads, err := api.ChainNotify(ctx)
@@ -54,7 +54,7 @@ func (ts *testSuite) testMiningReal(t *testing.T) {
}()
ctx := context.Background()
apis, sn := ts.makeNodes(t, 1, OneMiner)
apis, sn := ts.makeNodes(t, OneFull, OneMiner)
api := apis[0]
newHeads, err := api.ChainNotify(ctx)
@@ -93,7 +93,7 @@ func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExpo
// test making a deal with a fresh miner, and see if it starts to mine
ctx := context.Background()
n, sn := b(t, 1, []StorageMiner{
n, sn := b(t, OneFull, []StorageMiner{
{Full: 0, Preseal: PresealGenesis},
{Full: 0, Preseal: 0}, // TODO: Add support for miners on non-first full node
})
+68 -10
View File
@@ -8,17 +8,21 @@ import (
"testing"
"time"
"github.com/filecoin-project/specs-actors/actors/builtin"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-address"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apibstore"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/events"
"github.com/filecoin-project/lotus/chain/events/state"
"github.com/filecoin-project/lotus/chain/types"
@@ -29,7 +33,7 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 2, OneMiner)
n, sn := b(t, TwoFull, OneMiner)
paymentCreator := n[0]
paymentReceiver := n[1]
@@ -67,7 +71,7 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
t.Fatal(err)
}
channelAmt := int64(100000)
channelAmt := int64(7000)
channelInfo, err := paymentCreator.PaychGet(ctx, createrAddr, receiverAddr, abi.NewTokenAmount(channelAmt))
if err != nil {
t.Fatal(err)
@@ -133,17 +137,26 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
t.Fatal("Unable to settle payment channel")
}
creatorStore := adt.WrapStore(ctx, cbor.NewCborStore(apibstore.NewAPIBlockstore(paymentCreator)))
// wait for the receiver to submit their vouchers
ev := events.NewEvents(ctx, paymentCreator)
preds := state.NewStatePredicates(paymentCreator)
finished := make(chan struct{})
err = ev.StateChanged(func(ts *types.TipSet) (done bool, more bool, err error) {
act, err := paymentCreator.StateReadState(ctx, channel, ts.Key())
act, err := paymentCreator.StateGetActor(ctx, channel, ts.Key())
if err != nil {
return false, false, err
}
state := act.State.(paych.State)
if state.ToSend.GreaterThanEqual(abi.NewTokenAmount(6000)) {
state, err := paych.Load(creatorStore, act)
if err != nil {
return false, false, err
}
toSend, err := state.ToSend()
if err != nil {
return false, false, err
}
if toSend.GreaterThanEqual(abi.NewTokenAmount(6000)) {
return true, false, nil
}
return false, true, nil
@@ -156,7 +169,7 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
return true, nil
}, func(ctx context.Context, ts *types.TipSet) error {
return nil
}, int(build.MessageConfidence)+1, build.SealRandomnessLookbackLimit, func(oldTs, newTs *types.TipSet) (bool, events.StateChange, error) {
}, int(build.MessageConfidence)+1, build.Finality, func(oldTs, newTs *types.TipSet) (bool, events.StateChange, error) {
return preds.OnPaymentChannelActorChanged(channel, preds.OnToSendAmountChanges())(ctx, oldTs.Key(), newTs.Key())
})
if err != nil {
@@ -169,8 +182,53 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
t.Fatal("Timed out waiting for receiver to submit vouchers")
}
// Create a new voucher now that some vouchers have already been submitted
vouchRes, err := paymentCreator.PaychVoucherCreate(ctx, channel, abi.NewTokenAmount(1000), 3)
if err != nil {
t.Fatal(err)
}
if vouchRes.Voucher == nil {
t.Fatal(fmt.Errorf("Not enough funds to create voucher: missing %d", vouchRes.Shortfall))
}
vdelta, err := paymentReceiver.PaychVoucherAdd(ctx, channel, vouchRes.Voucher, nil, abi.NewTokenAmount(1000))
if err != nil {
t.Fatal(err)
}
if !vdelta.Equals(abi.NewTokenAmount(1000)) {
t.Fatal("voucher didn't have the right amount")
}
// Create a new voucher whose value would exceed the channel balance
excessAmt := abi.NewTokenAmount(1000)
vouchRes, err = paymentCreator.PaychVoucherCreate(ctx, channel, excessAmt, 4)
if err != nil {
t.Fatal(err)
}
if vouchRes.Voucher != nil {
t.Fatal("Expected not to be able to create voucher whose value would exceed channel balance")
}
if !vouchRes.Shortfall.Equals(excessAmt) {
t.Fatal(fmt.Errorf("Expected voucher shortfall of %d, got %d", excessAmt, vouchRes.Shortfall))
}
// Add a voucher whose value would exceed the channel balance
vouch := &paych.SignedVoucher{ChannelAddr: channel, Amount: excessAmt, Lane: 4, Nonce: 1}
vb, err := vouch.SigningBytes()
if err != nil {
t.Fatal(err)
}
sig, err := paymentCreator.WalletSign(ctx, createrAddr, vb)
if err != nil {
t.Fatal(err)
}
vouch.Signature = sig
_, err = paymentReceiver.PaychVoucherAdd(ctx, channel, vouch, nil, abi.NewTokenAmount(1000))
if err == nil {
t.Fatal(fmt.Errorf("Expected shortfall error of %d", excessAmt))
}
// wait for the settlement period to pass before collecting
waitForBlocks(ctx, t, bm, paymentReceiver, receiverAddr, paych.SettleDelay)
waitForBlocks(ctx, t, bm, paymentReceiver, receiverAddr, paych0.SettleDelay)
creatorPreCollectBalance, err := paymentCreator.WalletBalance(ctx, createrAddr)
if err != nil {
@@ -226,7 +284,7 @@ func waitForBlocks(ctx context.Context, t *testing.T, bm *BlockMiner, paymentRec
// Add a real block
m, err := paymentReceiver.MpoolPushMessage(ctx, &types.Message{
To: builtin.BurntFundsActorAddr,
To: builtin0.BurntFundsActorAddr,
From: receiverAddr,
Value: types.NewInt(0),
}, nil)
+44 -4
View File
@@ -4,14 +4,18 @@ import (
"context"
"testing"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"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/miner"
"github.com/filecoin-project/lotus/node"
)
type TestNode struct {
@@ -34,17 +38,27 @@ var PresealGenesis = -1
const GenesisPreseals = 2
// Options for setting up a mock storage miner
type StorageMiner struct {
Full int
Preseal int
}
type OptionGenerator func([]TestNode) node.Option
// Options for setting up a mock full node
type FullNodeOpts struct {
Lite bool // run node in "lite" mode
Opts OptionGenerator // generate dependency injection options
}
// APIBuilder is a function which is invoked in test suite to provide
// test nodes and networks
//
// fullOpts array defines options for each full node
// storage array defines storage nodes, numbers in the array specify full node
// index the storage node 'belongs' to
type APIBuilder func(t *testing.T, nFull int, storage []StorageMiner) ([]TestNode, []TestStorageNode)
type APIBuilder func(t *testing.T, full []FullNodeOpts, storage []StorageMiner) ([]TestNode, []TestStorageNode)
type testSuite struct {
makeNodes APIBuilder
}
@@ -62,13 +76,39 @@ func TestApis(t *testing.T, b APIBuilder) {
t.Run("testMiningReal", ts.testMiningReal)
}
func DefaultFullOpts(nFull int) []FullNodeOpts {
full := make([]FullNodeOpts, nFull)
for i := range full {
full[i] = FullNodeOpts{
Opts: func(nodes []TestNode) node.Option {
return node.Options()
},
}
}
return full
}
var OneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}}
var OneFull = DefaultFullOpts(1)
var TwoFull = DefaultFullOpts(2)
var FullNodeWithUpgradeAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
return FullNodeOpts{
Opts: func(nodes []TestNode) node.Option {
return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
Network: build.ActorUpgradeNetworkVersion,
Height: upgradeHeight,
Migration: stmgr.UpgradeActorsV2,
}})
},
}
}
func (ts *testSuite) testVersion(t *testing.T) {
build.RunningNodeType = build.NodeFull
ctx := context.Background()
apis, _ := ts.makeNodes(t, 1, OneMiner)
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
api := apis[0]
v, err := api.Version(ctx)
@@ -80,7 +120,7 @@ func (ts *testSuite) testVersion(t *testing.T) {
func (ts *testSuite) testID(t *testing.T) {
ctx := context.Background()
apis, _ := ts.makeNodes(t, 1, OneMiner)
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
api := apis[0]
id, err := api.ID(ctx)
@@ -92,7 +132,7 @@ func (ts *testSuite) testID(t *testing.T) {
func (ts *testSuite) testConnectTwo(t *testing.T) {
ctx := context.Background()
apis, _ := ts.makeNodes(t, 2, OneMiner)
apis, _ := ts.makeNodes(t, TwoFull, OneMiner)
p, err := apis[0].NetPeers(ctx)
if err != nil {
+49 -29
View File
@@ -3,6 +3,7 @@ package test
import (
"context"
"fmt"
"sync/atomic"
"os"
"strings"
@@ -31,8 +32,10 @@ func init() {
}
func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
ctx := context.Background()
n, sn := b(t, 1, OneMiner)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
n, sn := b(t, OneFull, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@@ -46,11 +49,11 @@ func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSect
}
build.Clock.Sleep(time.Second)
mine := true
mine := int64(1)
done := make(chan struct{})
go func() {
defer close(done)
for mine {
for atomic.LoadInt64(&mine) != 0 {
build.Clock.Sleep(blocktime)
if err := sn[0].MineOne(ctx, bminer.MineReq{Done: func(bool, abi.ChainEpoch, error) {
@@ -62,7 +65,7 @@ func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSect
pledgeSectors(t, ctx, miner, nSectors, 0, nil)
mine = false
atomic.StoreInt64(&mine, 0)
<-done
}
@@ -114,8 +117,25 @@ func pledgeSectors(t *testing.T, ctx context.Context, miner TestStorageNode, n,
}
func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
ctx := context.Background()
n, sn := b(t, 1, OneMiner)
for _, height := range []abi.ChainEpoch{
1, // before
162, // while sealing
5000, // while proving
} {
height := height // copy to satisfy lints
t.Run(fmt.Sprintf("upgrade-%d", height), func(t *testing.T) {
testWindowPostUpgrade(t, b, blocktime, nSectors, height)
})
}
}
func testWindowPostUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int,
upgradeHeight abi.ChainEpoch) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
n, sn := b(t, []FullNodeOpts{FullNodeWithUpgradeAt(upgradeHeight)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@@ -129,17 +149,24 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
}
build.Clock.Sleep(time.Second)
mine := true
done := make(chan struct{})
go func() {
defer close(done)
for mine {
for ctx.Err() == nil {
build.Clock.Sleep(blocktime)
if err := sn[0].MineOne(ctx, MineNext); err != nil {
if ctx.Err() != nil {
// context was canceled, ignore the error.
return
}
t.Error(err)
}
}
}()
defer func() {
cancel()
<-done
}()
pledgeSectors(t, ctx, miner, nSectors, 0, nil)
@@ -153,18 +180,16 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
require.NoError(t, err)
fmt.Printf("Running one proving period\n")
fmt.Printf("End for head.Height > %d\n", di.PeriodStart+di.WPoStProvingPeriod+2)
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
if head.Height() > di.PeriodStart+(di.WPoStProvingPeriod)+2 {
if head.Height() > di.PeriodStart+di.WPoStProvingPeriod+2 {
fmt.Printf("Now head.Height = %d\n", head.Height())
break
}
if head.Height()%100 == 0 {
fmt.Printf("@%d\n", head.Height())
}
build.Clock.Sleep(blocktime)
}
@@ -186,7 +211,6 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
require.Greater(t, len(parts), 0)
secs := parts[0].AllSectors
require.NoError(t, err)
n, err := secs.Count()
require.NoError(t, err)
require.Equal(t, uint64(2), n)
@@ -210,7 +234,6 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
require.Greater(t, len(parts), 0)
secs := parts[0].AllSectors
require.NoError(t, err)
n, err := secs.Count()
require.NoError(t, err)
require.Equal(t, uint64(2), n)
@@ -236,18 +259,17 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
require.NoError(t, err)
fmt.Printf("Go through another PP, wait for sectors to become faulty\n")
fmt.Printf("End for head.Height > %d\n", di.PeriodStart+di.WPoStProvingPeriod+2)
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
if head.Height() > di.PeriodStart+(di.WPoStProvingPeriod)+2 {
fmt.Printf("Now head.Height = %d\n", head.Height())
break
}
if head.Height()%100 == 0 {
fmt.Printf("@%d\n", head.Height())
}
build.Clock.Sleep(blocktime)
}
@@ -267,17 +289,17 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
di, err = client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
fmt.Printf("End for head.Height > %d\n", di.PeriodStart+di.WPoStProvingPeriod+2)
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
if head.Height() > di.PeriodStart+di.WPoStProvingPeriod+2 {
fmt.Printf("Now head.Height = %d\n", head.Height())
break
}
if head.Height()%100 == 0 {
fmt.Printf("@%d\n", head.Height())
}
build.Clock.Sleep(blocktime)
}
@@ -294,18 +316,19 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
pledgeSectors(t, ctx, miner, 1, nSectors, nil)
{
// wait a bit more
head, err := client.ChainHead(ctx)
// Wait until proven.
di, err = client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
waitUntil := head.Height() + 10
waitUntil := di.PeriodStart + di.WPoStProvingPeriod + 2
fmt.Printf("End for head.Height > %d\n", waitUntil)
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
if head.Height() > waitUntil {
fmt.Printf("Now head.Height = %d\n", head.Height())
break
}
}
@@ -318,7 +341,4 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
sectors = p.MinerPower.RawBytePower.Uint64() / uint64(ssz)
require.Equal(t, nSectors+GenesisPreseals-2+1, int(sectors)) // -2 not recovered sectors + 1 just pledged
mine = false
<-done
}
+6
View File
@@ -4,3 +4,9 @@
/dns4/bootstrap-4.testnet.fildev.network/tcp/1347/p2p/12D3KooWPkL9LrKRQgHtq7kn9ecNhGU9QaziG8R5tX8v9v7t3h34
/dns4/bootstrap-3.testnet.fildev.network/tcp/1347/p2p/12D3KooWKYSsbpgZ3HAjax5M1BXCwXLa6gVkUARciz7uN3FNtr7T
/dns4/bootstrap-5.testnet.fildev.network/tcp/1347/p2p/12D3KooWQYzqnLASJAabyMpPb1GcWZvNSe7JDcRuhdRqonFoiK9W
/dns4/lotus-bootstrap.forceup.cn/tcp/41778/p2p/12D3KooWFQsv3nRMUevZNWWsY1Wu6NUzUbawnWU5NcRhgKuJA37C
/dns4/bootstrap-0.starpool.in/tcp/12757/p2p/12D3KooWGHpBMeZbestVEWkfdnC9u7p6uFHXL1n7m1ZBqsEmiUzz
/dns4/bootstrap-1.starpool.in/tcp/12757/p2p/12D3KooWQZrGH1PxSNZPum99M1zNvjNFM33d1AAu5DcvdHptuU7u
/dns4/node.glif.io/tcp/1235/p2p/12D3KooWBF8cpp65hp2u9LK5mh19x67ftAam84z9LsfaquTDSBpt
/dns4/bootstrap-0.ipfsmain.cn/tcp/34721/p2p/12D3KooWQnwEGNqcM2nAcPtRR9rAX8Hrg4k9kJLCHoTR5chJfz6d
/dns4/bootstrap-1.ipfsmain.cn/tcp/34723/p2p/12D3KooWMKxMkD5DMpSWsW7dBddKxKT7L2GgbNuckz9otxvkvByP
+18 -8
View File
@@ -3,28 +3,38 @@
package build
import (
"math"
"os"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/lotus/chain/actors/policy"
)
const UpgradeBreezeHeight = -1
const BreezeGasTampingDuration = 0
const UpgradeSmokeHeight = -1
const UpgradeIgnitionHeight = -2
const UpgradeRefuelHeight = -3
const UpgradeTapeHeight = -4
var UpgradeActorsV2Height = abi.ChainEpoch(10)
var UpgradeLiftoffHeight = abi.ChainEpoch(-5)
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
}
func init() {
power0.ConsensusMinerMinPower = big.NewInt(2048)
miner0.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
if os.Getenv("LOTUS_DISABLE_V2_ACTOR_MIGRATION") == "1" {
UpgradeActorsV2Height = math.MaxInt64
UpgradeLiftoffHeight = 11
}
verifreg0.MinVerifiedDealSize = big.NewInt(256)
BuildType |= Build2k
}
+7 -1
View File
@@ -3,6 +3,8 @@ package build
import (
"sort"
"github.com/filecoin-project/go-address"
"github.com/libp2p/go-libp2p-core/protocol"
"github.com/filecoin-project/go-state-types/abi"
@@ -39,8 +41,12 @@ func DhtProtocolName(netName dtypes.NetworkName) protocol.ID {
func UseNewestNetwork() bool {
// TODO: Put these in a container we can iterate over
if UpgradeBreezeHeight <= 0 && UpgradeSmokeHeight <= 0 {
if UpgradeBreezeHeight <= 0 && UpgradeSmokeHeight <= 0 && UpgradeActorsV2Height <= 0 {
return true
}
return false
}
func SetAddressNetwork(n address.Network) {
address.CurrentNetwork = n
}
+24 -12
View File
@@ -4,12 +4,15 @@ package build
import (
"math/big"
"os"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
)
// /////
@@ -22,8 +25,8 @@ const UnixfsLinksPerLevel = 1024
// Consensus / Network
const AllowableClockDriftSecs = uint64(1)
const NewestNetworkVersion = network.Version2
const ActorUpgradeNetworkVersion = network.Version3
const NewestNetworkVersion = network.Version5
const ActorUpgradeNetworkVersion = network.Version4
// Epochs
const ForkLengthThreshold = Finality
@@ -32,7 +35,7 @@ const ForkLengthThreshold = Finality
var BlocksPerEpoch = uint64(builtin.ExpectedLeadersPerEpoch)
// Epochs
const Finality = miner0.ChainFinality
const Finality = policy.ChainFinality
const MessageConfidence = uint64(5)
// constants for Weight calculation
@@ -44,13 +47,8 @@ const WRatioDen = uint64(2)
// Proofs
// Epochs
const SealRandomnessLookback = Finality
// Epochs
const SealRandomnessLookbackLimit = SealRandomnessLookback + 2000 // TODO: Get from spec specs-actors
// Maximum lookback that randomness can be sourced from for a seal proof submission
const MaxSealLookback = SealRandomnessLookbackLimit + 2000 // TODO: Get from specs-actors
// TODO: unused
const SealRandomnessLookback = policy.SealRandomnessLookback
// /////
// Mining
@@ -58,23 +56,37 @@ const MaxSealLookback = SealRandomnessLookbackLimit + 2000 // TODO: Get from spe
// Epochs
const TicketRandomnessLookback = abi.ChainEpoch(1)
const WinningPoStSectorSetLookback = abi.ChainEpoch(10)
// /////
// Address
const AddressMainnetEnvVar = "_mainnet_"
// /////
// Devnet settings
var Devnet = true
const FilBase = uint64(2_000_000_000)
const FilAllocStorageMining = uint64(1_100_000_000)
const FilecoinPrecision = uint64(1_000_000_000_000_000_000)
const FilReserved = uint64(300_000_000)
var InitialRewardBalance *big.Int
var InitialFilReserved *big.Int
// TODO: Move other important consts here
func init() {
InitialRewardBalance = big.NewInt(int64(FilAllocStorageMining))
InitialRewardBalance = InitialRewardBalance.Mul(InitialRewardBalance, big.NewInt(int64(FilecoinPrecision)))
InitialFilReserved = big.NewInt(int64(FilReserved))
InitialFilReserved = InitialFilReserved.Mul(InitialFilReserved, big.NewInt(int64(FilecoinPrecision)))
if os.Getenv("LOTUS_ADDRESS_TYPE") == AddressMainnetEnvVar {
SetAddressNetwork(address.Mainnet)
}
}
// Sync
+23 -10
View File
@@ -13,7 +13,8 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/specs-actors/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/policy"
)
var (
@@ -32,7 +33,7 @@ var (
AllowableClockDriftSecs = uint64(1)
Finality = miner0.ChainFinality
Finality = policy.ChainFinality
ForkLengthThreshold = Finality
SlashablePowerDelay = 20
@@ -47,15 +48,13 @@ var (
BlsSignatureCacheSize = 40000
VerifSigCacheSize = 32000
SealRandomnessLookback = Finality
SealRandomnessLookbackLimit = SealRandomnessLookback + 2000
MaxSealLookback = SealRandomnessLookbackLimit + 2000
SealRandomnessLookback = policy.SealRandomnessLookback
TicketRandomnessLookback = abi.ChainEpoch(1)
WinningPoStSectorSetLookback = abi.ChainEpoch(10)
TicketRandomnessLookback = abi.ChainEpoch(1)
FilBase uint64 = 2_000_000_000
FilAllocStorageMining uint64 = 1_400_000_000
FilReserved uint64 = 300_000_000
FilecoinPrecision uint64 = 1_000_000_000_000_000_000
@@ -64,6 +63,13 @@ var (
v = v.Mul(v, big.NewInt(int64(FilecoinPrecision)))
return v
}()
InitialFilReserved = func() *big.Int {
v := big.NewInt(int64(FilReserved))
v = v.Mul(v, big.NewInt(int64(FilecoinPrecision)))
return v
}()
// Actor consts
// TODO: Pull from actors when its made not private
MinDealDuration = abi.ChainEpoch(180 * builtin.EpochsInDay)
@@ -74,12 +80,19 @@ var (
UpgradeBreezeHeight abi.ChainEpoch = -1
BreezeGasTampingDuration abi.ChainEpoch = 0
UpgradeSmokeHeight abi.ChainEpoch = -1
UpgradeSmokeHeight abi.ChainEpoch = -1
UpgradeIgnitionHeight abi.ChainEpoch = -2
UpgradeRefuelHeight abi.ChainEpoch = -3
UpgradeTapeHeight abi.ChainEpoch = -4
UpgradeActorsV2Height abi.ChainEpoch = 10
UpgradeLiftoffHeight abi.ChainEpoch = -5
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
}
NewestNetworkVersion = network.Version2
ActorUpgradeNetworkVersion = network.Version3
NewestNetworkVersion = network.Version5
ActorUpgradeNetworkVersion = network.Version4
Devnet = true
)
+34 -9
View File
@@ -5,11 +5,14 @@
package build
import (
"math"
"os"
"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/specs-actors/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/actors/policy"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
)
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
@@ -22,14 +25,36 @@ const BreezeGasTampingDuration = 120
const UpgradeSmokeHeight = 51000
const UpgradeIgnitionHeight = 94000
const UpgradeRefuelHeight = 130800
var UpgradeActorsV2Height = abi.ChainEpoch(138720)
const UpgradeTapeHeight = 140760
// This signals our tentative epoch for mainnet launch. Can make it later, but not earlier.
// Miners, clients, developers, custodians all need time to prepare.
// We still have upgrades and state changes to do, but can happen after signaling timing here.
const UpgradeLiftoffHeight = 148888
func init() {
power0.ConsensusMinerMinPower = big.NewInt(10 << 40)
miner0.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg32GiBV1: {},
abi.RegisteredSealProof_StackedDrg64GiBV1: {},
policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40))
policy.SetSupportedProofTypes(
abi.RegisteredSealProof_StackedDrg32GiBV1,
abi.RegisteredSealProof_StackedDrg64GiBV1,
)
if os.Getenv("LOTUS_USE_TEST_ADDRESSES") != "1" {
SetAddressNetwork(address.Mainnet)
}
if os.Getenv("LOTUS_DISABLE_V2_ACTOR_MIGRATION") == "1" {
UpgradeActorsV2Height = math.MaxInt64
}
Devnet = false
}
const BlockDelaySecs = uint64(builtin.EpochDurationSeconds)
const BlockDelaySecs = uint64(builtin0.EpochDurationSeconds)
const PropagationDelaySecs = uint64(6)
+1 -1
View File
@@ -29,7 +29,7 @@ func buildType() string {
}
// BuildVersion is the local build version, set by build system
const BuildVersion = "0.7.2"
const BuildVersion = "0.10.0"
func UserVersion() string {
return BuildVersion + buildType() + CurrentCommit
+20 -9
View File
@@ -7,8 +7,11 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt"
)
type Map interface {
@@ -21,18 +24,22 @@ type Map interface {
ForEach(v cbor.Unmarshaler, fn func(key string) error) error
}
func AsMap(store Store, root cid.Cid, version builtin.Version) (Map, error) {
func AsMap(store Store, root cid.Cid, version actors.Version) (Map, error) {
switch version {
case builtin.Version0:
case actors.Version0:
return adt0.AsMap(store, root)
case actors.Version2:
return adt2.AsMap(store, root)
}
return nil, xerrors.Errorf("unknown network version: %d", version)
}
func NewMap(store Store, version builtin.Version) (Map, error) {
func NewMap(store Store, version actors.Version) (Map, error) {
switch version {
case builtin.Version0:
case actors.Version0:
return adt0.MakeEmptyMap(store), nil
case actors.Version2:
return adt2.MakeEmptyMap(store), nil
}
return nil, xerrors.Errorf("unknown network version: %d", version)
}
@@ -49,17 +56,21 @@ type Array interface {
}
func AsArray(store Store, root cid.Cid, version network.Version) (Array, error) {
switch builtin.VersionForNetwork(version) {
case builtin.Version0:
switch actors.VersionForNetwork(version) {
case actors.Version0:
return adt0.AsArray(store, root)
case actors.Version2:
return adt2.AsArray(store, root)
}
return nil, xerrors.Errorf("unknown network version: %d", version)
}
func NewArray(store Store, version builtin.Version) (Array, error) {
func NewArray(store Store, version actors.Version) (Array, error) {
switch version {
case builtin.Version0:
case actors.Version0:
return adt0.MakeEmptyArray(store), nil
case actors.Version2:
return adt2.MakeEmptyArray(store), nil
}
return nil, xerrors.Errorf("unknown network version: %d", version)
}
+17 -7
View File
@@ -5,21 +5,31 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
)
func init() {
builtin.RegisterActorState(builtin0.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root)
})
builtin.RegisterActorState(builtin2.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root)
})
}
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
case builtin0.AccountActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
return load0(store, act.Head)
case builtin2.AccountActorCodeID:
return load2(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
+14 -2
View File
@@ -2,14 +2,26 @@ package account
import (
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/specs-actors/actors/builtin/account"
account0 "github.com/filecoin-project/specs-actors/actors/builtin/account"
)
var _ State = (*state0)(nil)
func load0(store adt.Store, root cid.Cid) (State, error) {
out := state0{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state0 struct {
account.State
account0.State
store adt.Store
}
+30
View File
@@ -0,0 +1,30 @@
package account
import (
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
account2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/account"
)
var _ State = (*state2)(nil)
func load2(store adt.Store, root cid.Cid) (State, error) {
out := state2{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state2 struct {
account2.State
store adt.Store
}
func (s *state2) PubkeyAddress() (address.Address, error) {
return s.Address, nil
}
+76 -19
View File
@@ -1,32 +1,28 @@
package builtin
import (
"fmt"
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof"
smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing"
"github.com/filecoin-project/go-state-types/network"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing"
)
type Version int
const (
Version0 = iota
)
// Converts a network version into a specs-actors version.
func VersionForNetwork(version network.Version) Version {
switch version {
case network.Version0, network.Version1, network.Version2:
return Version0
default:
panic(fmt.Sprintf("unsupported network version %d", version))
}
}
var SystemActorAddr = builtin0.SystemActorAddr
var BurntFundsActorAddr = builtin0.BurntFundsActorAddr
var ReserveAddress = makeAddress("t090")
var RootVerifierAddress = makeAddress("t080")
// TODO: Why does actors have 2 different versions of this?
type SectorInfo = proof0.SectorInfo
@@ -41,3 +37,64 @@ func FromV0FilterEstimate(v0 smoothing0.FilterEstimate) FilterEstimate {
func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower {
return miner0.QAPowerForWeight(size, duration, dealWeight, verifiedWeight)
}
func FromV2FilterEstimate(v1 smoothing2.FilterEstimate) FilterEstimate {
return (FilterEstimate)(v1)
}
type ActorStateLoader func(store adt.Store, root cid.Cid) (cbor.Marshaler, error)
var ActorStateLoaders = make(map[cid.Cid]ActorStateLoader)
func RegisterActorState(code cid.Cid, loader ActorStateLoader) {
ActorStateLoaders[code] = loader
}
func Load(store adt.Store, act *types.Actor) (cbor.Marshaler, error) {
loader, found := ActorStateLoaders[act.Code]
if !found {
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
return loader(store, act.Head)
}
func ActorNameByCode(c cid.Cid) string {
switch {
case builtin0.IsBuiltinActor(c):
return builtin0.ActorNameByCode(c)
case builtin2.IsBuiltinActor(c):
return builtin2.ActorNameByCode(c)
default:
return "<unknown>"
}
}
func IsBuiltinActor(c cid.Cid) bool {
return builtin0.IsBuiltinActor(c) || builtin2.IsBuiltinActor(c)
}
func IsAccountActor(c cid.Cid) bool {
return c == builtin0.AccountActorCodeID || c == builtin2.AccountActorCodeID
}
func IsStorageMinerActor(c cid.Cid) bool {
return c == builtin0.StorageMinerActorCodeID || c == builtin2.StorageMinerActorCodeID
}
func IsMultisigActor(c cid.Cid) bool {
return c == builtin0.MultisigActorCodeID || c == builtin2.MultisigActorCodeID
}
func IsPaymentChannelActor(c cid.Cid) bool {
return c == builtin0.PaymentChannelActorCodeID || c == builtin2.PaymentChannelActorCodeID
}
func makeAddress(addr string) address.Address {
ret, err := address.NewFromString(addr)
if err != nil {
panic(err)
}
return ret
}
+20 -7
View File
@@ -6,24 +6,34 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
)
func init() {
builtin.RegisterActorState(builtin0.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root)
})
builtin.RegisterActorState(builtin2.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root)
})
}
var Address = builtin0.InitActorAddr
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
case builtin0.InitActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
return load0(store, act.Head)
case builtin2.InitActorCodeID:
return load2(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@@ -41,4 +51,7 @@ type State interface {
// It should not be used in production code, as init actor entries are
// immutable.
Remove(addrs ...address.Address) error
// Sets the network's name. This should only be used on upgrade/fork.
SetNetworkName(name string) error
}
+17 -3
View File
@@ -3,21 +3,30 @@ package init
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/node/modules/dtypes"
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
)
var _ State = (*state0)(nil)
func load0(store adt.Store, root cid.Cid) (State, error) {
out := state0{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state0 struct {
init_.State
init0.State
store adt.Store
}
@@ -48,6 +57,11 @@ func (s *state0) NetworkName() (dtypes.NetworkName, error) {
return dtypes.NetworkName(s.State.NetworkName), nil
}
func (s *state0) SetNetworkName(name string) error {
s.State.NetworkName = name
return nil
}
func (s *state0) Remove(addrs ...address.Address) (err error) {
m, err := adt0.AsMap(s.store, s.State.AddressMap)
if err != nil {
+81
View File
@@ -0,0 +1,81 @@
package init
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/node/modules/dtypes"
init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init"
adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt"
)
var _ State = (*state2)(nil)
func load2(store adt.Store, root cid.Cid) (State, error) {
out := state2{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state2 struct {
init2.State
store adt.Store
}
func (s *state2) ResolveAddress(address address.Address) (address.Address, bool, error) {
return s.State.ResolveAddress(s.store, address)
}
func (s *state2) MapAddressToNewID(address address.Address) (address.Address, error) {
return s.State.MapAddressToNewID(s.store, address)
}
func (s *state2) ForEachActor(cb func(id abi.ActorID, address address.Address) error) error {
addrs, err := adt2.AsMap(s.store, s.State.AddressMap)
if err != nil {
return err
}
var actorID cbg.CborInt
return addrs.ForEach(&actorID, func(key string) error {
addr, err := address.NewFromBytes([]byte(key))
if err != nil {
return err
}
return cb(abi.ActorID(actorID), addr)
})
}
func (s *state2) NetworkName() (dtypes.NetworkName, error) {
return dtypes.NetworkName(s.State.NetworkName), nil
}
func (s *state2) SetNetworkName(name string) error {
s.State.NetworkName = name
return nil
}
func (s *state2) Remove(addrs ...address.Address) (err error) {
m, err := adt2.AsMap(s.store, s.State.AddressMap)
if err != nil {
return err
}
for _, addr := range addrs {
if err = m.Delete(abi.AddrKey(addr)); err != nil {
return xerrors.Errorf("failed to delete entry for address: %s; err: %w", addr, err)
}
}
amr, err := m.Root()
if err != nil {
return xerrors.Errorf("failed to get address map root: %w", err)
}
s.State.AddressMap = amr
return nil
}
+17 -8
View File
@@ -6,26 +6,35 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
func init() {
builtin.RegisterActorState(builtin0.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root)
})
builtin.RegisterActorState(builtin2.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root)
})
}
var Address = builtin0.StorageMarketActorAddr
func Load(store adt.Store, act *types.Actor) (st State, err error) {
switch act.Code {
case builtin0.StorageMarketActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
return load0(store, act.Head)
case builtin2.StorageMarketActorCodeID:
return load2(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
+24 -12
View File
@@ -5,17 +5,29 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
cbg "github.com/whyrusleeping/cbor-gen"
)
var _ State = (*state0)(nil)
func load0(store adt.Store, root cid.Cid) (State, error) {
out := state0{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state0 struct {
market.State
market0.State
store adt.Store
}
@@ -90,7 +102,7 @@ func (s *state0) LockedTable() (BalanceTable, error) {
func (s *state0) VerifyDealsForActivation(
minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch,
) (weight, verifiedWeight abi.DealWeight, err error) {
return market.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch)
return market0.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch)
}
type balanceTable0 struct {
@@ -114,7 +126,7 @@ type dealStates0 struct {
}
func (s *dealStates0) Get(dealID abi.DealID) (*DealState, bool, error) {
var deal0 market.DealState
var deal0 market0.DealState
found, err := s.Array.Get(uint64(dealID), &deal0)
if err != nil {
return nil, false, err
@@ -127,14 +139,14 @@ func (s *dealStates0) Get(dealID abi.DealID) (*DealState, bool, error) {
}
func (s *dealStates0) ForEach(cb func(dealID abi.DealID, ds DealState) error) error {
var ds0 market.DealState
var ds0 market0.DealState
return s.Array.ForEach(&ds0, func(idx int64) error {
return cb(abi.DealID(idx), fromV0DealState(ds0))
})
}
func (s *dealStates0) decode(val *cbg.Deferred) (*DealState, error) {
var ds0 market.DealState
var ds0 market0.DealState
if err := ds0.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err
}
@@ -146,7 +158,7 @@ func (s *dealStates0) array() adt.Array {
return s.Array
}
func fromV0DealState(v0 market.DealState) DealState {
func fromV0DealState(v0 market0.DealState) DealState {
return (DealState)(v0)
}
@@ -155,7 +167,7 @@ type dealProposals0 struct {
}
func (s *dealProposals0) Get(dealID abi.DealID) (*DealProposal, bool, error) {
var proposal0 market.DealProposal
var proposal0 market0.DealProposal
found, err := s.Array.Get(uint64(dealID), &proposal0)
if err != nil {
return nil, false, err
@@ -168,14 +180,14 @@ func (s *dealProposals0) Get(dealID abi.DealID) (*DealProposal, bool, error) {
}
func (s *dealProposals0) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error {
var dp0 market.DealProposal
var dp0 market0.DealProposal
return s.Array.ForEach(&dp0, func(idx int64) error {
return cb(abi.DealID(idx), fromV0DealProposal(dp0))
})
}
func (s *dealProposals0) decode(val *cbg.Deferred) (*DealProposal, error) {
var dp0 market.DealProposal
var dp0 market0.DealProposal
if err := dp0.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err
}
@@ -187,6 +199,6 @@ func (s *dealProposals0) array() adt.Array {
return s.Array
}
func fromV0DealProposal(v0 market.DealProposal) DealProposal {
func fromV0DealProposal(v0 market0.DealProposal) DealProposal {
return (DealProposal)(v0)
}
+205
View File
@@ -0,0 +1,205 @@
package market
import (
"bytes"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market"
adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt"
)
var _ State = (*state2)(nil)
func load2(store adt.Store, root cid.Cid) (State, error) {
out := state2{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state2 struct {
market2.State
store adt.Store
}
func (s *state2) TotalLocked() (abi.TokenAmount, error) {
fml := types.BigAdd(s.TotalClientLockedCollateral, s.TotalProviderLockedCollateral)
fml = types.BigAdd(fml, s.TotalClientStorageFee)
return fml, nil
}
func (s *state2) BalancesChanged(otherState State) (bool, error) {
otherState2, ok := otherState.(*state2)
if !ok {
// there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed
return true, nil
}
return !s.State.EscrowTable.Equals(otherState2.State.EscrowTable) || !s.State.LockedTable.Equals(otherState2.State.LockedTable), nil
}
func (s *state2) StatesChanged(otherState State) (bool, error) {
otherState2, ok := otherState.(*state2)
if !ok {
// there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed
return true, nil
}
return !s.State.States.Equals(otherState2.State.States), nil
}
func (s *state2) States() (DealStates, error) {
stateArray, err := adt2.AsArray(s.store, s.State.States)
if err != nil {
return nil, err
}
return &dealStates2{stateArray}, nil
}
func (s *state2) ProposalsChanged(otherState State) (bool, error) {
otherState2, ok := otherState.(*state2)
if !ok {
// there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed
return true, nil
}
return !s.State.Proposals.Equals(otherState2.State.Proposals), nil
}
func (s *state2) Proposals() (DealProposals, error) {
proposalArray, err := adt2.AsArray(s.store, s.State.Proposals)
if err != nil {
return nil, err
}
return &dealProposals2{proposalArray}, nil
}
func (s *state2) EscrowTable() (BalanceTable, error) {
bt, err := adt2.AsBalanceTable(s.store, s.State.EscrowTable)
if err != nil {
return nil, err
}
return &balanceTable2{bt}, nil
}
func (s *state2) LockedTable() (BalanceTable, error) {
bt, err := adt2.AsBalanceTable(s.store, s.State.LockedTable)
if err != nil {
return nil, err
}
return &balanceTable2{bt}, nil
}
func (s *state2) VerifyDealsForActivation(
minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch,
) (weight, verifiedWeight abi.DealWeight, err error) {
w, vw, _, err := market2.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch)
return w, vw, err
}
type balanceTable2 struct {
*adt2.BalanceTable
}
func (bt *balanceTable2) ForEach(cb func(address.Address, abi.TokenAmount) error) error {
asMap := (*adt2.Map)(bt.BalanceTable)
var ta abi.TokenAmount
return asMap.ForEach(&ta, func(key string) error {
a, err := address.NewFromBytes([]byte(key))
if err != nil {
return err
}
return cb(a, ta)
})
}
type dealStates2 struct {
adt.Array
}
func (s *dealStates2) Get(dealID abi.DealID) (*DealState, bool, error) {
var deal2 market2.DealState
found, err := s.Array.Get(uint64(dealID), &deal2)
if err != nil {
return nil, false, err
}
if !found {
return nil, false, nil
}
deal := fromV2DealState(deal2)
return &deal, true, nil
}
func (s *dealStates2) ForEach(cb func(dealID abi.DealID, ds DealState) error) error {
var ds1 market2.DealState
return s.Array.ForEach(&ds1, func(idx int64) error {
return cb(abi.DealID(idx), fromV2DealState(ds1))
})
}
func (s *dealStates2) decode(val *cbg.Deferred) (*DealState, error) {
var ds1 market2.DealState
if err := ds1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err
}
ds := fromV2DealState(ds1)
return &ds, nil
}
func (s *dealStates2) array() adt.Array {
return s.Array
}
func fromV2DealState(v1 market2.DealState) DealState {
return (DealState)(v1)
}
type dealProposals2 struct {
adt.Array
}
func (s *dealProposals2) Get(dealID abi.DealID) (*DealProposal, bool, error) {
var proposal2 market2.DealProposal
found, err := s.Array.Get(uint64(dealID), &proposal2)
if err != nil {
return nil, false, err
}
if !found {
return nil, false, nil
}
proposal := fromV2DealProposal(proposal2)
return &proposal, true, nil
}
func (s *dealProposals2) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error {
var dp1 market2.DealProposal
return s.Array.ForEach(&dp1, func(idx int64) error {
return cb(abi.DealID(idx), fromV2DealProposal(dp1))
})
}
func (s *dealProposals2) decode(val *cbg.Deferred) (*DealProposal, error) {
var dp1 market2.DealProposal
if err := dp1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err
}
dp := fromV2DealProposal(dp1)
return &dp, nil
}
func (s *dealProposals2) array() adt.Array {
return s.Array
}
func fromV2DealProposal(v1 market2.DealProposal) DealProposal {
return (DealProposal)(v1)
}
-313
View File
@@ -1,313 +0,0 @@
// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT.
package miner
import (
"fmt"
"io"
abi "github.com/filecoin-project/go-state-types/abi"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
)
var _ = xerrors.Errorf
var lengthBufSectorOnChainInfo = []byte{139}
func (t *SectorOnChainInfo) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write(lengthBufSectorOnChainInfo); err != nil {
return err
}
scratch := make([]byte, 9)
// t.SectorNumber (abi.SectorNumber) (uint64)
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.SectorNumber)); err != nil {
return err
}
// t.SealProof (abi.RegisteredSealProof) (int64)
if t.SealProof >= 0 {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.SealProof)); err != nil {
return err
}
} else {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.SealProof-1)); err != nil {
return err
}
}
// t.SealedCID (cid.Cid) (struct)
if err := cbg.WriteCidBuf(scratch, w, t.SealedCID); err != nil {
return xerrors.Errorf("failed to write cid field t.SealedCID: %w", err)
}
// t.DealIDs ([]abi.DealID) (slice)
if len(t.DealIDs) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.DealIDs was too long")
}
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.DealIDs))); err != nil {
return err
}
for _, v := range t.DealIDs {
if err := cbg.CborWriteHeader(w, cbg.MajUnsignedInt, uint64(v)); err != nil {
return err
}
}
// t.Activation (abi.ChainEpoch) (int64)
if t.Activation >= 0 {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Activation)); err != nil {
return err
}
} else {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.Activation-1)); err != nil {
return err
}
}
// t.Expiration (abi.ChainEpoch) (int64)
if t.Expiration >= 0 {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Expiration)); err != nil {
return err
}
} else {
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.Expiration-1)); err != nil {
return err
}
}
// t.DealWeight (big.Int) (struct)
if err := t.DealWeight.MarshalCBOR(w); err != nil {
return err
}
// t.VerifiedDealWeight (big.Int) (struct)
if err := t.VerifiedDealWeight.MarshalCBOR(w); err != nil {
return err
}
// t.InitialPledge (big.Int) (struct)
if err := t.InitialPledge.MarshalCBOR(w); err != nil {
return err
}
// t.ExpectedDayReward (big.Int) (struct)
if err := t.ExpectedDayReward.MarshalCBOR(w); err != nil {
return err
}
// t.ExpectedStoragePledge (big.Int) (struct)
if err := t.ExpectedStoragePledge.MarshalCBOR(w); err != nil {
return err
}
return nil
}
func (t *SectorOnChainInfo) UnmarshalCBOR(r io.Reader) error {
*t = SectorOnChainInfo{}
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 != 11 {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.SectorNumber (abi.SectorNumber) (uint64)
{
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.SectorNumber = abi.SectorNumber(extra)
}
// t.SealProof (abi.RegisteredSealProof) (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.SealProof = abi.RegisteredSealProof(extraI)
}
// t.SealedCID (cid.Cid) (struct)
{
c, err := cbg.ReadCid(br)
if err != nil {
return xerrors.Errorf("failed to read cid field t.SealedCID: %w", err)
}
t.SealedCID = c
}
// t.DealIDs ([]abi.DealID) (slice)
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if extra > cbg.MaxLength {
return fmt.Errorf("t.DealIDs: array too large (%d)", extra)
}
if maj != cbg.MajArray {
return fmt.Errorf("expected cbor array")
}
if extra > 0 {
t.DealIDs = make([]abi.DealID, extra)
}
for i := 0; i < int(extra); i++ {
maj, val, err := cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return xerrors.Errorf("failed to read uint64 for t.DealIDs slice: %w", err)
}
if maj != cbg.MajUnsignedInt {
return xerrors.Errorf("value read for array t.DealIDs was not a uint, instead got %d", maj)
}
t.DealIDs[i] = abi.DealID(val)
}
// t.Activation (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.Activation = abi.ChainEpoch(extraI)
}
// t.Expiration (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.Expiration = abi.ChainEpoch(extraI)
}
// t.DealWeight (big.Int) (struct)
{
if err := t.DealWeight.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.DealWeight: %w", err)
}
}
// t.VerifiedDealWeight (big.Int) (struct)
{
if err := t.VerifiedDealWeight.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.VerifiedDealWeight: %w", err)
}
}
// t.InitialPledge (big.Int) (struct)
{
if err := t.InitialPledge.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.InitialPledge: %w", err)
}
}
// t.ExpectedDayReward (big.Int) (struct)
{
if err := t.ExpectedDayReward.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.ExpectedDayReward: %w", err)
}
}
// t.ExpectedStoragePledge (big.Int) (struct)
{
if err := t.ExpectedStoragePledge.UnmarshalCBOR(br); err != nil {
return xerrors.Errorf("unmarshaling t.ExpectedStoragePledge: %w", err)
}
}
return nil
}
@@ -0,0 +1,180 @@
package miner
import (
"errors"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/exitcode"
)
type DeadlinesDiff map[uint64]*DeadlineDiff
func DiffDeadlines(pre, cur State) (*DeadlinesDiff, error) {
changed, err := pre.DeadlinesChanged(cur)
if err != nil {
return nil, err
}
if !changed {
return nil, nil
}
numDl, err := pre.NumDeadlines()
if err != nil {
return nil, err
}
dlDiff := make(DeadlinesDiff, numDl)
if err := pre.ForEachDeadline(func(idx uint64, preDl Deadline) error {
curDl, err := cur.LoadDeadline(idx)
if err != nil {
return err
}
diff, err := DiffDeadline(preDl, curDl)
if err != nil {
return err
}
dlDiff[idx] = diff
return nil
}); err != nil {
return nil, err
}
return &dlDiff, nil
}
type DeadlineDiff map[uint64]*PartitionDiff
func DiffDeadline(pre, cur Deadline) (*DeadlineDiff, error) {
changed, err := pre.PartitionsChanged(cur)
if err != nil {
return nil, err
}
if !changed {
return nil, nil
}
partDiff := make(DeadlineDiff)
if err := pre.ForEachPartition(func(idx uint64, prePart Partition) error {
// try loading current partition at this index
curPart, err := cur.LoadPartition(idx)
if err != nil {
if errors.Is(err, exitcode.ErrNotFound) {
// TODO correctness?
return nil // the partition was removed.
}
return err
}
// compare it with the previous partition
diff, err := DiffPartition(prePart, curPart)
if err != nil {
return err
}
partDiff[idx] = diff
return nil
}); err != nil {
return nil, err
}
// all previous partitions have been walked.
// all partitions in cur and not in prev are new... can they be faulty already?
// TODO is this correct?
if err := cur.ForEachPartition(func(idx uint64, curPart Partition) error {
if _, found := partDiff[idx]; found {
return nil
}
faults, err := curPart.FaultySectors()
if err != nil {
return err
}
recovering, err := curPart.RecoveringSectors()
if err != nil {
return err
}
partDiff[idx] = &PartitionDiff{
Removed: bitfield.New(),
Recovered: bitfield.New(),
Faulted: faults,
Recovering: recovering,
}
return nil
}); err != nil {
return nil, err
}
return &partDiff, nil
}
type PartitionDiff struct {
Removed bitfield.BitField
Recovered bitfield.BitField
Faulted bitfield.BitField
Recovering bitfield.BitField
}
func DiffPartition(pre, cur Partition) (*PartitionDiff, error) {
prevLiveSectors, err := pre.LiveSectors()
if err != nil {
return nil, err
}
curLiveSectors, err := cur.LiveSectors()
if err != nil {
return nil, err
}
removed, err := bitfield.SubtractBitField(prevLiveSectors, curLiveSectors)
if err != nil {
return nil, err
}
prevRecoveries, err := pre.RecoveringSectors()
if err != nil {
return nil, err
}
curRecoveries, err := cur.RecoveringSectors()
if err != nil {
return nil, err
}
recovering, err := bitfield.SubtractBitField(curRecoveries, prevRecoveries)
if err != nil {
return nil, err
}
prevFaults, err := pre.FaultySectors()
if err != nil {
return nil, err
}
curFaults, err := cur.FaultySectors()
if err != nil {
return nil, err
}
faulted, err := bitfield.SubtractBitField(curFaults, prevFaults)
if err != nil {
return nil, err
}
// all current good sectors
curActiveSectors, err := cur.ActiveSectors()
if err != nil {
return nil, err
}
// sectors that were previously fault and are now currently active are considered recovered.
recovered, err := bitfield.IntersectBitField(prevFaults, curActiveSectors)
if err != nil {
return nil, err
}
return &PartitionDiff{
Removed: removed,
Recovered: recovered,
Faulted: faulted,
Recovering: recovering,
}, nil
}
+24 -10
View File
@@ -11,28 +11,40 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/go-state-types/dline"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
)
// Unchanged between v0 and v1 actors
var PreCommitChallengeDelay = miner0.PreCommitChallengeDelay
func init() {
builtin.RegisterActorState(builtin0.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root)
})
builtin.RegisterActorState(builtin2.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root)
})
}
// Unchanged between v0 and v2 actors
var WPoStProvingPeriod = miner0.WPoStProvingPeriod
var WPoStPeriodDeadlines = miner0.WPoStPeriodDeadlines
var WPoStChallengeWindow = miner0.WPoStChallengeWindow
var WPoStChallengeLookback = miner0.WPoStChallengeLookback
var FaultDeclarationCutoff = miner0.FaultDeclarationCutoff
const MinSectorExpiration = miner0.MinSectorExpiration
func Load(store adt.Store, act *types.Actor) (st State, err error) {
switch act.Code {
case builtin0.StorageMinerActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
return load0(store, act.Head)
case builtin2.StorageMinerActorCodeID:
return load2(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@@ -46,6 +58,7 @@ type State interface {
VestedFunds(abi.ChainEpoch) (abi.TokenAmount, error)
// Funds locked for various reasons.
LockedFunds() (LockedFunds, error)
FeeDebt() (abi.TokenAmount, error)
GetSector(abi.SectorNumber) (*SectorOnChainInfo, error)
FindSector(abi.SectorNumber) (*SectorLocation, error)
@@ -132,6 +145,7 @@ type MinerInfo struct {
SealProofType abi.RegisteredSealProof
SectorSize abi.SectorSize
WindowPoStPartitionSectors uint64
ConsensusFaultElapsed abi.ChainEpoch
}
type SectorExpiration struct {
+24 -8
View File
@@ -4,21 +4,34 @@ import (
"bytes"
"errors"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/dline"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors/adt"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
)
var _ State = (*state0)(nil)
func load0(store adt.Store, root cid.Cid) (State, error) {
out := state0{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state0 struct {
miner0.State
store adt.Store
@@ -50,6 +63,10 @@ func (s *state0) LockedFunds() (LockedFunds, error) {
}, nil
}
func (s *state0) FeeDebt() (abi.TokenAmount, error) {
return big.Zero(), nil
}
func (s *state0) InitialPledge() (abi.TokenAmount, error) {
return s.State.InitialPledgeRequirement, nil
}
@@ -96,9 +113,7 @@ func (s *state0) NumLiveSectors() (uint64, error) {
// GetSectorExpiration returns the effective expiration of the given sector.
//
// If the sector isn't found or has already been terminated, this method returns
// nil and no error. If the sector does not expire early, the Early expiration
// field is 0.
// If the sector does not expire early, the Early expiration field is 0.
func (s *state0) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, error) {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
@@ -161,7 +176,7 @@ func (s *state0) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, e
return nil, err
}
if out.Early == 0 && out.OnTime == 0 {
return nil, nil
return nil, xerrors.Errorf("failed to find sector %d", num)
}
return &out, nil
}
@@ -278,6 +293,7 @@ func (s *state0) Info() (MinerInfo, error) {
SealProofType: info.SealProofType,
SectorSize: info.SectorSize,
WindowPoStPartitionSectors: info.WindowPoStPartitionSectors,
ConsensusFaultElapsed: -1,
}
if info.PendingWorkerKey != nil {
+407
View File
@@ -0,0 +1,407 @@
package miner
import (
"bytes"
"errors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/dline"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors/adt"
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt"
)
var _ State = (*state2)(nil)
func load2(store adt.Store, root cid.Cid) (State, error) {
out := state2{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state2 struct {
miner2.State
store adt.Store
}
type deadline2 struct {
miner2.Deadline
store adt.Store
}
type partition2 struct {
miner2.Partition
store adt.Store
}
func (s *state2) AvailableBalance(bal abi.TokenAmount) (abi.TokenAmount, error) {
return s.GetAvailableBalance(bal)
}
func (s *state2) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) {
return s.CheckVestedFunds(s.store, epoch)
}
func (s *state2) LockedFunds() (LockedFunds, error) {
return LockedFunds{
VestingFunds: s.State.LockedFunds,
InitialPledgeRequirement: s.State.InitialPledge,
PreCommitDeposits: s.State.PreCommitDeposits,
}, nil
}
func (s *state2) FeeDebt() (abi.TokenAmount, error) {
return s.State.FeeDebt, nil
}
func (s *state2) InitialPledge() (abi.TokenAmount, error) {
return s.State.InitialPledge, nil
}
func (s *state2) PreCommitDeposits() (abi.TokenAmount, error) {
return s.State.PreCommitDeposits, nil
}
func (s *state2) GetSector(num abi.SectorNumber) (*SectorOnChainInfo, error) {
info, ok, err := s.State.GetSector(s.store, num)
if !ok || err != nil {
return nil, err
}
ret := fromV2SectorOnChainInfo(*info)
return &ret, nil
}
func (s *state2) FindSector(num abi.SectorNumber) (*SectorLocation, error) {
dlIdx, partIdx, err := s.State.FindSector(s.store, num)
if err != nil {
return nil, err
}
return &SectorLocation{
Deadline: dlIdx,
Partition: partIdx,
}, nil
}
func (s *state2) NumLiveSectors() (uint64, error) {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return 0, err
}
var total uint64
if err := dls.ForEach(s.store, func(dlIdx uint64, dl *miner2.Deadline) error {
total += dl.LiveSectors
return nil
}); err != nil {
return 0, err
}
return total, nil
}
// GetSectorExpiration returns the effective expiration of the given sector.
//
// If the sector does not expire early, the Early expiration field is 0.
func (s *state2) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, error) {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return nil, err
}
// NOTE: this can be optimized significantly.
// 1. If the sector is non-faulty, it will either expire on-time (can be
// learned from the sector info), or in the next quantized expiration
// epoch (i.e., the first element in the partition's expiration queue.
// 2. If it's faulty, it will expire early within the first 14 entries
// of the expiration queue.
stopErr := errors.New("stop")
out := SectorExpiration{}
err = dls.ForEach(s.store, func(dlIdx uint64, dl *miner2.Deadline) error {
partitions, err := dl.PartitionsArray(s.store)
if err != nil {
return err
}
quant := s.State.QuantSpecForDeadline(dlIdx)
var part miner2.Partition
return partitions.ForEach(&part, func(partIdx int64) error {
if found, err := part.Sectors.IsSet(uint64(num)); err != nil {
return err
} else if !found {
return nil
}
if found, err := part.Terminated.IsSet(uint64(num)); err != nil {
return err
} else if found {
// already terminated
return stopErr
}
q, err := miner2.LoadExpirationQueue(s.store, part.ExpirationsEpochs, quant)
if err != nil {
return err
}
var exp miner2.ExpirationSet
return q.ForEach(&exp, func(epoch int64) error {
if early, err := exp.EarlySectors.IsSet(uint64(num)); err != nil {
return err
} else if early {
out.Early = abi.ChainEpoch(epoch)
return nil
}
if onTime, err := exp.OnTimeSectors.IsSet(uint64(num)); err != nil {
return err
} else if onTime {
out.OnTime = abi.ChainEpoch(epoch)
return stopErr
}
return nil
})
})
})
if err == stopErr {
err = nil
}
if err != nil {
return nil, err
}
if out.Early == 0 && out.OnTime == 0 {
return nil, xerrors.Errorf("failed to find sector %d", num)
}
return &out, nil
}
func (s *state2) GetPrecommittedSector(num abi.SectorNumber) (*SectorPreCommitOnChainInfo, error) {
info, ok, err := s.State.GetPrecommittedSector(s.store, num)
if !ok || err != nil {
return nil, err
}
ret := fromV2SectorPreCommitOnChainInfo(*info)
return &ret, nil
}
func (s *state2) LoadSectors(snos *bitfield.BitField) ([]*SectorOnChainInfo, error) {
sectors, err := miner2.LoadSectors(s.store, s.State.Sectors)
if err != nil {
return nil, err
}
// If no sector numbers are specified, load all.
if snos == nil {
infos := make([]*SectorOnChainInfo, 0, sectors.Length())
var info2 miner2.SectorOnChainInfo
if err := sectors.ForEach(&info2, func(_ int64) error {
info := fromV2SectorOnChainInfo(info2)
infos = append(infos, &info)
return nil
}); err != nil {
return nil, err
}
return infos, nil
}
// Otherwise, load selected.
infos2, err := sectors.Load(*snos)
if err != nil {
return nil, err
}
infos := make([]*SectorOnChainInfo, len(infos2))
for i, info2 := range infos2 {
info := fromV2SectorOnChainInfo(*info2)
infos[i] = &info
}
return infos, nil
}
func (s *state2) IsAllocated(num abi.SectorNumber) (bool, error) {
var allocatedSectors bitfield.BitField
if err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors); err != nil {
return false, err
}
return allocatedSectors.IsSet(uint64(num))
}
func (s *state2) LoadDeadline(idx uint64) (Deadline, error) {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return nil, err
}
dl, err := dls.LoadDeadline(s.store, idx)
if err != nil {
return nil, err
}
return &deadline2{*dl, s.store}, nil
}
func (s *state2) ForEachDeadline(cb func(uint64, Deadline) error) error {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return err
}
return dls.ForEach(s.store, func(i uint64, dl *miner2.Deadline) error {
return cb(i, &deadline2{*dl, s.store})
})
}
func (s *state2) NumDeadlines() (uint64, error) {
return miner2.WPoStPeriodDeadlines, nil
}
func (s *state2) DeadlinesChanged(other State) (bool, error) {
other2, ok := other.(*state2)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return s.State.Deadlines.Equals(other2.Deadlines), nil
}
func (s *state2) Info() (MinerInfo, error) {
info, err := s.State.GetInfo(s.store)
if err != nil {
return MinerInfo{}, err
}
var pid *peer.ID
if peerID, err := peer.IDFromBytes(info.PeerId); err == nil {
pid = &peerID
}
mi := MinerInfo{
Owner: info.Owner,
Worker: info.Worker,
ControlAddresses: info.ControlAddresses,
NewWorker: address.Undef,
WorkerChangeEpoch: -1,
PeerId: pid,
Multiaddrs: info.Multiaddrs,
SealProofType: info.SealProofType,
SectorSize: info.SectorSize,
WindowPoStPartitionSectors: info.WindowPoStPartitionSectors,
ConsensusFaultElapsed: info.ConsensusFaultElapsed,
}
if info.PendingWorkerKey != nil {
mi.NewWorker = info.PendingWorkerKey.NewWorker
mi.WorkerChangeEpoch = info.PendingWorkerKey.EffectiveAt
}
return mi, nil
}
func (s *state2) DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error) {
return s.State.DeadlineInfo(epoch), nil
}
func (s *state2) sectors() (adt.Array, error) {
return adt2.AsArray(s.store, s.Sectors)
}
func (s *state2) decodeSectorOnChainInfo(val *cbg.Deferred) (SectorOnChainInfo, error) {
var si miner2.SectorOnChainInfo
err := si.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return SectorOnChainInfo{}, err
}
return fromV2SectorOnChainInfo(si), nil
}
func (s *state2) precommits() (adt.Map, error) {
return adt2.AsMap(s.store, s.PreCommittedSectors)
}
func (s *state2) decodeSectorPreCommitOnChainInfo(val *cbg.Deferred) (SectorPreCommitOnChainInfo, error) {
var sp miner2.SectorPreCommitOnChainInfo
err := sp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return SectorPreCommitOnChainInfo{}, err
}
return fromV2SectorPreCommitOnChainInfo(sp), nil
}
func (d *deadline2) LoadPartition(idx uint64) (Partition, error) {
p, err := d.Deadline.LoadPartition(d.store, idx)
if err != nil {
return nil, err
}
return &partition2{*p, d.store}, nil
}
func (d *deadline2) ForEachPartition(cb func(uint64, Partition) error) error {
ps, err := d.Deadline.PartitionsArray(d.store)
if err != nil {
return err
}
var part miner2.Partition
return ps.ForEach(&part, func(i int64) error {
return cb(uint64(i), &partition2{part, d.store})
})
}
func (d *deadline2) PartitionsChanged(other Deadline) (bool, error) {
other2, ok := other.(*deadline2)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return d.Deadline.Partitions.Equals(other2.Deadline.Partitions), nil
}
func (d *deadline2) PostSubmissions() (bitfield.BitField, error) {
return d.Deadline.PostSubmissions, nil
}
func (p *partition2) AllSectors() (bitfield.BitField, error) {
return p.Partition.Sectors, nil
}
func (p *partition2) FaultySectors() (bitfield.BitField, error) {
return p.Partition.Faults, nil
}
func (p *partition2) RecoveringSectors() (bitfield.BitField, error) {
return p.Partition.Recoveries, nil
}
func fromV2SectorOnChainInfo(v2 miner2.SectorOnChainInfo) SectorOnChainInfo {
return SectorOnChainInfo{
SectorNumber: v2.SectorNumber,
SealProof: v2.SealProof,
SealedCID: v2.SealedCID,
DealIDs: v2.DealIDs,
Activation: v2.Activation,
Expiration: v2.Expiration,
DealWeight: v2.DealWeight,
VerifiedDealWeight: v2.VerifiedDealWeight,
InitialPledge: v2.InitialPledge,
ExpectedDayReward: v2.ExpectedDayReward,
ExpectedStoragePledge: v2.ExpectedStoragePledge,
}
}
func fromV2SectorPreCommitOnChainInfo(v2 miner2.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo {
return SectorPreCommitOnChainInfo{
Info: (SectorPreCommitInfo)(v2.Info),
PreCommitDeposit: v2.PreCommitDeposit,
PreCommitEpoch: v2.PreCommitEpoch,
DealWeight: v2.DealWeight,
VerifiedDealWeight: v2.VerifiedDealWeight,
}
}
+70
View File
@@ -0,0 +1,70 @@
package multisig
import (
"fmt"
"github.com/minio/blake2b-simd"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
multisig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
)
func Message(version actors.Version, from address.Address) MessageBuilder {
switch version {
case actors.Version0:
return message0{from}
case actors.Version2:
return message2{message0{from}}
default:
panic(fmt.Sprintf("unsupported actors version: %d", version))
}
}
type MessageBuilder interface {
// Create a new multisig with the specified parameters.
Create(signers []address.Address, threshold uint64,
vestingStart, vestingDuration abi.ChainEpoch,
initialAmount abi.TokenAmount) (*types.Message, error)
// Propose a transaction to the given multisig.
Propose(msig, target address.Address, amt abi.TokenAmount,
method abi.MethodNum, params []byte) (*types.Message, error)
// Approve a multisig transaction. The "hash" is optional.
Approve(msig address.Address, txID uint64, hash *ProposalHashData) (*types.Message, error)
// Cancel a multisig transaction. The "hash" is optional.
Cancel(msig address.Address, txID uint64, hash *ProposalHashData) (*types.Message, error)
}
// this type is the same between v0 and v2
type ProposalHashData = multisig2.ProposalHashData
func txnParams(id uint64, data *ProposalHashData) ([]byte, error) {
params := multisig2.TxnIDParams{ID: multisig2.TxnID(id)}
if data != nil {
if data.Requester.Protocol() != address.ID {
return nil, xerrors.Errorf("proposer address must be an ID address, was %s", data.Requester)
}
if data.Value.Sign() == -1 {
return nil, xerrors.Errorf("proposal value must be non-negative, was %s", data.Value)
}
if data.To == address.Undef {
return nil, xerrors.Errorf("proposed destination address must be set")
}
pser, err := data.Serialize()
if err != nil {
return nil, err
}
hash := blake2b.Sum256(pser)
params.ProposalHash = hash[:]
}
return actors.SerializeParams(&params)
}
+142
View File
@@ -0,0 +1,142 @@
package multisig
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
multisig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/actors"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/types"
)
type message0 struct{ from address.Address }
func (m message0) Create(
signers []address.Address, threshold uint64,
unlockStart, unlockDuration abi.ChainEpoch,
initialAmount abi.TokenAmount,
) (*types.Message, error) {
lenAddrs := uint64(len(signers))
if lenAddrs < threshold {
return nil, xerrors.Errorf("cannot require signing of more addresses than provided for multisig")
}
if threshold == 0 {
threshold = lenAddrs
}
if m.from == address.Undef {
return nil, xerrors.Errorf("must provide source address")
}
if unlockStart != 0 {
return nil, xerrors.Errorf("actors v0 does not support a non-zero vesting start time")
}
// Set up constructor parameters for multisig
msigParams := &multisig0.ConstructorParams{
Signers: signers,
NumApprovalsThreshold: threshold,
UnlockDuration: unlockDuration,
}
enc, actErr := actors.SerializeParams(msigParams)
if actErr != nil {
return nil, actErr
}
// new actors are created by invoking 'exec' on the init actor with the constructor params
execParams := &init0.ExecParams{
CodeCID: builtin0.MultisigActorCodeID,
ConstructorParams: enc,
}
enc, actErr = actors.SerializeParams(execParams)
if actErr != nil {
return nil, actErr
}
return &types.Message{
To: init_.Address,
From: m.from,
Method: builtin0.MethodsInit.Exec,
Params: enc,
Value: initialAmount,
}, nil
}
func (m message0) Propose(msig, to address.Address, amt abi.TokenAmount,
method abi.MethodNum, params []byte) (*types.Message, error) {
if msig == address.Undef {
return nil, xerrors.Errorf("must provide a multisig address for proposal")
}
if to == address.Undef {
return nil, xerrors.Errorf("must provide a target address for proposal")
}
if amt.Sign() == -1 {
return nil, xerrors.Errorf("must provide a non-negative amount for proposed send")
}
if m.from == address.Undef {
return nil, xerrors.Errorf("must provide source address")
}
enc, actErr := actors.SerializeParams(&multisig0.ProposeParams{
To: to,
Value: amt,
Method: method,
Params: params,
})
if actErr != nil {
return nil, xerrors.Errorf("failed to serialize parameters: %w", actErr)
}
return &types.Message{
To: msig,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin0.MethodsMultisig.Propose,
Params: enc,
}, nil
}
func (m message0) Approve(msig address.Address, txID uint64, hashData *ProposalHashData) (*types.Message, error) {
enc, err := txnParams(txID, hashData)
if err != nil {
return nil, err
}
return &types.Message{
To: msig,
From: m.from,
Value: types.NewInt(0),
Method: builtin0.MethodsMultisig.Approve,
Params: enc,
}, nil
}
func (m message0) Cancel(msig address.Address, txID uint64, hashData *ProposalHashData) (*types.Message, error) {
enc, err := txnParams(txID, hashData)
if err != nil {
return nil, err
}
return &types.Message{
To: msig,
From: m.from,
Value: types.NewInt(0),
Method: builtin0.MethodsMultisig.Cancel,
Params: enc,
}, nil
}
+71
View File
@@ -0,0 +1,71 @@
package multisig
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init"
multisig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/actors"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/types"
)
type message2 struct{ message0 }
func (m message2) Create(
signers []address.Address, threshold uint64,
unlockStart, unlockDuration abi.ChainEpoch,
initialAmount abi.TokenAmount,
) (*types.Message, error) {
lenAddrs := uint64(len(signers))
if lenAddrs < threshold {
return nil, xerrors.Errorf("cannot require signing of more addresses than provided for multisig")
}
if threshold == 0 {
threshold = lenAddrs
}
if m.from == address.Undef {
return nil, xerrors.Errorf("must provide source address")
}
// Set up constructor parameters for multisig
msigParams := &multisig2.ConstructorParams{
Signers: signers,
NumApprovalsThreshold: threshold,
UnlockDuration: unlockDuration,
StartEpoch: unlockStart,
}
enc, actErr := actors.SerializeParams(msigParams)
if actErr != nil {
return nil, actErr
}
// new actors are created by invoking 'exec' on the init actor with the constructor params
execParams := &init2.ExecParams{
CodeCID: builtin2.MultisigActorCodeID,
ConstructorParams: enc,
}
enc, actErr = actors.SerializeParams(execParams)
if actErr != nil {
return nil, actErr
}
return &types.Message{
To: init_.Address,
From: m.from,
Method: builtin2.MethodsInit.Exec,
Params: enc,
Value: initialAmount,
}, nil
}
@@ -6,23 +6,32 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/ipfs/go-cid"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
func init() {
builtin.RegisterActorState(builtin0.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root)
})
builtin.RegisterActorState(builtin2.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root)
})
}
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
case builtin0.MultisigActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
return load0(store, act.Head)
case builtin2.MultisigActorCodeID:
return load2(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@@ -5,15 +5,26 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors/adt"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
)
var _ State = (*state0)(nil)
func load0(store adt.Store, root cid.Cid) (State, error) {
out := state0{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state0 struct {
msig0.State
store adt.Store
+70
View File
@@ -0,0 +1,70 @@
package multisig
import (
"encoding/binary"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors/adt"
msig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig"
adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt"
)
var _ State = (*state2)(nil)
func load2(store adt.Store, root cid.Cid) (State, error) {
out := state2{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state2 struct {
msig2.State
store adt.Store
}
func (s *state2) LockedBalance(currEpoch abi.ChainEpoch) (abi.TokenAmount, error) {
return s.State.AmountLocked(currEpoch - s.State.StartEpoch), nil
}
func (s *state2) StartEpoch() (abi.ChainEpoch, error) {
return s.State.StartEpoch, nil
}
func (s *state2) UnlockDuration() (abi.ChainEpoch, error) {
return s.State.UnlockDuration, nil
}
func (s *state2) InitialBalance() (abi.TokenAmount, error) {
return s.State.InitialBalance, nil
}
func (s *state2) Threshold() (uint64, error) {
return s.State.NumApprovalsThreshold, nil
}
func (s *state2) Signers() ([]address.Address, error) {
return s.State.Signers, nil
}
func (s *state2) ForEachPendingTxn(cb func(id int64, txn Transaction) error) error {
arr, err := adt2.AsMap(s.store, s.State.PendingTxns)
if err != nil {
return err
}
var out msig2.Transaction
return arr.ForEach(&out, func(key string) error {
txid, n := binary.Varint([]byte(key))
if n <= 0 {
return xerrors.Errorf("invalid pending transaction key: %v", key)
}
return cb(txid, (Transaction)(out))
})
}
+28
View File
@@ -0,0 +1,28 @@
package paych
import (
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
)
func Message(version actors.Version, from address.Address) MessageBuilder {
switch version {
case actors.Version0:
return message0{from}
case actors.Version2:
return message2{from}
default:
panic(fmt.Sprintf("unsupported actors version: %d", version))
}
}
type MessageBuilder interface {
Create(to address.Address, initialAmount abi.TokenAmount) (*types.Message, error)
Update(paych address.Address, voucher *SignedVoucher, secret []byte) (*types.Message, error)
Settle(paych address.Address) (*types.Message, error)
Collect(paych address.Address) (*types.Message, error)
}
+74
View File
@@ -0,0 +1,74 @@
package paych
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/actors"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/types"
)
type message0 struct{ from address.Address }
func (m message0) Create(to address.Address, initialAmount abi.TokenAmount) (*types.Message, error) {
params, aerr := actors.SerializeParams(&paych0.ConstructorParams{From: m.from, To: to})
if aerr != nil {
return nil, aerr
}
enc, aerr := actors.SerializeParams(&init0.ExecParams{
CodeCID: builtin0.PaymentChannelActorCodeID,
ConstructorParams: params,
})
if aerr != nil {
return nil, aerr
}
return &types.Message{
To: init_.Address,
From: m.from,
Value: initialAmount,
Method: builtin0.MethodsInit.Exec,
Params: enc,
}, nil
}
func (m message0) Update(paych address.Address, sv *SignedVoucher, secret []byte) (*types.Message, error) {
params, aerr := actors.SerializeParams(&paych0.UpdateChannelStateParams{
Sv: *sv,
Secret: secret,
})
if aerr != nil {
return nil, aerr
}
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin0.MethodsPaych.UpdateChannelState,
Params: params,
}, nil
}
func (m message0) Settle(paych address.Address) (*types.Message, error) {
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin0.MethodsPaych.Settle,
}, nil
}
func (m message0) Collect(paych address.Address) (*types.Message, error) {
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin0.MethodsPaych.Collect,
}, nil
}
+74
View File
@@ -0,0 +1,74 @@
package paych
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init"
paych2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/actors"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/types"
)
type message2 struct{ from address.Address }
func (m message2) Create(to address.Address, initialAmount abi.TokenAmount) (*types.Message, error) {
params, aerr := actors.SerializeParams(&paych2.ConstructorParams{From: m.from, To: to})
if aerr != nil {
return nil, aerr
}
enc, aerr := actors.SerializeParams(&init2.ExecParams{
CodeCID: builtin2.PaymentChannelActorCodeID,
ConstructorParams: params,
})
if aerr != nil {
return nil, aerr
}
return &types.Message{
To: init_.Address,
From: m.from,
Value: initialAmount,
Method: builtin2.MethodsInit.Exec,
Params: enc,
}, nil
}
func (m message2) Update(paych address.Address, sv *SignedVoucher, secret []byte) (*types.Message, error) {
params, aerr := actors.SerializeParams(&paych2.UpdateChannelStateParams{
Sv: *sv,
Secret: secret,
})
if aerr != nil {
return nil, aerr
}
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin2.MethodsPaych.UpdateChannelState,
Params: params,
}, nil
}
func (m message2) Settle(paych address.Address) (*types.Message, error) {
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin2.MethodsPaych.Settle,
}, nil
}
func (m message2) Collect(paych address.Address) (*types.Message, error) {
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin2.MethodsPaych.Collect,
}, nil
}
+1 -2
View File
@@ -27,10 +27,9 @@ type mockLaneState struct {
func NewMockPayChState(from address.Address,
to address.Address,
settlingAt abi.ChainEpoch,
toSend abi.TokenAmount,
lanes map[uint64]paych.LaneState,
) paych.State {
return &mockState{from, to, settlingAt, toSend, lanes}
return &mockState{from: from, to: to, settlingAt: settlingAt, toSend: big.NewInt(0), lanes: lanes}
}
// NewMockLaneState constructs a state for a payment channel lane with the set fixed values
@@ -1,29 +1,42 @@
package paych
import (
"encoding/base64"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
big "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/ipfs/go-cid"
ipldcbor "github.com/ipfs/go-ipld-cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
func init() {
builtin.RegisterActorState(builtin0.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root)
})
builtin.RegisterActorState(builtin2.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root)
})
}
// Load returns an abstract copy of payment channel state, irregardless of actor version
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
case builtin0.PaymentChannelActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
return load0(store, act.Head)
case builtin2.PaymentChannelActorCodeID:
return load2(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@@ -58,3 +71,18 @@ type LaneState interface {
type SignedVoucher = paych0.SignedVoucher
type ModVerifyParams = paych0.ModVerifyParams
// DecodeSignedVoucher decodes base64 encoded signed voucher.
func DecodeSignedVoucher(s string) (*SignedVoucher, error) {
data, err := base64.RawURLEncoding.DecodeString(s)
if err != nil {
return nil, err
}
var sv SignedVoucher
if err := ipldcbor.DecodeInto(data, &sv); err != nil {
return nil, err
}
return &sv, nil
}
@@ -1,18 +1,31 @@
package paych
import (
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
big "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
)
var _ State = (*state0)(nil)
func load0(store adt.Store, root cid.Cid) (State, error) {
out := state0{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state0 struct {
paych.State
paych0.State
store adt.Store
lsAmt *adt0.Array
}
@@ -72,14 +85,14 @@ func (s *state0) ForEachLaneState(cb func(idx uint64, dl LaneState) error) error
// Note: we use a map instead of an array to store laneStates because the
// client sets the lane ID (the index) and potentially they could use a
// very large index.
var ls paych.LaneState
var ls paych0.LaneState
return lsamt.ForEach(&ls, func(i int64) error {
return cb(uint64(i), &laneState0{ls})
})
}
type laneState0 struct {
paych.LaneState
paych0.LaneState
}
func (ls *laneState0) Redeemed() (big.Int, error) {
+104
View File
@@ -0,0 +1,104 @@
package paych
import (
"github.com/ipfs/go-cid"
"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/lotus/chain/actors/adt"
paych2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/paych"
adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt"
)
var _ State = (*state2)(nil)
func load2(store adt.Store, root cid.Cid) (State, error) {
out := state2{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state2 struct {
paych2.State
store adt.Store
lsAmt *adt2.Array
}
// Channel owner, who has funded the actor
func (s *state2) From() (address.Address, error) {
return s.State.From, nil
}
// Recipient of payouts from channel
func (s *state2) To() (address.Address, error) {
return s.State.To, nil
}
// Height at which the channel can be `Collected`
func (s *state2) SettlingAt() (abi.ChainEpoch, error) {
return s.State.SettlingAt, nil
}
// Amount successfully redeemed through the payment channel, paid out on `Collect()`
func (s *state2) ToSend() (abi.TokenAmount, error) {
return s.State.ToSend, nil
}
func (s *state2) getOrLoadLsAmt() (*adt2.Array, error) {
if s.lsAmt != nil {
return s.lsAmt, nil
}
// Get the lane state from the chain
lsamt, err := adt2.AsArray(s.store, s.State.LaneStates)
if err != nil {
return nil, err
}
s.lsAmt = lsamt
return lsamt, nil
}
// Get total number of lanes
func (s *state2) LaneCount() (uint64, error) {
lsamt, err := s.getOrLoadLsAmt()
if err != nil {
return 0, err
}
return lsamt.Length(), nil
}
// Iterate lane states
func (s *state2) ForEachLaneState(cb func(idx uint64, dl LaneState) error) error {
// Get the lane state from the chain
lsamt, err := s.getOrLoadLsAmt()
if err != nil {
return err
}
// Note: we use a map instead of an array to store laneStates because the
// client sets the lane ID (the index) and potentially they could use a
// very large index.
var ls paych2.LaneState
return lsamt.ForEach(&ls, func(i int64) error {
return cb(uint64(i), &laneState2{ls})
})
}
type laneState2 struct {
paych2.LaneState
}
func (ls *laneState2) Redeemed() (big.Int, error) {
return ls.LaneState.Redeemed, nil
}
func (ls *laneState2) Nonce() (uint64, error) {
return ls.LaneState.Nonce, nil
}
+17 -7
View File
@@ -2,28 +2,37 @@ package power
import (
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
)
func init() {
builtin.RegisterActorState(builtin0.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root)
})
builtin.RegisterActorState(builtin2.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root)
})
}
var Address = builtin0.StoragePowerActorAddr
func Load(store adt.Store, act *types.Actor) (st State, err error) {
switch act.Code {
case builtin0.StoragePowerActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
return load0(store, act.Head)
case builtin2.StoragePowerActorCodeID:
return load2(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@@ -42,6 +51,7 @@ type State interface {
MinerPower(address.Address) (Claim, bool, error)
MinerNominalPowerMeetsConsensusMinimum(address.Address) (bool, error)
ListAllMiners() ([]address.Address, error)
ForEachClaim(func(miner address.Address, claim Claim) error) error
}
type Claim struct {
+35 -3
View File
@@ -3,13 +3,26 @@ package power
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/util/adt"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
)
var _ State = (*state0)(nil)
func load0(store adt.Store, root cid.Cid) (State, error) {
out := state0{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state0 struct {
power0.State
store adt.Store
@@ -35,7 +48,7 @@ func (s *state0) TotalCommitted() (Claim, error) {
}
func (s *state0) MinerPower(addr address.Address) (Claim, bool, error) {
claims, err := adt.AsMap(s.store, s.Claims)
claims, err := adt0.AsMap(s.store, s.Claims)
if err != nil {
return Claim{}, false, err
}
@@ -63,7 +76,7 @@ func (s *state0) MinerCounts() (uint64, uint64, error) {
}
func (s *state0) ListAllMiners() ([]address.Address, error) {
claims, err := adt.AsMap(s.store, s.Claims)
claims, err := adt0.AsMap(s.store, s.Claims)
if err != nil {
return nil, err
}
@@ -83,3 +96,22 @@ func (s *state0) ListAllMiners() ([]address.Address, error) {
return miners, nil
}
func (s *state0) ForEachClaim(cb func(miner address.Address, claim Claim) error) error {
claims, err := adt0.AsMap(s.store, s.Claims)
if err != nil {
return err
}
var claim power0.Claim
return claims.ForEach(&claim, func(k string) error {
a, err := address.NewFromBytes([]byte(k))
if err != nil {
return err
}
return cb(a, Claim{
RawBytePower: claim.RawBytePower,
QualityAdjPower: claim.QualityAdjPower,
})
})
}
+117
View File
@@ -0,0 +1,117 @@
package power
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
power2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/power"
adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt"
)
var _ State = (*state2)(nil)
func load2(store adt.Store, root cid.Cid) (State, error) {
out := state2{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state2 struct {
power2.State
store adt.Store
}
func (s *state2) TotalLocked() (abi.TokenAmount, error) {
return s.TotalPledgeCollateral, nil
}
func (s *state2) TotalPower() (Claim, error) {
return Claim{
RawBytePower: s.TotalRawBytePower,
QualityAdjPower: s.TotalQualityAdjPower,
}, nil
}
// Committed power to the network. Includes miners below the minimum threshold.
func (s *state2) TotalCommitted() (Claim, error) {
return Claim{
RawBytePower: s.TotalBytesCommitted,
QualityAdjPower: s.TotalQABytesCommitted,
}, nil
}
func (s *state2) MinerPower(addr address.Address) (Claim, bool, error) {
claims, err := adt2.AsMap(s.store, s.Claims)
if err != nil {
return Claim{}, false, err
}
var claim power2.Claim
ok, err := claims.Get(abi.AddrKey(addr), &claim)
if err != nil {
return Claim{}, false, err
}
return Claim{
RawBytePower: claim.RawBytePower,
QualityAdjPower: claim.QualityAdjPower,
}, ok, nil
}
func (s *state2) MinerNominalPowerMeetsConsensusMinimum(a address.Address) (bool, error) {
return s.State.MinerNominalPowerMeetsConsensusMinimum(s.store, a)
}
func (s *state2) TotalPowerSmoothed() (builtin.FilterEstimate, error) {
return builtin.FromV2FilterEstimate(s.State.ThisEpochQAPowerSmoothed), nil
}
func (s *state2) MinerCounts() (uint64, uint64, error) {
return uint64(s.State.MinerAboveMinPowerCount), uint64(s.State.MinerCount), nil
}
func (s *state2) ListAllMiners() ([]address.Address, error) {
claims, err := adt2.AsMap(s.store, s.Claims)
if err != nil {
return nil, err
}
var miners []address.Address
err = claims.ForEach(nil, func(k string) error {
a, err := address.NewFromBytes([]byte(k))
if err != nil {
return err
}
miners = append(miners, a)
return nil
})
if err != nil {
return nil, err
}
return miners, nil
}
func (s *state2) ForEachClaim(cb func(miner address.Address, claim Claim) error) error {
claims, err := adt2.AsMap(s.store, s.Claims)
if err != nil {
return err
}
var claim power2.Claim
return claims.ForEach(&claim, func(k string) error {
a, err := address.NewFromBytes([]byte(k))
if err != nil {
return err
}
return cb(a, Claim{
RawBytePower: claim.RawBytePower,
QualityAdjPower: claim.QualityAdjPower,
})
})
}
+14 -6
View File
@@ -3,27 +3,35 @@ package reward
import (
"github.com/filecoin-project/go-state-types/abi"
reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
func init() {
builtin.RegisterActorState(builtin0.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root)
})
builtin.RegisterActorState(builtin2.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root)
})
}
var Address = builtin0.RewardActorAddr
func Load(store adt.Store, act *types.Actor) (st State, err error) {
switch act.Code {
case builtin0.RewardActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
return load0(store, act.Head)
case builtin2.RewardActorCodeID:
return load2(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
+19 -7
View File
@@ -2,17 +2,29 @@ package reward
import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/specs-actors/actors/util/smoothing"
reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward"
smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing"
)
var _ State = (*state0)(nil)
func load0(store adt.Store, root cid.Cid) (State, error) {
out := state0{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state0 struct {
reward.State
reward0.State
store adt.Store
}
@@ -45,7 +57,7 @@ func (s *state0) CumsumBaseline() (abi.StoragePower, error) {
}
func (s *state0) CumsumRealized() (abi.StoragePower, error) {
return s.State.CumsumBaseline, nil
return s.State.CumsumRealized, nil
}
func (s *state0) InitialPledgeForPower(sectorWeight abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) {
@@ -54,7 +66,7 @@ func (s *state0) InitialPledgeForPower(sectorWeight abi.StoragePower, networkTot
s.State.ThisEpochBaselinePower,
networkTotalPledge,
s.State.ThisEpochRewardSmoothed,
&smoothing.FilterEstimate{
&smoothing0.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
},
@@ -63,7 +75,7 @@ func (s *state0) InitialPledgeForPower(sectorWeight abi.StoragePower, networkTot
func (s *state0) PreCommitDepositForPower(networkQAPower builtin.FilterEstimate, sectorWeight abi.StoragePower) (abi.TokenAmount, error) {
return miner0.PreCommitDepositForPower(s.State.ThisEpochRewardSmoothed,
&smoothing.FilterEstimate{
&smoothing0.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
},
+86
View File
@@ -0,0 +1,86 @@
package reward
import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
reward2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/reward"
smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing"
)
var _ State = (*state2)(nil)
func load2(store adt.Store, root cid.Cid) (State, error) {
out := state2{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state2 struct {
reward2.State
store adt.Store
}
func (s *state2) ThisEpochReward() (abi.StoragePower, error) {
return s.State.ThisEpochReward, nil
}
func (s *state2) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) {
return builtin.FilterEstimate{
PositionEstimate: s.State.ThisEpochRewardSmoothed.PositionEstimate,
VelocityEstimate: s.State.ThisEpochRewardSmoothed.VelocityEstimate,
}, nil
}
func (s *state2) ThisEpochBaselinePower() (abi.StoragePower, error) {
return s.State.ThisEpochBaselinePower, nil
}
func (s *state2) TotalStoragePowerReward() (abi.TokenAmount, error) {
return s.State.TotalStoragePowerReward, nil
}
func (s *state2) EffectiveBaselinePower() (abi.StoragePower, error) {
return s.State.EffectiveBaselinePower, nil
}
func (s *state2) EffectiveNetworkTime() (abi.ChainEpoch, error) {
return s.State.EffectiveNetworkTime, nil
}
func (s *state2) CumsumBaseline() (abi.StoragePower, error) {
return s.State.CumsumBaseline, nil
}
func (s *state2) CumsumRealized() (abi.StoragePower, error) {
return s.State.CumsumRealized, nil
}
func (s *state2) InitialPledgeForPower(qaPower abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) {
return miner2.InitialPledgeForPower(
qaPower,
s.State.ThisEpochBaselinePower,
s.State.ThisEpochRewardSmoothed,
smoothing2.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
},
circSupply,
), nil
}
func (s *state2) PreCommitDepositForPower(networkQAPower builtin.FilterEstimate, sectorWeight abi.StoragePower) (abi.TokenAmount, error) {
return miner2.PreCommitDepositForPower(s.State.ThisEpochRewardSmoothed,
smoothing2.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
},
sectorWeight), nil
}
+46
View File
@@ -0,0 +1,46 @@
package verifreg
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/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
)
func getDataCap(store adt.Store, ver actors.Version, root cid.Cid, addr address.Address) (bool, abi.StoragePower, error) {
if addr.Protocol() != address.ID {
return false, big.Zero(), xerrors.Errorf("can only look up ID addresses")
}
vh, err := adt.AsMap(store, root, ver)
if err != nil {
return false, big.Zero(), xerrors.Errorf("loading verifreg: %w", err)
}
var dcap abi.StoragePower
if found, err := vh.Get(abi.AddrKey(addr), &dcap); err != nil {
return false, big.Zero(), xerrors.Errorf("looking up addr: %w", err)
} else if !found {
return false, big.Zero(), nil
}
return true, dcap, nil
}
func forEachCap(store adt.Store, ver actors.Version, root cid.Cid, cb func(addr address.Address, dcap abi.StoragePower) error) error {
vh, err := adt.AsMap(store, root, ver)
if err != nil {
return xerrors.Errorf("loading verified clients: %w", err)
}
var dcap abi.StoragePower
return vh.ForEach(&dcap, func(key string) error {
a, err := address.NewFromBytes([]byte(key))
if err != nil {
return err
}
return cb(a, dcap)
})
}
+18 -41
View File
@@ -3,69 +3,46 @@ package verifreg
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
)
var _ State = (*state0)(nil)
func load0(store adt.Store, root cid.Cid) (State, error) {
out := state0{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state0 struct {
verifreg0.State
store adt.Store
}
func getDataCap(store adt.Store, root cid.Cid, addr address.Address) (bool, abi.StoragePower, error) {
if addr.Protocol() != address.ID {
return false, big.Zero(), xerrors.Errorf("can only look up ID addresses")
}
vh, err := adt0.AsMap(store, root)
if err != nil {
return false, big.Zero(), xerrors.Errorf("loading verifreg: %w", err)
}
var dcap abi.StoragePower
if found, err := vh.Get(abi.AddrKey(addr), &dcap); err != nil {
return false, big.Zero(), xerrors.Errorf("looking up addr: %w", err)
} else if !found {
return false, big.Zero(), nil
}
return true, dcap, nil
func (s *state0) RootKey() (address.Address, error) {
return s.State.RootKey, nil
}
func (s *state0) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) {
return getDataCap(s.store, s.State.VerifiedClients, addr)
return getDataCap(s.store, actors.Version0, s.State.VerifiedClients, addr)
}
func (s *state0) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) {
return getDataCap(s.store, s.State.Verifiers, addr)
}
func forEachCap(store adt.Store, root cid.Cid, cb func(addr address.Address, dcap abi.StoragePower) error) error {
vh, err := adt0.AsMap(store, root)
if err != nil {
return xerrors.Errorf("loading verified clients: %w", err)
}
var dcap abi.StoragePower
return vh.ForEach(&dcap, func(key string) error {
a, err := address.NewFromBytes([]byte(key))
if err != nil {
return err
}
return cb(a, dcap)
})
return getDataCap(s.store, actors.Version0, s.State.Verifiers, addr)
}
func (s *state0) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error {
return forEachCap(s.store, s.State.Verifiers, cb)
return forEachCap(s.store, actors.Version0, s.State.Verifiers, cb)
}
func (s *state0) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error {
return forEachCap(s.store, s.State.VerifiedClients, cb)
return forEachCap(s.store, actors.Version0, s.State.VerifiedClients, cb)
}
+48
View File
@@ -0,0 +1,48 @@
package verifreg
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt"
verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg"
)
var _ State = (*state2)(nil)
func load2(store adt.Store, root cid.Cid) (State, error) {
out := state2{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state2 struct {
verifreg2.State
store adt.Store
}
func (s *state2) RootKey() (address.Address, error) {
return s.State.RootKey, nil
}
func (s *state2) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) {
return getDataCap(s.store, actors.Version2, s.State.VerifiedClients, addr)
}
func (s *state2) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) {
return getDataCap(s.store, actors.Version2, s.State.Verifiers, addr)
}
func (s *state2) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error {
return forEachCap(s.store, actors.Version2, s.State.Verifiers, cb)
}
func (s *state2) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error {
return forEachCap(s.store, actors.Version2, s.State.VerifiedClients, cb)
}
+16 -6
View File
@@ -3,26 +3,35 @@ package verifreg
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
func init() {
builtin.RegisterActorState(builtin0.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root)
})
builtin.RegisterActorState(builtin2.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root)
})
}
var Address = builtin0.VerifiedRegistryActorAddr
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
case builtin0.VerifiedRegistryActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
return load0(store, act.Head)
case builtin2.VerifiedRegistryActorCodeID:
return load2(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@@ -30,6 +39,7 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
type State interface {
cbor.Marshaler
RootKey() (address.Address, error)
VerifiedClientDataCap(address.Address) (bool, abi.StoragePower, error)
VerifierDataCap(address.Address) (bool, abi.StoragePower, error)
ForEachVerifier(func(addr address.Address, dcap abi.StoragePower) error) error
+116
View File
@@ -0,0 +1,116 @@
package policy
import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market"
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg"
)
const (
ChainFinality = miner0.ChainFinality
SealRandomnessLookback = ChainFinality
)
// SetSupportedProofTypes sets supported proof types, across all actor versions.
// This should only be used for testing.
func SetSupportedProofTypes(types ...abi.RegisteredSealProof) {
newTypes := make(map[abi.RegisteredSealProof]struct{}, len(types))
for _, t := range types {
newTypes[t] = struct{}{}
}
// Set for all miner versions.
miner0.SupportedProofTypes = newTypes
miner2.SupportedProofTypes = newTypes
}
// AddSupportedProofTypes sets supported proof types, across all actor versions.
// This should only be used for testing.
func AddSupportedProofTypes(types ...abi.RegisteredSealProof) {
for _, t := range types {
// Set for all miner versions.
miner0.SupportedProofTypes[t] = struct{}{}
miner2.SupportedProofTypes[t] = struct{}{}
}
}
// SetPreCommitChallengeDelay sets the pre-commit challenge delay across all
// actors versions. Use for testing.
func SetPreCommitChallengeDelay(delay abi.ChainEpoch) {
// Set for all miner versions.
miner0.PreCommitChallengeDelay = delay
miner2.PreCommitChallengeDelay = delay
}
// TODO: this function shouldn't really exist. Instead, the API should expose the precommit delay.
func GetPreCommitChallengeDelay() abi.ChainEpoch {
return miner0.PreCommitChallengeDelay
}
// SetConsensusMinerMinPower sets the minimum power of an individual miner must
// meet for leader election, across all actor versions. This should only be used
// for testing.
func SetConsensusMinerMinPower(p abi.StoragePower) {
power0.ConsensusMinerMinPower = p
for _, policy := range builtin2.SealProofPolicies {
policy.ConsensusMinerMinPower = p
}
}
// SetMinVerifiedDealSize sets the minimum size of a verified deal. This should
// only be used for testing.
func SetMinVerifiedDealSize(size abi.StoragePower) {
verifreg0.MinVerifiedDealSize = size
verifreg2.MinVerifiedDealSize = size
}
func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) abi.ChainEpoch {
switch ver {
case actors.Version0:
return miner0.MaxSealDuration[t]
case actors.Version2:
return miner2.MaxProveCommitDuration[t]
default:
panic("unsupported actors version")
}
}
func DealProviderCollateralBounds(
size abi.PaddedPieceSize, verified bool,
rawBytePower, qaPower, baselinePower abi.StoragePower,
circulatingFil abi.TokenAmount, nwVer network.Version,
) (min, max abi.TokenAmount) {
switch actors.VersionForNetwork(nwVer) {
case actors.Version0:
return market0.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil, nwVer)
case actors.Version2:
return market2.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil)
default:
panic("unsupported network version")
}
}
// Sets the challenge window and scales the proving period to match (such that
// there are always 48 challenge windows in a proving period).
func SetWPoStChallengeWindow(period abi.ChainEpoch) {
miner0.WPoStChallengeWindow = period
miner0.WPoStProvingPeriod = period * abi.ChainEpoch(miner0.WPoStPeriodDeadlines)
miner2.WPoStChallengeWindow = period
miner2.WPoStProvingPeriod = period * abi.ChainEpoch(miner2.WPoStPeriodDeadlines)
}
func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch {
if nwVer <= network.Version3 {
return 10
}
return ChainFinality
}
+50
View File
@@ -0,0 +1,50 @@
package policy
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-state-types/abi"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg"
)
func TestSupportedProofTypes(t *testing.T) {
var oldTypes []abi.RegisteredSealProof
for t := range miner0.SupportedProofTypes {
oldTypes = append(oldTypes, t)
}
t.Cleanup(func() {
SetSupportedProofTypes(oldTypes...)
})
SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
require.EqualValues(t,
miner0.SupportedProofTypes,
map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
},
)
AddSupportedProofTypes(abi.RegisteredSealProof_StackedDrg8MiBV1)
require.EqualValues(t,
miner0.SupportedProofTypes,
map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
abi.RegisteredSealProof_StackedDrg8MiBV1: {},
},
)
}
// Tests assumptions about policies being the same between actor versions.
func TestAssumptions(t *testing.T) {
require.EqualValues(t, miner0.SupportedProofTypes, miner2.SupportedProofTypes)
require.Equal(t, miner0.PreCommitChallengeDelay, miner2.PreCommitChallengeDelay)
require.Equal(t, miner0.ChainFinality, miner2.ChainFinality)
require.Equal(t, miner0.WPoStChallengeWindow, miner2.WPoStChallengeWindow)
require.Equal(t, miner0.WPoStProvingPeriod, miner2.WPoStProvingPeriod)
require.Equal(t, miner0.WPoStPeriodDeadlines, miner2.WPoStPeriodDeadlines)
require.True(t, verifreg0.MinVerifiedDealSize.Equals(verifreg2.MinVerifiedDealSize))
}
+26
View File
@@ -0,0 +1,26 @@
package actors
import (
"fmt"
"github.com/filecoin-project/go-state-types/network"
)
type Version int
const (
Version0 Version = 0
Version2 Version = 2
)
// Converts a network version into an actors adt version.
func VersionForNetwork(version network.Version) Version {
switch version {
case network.Version0, network.Version1, network.Version2, network.Version3:
return Version0
case network.Version4, network.Version5:
return Version2
default:
panic(fmt.Sprintf("unsupported network version %d", version))
}
}
+4
View File
@@ -60,6 +60,10 @@ func (bts *BadBlockCache) Remove(c cid.Cid) {
bts.badBlocks.Remove(c)
}
func (bts *BadBlockCache) Purge() {
bts.badBlocks.Purge()
}
func (bts *BadBlockCache) Has(c cid.Cid) (BadBlockReason, bool) {
rval, ok := bts.badBlocks.Get(c)
if !ok {
+3 -3
View File
@@ -581,7 +581,7 @@ func createEmptyMinerState(ctx context.Context, t *testing.T, store adt.Store, o
func createSectorsAMT(ctx context.Context, t *testing.T, store adt.Store, sectors []miner.SectorOnChainInfo) cid.Cid {
root := adt.MakeEmptyArray(store)
for _, sector := range sectors {
sector := sector
sector := (miner0.SectorOnChainInfo)(sector)
err := root.Set(uint64(sector.SectorNumber), &sector)
require.NoError(t, err)
}
@@ -614,8 +614,8 @@ const (
)
// returns a unique SectorPreCommitInfo with each invocation with SectorNumber set to `sectorNo`.
func newSectorPreCommitInfo(sectorNo abi.SectorNumber, sealed cid.Cid, expiration abi.ChainEpoch) *miner.SectorPreCommitInfo {
return &miner.SectorPreCommitInfo{
func newSectorPreCommitInfo(sectorNo abi.SectorNumber, sealed cid.Cid, expiration abi.ChainEpoch) *miner0.SectorPreCommitInfo {
return &miner0.SectorPreCommitInfo{
SealProof: abi.RegisteredSealProof_StackedDrg32GiBV1,
SectorNumber: sectorNo,
SealedCID: sealed,
+24 -2
View File
@@ -2,6 +2,7 @@ package events
import (
"context"
"sync"
"github.com/filecoin-project/go-state-types/abi"
"golang.org/x/xerrors"
@@ -17,6 +18,8 @@ type tsCacheAPI interface {
// tipSetCache implements a simple ring-buffer cache to keep track of recent
// tipsets
type tipSetCache struct {
mu sync.RWMutex
cache []*types.TipSet
start int
len int
@@ -35,6 +38,9 @@ func newTSCache(cap abi.ChainEpoch, storage tsCacheAPI) *tipSetCache {
}
func (tsc *tipSetCache) add(ts *types.TipSet) error {
tsc.mu.Lock()
defer tsc.mu.Unlock()
if tsc.len > 0 {
if tsc.cache[tsc.start].Height() >= ts.Height() {
return xerrors.Errorf("tipSetCache.add: expected new tipset height to be at least %d, was %d", tsc.cache[tsc.start].Height()+1, ts.Height())
@@ -65,6 +71,13 @@ func (tsc *tipSetCache) add(ts *types.TipSet) error {
}
func (tsc *tipSetCache) revert(ts *types.TipSet) error {
tsc.mu.Lock()
defer tsc.mu.Unlock()
return tsc.revertUnlocked(ts)
}
func (tsc *tipSetCache) revertUnlocked(ts *types.TipSet) error {
if tsc.len == 0 {
return nil // this can happen, and it's fine
}
@@ -77,7 +90,7 @@ func (tsc *tipSetCache) revert(ts *types.TipSet) error {
tsc.start = normalModulo(tsc.start-1, len(tsc.cache))
tsc.len--
_ = tsc.revert(nil) // revert null block gap
_ = tsc.revertUnlocked(nil) // revert null block gap
return nil
}
@@ -95,7 +108,10 @@ func (tsc *tipSetCache) getNonNull(height abi.ChainEpoch) (*types.TipSet, error)
}
func (tsc *tipSetCache) get(height abi.ChainEpoch) (*types.TipSet, error) {
tsc.mu.RLock()
if tsc.len == 0 {
tsc.mu.RUnlock()
log.Warnf("tipSetCache.get: cache is empty, requesting from storage (h=%d)", height)
return tsc.storage.ChainGetTipSetByHeight(context.TODO(), height, types.EmptyTSK)
}
@@ -103,6 +119,7 @@ func (tsc *tipSetCache) get(height abi.ChainEpoch) (*types.TipSet, error) {
headH := tsc.cache[tsc.start].Height()
if height > headH {
tsc.mu.RUnlock()
return nil, xerrors.Errorf("tipSetCache.get: requested tipset not in cache (req: %d, cache head: %d)", height, headH)
}
@@ -116,15 +133,20 @@ func (tsc *tipSetCache) get(height abi.ChainEpoch) (*types.TipSet, error) {
}
if height < tail.Height() {
tsc.mu.RUnlock()
log.Warnf("tipSetCache.get: requested tipset not in cache, requesting from storage (h=%d; tail=%d)", height, tail.Height())
return tsc.storage.ChainGetTipSetByHeight(context.TODO(), height, tail.Key())
}
return tsc.cache[normalModulo(tsc.start-int(headH-height), clen)], nil
ts := tsc.cache[normalModulo(tsc.start-int(headH-height), clen)]
tsc.mu.RUnlock()
return ts, nil
}
func (tsc *tipSetCache) best() (*types.TipSet, error) {
tsc.mu.RLock()
best := tsc.cache[tsc.start]
tsc.mu.RUnlock()
if best == nil {
return tsc.storage.ChainHead(context.TODO())
}
+1 -1
View File
@@ -117,7 +117,7 @@ func (c *client) doRequest(
res, err := c.sendRequestToPeer(ctx, peer, req)
if err != nil {
if !xerrors.Is(err, network.ErrNoConn) {
log.Warnf("could not connect to peer %s: %s",
log.Warnf("could not send request to peer %s: %s",
peer.String(), err)
}
continue
+29 -17
View File
@@ -9,12 +9,12 @@ import (
"time"
"github.com/filecoin-project/specs-actors/actors/runtime/proof"
"github.com/google/uuid"
"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"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-blockservice"
"github.com/ipfs/go-cid"
@@ -28,6 +28,7 @@ import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/beacon"
genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/lotus/chain/stmgr"
@@ -38,6 +39,7 @@ import (
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
"github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/journal"
"github.com/filecoin-project/lotus/lib/blockstore"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/node/repo"
@@ -70,7 +72,7 @@ type ChainGen struct {
GetMessages func(*ChainGen) ([]*types.SignedMessage, error)
w *wallet.Wallet
w *wallet.LocalWallet
eppProvs map[address.Address]WinningPoStProver
Miners []address.Address
@@ -121,9 +123,9 @@ var DefaultRemainderAccountActor = genesis.Actor{
}
func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
miner0.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
}
j := journal.NilJournal()
// TODO: we really shouldn't modify a global variable here.
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
mr := repo.NewMemory(nil)
lr, err := mr.Lock(repo.StorageMiner)
@@ -153,14 +155,14 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err)
}
banker, err := w.GenerateKey(crypto.SigTypeSecp256k1)
banker, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
return nil, xerrors.Errorf("failed to generate banker key: %w", err)
}
receievers := make([]address.Address, msgsPerBlock)
for r := range receievers {
receievers[r], err = w.GenerateKey(crypto.SigTypeBLS)
receievers[r], err = w.WalletNew(context.Background(), crypto.SigTypeBLS)
if err != nil {
return nil, xerrors.Errorf("failed to generate receiver key: %w", err)
}
@@ -190,11 +192,11 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
return nil, err
}
mk1, err := w.Import(k1)
mk1, err := w.WalletImport(context.Background(), k1)
if err != nil {
return nil, err
}
mk2, err := w.Import(k2)
mk2, err := w.WalletImport(context.Background(), k2)
if err != nil {
return nil, err
}
@@ -225,16 +227,16 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
},
VerifregRootKey: DefaultVerifregRootkeyActor,
RemainderAccount: DefaultRemainderAccountActor,
NetworkName: "",
NetworkName: uuid.New().String(),
Timestamp: uint64(build.Clock.Now().Add(-500 * time.Duration(build.BlockDelaySecs) * time.Second).Unix()),
}
genb, err := genesis2.MakeGenesisBlock(context.TODO(), bs, sys, tpl)
genb, err := genesis2.MakeGenesisBlock(context.TODO(), j, bs, sys, tpl)
if err != nil {
return nil, xerrors.Errorf("make genesis block failed: %w", err)
}
cs := store.NewChainStore(bs, ds, sys)
cs := store.NewChainStore(bs, ds, sys, j)
genfb := &types.FullBlock{Header: genb.Genesis}
gents := store.NewFullTipSet([]*types.FullBlock{genfb})
@@ -374,7 +376,13 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
return nil, nil, nil, xerrors.Errorf("get miner worker: %w", err)
}
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, ticketRand)
sf := func(ctx context.Context, a address.Address, i []byte) (*crypto.Signature, error) {
return cg.w.WalletSign(ctx, a, i, api.MsgMeta{
Type: api.MTUnknown,
})
}
vrfout, err := ComputeVRF(ctx, sf, worker, ticketRand)
if err != nil {
return nil, nil, nil, xerrors.Errorf("compute VRF: %w", err)
}
@@ -506,7 +514,7 @@ func (cg *ChainGen) Banker() address.Address {
return cg.banker
}
func (cg *ChainGen) Wallet() *wallet.Wallet {
func (cg *ChainGen) Wallet() *wallet.LocalWallet {
return cg.w
}
@@ -528,7 +536,9 @@ func getRandomMessages(cg *ChainGen) ([]*types.SignedMessage, error) {
GasPremium: types.NewInt(0),
}
sig, err := cg.w.Sign(context.TODO(), cg.banker, msg.Cid().Bytes())
sig, err := cg.w.WalletSign(context.TODO(), cg.banker, msg.Cid().Bytes(), api.MsgMeta{
Type: api.MTUnknown, // testing
})
if err != nil {
return nil, err
}
@@ -559,7 +569,7 @@ type MiningCheckAPI interface {
}
type mca struct {
w *wallet.Wallet
w *wallet.LocalWallet
sm *stmgr.StateManager
pv ffiwrapper.Verifier
bcn beacon.Schedule
@@ -588,7 +598,9 @@ func (mca mca) MinerGetBaseInfo(ctx context.Context, maddr address.Address, epoc
}
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*crypto.Signature, error) {
return mca.w.Sign(ctx, a, v)
return mca.w.WalletSign(ctx, a, v, api.MsgMeta{
Type: api.MTUnknown,
})
}
type WinningPoStProver interface {
+4 -9
View File
@@ -4,21 +4,16 @@ import (
"testing"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/lotus/chain/actors/policy"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
)
func init() {
miner0.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
}
power0.ConsensusMinerMinPower = big.NewInt(2048)
verifreg0.MinVerifiedDealSize = big.NewInt(256)
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
}
func testGeneration(t testing.TB, n int, msgs int, sectors int) {
+10 -10
View File
@@ -6,6 +6,9 @@ import (
"encoding/json"
"fmt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/journal"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
cbor "github.com/ipfs/go-ipld-cbor"
@@ -24,7 +27,6 @@ import (
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
@@ -115,7 +117,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
return nil, nil, xerrors.Errorf("putting empty object: %w", err)
}
state, err := state.NewStateTree(cst, builtin.Version0)
state, err := state.NewStateTree(cst, types.StateTreeVersion0)
if err != nil {
return nil, nil, xerrors.Errorf("making new state tree: %w", err)
}
@@ -296,14 +298,9 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
return nil, nil, xerrors.Errorf("somehow overallocated filecoin (allocated = %s)", types.FIL(totalFilAllocated))
}
remAccKey, err := address.NewIDAddress(90)
if err != nil {
return nil, nil, err
}
template.RemainderAccount.Balance = remainingFil
if err := createMultisigAccount(ctx, bs, cst, state, remAccKey, template.RemainderAccount, keyIDs); err != nil {
if err := createMultisigAccount(ctx, bs, cst, state, builtin.ReserveAddress, template.RemainderAccount, keyIDs); err != nil {
return nil, nil, xerrors.Errorf("failed to set up remainder account: %w", err)
}
@@ -470,7 +467,10 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
return st, nil
}
func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys vm.SyscallBuilder, template genesis.Template) (*GenesisBootstrap, error) {
func MakeGenesisBlock(ctx context.Context, j journal.Journal, bs bstore.Blockstore, sys vm.SyscallBuilder, template genesis.Template) (*GenesisBootstrap, error) {
if j == nil {
j = journal.NilJournal()
}
st, keyIDs, err := MakeInitialStateTree(ctx, bs, template)
if err != nil {
return nil, xerrors.Errorf("make initial state tree failed: %w", err)
@@ -482,7 +482,7 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys vm.SyscallB
}
// temp chainstore
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys)
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys, j)
// Verify PreSealed Data
stateroot, err = VerifyPreSealedData(ctx, cs, stateroot, template, keyIDs)
+4 -3
View File
@@ -15,11 +15,10 @@ import (
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/lib/sigs/bls"
)
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, bt *api.BlockTemplate) (*types.FullBlock, error) {
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w api.WalletAPI, bt *api.BlockTemplate) (*types.FullBlock, error) {
pts, err := sm.ChainStore().LoadTipSet(bt.Parents)
if err != nil {
@@ -131,7 +130,9 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
return nil, xerrors.Errorf("failed to get signing bytes for block: %w", err)
}
sig, err := w.Sign(ctx, waddr, nosigbytes)
sig, err := w.WalletSign(ctx, waddr, nosigbytes, api.MsgMeta{
Type: api.MTBlock,
})
if err != nil {
return nil, xerrors.Errorf("failed to sign new block: %w", err)
}
+4
View File
@@ -105,6 +105,10 @@ func checkFault(t ds.Datastore, key ds.Key, bh *types.BlockHeader, faultType str
return err
}
if other == bh.Cid() {
return nil
}
return xerrors.Errorf("produced block would trigger '%s' consensus fault; miner: %s; bh: %s, other: %s", faultType, bh.Miner, bh.Cid(), other)
}
+4 -2
View File
@@ -120,9 +120,10 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
return cid.Undef, err
}
fm.lk.Lock()
defer fm.lk.Unlock()
bal, err := fm.api.StateMarketBalance(ctx, addr, types.EmptyTSK)
if err != nil {
fm.lk.Unlock()
return cid.Undef, err
}
@@ -138,7 +139,6 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
toAdd = types.NewInt(0)
}
fm.available[idAddr] = big.Add(avail, toAdd)
fm.lk.Unlock()
log.Infof("Funds operation w/ Expected Balance: %s, In State: %s, Requested: %s, Adding: %s", avail.String(), stateAvail.String(), amt.String(), toAdd.String())
@@ -148,6 +148,7 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
params, err := actors.SerializeParams(&addr)
if err != nil {
fm.available[idAddr] = avail
return cid.Undef, err
}
@@ -159,6 +160,7 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
Params: params,
}, nil)
if err != nil {
fm.available[idAddr] = avail
return cid.Undef, err
}
+24 -14
View File
@@ -57,9 +57,10 @@ func addFundsMsg(toAdd abi.TokenAmount, addr address.Address, wallet address.Add
}
type expectedResult struct {
addAmt abi.TokenAmount
shouldAdd bool
err error
addAmt abi.TokenAmount
shouldAdd bool
err error
cachedAvailable abi.TokenAmount
}
func TestAddFunds(t *testing.T) {
@@ -88,8 +89,9 @@ func TestAddFunds(t *testing.T) {
addAmounts: []abi.TokenAmount{abi.NewTokenAmount(100)},
expectedResults: []expectedResult{
{
shouldAdd: false,
err: nil,
shouldAdd: false,
err: nil,
cachedAvailable: abi.NewTokenAmount(100),
},
},
},
@@ -102,18 +104,21 @@ func TestAddFunds(t *testing.T) {
err: nil,
},
{
addAmt: abi.NewTokenAmount(100),
shouldAdd: true,
err: nil,
addAmt: abi.NewTokenAmount(100),
shouldAdd: true,
err: nil,
cachedAvailable: abi.NewTokenAmount(200),
},
{
addAmt: abi.NewTokenAmount(50),
shouldAdd: true,
err: nil,
addAmt: abi.NewTokenAmount(50),
shouldAdd: true,
err: nil,
cachedAvailable: abi.NewTokenAmount(250),
},
{
shouldAdd: false,
err: nil,
shouldAdd: false,
err: nil,
cachedAvailable: abi.NewTokenAmount(250),
},
},
},
@@ -132,7 +137,8 @@ func TestAddFunds(t *testing.T) {
addAmounts: []abi.TokenAmount{abi.NewTokenAmount(100)},
expectedResults: []expectedResult{
{
err: errors.New("something went wrong"),
err: errors.New("something went wrong"),
cachedAvailable: abi.NewTokenAmount(0),
},
},
},
@@ -183,6 +189,10 @@ func TestAddFunds(t *testing.T) {
} else {
require.EqualError(t, err, expected.err.Error())
}
if !expected.cachedAvailable.Nil() {
require.Equal(t, expected.cachedAvailable, fundMgr.available[addr])
}
}
})
}
+32 -15
View File
@@ -10,7 +10,9 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
)
type ActorLookup func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error)
@@ -27,19 +29,33 @@ type CostKey struct {
}
var Costs = map[CostKey]int64{
{builtin.InitActorCodeID, 2}: 8916753,
{builtin.StorageMarketActorCodeID, 2}: 6955002,
{builtin.StorageMarketActorCodeID, 4}: 245436108,
{builtin.StorageMinerActorCodeID, 4}: 2315133,
{builtin.StorageMinerActorCodeID, 5}: 1600271356,
{builtin.StorageMinerActorCodeID, 6}: 22864493,
{builtin.StorageMinerActorCodeID, 7}: 142002419,
{builtin.StorageMinerActorCodeID, 10}: 23008274,
{builtin.StorageMinerActorCodeID, 11}: 19303178,
{builtin.StorageMinerActorCodeID, 14}: 566356835,
{builtin.StorageMinerActorCodeID, 16}: 5325185,
{builtin.StorageMinerActorCodeID, 18}: 2328637,
{builtin.StoragePowerActorCodeID, 2}: 23600956,
{builtin0.InitActorCodeID, 2}: 8916753,
{builtin0.StorageMarketActorCodeID, 2}: 6955002,
{builtin0.StorageMarketActorCodeID, 4}: 245436108,
{builtin0.StorageMinerActorCodeID, 4}: 2315133,
{builtin0.StorageMinerActorCodeID, 5}: 1600271356,
{builtin0.StorageMinerActorCodeID, 6}: 22864493,
{builtin0.StorageMinerActorCodeID, 7}: 142002419,
{builtin0.StorageMinerActorCodeID, 10}: 23008274,
{builtin0.StorageMinerActorCodeID, 11}: 19303178,
{builtin0.StorageMinerActorCodeID, 14}: 566356835,
{builtin0.StorageMinerActorCodeID, 16}: 5325185,
{builtin0.StorageMinerActorCodeID, 18}: 2328637,
{builtin0.StoragePowerActorCodeID, 2}: 23600956,
// TODO: Just reuse v0 values for now, this isn't actually used
{builtin2.InitActorCodeID, 2}: 8916753,
{builtin2.StorageMarketActorCodeID, 2}: 6955002,
{builtin2.StorageMarketActorCodeID, 4}: 245436108,
{builtin2.StorageMinerActorCodeID, 4}: 2315133,
{builtin2.StorageMinerActorCodeID, 5}: 1600271356,
{builtin2.StorageMinerActorCodeID, 6}: 22864493,
{builtin2.StorageMinerActorCodeID, 7}: 142002419,
{builtin2.StorageMinerActorCodeID, 10}: 23008274,
{builtin2.StorageMinerActorCodeID, 11}: 19303178,
{builtin2.StorageMinerActorCodeID, 14}: 566356835,
{builtin2.StorageMinerActorCodeID, 16}: 5325185,
{builtin2.StorageMinerActorCodeID, 18}: 2328637,
{builtin2.StoragePowerActorCodeID, 2}: 23600956,
}
func failedGuess(msg *types.SignedMessage) int64 {
@@ -51,7 +67,8 @@ func failedGuess(msg *types.SignedMessage) int64 {
}
func GuessGasUsed(ctx context.Context, tsk types.TipSetKey, msg *types.SignedMessage, al ActorLookup) (int64, error) {
if msg.Message.Method == builtin.MethodSend {
// MethodSend is the same in all versions.
if msg.Message.Method == builtin0.MethodSend {
switch msg.Message.From.Protocol() {
case address.BLS:
return 1298450, nil
+56 -91
View File
@@ -55,6 +55,7 @@ var baseFeeLowerBoundFactor = types.NewInt(10)
var baseFeeLowerBoundFactorConservative = types.NewInt(100)
var MaxActorPendingMessages = 1000
var MaxUntrustedActorPendingMessages = 10
var MaxNonceGap = uint64(4)
@@ -75,8 +76,6 @@ var (
ErrRBFTooLowPremium = errors.New("replace by fee has too low GasPremium")
ErrTooManyPendingMessages = errors.New("too many pending messages for actor")
ErrNonceGap = errors.New("unfulfilled nonce gap")
ErrTryAgain = errors.New("state inconsistency while pushing message; please try again")
)
const (
@@ -160,6 +159,7 @@ type MessagePool struct {
sigValCache *lru.TwoQueueCache
evtTypes [3]journal.EventType
journal journal.Journal
}
type msgSet struct {
@@ -197,9 +197,17 @@ func CapGasFee(msg *types.Message, maxFee abi.TokenAmount) {
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) {
func (ms *msgSet) add(m *types.SignedMessage, mp *MessagePool, strict, untrusted bool) (bool, error) {
nextNonce := ms.nextNonce
nonceGap := false
maxNonceGap := MaxNonceGap
maxActorPendingMessages := MaxActorPendingMessages
if untrusted {
maxNonceGap = 0
maxActorPendingMessages = MaxUntrustedActorPendingMessages
}
switch {
case m.Message.Nonce == nextNonce:
nextNonce++
@@ -208,7 +216,7 @@ func (ms *msgSet) add(m *types.SignedMessage, mp *MessagePool, strict bool) (boo
nextNonce++
}
case strict && m.Message.Nonce > nextNonce+MaxNonceGap:
case strict && m.Message.Nonce > nextNonce+maxNonceGap:
return false, xerrors.Errorf("message nonce has too big a gap from expected nonce (Nonce: %d, nextNonce: %d): %w", m.Message.Nonce, nextNonce, ErrNonceGap)
case m.Message.Nonce > nextNonce:
@@ -244,7 +252,7 @@ func (ms *msgSet) add(m *types.SignedMessage, mp *MessagePool, strict bool) (boo
//ms.requiredFunds.Sub(ms.requiredFunds, exms.Message.Value.Int)
}
if !has && strict && len(ms.msgs) > MaxActorPendingMessages {
if !has && strict && len(ms.msgs) >= maxActorPendingMessages {
log.Errorf("too many pending messages from actor %s", m.Message.From)
return false, ErrTooManyPendingMessages
}
@@ -309,7 +317,7 @@ func (ms *msgSet) getRequiredFunds(nonce uint64) types.BigInt {
return types.BigInt{Int: requiredFunds}
}
func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*MessagePool, error) {
func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName, j journal.Journal) (*MessagePool, error) {
cache, _ := lru.New2Q(build.BlsSignatureCacheSize)
verifcache, _ := lru.New2Q(build.VerifSigCacheSize)
@@ -318,6 +326,10 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*Messa
return nil, xerrors.Errorf("error loading mpool config: %w", err)
}
if j == nil {
j = journal.NilJournal()
}
mp := &MessagePool{
ds: ds,
addSema: make(chan struct{}, 1),
@@ -337,10 +349,11 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*Messa
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"),
evtTypeMpoolAdd: j.RegisterEventType("mpool", "add"),
evtTypeMpoolRemove: j.RegisterEventType("mpool", "remove"),
evtTypeMpoolRepub: j.RegisterEventType("mpool", "repub"),
},
journal: j,
}
// enable initial prunes
@@ -486,7 +499,7 @@ func (mp *MessagePool) Push(m *types.SignedMessage) (cid.Cid, error) {
}
mp.curTsLk.Lock()
publish, err := mp.addTs(m, mp.curTs, true)
publish, err := mp.addTs(m, mp.curTs, true, false)
if err != nil {
mp.curTsLk.Unlock()
return cid.Undef, err
@@ -553,7 +566,7 @@ func (mp *MessagePool) Add(m *types.SignedMessage) error {
mp.curTsLk.Lock()
defer mp.curTsLk.Unlock()
_, err = mp.addTs(m, mp.curTs, false)
_, err = mp.addTs(m, mp.curTs, false, false)
return err
}
@@ -621,7 +634,7 @@ func (mp *MessagePool) checkBalance(m *types.SignedMessage, curTs *types.TipSet)
return nil
}
func (mp *MessagePool) addTs(m *types.SignedMessage, curTs *types.TipSet, local bool) (bool, error) {
func (mp *MessagePool) addTs(m *types.SignedMessage, curTs *types.TipSet, local, untrusted bool) (bool, error) {
snonce, err := mp.getStateNonce(m.Message.From, curTs)
if err != nil {
return false, xerrors.Errorf("failed to look up actor state nonce: %s: %w", err, ErrSoftValidationFailure)
@@ -643,7 +656,7 @@ func (mp *MessagePool) addTs(m *types.SignedMessage, curTs *types.TipSet, local
return false, err
}
return publish, mp.addLocked(m, !local)
return publish, mp.addLocked(m, !local, untrusted)
}
func (mp *MessagePool) addLoaded(m *types.SignedMessage) error {
@@ -678,17 +691,17 @@ func (mp *MessagePool) addLoaded(m *types.SignedMessage) error {
return err
}
return mp.addLocked(m, false)
return mp.addLocked(m, false, false)
}
func (mp *MessagePool) addSkipChecks(m *types.SignedMessage) error {
mp.lk.Lock()
defer mp.lk.Unlock()
return mp.addLocked(m, false)
return mp.addLocked(m, false, false)
}
func (mp *MessagePool) addLocked(m *types.SignedMessage, strict bool) error {
func (mp *MessagePool) addLocked(m *types.SignedMessage, strict, untrusted bool) error {
log.Debugf("mpooladd: %s %d", m.Message.From, m.Message.Nonce)
if m.Signature.Type == crypto.SigTypeBLS {
mp.blsSigCache.Add(m.Cid(), m.Signature)
@@ -715,7 +728,7 @@ func (mp *MessagePool) addLocked(m *types.SignedMessage, strict bool) error {
mp.pending[m.Message.From] = mset
}
incr, err := mset.add(m, mp, strict)
incr, err := mset.add(m, mp, strict, untrusted)
if err != nil {
log.Debug(err)
return err
@@ -737,7 +750,7 @@ func (mp *MessagePool) addLocked(m *types.SignedMessage, strict bool) error {
Message: m,
}, localUpdates)
journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolAdd], func() interface{} {
mp.journal.RecordEvent(mp.evtTypes[evtTypeMpoolAdd], func() interface{} {
return MessagePoolEvt{
Action: "add",
Messages: []MessagePoolEvtMessage{{Message: m.Message, CID: m.Cid()}},
@@ -795,96 +808,48 @@ func (mp *MessagePool) getStateBalance(addr address.Address, ts *types.TipSet) (
return act.Balance, nil
}
func (mp *MessagePool) PushWithNonce(ctx context.Context, addr address.Address, cb func(address.Address, uint64) (*types.SignedMessage, error)) (*types.SignedMessage, error) {
// this method is provided for the gateway to push messages.
// differences from Push:
// - strict checks are enabled
// - extra strict add checks are used when adding the messages to the msgSet
// that means: no nonce gaps, at most 10 pending messages for the actor
func (mp *MessagePool) PushUntrusted(m *types.SignedMessage) (cid.Cid, error) {
err := mp.checkMessage(m)
if err != nil {
return cid.Undef, err
}
// serialize push access to reduce lock contention
mp.addSema <- struct{}{}
defer func() {
<-mp.addSema
}()
mp.curTsLk.Lock()
mp.lk.Lock()
curTs := mp.curTs
fromKey := addr
if fromKey.Protocol() == address.ID {
var err error
fromKey, err = mp.api.StateAccountKey(ctx, fromKey, mp.curTs)
if err != nil {
mp.lk.Unlock()
mp.curTsLk.Unlock()
return nil, xerrors.Errorf("resolving sender key: %w", err)
}
}
nonce, err := mp.getNonceLocked(fromKey, mp.curTs)
msgb, err := m.Serialize()
if err != nil {
mp.lk.Unlock()
mp.curTsLk.Unlock()
return nil, xerrors.Errorf("get nonce locked failed: %w", err)
return cid.Undef, err
}
// release the locks for signing
mp.lk.Unlock()
mp.curTsLk.Lock()
publish, err := mp.addTs(m, mp.curTs, false, true)
if err != nil {
mp.curTsLk.Unlock()
return cid.Undef, err
}
mp.curTsLk.Unlock()
msg, err := cb(fromKey, nonce)
if err != nil {
return nil, err
}
err = mp.checkMessage(msg)
if err != nil {
return nil, err
}
msgb, err := msg.Serialize()
if err != nil {
return nil, err
}
// reacquire the locks and check state for consistency
mp.curTsLk.Lock()
defer mp.curTsLk.Unlock()
if mp.curTs != curTs {
return nil, ErrTryAgain
}
mp.lk.Lock()
defer mp.lk.Unlock()
nonce2, err := mp.getNonceLocked(fromKey, mp.curTs)
if err != nil {
return nil, xerrors.Errorf("get nonce locked failed: %w", err)
}
if nonce2 != nonce {
return nil, ErrTryAgain
}
publish, err := mp.verifyMsgBeforeAdd(msg, curTs, true)
if err != nil {
return nil, err
}
if err := mp.checkBalance(msg, curTs); err != nil {
return nil, err
}
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 {
log.Errorf("addLocal failed: %+v", err)
if err := mp.addLocal(m, msgb); err != nil {
mp.lk.Unlock()
return cid.Undef, err
}
mp.lk.Unlock()
if publish {
err = mp.api.PubSubPublish(build.MessagesTopic(mp.netName), msgb)
}
return msg, err
return m.Cid(), err
}
func (mp *MessagePool) Remove(from address.Address, nonce uint64, applied bool) {
@@ -906,7 +871,7 @@ func (mp *MessagePool) remove(from address.Address, nonce uint64, applied bool)
Message: m,
}, localUpdates)
journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolRemove], func() interface{} {
mp.journal.RecordEvent(mp.evtTypes[evtTypeMpoolRemove], func() interface{} {
return MessagePoolEvt{
Action: "remove",
Messages: []MessagePoolEvtMessage{{Message: m.Message, CID: m.Cid()}}}
+21 -21
View File
@@ -225,14 +225,14 @@ func TestMessagePool(t *testing.T) {
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
a := tma.nextBlock()
sender, err := w.GenerateKey(crypto.SigTypeBLS)
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
if err != nil {
t.Fatal(err)
}
@@ -266,14 +266,14 @@ func TestMessagePoolMessagesInEachBlock(t *testing.T) {
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
a := tma.nextBlock()
sender, err := w.GenerateKey(crypto.SigTypeBLS)
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
if err != nil {
t.Fatal(err)
}
@@ -315,7 +315,7 @@ func TestRevertMessages(t *testing.T) {
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -323,7 +323,7 @@ func TestRevertMessages(t *testing.T) {
a := tma.nextBlock()
b := tma.nextBlock()
sender, err := w.GenerateKey(crypto.SigTypeBLS)
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
if err != nil {
t.Fatal(err)
}
@@ -378,7 +378,7 @@ func TestPruningSimple(t *testing.T) {
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -386,7 +386,7 @@ func TestPruningSimple(t *testing.T) {
a := tma.nextBlock()
tma.applyBlock(t, a)
sender, err := w.GenerateKey(crypto.SigTypeBLS)
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
if err != nil {
t.Fatal(err)
}
@@ -422,7 +422,7 @@ func TestLoadLocal(t *testing.T) {
tma := newTestMpoolAPI()
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -433,7 +433,7 @@ func TestLoadLocal(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -443,7 +443,7 @@ func TestLoadLocal(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -465,7 +465,7 @@ func TestLoadLocal(t *testing.T) {
t.Fatal(err)
}
mp, err = New(tma, ds, "mptest")
mp, err = New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -494,7 +494,7 @@ func TestClearAll(t *testing.T) {
tma := newTestMpoolAPI()
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -505,7 +505,7 @@ func TestClearAll(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -515,7 +515,7 @@ func TestClearAll(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -548,7 +548,7 @@ func TestClearNonLocal(t *testing.T) {
tma := newTestMpoolAPI()
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -559,7 +559,7 @@ func TestClearNonLocal(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -569,7 +569,7 @@ func TestClearNonLocal(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -609,7 +609,7 @@ func TestUpdates(t *testing.T) {
tma := newTestMpoolAPI()
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -620,7 +620,7 @@ func TestUpdates(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -630,7 +630,7 @@ func TestUpdates(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
+4 -5
View File
@@ -11,7 +11,6 @@ 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"
)
@@ -148,14 +147,14 @@ loop:
}
if len(msgs) > 0 {
journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolRepub], func() interface{} {
msgs := make([]MessagePoolEvtMessage, 0, len(msgs))
mp.journal.RecordEvent(mp.evtTypes[evtTypeMpoolRepub], func() interface{} {
msgsEv := make([]MessagePoolEvtMessage, 0, len(msgs))
for _, m := range msgs {
msgs = append(msgs, MessagePoolEvtMessage{Message: m.Message, CID: m.Cid()})
msgsEv = append(msgsEv, MessagePoolEvtMessage{Message: m.Message, CID: m.Cid()})
}
return MessagePoolEvt{
Action: "repub",
Messages: msgs,
Messages: msgsEv,
}
})
}
+4 -3
View File
@@ -1,6 +1,7 @@
package messagepool
import (
"context"
"testing"
"time"
@@ -21,7 +22,7 @@ func TestRepubMessages(t *testing.T) {
tma := newTestMpoolAPI()
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -32,7 +33,7 @@ func TestRepubMessages(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -42,7 +43,7 @@ func TestRepubMessages(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
+33 -31
View File
@@ -13,6 +13,10 @@ import (
"sort"
"testing"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
logging "github.com/ipfs/go-log"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/build"
@@ -21,12 +25,10 @@ import (
"github.com/filecoin-project/lotus/chain/types/mock"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
"github.com/filecoin-project/lotus/api"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
logging "github.com/ipfs/go-log"
)
func init() {
@@ -34,7 +36,7 @@ func init() {
MaxActorPendingMessages = 1000000
}
func makeTestMessage(w *wallet.Wallet, from, to address.Address, nonce uint64, gasLimit int64, gasPrice uint64) *types.SignedMessage {
func makeTestMessage(w *wallet.LocalWallet, from, to address.Address, nonce uint64, gasLimit int64, gasPrice uint64) *types.SignedMessage {
msg := &types.Message{
From: from,
To: to,
@@ -45,7 +47,7 @@ func makeTestMessage(w *wallet.Wallet, from, to address.Address, nonce uint64, g
GasFeeCap: types.NewInt(100 + gasPrice),
GasPremium: types.NewInt(gasPrice),
}
sig, err := w.Sign(context.TODO(), from, msg.Cid().Bytes())
sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{})
if err != nil {
panic(err)
}
@@ -58,7 +60,7 @@ func makeTestMessage(w *wallet.Wallet, from, to address.Address, nonce uint64, g
func makeTestMpool() (*MessagePool, *testMpoolAPI) {
tma := newTestMpoolAPI()
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "test")
mp, err := New(tma, ds, "test", nil)
if err != nil {
panic(err)
}
@@ -75,7 +77,7 @@ func TestMessageChains(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -85,7 +87,7 @@ func TestMessageChains(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -313,7 +315,7 @@ func TestMessageChainSkipping(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -323,7 +325,7 @@ func TestMessageChainSkipping(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -389,7 +391,7 @@ func TestBasicMessageSelection(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -399,7 +401,7 @@ func TestBasicMessageSelection(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -533,7 +535,7 @@ func TestMessageSelectionTrimming(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -543,7 +545,7 @@ func TestMessageSelectionTrimming(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -596,7 +598,7 @@ func TestPriorityMessageSelection(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -606,7 +608,7 @@ func TestPriorityMessageSelection(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -675,7 +677,7 @@ func TestPriorityMessageSelection2(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -685,7 +687,7 @@ func TestPriorityMessageSelection2(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -744,7 +746,7 @@ func TestPriorityMessageSelection3(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -754,7 +756,7 @@ func TestPriorityMessageSelection3(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -841,7 +843,7 @@ func TestOptimalMessageSelection1(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -851,7 +853,7 @@ func TestOptimalMessageSelection1(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -908,7 +910,7 @@ func TestOptimalMessageSelection2(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -918,7 +920,7 @@ func TestOptimalMessageSelection2(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -984,7 +986,7 @@ func TestOptimalMessageSelection3(t *testing.T) {
nActors := 10
// the actors
var actors []address.Address
var wallets []*wallet.Wallet
var wallets []*wallet.LocalWallet
for i := 0; i < nActors; i++ {
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
@@ -992,7 +994,7 @@ func TestOptimalMessageSelection3(t *testing.T) {
t.Fatal(err)
}
a, err := w.GenerateKey(crypto.SigTypeSecp256k1)
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -1064,7 +1066,7 @@ func testCompetitiveMessageSelection(t *testing.T, rng *rand.Rand, getPremium fu
nActors := 300
// the actors
var actors []address.Address
var wallets []*wallet.Wallet
var wallets []*wallet.LocalWallet
for i := 0; i < nActors; i++ {
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
@@ -1072,7 +1074,7 @@ func testCompetitiveMessageSelection(t *testing.T, rng *rand.Rand, getPremium fu
t.Fatal(err)
}
a, err := w.GenerateKey(crypto.SigTypeSecp256k1)
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -1330,7 +1332,7 @@ readLoop:
}
actorMap := make(map[address.Address]address.Address)
actorWallets := make(map[address.Address]*wallet.Wallet)
actorWallets := make(map[address.Address]api.WalletAPI)
for _, m := range msgs {
baseNonce := baseNonces[m.Message.From]
@@ -1342,7 +1344,7 @@ readLoop:
t.Fatal(err)
}
a, err := w.GenerateKey(crypto.SigTypeSecp256k1)
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -1360,7 +1362,7 @@ readLoop:
m.Message.From = localActor
m.Message.Nonce -= baseNonce
sig, err := w.Sign(context.TODO(), localActor, m.Message.Cid().Bytes())
sig, err := w.WalletSign(context.TODO(), localActor, m.Message.Cid().Bytes(), api.MsgMeta{})
if err != nil {
t.Fatal(err)
}
+161
View File
@@ -0,0 +1,161 @@
package messagesigner
import (
"bytes"
"context"
"sync"
"github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/namespace"
logging "github.com/ipfs/go-log/v2"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes"
)
const dsKeyActorNonce = "ActorNextNonce"
var log = logging.Logger("messagesigner")
type MpoolNonceAPI interface {
GetNonce(address.Address) (uint64, error)
}
// MessageSigner keeps track of nonces per address, and increments the nonce
// when signing a message
type MessageSigner struct {
wallet api.WalletAPI
lk sync.Mutex
mpool MpoolNonceAPI
ds datastore.Batching
}
func NewMessageSigner(wallet api.WalletAPI, mpool MpoolNonceAPI, ds dtypes.MetadataDS) *MessageSigner {
ds = namespace.Wrap(ds, datastore.NewKey("/message-signer/"))
return &MessageSigner{
wallet: wallet,
mpool: mpool,
ds: ds,
}
}
// SignMessage increments the nonce for the message From address, and signs
// the message
func (ms *MessageSigner) SignMessage(ctx context.Context, msg *types.Message, cb func(*types.SignedMessage) error) (*types.SignedMessage, error) {
ms.lk.Lock()
defer ms.lk.Unlock()
// Get the next message nonce
nonce, err := ms.nextNonce(msg.From)
if err != nil {
return nil, xerrors.Errorf("failed to create nonce: %w", err)
}
// Sign the message with the nonce
msg.Nonce = nonce
mb, err := msg.ToStorageBlock()
if err != nil {
return nil, xerrors.Errorf("serializing message: %w", err)
}
sig, err := ms.wallet.WalletSign(ctx, msg.From, mb.Cid().Bytes(), api.MsgMeta{
Type: api.MTChainMsg,
Extra: mb.RawData(),
})
if err != nil {
return nil, xerrors.Errorf("failed to sign message: %w", err)
}
// Callback with the signed message
smsg := &types.SignedMessage{
Message: *msg,
Signature: *sig,
}
err = cb(smsg)
if err != nil {
return nil, err
}
// If the callback executed successfully, write the nonce to the datastore
if err := ms.saveNonce(msg.From, nonce); err != nil {
return nil, xerrors.Errorf("failed to save nonce: %w", err)
}
return smsg, nil
}
// nextNonce gets the next nonce for the given address.
// If there is no nonce in the datastore, gets the nonce from the message pool.
func (ms *MessageSigner) nextNonce(addr address.Address) (uint64, error) {
// Nonces used to be created by the mempool and we need to support nodes
// that have mempool nonces, so first check the mempool for a nonce for
// this address. Note that the mempool returns the actor state's nonce
// by default.
nonce, err := ms.mpool.GetNonce(addr)
if err != nil {
return 0, xerrors.Errorf("failed to get nonce from mempool: %w", err)
}
// Get the next nonce for this address from the datastore
addrNonceKey := ms.dstoreKey(addr)
dsNonceBytes, err := ms.ds.Get(addrNonceKey)
switch {
case xerrors.Is(err, datastore.ErrNotFound):
// If a nonce for this address hasn't yet been created in the
// datastore, just use the nonce from the mempool
return nonce, nil
case err != nil:
return 0, xerrors.Errorf("failed to get nonce from datastore: %w", err)
default:
// There is a nonce in the datastore, so unmarshall it
maj, dsNonce, err := cbg.CborReadHeader(bytes.NewReader(dsNonceBytes))
if err != nil {
return 0, xerrors.Errorf("failed to parse nonce from datastore: %w", err)
}
if maj != cbg.MajUnsignedInt {
return 0, xerrors.Errorf("bad cbor type parsing nonce from datastore")
}
// The message pool nonce should be <= than the datastore nonce
if nonce <= dsNonce {
nonce = dsNonce
} else {
log.Warnf("mempool nonce was larger than datastore nonce (%d > %d)", nonce, dsNonce)
}
return nonce, nil
}
}
// saveNonce increments the nonce for this address and writes it to the
// datastore
func (ms *MessageSigner) saveNonce(addr address.Address, nonce uint64) error {
// Increment the nonce
nonce++
// Write the nonce to the datastore
addrNonceKey := ms.dstoreKey(addr)
buf := bytes.Buffer{}
_, err := buf.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, nonce))
if err != nil {
return xerrors.Errorf("failed to marshall nonce: %w", err)
}
err = ms.ds.Put(addrNonceKey, buf.Bytes())
if err != nil {
return xerrors.Errorf("failed to write nonce to datastore: %w", err)
}
return nil
}
func (ms *MessageSigner) dstoreKey(addr address.Address) datastore.Key {
return datastore.KeyWithNamespaces([]string{dsKeyActorNonce, addr.String()})
}
+201
View File
@@ -0,0 +1,201 @@
package messagesigner
import (
"context"
"sync"
"testing"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/stretchr/testify/require"
ds_sync "github.com/ipfs/go-datastore/sync"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-datastore"
)
type mockMpool struct {
lk sync.RWMutex
nonces map[address.Address]uint64
}
func newMockMpool() *mockMpool {
return &mockMpool{nonces: make(map[address.Address]uint64)}
}
func (mp *mockMpool) setNonce(addr address.Address, nonce uint64) {
mp.lk.Lock()
defer mp.lk.Unlock()
mp.nonces[addr] = nonce
}
func (mp *mockMpool) GetNonce(addr address.Address) (uint64, error) {
mp.lk.RLock()
defer mp.lk.RUnlock()
return mp.nonces[addr], nil
}
func TestMessageSignerSignMessage(t *testing.T) {
ctx := context.Background()
w, _ := wallet.NewWallet(wallet.NewMemKeyStore())
from1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
require.NoError(t, err)
from2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
require.NoError(t, err)
to1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
require.NoError(t, err)
to2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
require.NoError(t, err)
type msgSpec struct {
msg *types.Message
mpoolNonce [1]uint64
expNonce uint64
cbErr error
}
tests := []struct {
name string
msgs []msgSpec
}{{
// No nonce yet in datastore
name: "no nonce yet",
msgs: []msgSpec{{
msg: &types.Message{
To: to1,
From: from1,
},
expNonce: 0,
}},
}, {
// Get nonce value of zero from mpool
name: "mpool nonce zero",
msgs: []msgSpec{{
msg: &types.Message{
To: to1,
From: from1,
},
mpoolNonce: [1]uint64{0},
expNonce: 0,
}},
}, {
// Get non-zero nonce value from mpool
name: "mpool nonce set",
msgs: []msgSpec{{
msg: &types.Message{
To: to1,
From: from1,
},
mpoolNonce: [1]uint64{5},
expNonce: 5,
}, {
msg: &types.Message{
To: to1,
From: from1,
},
// Should adjust datastore nonce because mpool nonce is higher
mpoolNonce: [1]uint64{10},
expNonce: 10,
}},
}, {
// Nonce should increment independently for each address
name: "nonce increments per address",
msgs: []msgSpec{{
msg: &types.Message{
To: to1,
From: from1,
},
expNonce: 0,
}, {
msg: &types.Message{
To: to1,
From: from1,
},
expNonce: 1,
}, {
msg: &types.Message{
To: to2,
From: from2,
},
mpoolNonce: [1]uint64{5},
expNonce: 5,
}, {
msg: &types.Message{
To: to2,
From: from2,
},
expNonce: 6,
}, {
msg: &types.Message{
To: to1,
From: from1,
},
expNonce: 2,
}},
}, {
name: "recover from callback error",
msgs: []msgSpec{{
// No nonce yet in datastore
msg: &types.Message{
To: to1,
From: from1,
},
expNonce: 0,
}, {
// Increment nonce
msg: &types.Message{
To: to1,
From: from1,
},
expNonce: 1,
}, {
// Callback returns error
msg: &types.Message{
To: to1,
From: from1,
},
cbErr: xerrors.Errorf("err"),
}, {
// Callback successful, should increment nonce in datastore
msg: &types.Message{
To: to1,
From: from1,
},
expNonce: 2,
}},
}}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
mpool := newMockMpool()
ds := ds_sync.MutexWrap(datastore.NewMapDatastore())
ms := NewMessageSigner(w, mpool, ds)
for _, m := range tt.msgs {
if len(m.mpoolNonce) == 1 {
mpool.setNonce(m.msg.From, m.mpoolNonce[0])
}
merr := m.cbErr
smsg, err := ms.SignMessage(ctx, m.msg, func(message *types.SignedMessage) error {
return merr
})
if m.cbErr != nil {
require.Error(t, err)
require.Nil(t, smsg)
} else {
require.NoError(t, err)
require.Equal(t, m.expNonce, smsg.Message.Nonce)
}
}
})
}
}
+64 -31
View File
@@ -13,7 +13,8 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
cbg "github.com/whyrusleeping/cbor-gen"
@@ -26,7 +27,7 @@ var log = logging.Logger("statetree")
// StateTree stores actors state by their ID.
type StateTree struct {
root adt.Map
version builtin.Version // TODO
version types.StateTreeVersion
info cid.Cid
Store cbor.IpldStore
@@ -120,15 +121,41 @@ func (ss *stateSnaps) deleteActor(addr address.Address) {
ss.layers[len(ss.layers)-1].actors[addr] = streeOp{Delete: true}
}
func NewStateTree(cst cbor.IpldStore, version builtin.Version) (*StateTree, error) {
var info cid.Cid
switch version {
case builtin.Version0:
// info is undefined
default:
return nil, xerrors.Errorf("unsupported state tree version: %d", version)
// VersionForNetwork returns the state tree version for the given network
// version.
func VersionForNetwork(ver network.Version) types.StateTreeVersion {
if actors.VersionForNetwork(ver) == actors.Version0 {
return types.StateTreeVersion0
}
root, err := adt.NewMap(adt.WrapStore(context.TODO(), cst), version)
return types.StateTreeVersion1
}
func adtForSTVersion(ver types.StateTreeVersion) actors.Version {
switch ver {
case types.StateTreeVersion0:
return actors.Version0
case types.StateTreeVersion1:
return actors.Version2
default:
panic("unhandled state tree version")
}
}
func NewStateTree(cst cbor.IpldStore, ver types.StateTreeVersion) (*StateTree, error) {
var info cid.Cid
switch ver {
case types.StateTreeVersion0:
// info is undefined
case types.StateTreeVersion1:
var err error
info, err = cst.Put(context.TODO(), new(types.StateInfo0))
if err != nil {
return nil, err
}
default:
return nil, xerrors.Errorf("unsupported state tree version: %d", ver)
}
root, err := adt.NewMap(adt.WrapStore(context.TODO(), cst), adtForSTVersion(ver))
if err != nil {
return nil, err
}
@@ -136,7 +163,7 @@ func NewStateTree(cst cbor.IpldStore, version builtin.Version) (*StateTree, erro
return &StateTree{
root: root,
info: info,
version: version,
version: ver,
Store: cst,
snaps: newStateSnaps(),
}, nil
@@ -148,30 +175,31 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
if err := cst.Get(context.TODO(), c, &root); err != nil {
// We failed to decode as the new version, must be an old version.
root.Actors = c
root.Version = builtin.Version0
}
// If that fails, load as an old-style state-tree (direct hampt, version 0.
nd, err := adt.AsMap(adt.WrapStore(context.TODO(), cst), root.Actors, builtin.Version(root.Version))
if err != nil {
log.Errorf("loading hamt node %s failed: %s", c, err)
return nil, err
root.Version = types.StateTreeVersion0
}
switch root.Version {
case builtin.Version0:
// supported
case types.StateTreeVersion0, types.StateTreeVersion1:
// Load the actual state-tree HAMT.
nd, err := adt.AsMap(
adt.WrapStore(context.TODO(), cst), root.Actors,
adtForSTVersion(root.Version),
)
if err != nil {
log.Errorf("loading hamt node %s failed: %s", c, err)
return nil, err
}
return &StateTree{
root: nd,
info: root.Info,
version: root.Version,
Store: cst,
snaps: newStateSnaps(),
}, nil
default:
return nil, xerrors.Errorf("unsupported state tree version: %d", root.Version)
}
return &StateTree{
root: nd,
info: root.Info,
version: builtin.Version(root.Version),
Store: cst,
snaps: newStateSnaps(),
}, nil
}
func (st *StateTree) SetActor(addr address.Address, act *types.Actor) error {
@@ -305,11 +333,11 @@ func (st *StateTree) Flush(ctx context.Context) (cid.Cid, error) {
return cid.Undef, xerrors.Errorf("failed to flush state-tree hamt: %w", err)
}
// If we're version 0, return a raw tree.
if st.version == builtin.Version0 {
if st.version == types.StateTreeVersion0 {
return root, nil
}
// Otherwise, return a versioned tree.
return st.Store.Put(ctx, &types.StateRoot{Version: uint64(st.version), Actors: root, Info: st.info})
return st.Store.Put(ctx, &types.StateRoot{Version: st.version, Actors: root, Info: st.info})
}
func (st *StateTree) Snapshot(ctx context.Context) error {
@@ -395,6 +423,11 @@ func (st *StateTree) ForEach(f func(address.Address, *types.Actor) error) error
})
}
// Version returns the version of the StateTree data structure in use.
func (st *StateTree) Version() types.StateTreeVersion {
return st.version
}
func Diff(oldTree, newTree *StateTree) (map[string]types.Actor, error) {
out := map[string]types.Actor{}
+8 -7
View File
@@ -9,16 +9,16 @@ import (
cbor "github.com/ipfs/go-ipld-cbor"
address "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/build"
builtin2 "github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
func BenchmarkStateTreeSet(b *testing.B) {
cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst, builtin2.VersionForNetwork(build.NewestNetworkVersion))
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
if err != nil {
b.Fatal(err)
}
@@ -45,7 +45,7 @@ func BenchmarkStateTreeSet(b *testing.B) {
func BenchmarkStateTreeSetFlush(b *testing.B) {
cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst, builtin2.VersionForNetwork(build.NewestNetworkVersion))
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
if err != nil {
b.Fatal(err)
}
@@ -75,7 +75,7 @@ func BenchmarkStateTreeSetFlush(b *testing.B) {
func BenchmarkStateTree10kGetActor(b *testing.B) {
cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst, builtin2.VersionForNetwork(build.NewestNetworkVersion))
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
if err != nil {
b.Fatal(err)
}
@@ -117,7 +117,7 @@ func BenchmarkStateTree10kGetActor(b *testing.B) {
func TestSetCache(t *testing.T) {
cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst, builtin2.VersionForNetwork(build.NewestNetworkVersion))
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
if err != nil {
t.Fatal(err)
}
@@ -154,7 +154,7 @@ func TestSetCache(t *testing.T) {
func TestSnapshots(t *testing.T) {
ctx := context.Background()
cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst, builtin2.VersionForNetwork(build.NewestNetworkVersion))
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
if err != nil {
t.Fatal(err)
}
@@ -237,7 +237,8 @@ func assertNotHas(t *testing.T, st *StateTree, addr address.Address) {
func TestStateTreeConsistency(t *testing.T) {
cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst, builtin2.VersionForNetwork(build.NewestNetworkVersion))
// TODO: ActorUpgrade: this test tests pre actors v2
st, err := NewStateTree(cst, VersionForNetwork(network.Version3))
if err != nil {
t.Fatal(err)
}
+62 -18
View File
@@ -2,10 +2,10 @@ package stmgr
import (
"context"
"errors"
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/ipfs/go-cid"
"go.opencensus.io/trace"
@@ -18,14 +18,47 @@ import (
"github.com/filecoin-project/lotus/chain/vm"
)
func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate cid.Cid, r vm.Rand, bheight abi.ChainEpoch) (*api.InvocResult, error) {
ctx, span := trace.StartSpan(ctx, "statemanager.CallRaw")
var ErrExpensiveFork = errors.New("refusing explicit call due to state fork at epoch")
func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) {
ctx, span := trace.StartSpan(ctx, "statemanager.Call")
defer span.End()
// If no tipset is provided, try to find one without a fork.
if ts == nil {
ts = sm.cs.GetHeaviestTipSet()
// Search back till we find a height with no fork, or we reach the beginning.
for ts.Height() > 0 && sm.hasExpensiveFork(ctx, ts.Height()-1) {
var err error
ts, err = sm.cs.GetTipSetFromKey(ts.Parents())
if err != nil {
return nil, xerrors.Errorf("failed to find a non-forking epoch: %w", err)
}
}
}
bstate := ts.ParentState()
bheight := ts.Height()
// If we have to run an expensive migration, and we're not at genesis,
// return an error because the migration will take too long.
//
// We allow this at height 0 for at-genesis migrations (for testing).
if bheight-1 > 0 && sm.hasExpensiveFork(ctx, bheight-1) {
return nil, ErrExpensiveFork
}
// Run the (not expensive) migration.
bstate, err := sm.handleStateForks(ctx, bstate, bheight-1, nil, ts)
if err != nil {
return nil, fmt.Errorf("failed to handle fork: %w", err)
}
vmopt := &vm.VMOpts{
StateBase: bstate,
Epoch: bheight,
Rand: r,
Rand: store.NewChainRand(sm.cs, ts.Cids()),
Bstore: sm.cs.Blockstore(),
Syscalls: sm.cs.VMSys(),
CircSupplyCalc: sm.GetCirculatingSupply,
@@ -33,7 +66,7 @@ func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate
BaseFee: types.NewInt(0),
}
vmi, err := vm.NewVM(ctx, vmopt)
vmi, err := sm.newVM(ctx, vmopt)
if err != nil {
return nil, xerrors.Errorf("failed to set up vm: %w", err)
}
@@ -89,24 +122,30 @@ func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate
}
func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) {
if ts == nil {
ts = sm.cs.GetHeaviestTipSet()
}
state := ts.ParentState()
r := store.NewChainRand(sm.cs, ts.Cids())
return sm.CallRaw(ctx, msg, state, r, ts.Height())
}
func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet) (*api.InvocResult, error) {
ctx, span := trace.StartSpan(ctx, "statemanager.CallWithGas")
defer span.End()
if ts == nil {
ts = sm.cs.GetHeaviestTipSet()
// Search back till we find a height with no fork, or we reach the beginning.
// We need the _previous_ height to have no fork, because we'll
// run the fork logic in `sm.TipSetState`. We need the _current_
// height to have no fork, because we'll run it inside this
// function before executing the given message.
for ts.Height() > 0 && (sm.hasExpensiveFork(ctx, ts.Height()) || sm.hasExpensiveFork(ctx, ts.Height()-1)) {
var err error
ts, err = sm.cs.GetTipSetFromKey(ts.Parents())
if err != nil {
return nil, xerrors.Errorf("failed to find a non-forking epoch: %w", err)
}
}
}
// When we're not at the genesis block, make sure we don't have an expensive migration.
if ts.Height() > 0 && (sm.hasExpensiveFork(ctx, ts.Height()) || sm.hasExpensiveFork(ctx, ts.Height()-1)) {
return nil, ErrExpensiveFork
}
state, _, err := sm.TipSetState(ctx, ts)
@@ -114,6 +153,11 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
return nil, xerrors.Errorf("computing tipset state: %w", err)
}
state, err = sm.handleStateForks(ctx, state, ts.Height(), nil, ts)
if err != nil {
return nil, fmt.Errorf("failed to handle fork: %w", err)
}
r := store.NewChainRand(sm.cs, ts.Cids())
if span.IsRecordingEvents() {
@@ -134,7 +178,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
NtwkVersion: sm.GetNtwkVersion,
BaseFee: ts.Blocks()[0].ParentBaseFee,
}
vmi, err := vm.NewVM(ctx, vmopt)
vmi, err := sm.newVM(ctx, vmopt)
if err != nil {
return nil, xerrors.Errorf("failed to set up vm: %w", err)
}
+575 -40
View File
@@ -1,44 +1,174 @@
package stmgr
import (
"bytes"
"context"
"encoding/binary"
"math"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"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/network"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"golang.org/x/xerrors"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
multisig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/specs-actors/actors/migration/nv3"
m2 "github.com/filecoin-project/specs-actors/v2/actors/migration"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/adt"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
cbor "github.com/ipfs/go-ipld-cbor"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/vm"
bstore "github.com/filecoin-project/lotus/lib/blockstore"
"github.com/filecoin-project/lotus/lib/bufbstore"
)
var ForksAtHeight = map[abi.ChainEpoch]func(context.Context, *StateManager, types.StateTree, *types.TipSet) error{
build.UpgradeBreezeHeight: UpgradeFaucetBurnRecovery,
// UpgradeFunc is a migration function run at every upgrade.
//
// - The oldState is the state produced by the upgrade epoch.
// - The returned newState is the new state that will be used by the next epoch.
// - The height is the upgrade epoch height (already executed).
// - The tipset is the tipset for the last non-null block before the upgrade. Do
// not assume that ts.Height() is the upgrade height.
type UpgradeFunc func(ctx context.Context, sm *StateManager, cb ExecCallback, oldState cid.Cid, height abi.ChainEpoch, ts *types.TipSet) (newState cid.Cid, err error)
type Upgrade struct {
Height abi.ChainEpoch
Network network.Version
Expensive bool
Migration UpgradeFunc
}
func (sm *StateManager) handleStateForks(ctx context.Context, st types.StateTree, height abi.ChainEpoch, ts *types.TipSet) (err error) {
f, ok := ForksAtHeight[height]
if ok {
err := f(ctx, sm, st, ts)
if err != nil {
return err
type UpgradeSchedule []Upgrade
func DefaultUpgradeSchedule() UpgradeSchedule {
var us UpgradeSchedule
updates := []Upgrade{{
Height: build.UpgradeBreezeHeight,
Network: network.Version1,
Migration: UpgradeFaucetBurnRecovery,
}, {
Height: build.UpgradeSmokeHeight,
Network: network.Version2,
Migration: nil,
}, {
Height: build.UpgradeIgnitionHeight,
Network: network.Version3,
Migration: UpgradeIgnition,
}, {
Height: build.UpgradeRefuelHeight,
Network: network.Version3,
Migration: UpgradeRefuel,
}, {
Height: build.UpgradeActorsV2Height,
Network: network.Version4,
Expensive: true,
Migration: UpgradeActorsV2,
}, {
Height: build.UpgradeTapeHeight,
Network: network.Version5,
}, {
Height: build.UpgradeLiftoffHeight,
Network: network.Version5,
Migration: UpgradeLiftoff,
}}
if build.UpgradeActorsV2Height == math.MaxInt64 { // disable actors upgrade
updates = []Upgrade{{
Height: build.UpgradeBreezeHeight,
Network: network.Version1,
Migration: UpgradeFaucetBurnRecovery,
}, {
Height: build.UpgradeSmokeHeight,
Network: network.Version2,
Migration: nil,
}, {
Height: build.UpgradeIgnitionHeight,
Network: network.Version3,
Migration: UpgradeIgnition,
}, {
Height: build.UpgradeRefuelHeight,
Network: network.Version3,
Migration: UpgradeRefuel,
}, {
Height: build.UpgradeLiftoffHeight,
Network: network.Version3,
Migration: UpgradeLiftoff,
}}
}
for _, u := range updates {
if u.Height < 0 {
// upgrade disabled
continue
}
us = append(us, u)
}
return us
}
func (us UpgradeSchedule) Validate() error {
// Make sure we're not trying to upgrade to version 0.
for _, u := range us {
if u.Network <= 0 {
return xerrors.Errorf("cannot upgrade to version <= 0: %d", u.Network)
}
}
// Make sure all the upgrades make sense.
for i := 1; i < len(us); i++ {
prev := &us[i-1]
curr := &us[i]
if !(prev.Network <= curr.Network) {
return xerrors.Errorf("cannot downgrade from version %d to version %d", prev.Network, curr.Network)
}
// Make sure the heights make sense.
if prev.Height < 0 {
// Previous upgrade was disabled.
continue
}
if !(prev.Height < curr.Height) {
return xerrors.Errorf("upgrade heights must be strictly increasing: upgrade %d was at height %d, followed by upgrade %d at height %d", i-1, prev.Height, i, curr.Height)
}
}
return nil
}
type forEachTree interface {
ForEach(func(address.Address, *types.Actor) error) error
func (sm *StateManager) handleStateForks(ctx context.Context, root cid.Cid, height abi.ChainEpoch, cb ExecCallback, ts *types.TipSet) (cid.Cid, error) {
retCid := root
var err error
f, ok := sm.stateMigrations[height]
if ok {
retCid, err = f(ctx, sm, cb, root, height, ts)
if err != nil {
return cid.Undef, err
}
}
return retCid, nil
}
func doTransfer(tree types.StateTree, from, to address.Address, amt abi.TokenAmount) error {
func (sm *StateManager) hasExpensiveFork(ctx context.Context, height abi.ChainEpoch) bool {
_, ok := sm.expensiveUpgrades[height]
return ok
}
func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address, amt abi.TokenAmount) error {
fromAct, err := tree.GetActor(from)
if err != nil {
return xerrors.Errorf("failed to get 'from' actor for transfer: %w", err)
@@ -64,10 +194,43 @@ func doTransfer(tree types.StateTree, from, to address.Address, amt abi.TokenAmo
return xerrors.Errorf("failed to persist to actor: %w", err)
}
if cb != nil {
// record the transfer in execution traces
fakeMsg := &types.Message{
From: from,
To: to,
Value: amt,
Nonce: math.MaxUint64,
}
fakeRct := &types.MessageReceipt{
ExitCode: 0,
Return: nil,
GasUsed: 0,
}
if err := cb(fakeMsg.Cid(), fakeMsg, &vm.ApplyRet{
MessageReceipt: *fakeRct,
ActorErr: nil,
ExecutionTrace: types.ExecutionTrace{
Msg: fakeMsg,
MsgRct: fakeRct,
Error: "",
Duration: 0,
GasCharges: nil,
Subcalls: nil,
},
Duration: 0,
GasCosts: vm.ZeroGasOutputs(),
}); err != nil {
return xerrors.Errorf("recording transfer: %w", err)
}
}
return nil
}
func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types.StateTree, ts *types.TipSet) error {
func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
// Some initial parameters
FundsForMiners := types.FromFil(1_000_000)
LookbackEpoch := abi.ChainEpoch(32000)
@@ -94,22 +257,22 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
// Grab lookback state for account checks
lbts, err := sm.ChainStore().GetTipsetByHeight(ctx, LookbackEpoch, ts, false)
if err != nil {
return xerrors.Errorf("failed to get tipset at lookback height: %w", err)
return cid.Undef, xerrors.Errorf("failed to get tipset at lookback height: %w", err)
}
lbtree, err := sm.ParentState(lbts)
if err != nil {
return xerrors.Errorf("loading state tree failed: %w", err)
return cid.Undef, xerrors.Errorf("loading state tree failed: %w", err)
}
ReserveAddress, err := address.NewFromString("t090")
if err != nil {
return xerrors.Errorf("failed to parse reserve address: %w", err)
return cid.Undef, xerrors.Errorf("failed to parse reserve address: %w", err)
}
fetree, ok := tree.(forEachTree)
if !ok {
return xerrors.Errorf("fork transition state tree doesnt support ForEach (%T)", tree)
tree, err := sm.StateTree(root)
if err != nil {
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
}
type transfer struct {
@@ -121,7 +284,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
var transfers []transfer
// Take all excess funds away, put them into the reserve account
err = fetree.ForEach(func(addr address.Address, act *types.Actor) error {
err = tree.ForEach(func(addr address.Address, act *types.Actor) error {
switch act.Code {
case builtin0.AccountActorCodeID, builtin0.MultisigActorCodeID, builtin0.PaymentChannelActorCodeID:
sysAcc, err := isSystemAccount(addr)
@@ -163,13 +326,13 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
return nil
})
if err != nil {
return xerrors.Errorf("foreach over state tree failed: %w", err)
return cid.Undef, xerrors.Errorf("foreach over state tree failed: %w", err)
}
// Execute transfers from previous step
for _, t := range transfers {
if err := doTransfer(tree, t.From, t.To, t.Amt); err != nil {
return xerrors.Errorf("transfer %s %s->%s failed: %w", t.Amt, t.From, t.To, err)
if err := doTransfer(cb, tree, t.From, t.To, t.Amt); err != nil {
return cid.Undef, xerrors.Errorf("transfer %s %s->%s failed: %w", t.Amt, t.From, t.To, err)
}
}
@@ -177,19 +340,19 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
var ps power0.State
powAct, err := tree.GetActor(builtin0.StoragePowerActorAddr)
if err != nil {
return xerrors.Errorf("failed to load power actor: %w", err)
return cid.Undef, xerrors.Errorf("failed to load power actor: %w", err)
}
cst := cbor.NewCborStore(sm.ChainStore().Blockstore())
if err := cst.Get(ctx, powAct.Head, &ps); err != nil {
return xerrors.Errorf("failed to get power actor state: %w", err)
return cid.Undef, xerrors.Errorf("failed to get power actor state: %w", err)
}
totalPower := ps.TotalBytesCommitted
var transfersBack []transfer
// Now, we return some funds to places where they are needed
err = fetree.ForEach(func(addr address.Address, act *types.Actor) error {
err = tree.ForEach(func(addr address.Address, act *types.Actor) error {
lbact, err := lbtree.GetActor(addr)
if err != nil {
if !xerrors.Is(err, types.ErrActorNotFound) {
@@ -267,53 +430,425 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
return nil
})
if err != nil {
return xerrors.Errorf("foreach over state tree failed: %w", err)
return cid.Undef, xerrors.Errorf("foreach over state tree failed: %w", err)
}
for _, t := range transfersBack {
if err := doTransfer(tree, t.From, t.To, t.Amt); err != nil {
return xerrors.Errorf("transfer %s %s->%s failed: %w", t.Amt, t.From, t.To, err)
if err := doTransfer(cb, tree, t.From, t.To, t.Amt); err != nil {
return cid.Undef, xerrors.Errorf("transfer %s %s->%s failed: %w", t.Amt, t.From, t.To, err)
}
}
// transfer all burnt funds back to the reserve account
burntAct, err := tree.GetActor(builtin0.BurntFundsActorAddr)
if err != nil {
return xerrors.Errorf("failed to load burnt funds actor: %w", err)
return cid.Undef, xerrors.Errorf("failed to load burnt funds actor: %w", err)
}
if err := doTransfer(tree, builtin0.BurntFundsActorAddr, ReserveAddress, burntAct.Balance); err != nil {
return xerrors.Errorf("failed to unburn funds: %w", err)
if err := doTransfer(cb, tree, builtin0.BurntFundsActorAddr, ReserveAddress, burntAct.Balance); err != nil {
return cid.Undef, xerrors.Errorf("failed to unburn funds: %w", err)
}
// Top up the reimbursement service
reimbAddr, err := address.NewFromString("t0111")
if err != nil {
return xerrors.Errorf("failed to parse reimbursement service address")
return cid.Undef, xerrors.Errorf("failed to parse reimbursement service address")
}
reimb, err := tree.GetActor(reimbAddr)
if err != nil {
return xerrors.Errorf("failed to load reimbursement account actor: %w", err)
return cid.Undef, xerrors.Errorf("failed to load reimbursement account actor: %w", err)
}
difference := types.BigSub(DesiredReimbursementBalance, reimb.Balance)
if err := doTransfer(tree, ReserveAddress, reimbAddr, difference); err != nil {
return xerrors.Errorf("failed to top up reimbursement account: %w", err)
if err := doTransfer(cb, tree, ReserveAddress, reimbAddr, difference); err != nil {
return cid.Undef, xerrors.Errorf("failed to top up reimbursement account: %w", err)
}
// Now, a final sanity check to make sure the balances all check out
total := abi.NewTokenAmount(0)
err = fetree.ForEach(func(addr address.Address, act *types.Actor) error {
err = tree.ForEach(func(addr address.Address, act *types.Actor) error {
total = types.BigAdd(total, act.Balance)
return nil
})
if err != nil {
return xerrors.Errorf("checking final state balance failed: %w", err)
return cid.Undef, xerrors.Errorf("checking final state balance failed: %w", err)
}
exp := types.FromFil(build.FilBase)
if !exp.Equals(total) {
return xerrors.Errorf("resultant state tree account balance was not correct: %s", total)
return cid.Undef, xerrors.Errorf("resultant state tree account balance was not correct: %s", total)
}
return tree.Flush(ctx)
}
func UpgradeIgnition(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
store := sm.cs.Store(ctx)
if build.UpgradeLiftoffHeight <= epoch {
return cid.Undef, xerrors.Errorf("liftoff height must be beyond ignition height")
}
nst, err := nv3.MigrateStateTree(ctx, store, root, epoch)
if err != nil {
return cid.Undef, xerrors.Errorf("migrating actors state: %w", err)
}
tree, err := sm.StateTree(nst)
if err != nil {
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
}
err = setNetworkName(ctx, store, tree, "ignition")
if err != nil {
return cid.Undef, xerrors.Errorf("setting network name: %w", err)
}
split1, err := address.NewFromString("t0115")
if err != nil {
return cid.Undef, xerrors.Errorf("first split address: %w", err)
}
split2, err := address.NewFromString("t0116")
if err != nil {
return cid.Undef, xerrors.Errorf("second split address: %w", err)
}
err = resetGenesisMsigs(ctx, sm, store, tree, build.UpgradeLiftoffHeight)
if err != nil {
return cid.Undef, xerrors.Errorf("resetting genesis msig start epochs: %w", err)
}
err = splitGenesisMultisig(ctx, cb, split1, store, tree, 50)
if err != nil {
return cid.Undef, xerrors.Errorf("splitting first msig: %w", err)
}
err = splitGenesisMultisig(ctx, cb, split2, store, tree, 50)
if err != nil {
return cid.Undef, xerrors.Errorf("splitting second msig: %w", err)
}
err = nv3.CheckStateTree(ctx, store, nst, epoch, builtin0.TotalFilecoin)
if err != nil {
return cid.Undef, xerrors.Errorf("sanity check after ignition upgrade failed: %w", err)
}
return tree.Flush(ctx)
}
func UpgradeRefuel(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
store := sm.cs.Store(ctx)
tree, err := sm.StateTree(root)
if err != nil {
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
}
addr, err := address.NewFromString("t0122")
if err != nil {
return cid.Undef, xerrors.Errorf("getting address: %w", err)
}
err = resetMultisigVesting(ctx, store, tree, addr, 0, 0, big.Zero())
if err != nil {
return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err)
}
err = resetMultisigVesting(ctx, store, tree, builtin.ReserveAddress, 0, 0, big.Zero())
if err != nil {
return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err)
}
err = resetMultisigVesting(ctx, store, tree, builtin.RootVerifierAddress, 0, 0, big.Zero())
if err != nil {
return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err)
}
return tree.Flush(ctx)
}
func UpgradeActorsV2(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
buf := bufbstore.NewTieredBstore(sm.cs.Blockstore(), bstore.NewTemporarySync())
store := store.ActorStore(ctx, buf)
info, err := store.Put(ctx, new(types.StateInfo0))
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create new state info for actors v2: %w", err)
}
newHamtRoot, err := m2.MigrateStateTree(ctx, store, root, epoch, m2.DefaultConfig())
if err != nil {
return cid.Undef, xerrors.Errorf("upgrading to actors v2: %w", err)
}
newRoot, err := store.Put(ctx, &types.StateRoot{
Version: types.StateTreeVersion1,
Actors: newHamtRoot,
Info: info,
})
if err != nil {
return cid.Undef, xerrors.Errorf("failed to persist new state root: %w", err)
}
// perform some basic sanity checks to make sure everything still works.
if newSm, err := state.LoadStateTree(store, newRoot); err != nil {
return cid.Undef, xerrors.Errorf("state tree sanity load failed: %w", err)
} else if newRoot2, err := newSm.Flush(ctx); err != nil {
return cid.Undef, xerrors.Errorf("state tree sanity flush failed: %w", err)
} else if newRoot2 != newRoot {
return cid.Undef, xerrors.Errorf("state-root mismatch: %s != %s", newRoot, newRoot2)
} else if _, err := newSm.GetActor(builtin0.InitActorAddr); err != nil {
return cid.Undef, xerrors.Errorf("failed to load init actor after upgrade: %w", err)
}
{
from := buf
to := buf.Read()
if err := vm.Copy(ctx, from, to, newRoot); err != nil {
return cid.Undef, xerrors.Errorf("copying migrated tree: %w", err)
}
}
return newRoot, nil
}
func UpgradeLiftoff(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
tree, err := sm.StateTree(root)
if err != nil {
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
}
err = setNetworkName(ctx, sm.cs.Store(ctx), tree, "mainnet")
if err != nil {
return cid.Undef, xerrors.Errorf("setting network name: %w", err)
}
return tree.Flush(ctx)
}
func setNetworkName(ctx context.Context, store adt.Store, tree *state.StateTree, name string) error {
ia, err := tree.GetActor(builtin0.InitActorAddr)
if err != nil {
return xerrors.Errorf("getting init actor: %w", err)
}
initState, err := init_.Load(store, ia)
if err != nil {
return xerrors.Errorf("reading init state: %w", err)
}
if err := initState.SetNetworkName(name); err != nil {
return xerrors.Errorf("setting network name: %w", err)
}
ia.Head, err = store.Put(ctx, initState)
if err != nil {
return xerrors.Errorf("writing new init state: %w", err)
}
if err := tree.SetActor(builtin0.InitActorAddr, ia); err != nil {
return xerrors.Errorf("setting init actor: %w", err)
}
return nil
}
func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Address, store adt0.Store, tree *state.StateTree, portions uint64) error {
if portions < 1 {
return xerrors.Errorf("cannot split into 0 portions")
}
mact, err := tree.GetActor(addr)
if err != nil {
return xerrors.Errorf("getting msig actor: %w", err)
}
mst, err := multisig.Load(store, mact)
if err != nil {
return xerrors.Errorf("getting msig state: %w", err)
}
signers, err := mst.Signers()
if err != nil {
return xerrors.Errorf("getting msig signers: %w", err)
}
thresh, err := mst.Threshold()
if err != nil {
return xerrors.Errorf("getting msig threshold: %w", err)
}
ibal, err := mst.InitialBalance()
if err != nil {
return xerrors.Errorf("getting msig initial balance: %w", err)
}
se, err := mst.StartEpoch()
if err != nil {
return xerrors.Errorf("getting msig start epoch: %w", err)
}
ud, err := mst.UnlockDuration()
if err != nil {
return xerrors.Errorf("getting msig unlock duration: %w", err)
}
pending, err := adt0.MakeEmptyMap(store).Root()
if err != nil {
return xerrors.Errorf("failed to create empty map: %w", err)
}
newIbal := big.Div(ibal, types.NewInt(portions))
newState := &multisig0.State{
Signers: signers,
NumApprovalsThreshold: thresh,
NextTxnID: 0,
InitialBalance: newIbal,
StartEpoch: se,
UnlockDuration: ud,
PendingTxns: pending,
}
scid, err := store.Put(ctx, newState)
if err != nil {
return xerrors.Errorf("storing new state: %w", err)
}
newActor := types.Actor{
Code: builtin0.MultisigActorCodeID,
Head: scid,
Nonce: 0,
Balance: big.Zero(),
}
i := uint64(0)
for i < portions {
keyAddr, err := makeKeyAddr(addr, i)
if err != nil {
return xerrors.Errorf("creating key address: %w", err)
}
idAddr, err := tree.RegisterNewAddress(keyAddr)
if err != nil {
return xerrors.Errorf("registering new address: %w", err)
}
err = tree.SetActor(idAddr, &newActor)
if err != nil {
return xerrors.Errorf("setting new msig actor state: %w", err)
}
if err := doTransfer(cb, tree, addr, idAddr, newIbal); err != nil {
return xerrors.Errorf("transferring split msig balance: %w", err)
}
i++
}
return nil
}
func makeKeyAddr(splitAddr address.Address, count uint64) (address.Address, error) {
var b bytes.Buffer
if err := splitAddr.MarshalCBOR(&b); err != nil {
return address.Undef, xerrors.Errorf("marshalling split address: %w", err)
}
if err := binary.Write(&b, binary.BigEndian, count); err != nil {
return address.Undef, xerrors.Errorf("writing count into a buffer: %w", err)
}
if err := binary.Write(&b, binary.BigEndian, []byte("Ignition upgrade")); err != nil {
return address.Undef, xerrors.Errorf("writing fork name into a buffer: %w", err)
}
addr, err := address.NewActorAddress(b.Bytes())
if err != nil {
return address.Undef, xerrors.Errorf("create actor address: %w", err)
}
return addr, nil
}
// TODO: After the Liftoff epoch, refactor this to use resetMultisigVesting
func resetGenesisMsigs(ctx context.Context, sm *StateManager, store adt0.Store, tree *state.StateTree, startEpoch abi.ChainEpoch) error {
gb, err := sm.cs.GetGenesis()
if err != nil {
return xerrors.Errorf("getting genesis block: %w", err)
}
gts, err := types.NewTipSet([]*types.BlockHeader{gb})
if err != nil {
return xerrors.Errorf("getting genesis tipset: %w", err)
}
cst := cbor.NewCborStore(sm.cs.Blockstore())
genesisTree, err := state.LoadStateTree(cst, gts.ParentState())
if err != nil {
return xerrors.Errorf("loading state tree: %w", err)
}
err = genesisTree.ForEach(func(addr address.Address, genesisActor *types.Actor) error {
if genesisActor.Code == builtin0.MultisigActorCodeID {
currActor, err := tree.GetActor(addr)
if err != nil {
return xerrors.Errorf("loading actor: %w", err)
}
var currState multisig0.State
if err := store.Get(ctx, currActor.Head, &currState); err != nil {
return xerrors.Errorf("reading multisig state: %w", err)
}
currState.StartEpoch = startEpoch
currActor.Head, err = store.Put(ctx, &currState)
if err != nil {
return xerrors.Errorf("writing new multisig state: %w", err)
}
if err := tree.SetActor(addr, currActor); err != nil {
return xerrors.Errorf("setting multisig actor: %w", err)
}
}
return nil
})
if err != nil {
return xerrors.Errorf("iterating over genesis actors: %w", err)
}
return nil
}
func resetMultisigVesting(ctx context.Context, store adt0.Store, tree *state.StateTree, addr address.Address, startEpoch abi.ChainEpoch, duration abi.ChainEpoch, balance abi.TokenAmount) error {
act, err := tree.GetActor(addr)
if err != nil {
return xerrors.Errorf("getting actor: %w", err)
}
if !builtin.IsMultisigActor(act.Code) {
return xerrors.Errorf("actor wasn't msig: %w", err)
}
var msigState multisig0.State
if err := store.Get(ctx, act.Head, &msigState); err != nil {
return xerrors.Errorf("reading multisig state: %w", err)
}
msigState.StartEpoch = startEpoch
msigState.UnlockDuration = duration
msigState.InitialBalance = balance
act.Head, err = store.Put(ctx, &msigState)
if err != nil {
return xerrors.Errorf("writing new multisig state: %w", err)
}
if err := tree.SetActor(addr, act); err != nil {
return xerrors.Errorf("setting multisig actor: %w", err)
}
return nil
+143 -49
View File
@@ -6,39 +6,37 @@ import (
"io"
"testing"
"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/specs-actors/actors/builtin"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/ipfs/go-cid"
ipldcbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log"
"github.com/stretchr/testify/require"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/specs-actors/actors/builtin"
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
lotusinit "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/stmgr"
. "github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log"
cbg "github.com/whyrusleeping/cbor-gen"
)
func init() {
miner0.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
}
power0.ConsensusMinerMinPower = big.NewInt(2048)
verifreg0.MinVerifiedDealSize = big.NewInt(256)
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
}
const testForkHeight = 40
@@ -46,6 +44,10 @@ const testForkHeight = 40
type testActor struct {
}
// must use existing actor that an account is allowed to exec.
func (testActor) Code() cid.Cid { return builtin.PaymentChannelActorCodeID }
func (testActor) State() cbor.Er { return new(testActorState) }
type testActorState struct {
HasUpgraded uint64
}
@@ -66,7 +68,7 @@ func (tas *testActorState) UnmarshalCBOR(r io.Reader) error {
return nil
}
func (ta *testActor) Exports() []interface{} {
func (ta testActor) Exports() []interface{} {
return []interface{}{
1: ta.Constructor,
2: ta.TestMethod,
@@ -76,7 +78,7 @@ func (ta *testActor) Exports() []interface{} {
func (ta *testActor) Constructor(rt runtime.Runtime, params *abi.EmptyValue) *abi.EmptyValue {
rt.ValidateImmediateCallerAcceptAny()
rt.StateCreate(&testActorState{11})
fmt.Println("NEW ACTOR ADDRESS IS: ", rt.Receiver())
//fmt.Println("NEW ACTOR ADDRESS IS: ", rt.Receiver())
return abi.Empty
}
@@ -109,46 +111,57 @@ func TestForkHeightTriggers(t *testing.T) {
t.Fatal(err)
}
sm := NewStateManager(cg.ChainStore())
inv := vm.NewInvoker()
// predicting the address here... may break if other assumptions change
taddr, err := address.NewIDAddress(1002)
if err != nil {
t.Fatal(err)
}
stmgr.ForksAtHeight[testForkHeight] = func(ctx context.Context, sm *StateManager, st types.StateTree, ts *types.TipSet) error {
cst := cbor.NewCborStore(sm.ChainStore().Blockstore())
sm, err := NewStateManagerWithUpgradeSchedule(
cg.ChainStore(), UpgradeSchedule{{
Network: 1,
Height: testForkHeight,
Migration: func(ctx context.Context, sm *StateManager, cb ExecCallback,
root cid.Cid, height abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
cst := ipldcbor.NewCborStore(sm.ChainStore().Blockstore())
act, err := st.GetActor(taddr)
if err != nil {
return err
}
st, err := sm.StateTree(root)
if err != nil {
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
}
var tas testActorState
if err := cst.Get(ctx, act.Head, &tas); err != nil {
return xerrors.Errorf("in fork handler, failed to run get: %w", err)
}
act, err := st.GetActor(taddr)
if err != nil {
return cid.Undef, err
}
tas.HasUpgraded = 55
var tas testActorState
if err := cst.Get(ctx, act.Head, &tas); err != nil {
return cid.Undef, xerrors.Errorf("in fork handler, failed to run get: %w", err)
}
ns, err := cst.Put(ctx, &tas)
if err != nil {
return err
}
tas.HasUpgraded = 55
act.Head = ns
ns, err := cst.Put(ctx, &tas)
if err != nil {
return cid.Undef, err
}
if err := st.SetActor(taddr, act); err != nil {
return err
}
act.Head = ns
return nil
if err := st.SetActor(taddr, act); err != nil {
return cid.Undef, err
}
return st.Flush(ctx)
}}})
if err != nil {
t.Fatal(err)
}
inv.Register(builtin.PaymentChannelActorCodeID, &testActor{}, &testActorState{})
inv := vm.NewActorRegistry()
inv.Register(nil, testActor{})
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (*vm.VM, error) {
nvm, err := vm.NewVM(ctx, vmopt)
if err != nil {
@@ -162,7 +175,7 @@ func TestForkHeightTriggers(t *testing.T) {
var msgs []*types.SignedMessage
enc, err := actors.SerializeParams(&init_.ExecParams{CodeCID: builtin.PaymentChannelActorCodeID})
enc, err := actors.SerializeParams(&init0.ExecParams{CodeCID: (testActor{}).Code()})
if err != nil {
t.Fatal(err)
}
@@ -174,7 +187,7 @@ func TestForkHeightTriggers(t *testing.T) {
Params: enc,
GasLimit: types.TestGasLimit,
}
sig, err := cg.Wallet().Sign(ctx, cg.Banker(), m.Cid().Bytes())
sig, err := cg.Wallet().WalletSign(ctx, cg.Banker(), m.Cid().Bytes(), api.MsgMeta{})
if err != nil {
t.Fatal(err)
}
@@ -202,7 +215,7 @@ func TestForkHeightTriggers(t *testing.T) {
}
nonce++
sig, err := cg.Wallet().Sign(ctx, cg.Banker(), m.Cid().Bytes())
sig, err := cg.Wallet().WalletSign(ctx, cg.Banker(), m.Cid().Bytes(), api.MsgMeta{})
if err != nil {
return nil, err
}
@@ -222,3 +235,84 @@ func TestForkHeightTriggers(t *testing.T) {
}
}
}
func TestForkRefuseCall(t *testing.T) {
logging.SetAllLoggers(logging.LevelInfo)
ctx := context.TODO()
cg, err := gen.NewGenerator()
if err != nil {
t.Fatal(err)
}
sm, err := NewStateManagerWithUpgradeSchedule(
cg.ChainStore(), UpgradeSchedule{{
Network: 1,
Expensive: true,
Height: testForkHeight,
Migration: func(ctx context.Context, sm *StateManager, cb ExecCallback,
root cid.Cid, height abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
return root, nil
}}})
if err != nil {
t.Fatal(err)
}
inv := vm.NewActorRegistry()
inv.Register(nil, testActor{})
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (*vm.VM, error) {
nvm, err := vm.NewVM(ctx, vmopt)
if err != nil {
return nil, err
}
nvm.SetInvoker(inv)
return nvm, nil
})
cg.SetStateManager(sm)
enc, err := actors.SerializeParams(&init0.ExecParams{CodeCID: (testActor{}).Code()})
if err != nil {
t.Fatal(err)
}
m := &types.Message{
From: cg.Banker(),
To: lotusinit.Address,
Method: builtin.MethodsInit.Exec,
Params: enc,
GasLimit: types.TestGasLimit,
Value: types.NewInt(0),
GasPremium: types.NewInt(0),
GasFeeCap: types.NewInt(0),
}
for i := 0; i < 50; i++ {
ts, err := cg.NextTipSet()
if err != nil {
t.Fatal(err)
}
ret, err := sm.CallWithGas(ctx, m, nil, ts.TipSet.TipSet())
switch ts.TipSet.TipSet().Height() {
case testForkHeight, testForkHeight + 1:
// If I had a fork, or I _will_ have a fork, it should fail.
require.Equal(t, ErrExpensiveFork, err)
default:
require.NoError(t, err)
require.True(t, ret.MsgRct.ExitCode.IsSuccess())
}
// Call just runs on the parent state for a tipset, so we only
// expect an error at the fork height.
ret, err = sm.Call(ctx, m, ts.TipSet.TipSet())
switch ts.TipSet.TipSet().Height() {
case testForkHeight + 1:
require.Equal(t, ErrExpensiveFork, err)
default:
require.NoError(t, err)
require.True(t, ret.MsgRct.ExitCode.IsSuccess())
}
}
}
+318 -95
View File
@@ -2,9 +2,12 @@ package stmgr
import (
"context"
"errors"
"fmt"
"sync"
"github.com/filecoin-project/lotus/chain/actors/builtin"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
@@ -24,7 +27,6 @@ import (
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
@@ -36,26 +38,93 @@ import (
"github.com/filecoin-project/lotus/chain/vm"
)
const LookbackNoLimit = abi.ChainEpoch(-1)
var log = logging.Logger("statemgr")
type StateManagerAPI interface {
LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error)
LookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
}
type versionSpec struct {
networkVersion network.Version
atOrBelow abi.ChainEpoch
}
type StateManager struct {
cs *store.ChainStore
stCache map[string][]cid.Cid
compWait map[string]chan struct{}
stlk sync.Mutex
genesisMsigLk sync.Mutex
newVM func(context.Context, *vm.VMOpts) (*vm.VM, error)
genInfo *genesisInfo
// Determines the network version at any given epoch.
networkVersions []versionSpec
latestVersion network.Version
// Maps chain epochs to upgrade functions.
stateMigrations map[abi.ChainEpoch]UpgradeFunc
// A set of potentially expensive/time consuming upgrades. Explicit
// calls for, e.g., gas estimation fail against this epoch with
// ErrExpensiveFork.
expensiveUpgrades map[abi.ChainEpoch]struct{}
stCache map[string][]cid.Cid
compWait map[string]chan struct{}
stlk sync.Mutex
genesisMsigLk sync.Mutex
newVM func(context.Context, *vm.VMOpts) (*vm.VM, error)
preIgnitionGenInfos *genesisInfo
postIgnitionGenInfos *genesisInfo
}
func NewStateManager(cs *store.ChainStore) *StateManager {
return &StateManager{
newVM: vm.NewVM,
cs: cs,
stCache: make(map[string][]cid.Cid),
compWait: make(map[string]chan struct{}),
sm, err := NewStateManagerWithUpgradeSchedule(cs, DefaultUpgradeSchedule())
if err != nil {
panic(fmt.Sprintf("default upgrade schedule is invalid: %s", err))
}
return sm
}
func NewStateManagerWithUpgradeSchedule(cs *store.ChainStore, us UpgradeSchedule) (*StateManager, error) {
// If we have upgrades, make sure they're in-order and make sense.
if err := us.Validate(); err != nil {
return nil, err
}
stateMigrations := make(map[abi.ChainEpoch]UpgradeFunc, len(us))
expensiveUpgrades := make(map[abi.ChainEpoch]struct{}, len(us))
var networkVersions []versionSpec
lastVersion := network.Version0
if len(us) > 0 {
// If we have any upgrades, process them and create a version
// schedule.
for _, upgrade := range us {
if upgrade.Migration != nil {
stateMigrations[upgrade.Height] = upgrade.Migration
}
if upgrade.Expensive {
expensiveUpgrades[upgrade.Height] = struct{}{}
}
networkVersions = append(networkVersions, versionSpec{
networkVersion: lastVersion,
atOrBelow: upgrade.Height,
})
lastVersion = upgrade.Network
}
} else {
// Otherwise, go directly to the latest version.
lastVersion = build.NewestNetworkVersion
}
return &StateManager{
networkVersions: networkVersions,
latestVersion: lastVersion,
stateMigrations: stateMigrations,
expensiveUpgrades: expensiveUpgrades,
newVM: vm.NewVM,
cs: cs,
stCache: make(map[string][]cid.Cid),
compWait: make(map[string]chan struct{}),
}, nil
}
func cidsToKey(cids []cid.Cid) string {
@@ -123,9 +192,8 @@ func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (st c
return st, rec, nil
}
func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (cid.Cid, []*api.InvocResult, error) {
var trace []*api.InvocResult
st, _, err := sm.computeTipSetState(ctx, ts, func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
func traceFunc(trace *[]*api.InvocResult) func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
return func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
ir := &api.InvocResult{
Msg: msg,
MsgRct: &ret.MessageReceipt,
@@ -135,9 +203,14 @@ func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (c
if ret.ActorErr != nil {
ir.Error = ret.ActorErr.Error()
}
trace = append(trace, ir)
*trace = append(*trace, ir)
return nil
})
}
}
func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (cid.Cid, []*api.InvocResult, error) {
var trace []*api.InvocResult
st, _, err := sm.computeTipSetState(ctx, ts, traceFunc(&trace))
if err != nil {
return cid.Undef, nil, err
}
@@ -149,20 +222,24 @@ type ExecCallback func(cid.Cid, *types.Message, *vm.ApplyRet) error
func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEpoch, pstate cid.Cid, bms []store.BlockMessages, epoch abi.ChainEpoch, r vm.Rand, cb ExecCallback, baseFee abi.TokenAmount, ts *types.TipSet) (cid.Cid, cid.Cid, error) {
vmopt := &vm.VMOpts{
StateBase: pstate,
Epoch: epoch,
Rand: r,
Bstore: sm.cs.Blockstore(),
Syscalls: sm.cs.VMSys(),
CircSupplyCalc: sm.GetCirculatingSupply,
NtwkVersion: sm.GetNtwkVersion,
BaseFee: baseFee,
makeVmWithBaseState := func(base cid.Cid) (*vm.VM, error) {
vmopt := &vm.VMOpts{
StateBase: base,
Epoch: epoch,
Rand: r,
Bstore: sm.cs.Blockstore(),
Syscalls: sm.cs.VMSys(),
CircSupplyCalc: sm.GetCirculatingSupply,
NtwkVersion: sm.GetNtwkVersion,
BaseFee: baseFee,
}
return sm.newVM(ctx, vmopt)
}
vmi, err := sm.newVM(ctx, vmopt)
vmi, err := makeVmWithBaseState(pstate)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err)
}
runCron := func() error {
@@ -200,21 +277,34 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
}
for i := parentEpoch; i < epoch; i++ {
if i > parentEpoch {
// run cron for null rounds if any
if err := runCron(); err != nil {
return cid.Undef, cid.Undef, err
}
pstate, err = vmi.Flush(ctx)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("flushing vm: %w", err)
}
}
// handle state forks
// XXX: The state tree
err = sm.handleStateForks(ctx, vmi.StateTree(), i, ts)
newState, err := sm.handleStateForks(ctx, pstate, i, cb, ts)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("error handling state forks: %w", err)
}
if i > parentEpoch {
// run cron for null rounds if any
if err := runCron(); err != nil {
return cid.Cid{}, cid.Cid{}, err
if pstate != newState {
vmi, err = makeVmWithBaseState(newState)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err)
}
}
vmi.SetBlockHeight(i + 1)
pstate = newState
}
var receipts []cbg.CBORMarshaler
@@ -257,7 +347,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
sysAct, actErr := vmi.StateTree().GetActor(builtin0.SystemActorAddr)
if actErr != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get system actor: %w", err)
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get system actor: %w", actErr)
}
rwMsg := &types.Message{
@@ -273,7 +363,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
}
ret, actErr := vmi.ApplyImplicitMessage(ctx, rwMsg)
if actErr != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to apply reward message for miner %s: %w", b.Miner, err)
return cid.Undef, cid.Undef, xerrors.Errorf("failed to apply reward message for miner %s: %w", b.Miner, actErr)
}
if cb != nil {
if err := cb(rwMsg.Cid(), rwMsg, ret); err != nil {
@@ -291,7 +381,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
}
// XXX: Is the height correct? Or should it be epoch-1?
rectarr, err := adt.NewArray(sm.cs.Store(ctx), builtin.VersionForNetwork(sm.GetNtwkVersion(ctx, epoch)))
rectarr, err := adt.NewArray(sm.cs.Store(ctx), actors.VersionForNetwork(sm.GetNtwkVersion(ctx, epoch)))
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to create receipts amt: %w", err)
}
@@ -426,16 +516,7 @@ func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.T
return nil, fmt.Errorf("failed to load message: %w", err)
}
r, _, err := sm.tipsetExecutedMessage(ts, msg, m.VMMessage())
if err != nil {
return nil, err
}
if r != nil {
return r, nil
}
_, r, _, err = sm.searchBackForMsg(ctx, ts, m)
_, r, _, err := sm.searchBackForMsg(ctx, ts, m, LookbackNoLimit)
if err != nil {
return nil, fmt.Errorf("failed to look back through chain for message: %w", err)
}
@@ -444,9 +525,9 @@ func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.T
}
// WaitForMessage blocks until a message appears on chain. It looks backwards in the chain to see if this has already
// happened. It guarantees that the message has been on chain for at least confidence epochs without being reverted
// before returning.
func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confidence uint64) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
// happened, with an optional limit to how many epochs it will search. It guarantees that the message has been on
// chain for at least confidence epochs without being reverted before returning.
func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confidence uint64, lookbackLimit abi.ChainEpoch) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
@@ -484,7 +565,7 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confid
var backFm cid.Cid
backSearchWait := make(chan struct{})
go func() {
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head[0].Val, msg)
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head[0].Val, msg, lookbackLimit)
if err != nil {
log.Warnf("failed to look back through chain for message: %w", err)
return
@@ -576,7 +657,7 @@ func (sm *StateManager) SearchForMessage(ctx context.Context, mcid cid.Cid) (*ty
return head, r, foundMsg, nil
}
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head, msg)
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head, msg, LookbackNoLimit)
if err != nil {
log.Warnf("failed to look back through chain for message %s", mcid)
@@ -590,11 +671,33 @@ func (sm *StateManager) SearchForMessage(ctx context.Context, mcid cid.Cid) (*ty
return fts, r, foundMsg, nil
}
func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet, m types.ChainMsg) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
// searchBackForMsg searches up to limit tipsets backwards from the given
// tipset for a message receipt.
// If limit is
// - 0 then no tipsets are searched
// - 5 then five tipset are searched
// - LookbackNoLimit then there is no limit
func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet, m types.ChainMsg, limit abi.ChainEpoch) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
limitHeight := from.Height() - limit
noLimit := limit == LookbackNoLimit
cur := from
curActor, err := sm.LoadActor(ctx, m.VMMessage().From, cur)
if err != nil {
return nil, nil, cid.Undef, xerrors.Errorf("failed to load initital tipset")
}
mFromId, err := sm.LookupID(ctx, m.VMMessage().From, from)
if err != nil {
return nil, nil, cid.Undef, xerrors.Errorf("looking up From id address: %w", err)
}
mNonce := m.VMMessage().Nonce
for {
if cur.Height() == 0 {
// If we've reached the genesis block, or we've reached the limit of
// how far back to look
if cur.Height() == 0 || !noLimit && cur.Height() <= limitHeight {
// it ain't here!
return nil, nil, cid.Undef, nil
}
@@ -605,32 +708,37 @@ func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet
default:
}
act, err := sm.LoadActor(ctx, m.VMMessage().From, cur)
if err != nil {
return nil, nil, cid.Cid{}, err
}
// we either have no messages from the sender, or the latest message we found has a lower nonce than the one being searched for,
// either way, no reason to lookback, it ain't there
if act.Nonce == 0 || act.Nonce < m.VMMessage().Nonce {
if curActor == nil || curActor.Nonce == 0 || curActor.Nonce < mNonce {
return nil, nil, cid.Undef, nil
}
ts, err := sm.cs.LoadTipSet(cur.Parents())
pts, err := sm.cs.LoadTipSet(cur.Parents())
if err != nil {
return nil, nil, cid.Undef, fmt.Errorf("failed to load tipset during msg wait searchback: %w", err)
return nil, nil, cid.Undef, xerrors.Errorf("failed to load tipset during msg wait searchback: %w", err)
}
r, foundMsg, err := sm.tipsetExecutedMessage(ts, m.Cid(), m.VMMessage())
if err != nil {
return nil, nil, cid.Undef, fmt.Errorf("checking for message execution during lookback: %w", err)
act, err := sm.LoadActor(ctx, mFromId, pts)
actorNoExist := errors.Is(err, types.ErrActorNotFound)
if err != nil && !actorNoExist {
return nil, nil, cid.Cid{}, xerrors.Errorf("failed to load the actor: %w", err)
}
if r != nil {
return ts, r, foundMsg, nil
// check that between cur and parent tipset the nonce fell into range of our message
if actorNoExist || (curActor.Nonce > mNonce && act.Nonce <= mNonce) {
r, foundMsg, err := sm.tipsetExecutedMessage(cur, m.Cid(), m.VMMessage())
if err != nil {
return nil, nil, cid.Undef, xerrors.Errorf("checking for message execution during lookback: %w", err)
}
if r != nil {
return pts, r, foundMsg, nil
}
}
cur = ts
cur = pts
curActor = act
}
}
@@ -837,7 +945,7 @@ func (sm *StateManager) setupGenesisActors(ctx context.Context) error {
totalsByEpoch := make(map[abi.ChainEpoch]abi.TokenAmount)
err = sTree.ForEach(func(kaddr address.Address, act *types.Actor) error {
if act.IsMultisigActor() {
if builtin.IsMultisigActor(act.Code) {
s, err := multisig.Load(sm.cs.Store(ctx), act)
if err != nil {
return err
@@ -869,7 +977,7 @@ func (sm *StateManager) setupGenesisActors(ctx context.Context) error {
totalsByEpoch[ud] = ib
}
} else if act.IsAccountActor() {
} else if builtin.IsAccountActor(act.Code) {
// should exclude burnt funds actor and "remainder account actor"
// should only ever be "faucet" accounts in testnets
if kaddr == builtin0.BurntFundsActorAddr {
@@ -904,7 +1012,7 @@ func (sm *StateManager) setupGenesisActors(ctx context.Context) error {
gi.genesisMsigs = append(gi.genesisMsigs, ns)
}
sm.genInfo = &gi
sm.preIgnitionGenInfos = &gi
return nil
}
@@ -912,7 +1020,7 @@ func (sm *StateManager) setupGenesisActors(ctx context.Context) error {
// sets up information about the actors in the genesis state
// For testnet we use a hardcoded set of multisig states, instead of what's actually in the genesis multisigs
// We also do not consider ANY account actors (including the faucet)
func (sm *StateManager) setupGenesisActorsTestnet(ctx context.Context) error {
func (sm *StateManager) setupPreIgnitionGenesisActorsTestnet(ctx context.Context) error {
gi := genesisInfo{}
@@ -981,7 +1089,87 @@ func (sm *StateManager) setupGenesisActorsTestnet(ctx context.Context) error {
gi.genesisMsigs = append(gi.genesisMsigs, ns)
}
sm.genInfo = &gi
sm.preIgnitionGenInfos = &gi
return nil
}
// sets up information about the actors in the genesis state, post the ignition fork
func (sm *StateManager) setupPostIgnitionGenesisActors(ctx context.Context) error {
gi := genesisInfo{}
gb, err := sm.cs.GetGenesis()
if err != nil {
return xerrors.Errorf("getting genesis block: %w", err)
}
gts, err := types.NewTipSet([]*types.BlockHeader{gb})
if err != nil {
return xerrors.Errorf("getting genesis tipset: %w", err)
}
st, _, err := sm.TipSetState(ctx, gts)
if err != nil {
return xerrors.Errorf("getting genesis tipset state: %w", err)
}
cst := cbor.NewCborStore(sm.cs.Blockstore())
sTree, err := state.LoadStateTree(cst, st)
if err != nil {
return xerrors.Errorf("loading state tree: %w", err)
}
// Unnecessary, should be removed
gi.genesisMarketFunds, err = getFilMarketLocked(ctx, sTree)
if err != nil {
return xerrors.Errorf("setting up genesis market funds: %w", err)
}
// Unnecessary, should be removed
gi.genesisPledge, err = getFilPowerLocked(ctx, sTree)
if err != nil {
return xerrors.Errorf("setting up genesis pledge: %w", err)
}
totalsByEpoch := make(map[abi.ChainEpoch]abi.TokenAmount)
// 6 months
sixMonths := abi.ChainEpoch(183 * builtin0.EpochsInDay)
totalsByEpoch[sixMonths] = big.NewInt(49_929_341)
totalsByEpoch[sixMonths] = big.Add(totalsByEpoch[sixMonths], big.NewInt(32_787_700))
// 1 year
oneYear := abi.ChainEpoch(365 * builtin0.EpochsInDay)
totalsByEpoch[oneYear] = big.NewInt(22_421_712)
// 2 years
twoYears := abi.ChainEpoch(2 * 365 * builtin0.EpochsInDay)
totalsByEpoch[twoYears] = big.NewInt(7_223_364)
// 3 years
threeYears := abi.ChainEpoch(3 * 365 * builtin0.EpochsInDay)
totalsByEpoch[threeYears] = big.NewInt(87_637_883)
// 6 years
sixYears := abi.ChainEpoch(6 * 365 * builtin0.EpochsInDay)
totalsByEpoch[sixYears] = big.NewInt(100_000_000)
totalsByEpoch[sixYears] = big.Add(totalsByEpoch[sixYears], big.NewInt(300_000_000))
gi.genesisMsigs = make([]msig0.State, 0, len(totalsByEpoch))
for k, v := range totalsByEpoch {
ns := msig0.State{
// In the pre-ignition logic, we incorrectly set this value in Fil, not attoFil, an off-by-10^18 error
InitialBalance: big.Mul(v, big.NewInt(int64(build.FilecoinPrecision))),
UnlockDuration: k,
PendingTxns: cid.Undef,
// In the pre-ignition logic, the start epoch was 0. This changes in the fork logic of the Ignition upgrade itself.
StartEpoch: build.UpgradeLiftoffHeight,
}
gi.genesisMsigs = append(gi.genesisMsigs, ns)
}
sm.postIgnitionGenInfos = &gi
return nil
}
@@ -991,13 +1179,23 @@ func (sm *StateManager) setupGenesisActorsTestnet(ctx context.Context) error {
// - For Accounts, it counts max(currentBalance - genesisBalance, 0).
func (sm *StateManager) GetFilVested(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) {
vf := big.Zero()
for _, v := range sm.genInfo.genesisMsigs {
au := big.Sub(v.InitialBalance, v.AmountLocked(height))
vf = big.Add(vf, au)
if height <= build.UpgradeIgnitionHeight {
for _, v := range sm.preIgnitionGenInfos.genesisMsigs {
au := big.Sub(v.InitialBalance, v.AmountLocked(height))
vf = big.Add(vf, au)
}
} else {
for _, v := range sm.postIgnitionGenInfos.genesisMsigs {
// In the pre-ignition logic, we simply called AmountLocked(height), assuming startEpoch was 0.
// The start epoch changed in the Ignition upgrade.
au := big.Sub(v.InitialBalance, v.AmountLocked(height-v.StartEpoch))
vf = big.Add(vf, au)
}
}
// there should not be any such accounts in testnet (and also none in mainnet?)
for _, v := range sm.genInfo.genesisActors {
// continue to use preIgnitionGenInfos, nothing changed at the Ignition epoch
for _, v := range sm.preIgnitionGenInfos.genesisActors {
act, err := st.GetActor(v.addr)
if err != nil {
return big.Zero(), xerrors.Errorf("failed to get actor: %w", err)
@@ -1009,12 +1207,27 @@ func (sm *StateManager) GetFilVested(ctx context.Context, height abi.ChainEpoch,
}
}
vf = big.Add(vf, sm.genInfo.genesisPledge)
vf = big.Add(vf, sm.genInfo.genesisMarketFunds)
// After UpgradeActorsV2Height these funds are accounted for in GetFilReserveDisbursed
if height <= build.UpgradeActorsV2Height {
// continue to use preIgnitionGenInfos, nothing changed at the Ignition epoch
vf = big.Add(vf, sm.preIgnitionGenInfos.genesisPledge)
// continue to use preIgnitionGenInfos, nothing changed at the Ignition epoch
vf = big.Add(vf, sm.preIgnitionGenInfos.genesisMarketFunds)
}
return vf, nil
}
func GetFilReserveDisbursed(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) {
ract, err := st.GetActor(builtin.ReserveAddress)
if err != nil {
return big.Zero(), xerrors.Errorf("failed to get reserve actor: %w", err)
}
// If money enters the reserve actor, this could lead to a negative term
return big.Sub(big.NewFromGo(build.InitialFilReserved), ract.Balance), nil
}
func GetFilMined(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) {
ractor, err := st.GetActor(reward.Address)
if err != nil {
@@ -1084,10 +1297,16 @@ func GetFilBurnt(ctx context.Context, st *state.StateTree) (abi.TokenAmount, err
func (sm *StateManager) GetCirculatingSupplyDetailed(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (api.CirculatingSupply, error) {
sm.genesisMsigLk.Lock()
defer sm.genesisMsigLk.Unlock()
if sm.genInfo == nil {
err := sm.setupGenesisActorsTestnet(ctx)
if sm.preIgnitionGenInfos == nil {
err := sm.setupPreIgnitionGenesisActorsTestnet(ctx)
if err != nil {
return api.CirculatingSupply{}, xerrors.Errorf("failed to setup genesis information: %w", err)
return api.CirculatingSupply{}, xerrors.Errorf("failed to setup pre-ignition genesis information: %w", err)
}
}
if sm.postIgnitionGenInfos == nil {
err := sm.setupPostIgnitionGenesisActors(ctx)
if err != nil {
return api.CirculatingSupply{}, xerrors.Errorf("failed to setup post-ignition genesis information: %w", err)
}
}
@@ -1096,6 +1315,14 @@ func (sm *StateManager) GetCirculatingSupplyDetailed(ctx context.Context, height
return api.CirculatingSupply{}, xerrors.Errorf("failed to calculate filVested: %w", err)
}
filReserveDisbursed := big.Zero()
if height > build.UpgradeActorsV2Height {
filReserveDisbursed, err = GetFilReserveDisbursed(ctx, st)
if err != nil {
return api.CirculatingSupply{}, xerrors.Errorf("failed to calculate filReserveDisbursed: %w", err)
}
}
filMined, err := GetFilMined(ctx, st)
if err != nil {
return api.CirculatingSupply{}, xerrors.Errorf("failed to calculate filMined: %w", err)
@@ -1112,6 +1339,7 @@ func (sm *StateManager) GetCirculatingSupplyDetailed(ctx context.Context, height
}
ret := types.BigAdd(filVested, filMined)
ret = types.BigAdd(ret, filReserveDisbursed)
ret = types.BigSub(ret, filBurnt)
ret = types.BigSub(ret, filLocked)
@@ -1138,21 +1366,14 @@ func (sm *StateManager) GetCirculatingSupply(ctx context.Context, height abi.Cha
}
func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoch) network.Version {
// TODO: move hard fork epoch checks to a schedule defined in build/
if build.UseNewestNetwork() {
return build.NewestNetworkVersion
// The epochs here are the _last_ epoch for every version, or -1 if the
// version is disabled.
for _, spec := range sm.networkVersions {
if height <= spec.atOrBelow {
return spec.networkVersion
}
}
if height <= build.UpgradeBreezeHeight {
return network.Version0
}
if height <= build.UpgradeSmokeHeight {
return network.Version1
}
return build.NewestNetworkVersion
return sm.latestVersion
}
func (sm *StateManager) GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error) {
@@ -1190,3 +1411,5 @@ func (sm *StateManager) GetMarketState(ctx context.Context, ts *types.TipSet) (m
}
return actState, nil
}
var _ StateManagerAPI = (*StateManager)(nil)
+121 -74
View File
@@ -9,6 +9,11 @@ import (
"runtime"
"strings"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/policy"
cid "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
@@ -17,22 +22,14 @@ import (
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/rt"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
account0 "github.com/filecoin-project/specs-actors/actors/builtin/account"
cron0 "github.com/filecoin-project/specs-actors/actors/builtin/cron"
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
exported0 "github.com/filecoin-project/specs-actors/actors/builtin/exported"
proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof"
exported2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/exported"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
@@ -102,6 +99,7 @@ func GetPowerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr addres
}
var mpow power.Claim
var minpow bool
if maddr != address.Undef {
var found bool
mpow, found, err = pas.MinerPower(maddr)
@@ -109,11 +107,11 @@ func GetPowerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr addres
// TODO: return an error when not found?
return power.Claim{}, power.Claim{}, false, err
}
}
minpow, err := pas.MinerNominalPowerMeetsConsensusMinimum(maddr)
if err != nil {
return power.Claim{}, power.Claim{}, false, err
minpow, err = pas.MinerNominalPowerMeetsConsensusMinimum(maddr)
if err != nil {
return power.Claim{}, power.Claim{}, false, err
}
}
return mpow, tpow, minpow, nil
@@ -368,6 +366,16 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
return cid.Undef, nil, err
}
for i := ts.Height(); i < height; i++ {
// handle state forks
base, err = sm.handleStateForks(ctx, base, i, traceFunc(&trace), ts)
if err != nil {
return cid.Undef, nil, xerrors.Errorf("error handling state forks: %w", err)
}
// TODO: should we also run cron here?
}
r := store.NewChainRand(sm.cs, ts.Cids())
vmopt := &vm.VMOpts{
StateBase: base,
@@ -379,21 +387,11 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
NtwkVersion: sm.GetNtwkVersion,
BaseFee: ts.Blocks()[0].ParentBaseFee,
}
vmi, err := vm.NewVM(ctx, vmopt)
vmi, err := sm.newVM(ctx, vmopt)
if err != nil {
return cid.Undef, nil, err
}
for i := ts.Height(); i < height; i++ {
// handle state forks
err = sm.handleStateForks(ctx, vmi.StateTree(), i, ts)
if err != nil {
return cid.Undef, nil, xerrors.Errorf("error handling state forks: %w", err)
}
// TODO: should we also run cron here?
}
for i, msg := range msgs {
// TODO: Use the signed message length for secp messages
ret, err := vmi.ApplyMessage(ctx, msg)
@@ -415,8 +413,9 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
func GetLookbackTipSetForRound(ctx context.Context, sm *StateManager, ts *types.TipSet, round abi.ChainEpoch) (*types.TipSet, error) {
var lbr abi.ChainEpoch
if round > build.WinningPoStSectorSetLookback {
lbr = round - build.WinningPoStSectorSetLookback
lb := policy.GetWinningPoStSectorSetLookback(sm.GetNtwkVersion(ctx, round))
if round > lb {
lbr = round - lb
}
// more null blocks than our lookback
@@ -496,7 +495,7 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule
return nil, nil
}
mpow, tpow, hmp, err := GetPowerRaw(ctx, sm, lbst, maddr)
mpow, tpow, _, err := GetPowerRaw(ctx, sm, lbst, maddr)
if err != nil {
return nil, xerrors.Errorf("failed to get power: %w", err)
}
@@ -511,15 +510,21 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule
return nil, xerrors.Errorf("resolving worker address: %w", err)
}
// TODO: Not ideal performance...This method reloads miner and power state (already looked up here and in GetPowerRaw)
eligible, err := MinerEligibleToMine(ctx, sm, maddr, ts, lbts)
if err != nil {
return nil, xerrors.Errorf("determining miner eligibility: %w", err)
}
return &api.MiningBaseInfo{
MinerPower: mpow.QualityAdjPower,
NetworkPower: tpow.QualityAdjPower,
Sectors: sectors,
WorkerKey: worker,
SectorSize: info.SectorSize,
PrevBeaconEntry: *prev,
BeaconEntries: entries,
HasMinPower: hmp,
MinerPower: mpow.QualityAdjPower,
NetworkPower: tpow.QualityAdjPower,
Sectors: sectors,
WorkerKey: worker,
SectorSize: info.SectorSize,
PrevBeaconEntry: *prev,
BeaconEntries: entries,
EligibleForMining: eligible,
}, nil
}
@@ -533,42 +538,23 @@ type MethodMeta struct {
var MethodsMap = map[cid.Cid]map[abi.MethodNum]MethodMeta{}
func init() {
cidToMethods := map[cid.Cid][2]interface{}{
// builtin.SystemActorCodeID: {builtin.MethodsSystem, system.Actor{} }- apparently it doesn't have methods
builtin0.InitActorCodeID: {builtin0.MethodsInit, init0.Actor{}},
builtin0.CronActorCodeID: {builtin0.MethodsCron, cron0.Actor{}},
builtin0.AccountActorCodeID: {builtin0.MethodsAccount, account0.Actor{}},
builtin0.StoragePowerActorCodeID: {builtin0.MethodsPower, power0.Actor{}},
builtin0.StorageMinerActorCodeID: {builtin0.MethodsMiner, miner0.Actor{}},
builtin0.StorageMarketActorCodeID: {builtin0.MethodsMarket, market0.Actor{}},
builtin0.PaymentChannelActorCodeID: {builtin0.MethodsPaych, paych0.Actor{}},
builtin0.MultisigActorCodeID: {builtin0.MethodsMultisig, msig0.Actor{}},
builtin0.RewardActorCodeID: {builtin0.MethodsReward, reward0.Actor{}},
builtin0.VerifiedRegistryActorCodeID: {builtin0.MethodsVerifiedRegistry, verifreg0.Actor{}},
}
// TODO: combine with the runtime actor registry.
var actors []rt.VMActor
actors = append(actors, exported0.BuiltinActors()...)
actors = append(actors, exported2.BuiltinActors()...)
for c, m := range cidToMethods {
exports := m[1].(vm.Invokee).Exports()
for _, actor := range actors {
exports := actor.Exports()
methods := make(map[abi.MethodNum]MethodMeta, len(exports))
// Explicitly add send, it's special.
// Note that builtin2.MethodSend = builtin0.MethodSend = 0.
methods[builtin0.MethodSend] = MethodMeta{
Name: "Send",
Params: reflect.TypeOf(new(abi.EmptyValue)),
Ret: reflect.TypeOf(new(abi.EmptyValue)),
}
// Learn method names from the builtin.Methods* structs.
rv := reflect.ValueOf(m[0])
rt := rv.Type()
nf := rt.NumField()
methodToName := make([]string, len(exports))
for i := 0; i < nf; i++ {
name := rt.Field(i).Name
number := rv.Field(i).Interface().(abi.MethodNum)
methodToName[number] = name
}
// Iterate over exported methods. Some of these _may_ be nil and
// must be skipped.
for number, export := range exports {
@@ -579,22 +565,19 @@ func init() {
ev := reflect.ValueOf(export)
et := ev.Type()
// Make sure the method name is correct.
// This is just a nice sanity check.
// Extract the method names using reflection. These
// method names always match the field names in the
// `builtin.Method*` structs (tested in the specs-actors
// tests).
fnName := runtime.FuncForPC(ev.Pointer()).Name()
fnName = strings.TrimSuffix(fnName[strings.LastIndexByte(fnName, '.')+1:], "-fm")
mName := methodToName[number]
if mName != fnName {
panic(fmt.Sprintf(
"actor method name is %s but exported method name is %s",
fnName, mName,
))
}
switch abi.MethodNum(number) {
case builtin0.MethodSend:
// Note that builtin2.MethodSend = builtin0.MethodSend = 0.
panic("method 0 is reserved for Send")
case builtin0.MethodConstructor:
// Note that builtin2.MethodConstructor = builtin0.MethodConstructor = 1.
if fnName != "Constructor" {
panic("method 1 is reserved for Constructor")
}
@@ -606,7 +589,7 @@ func init() {
Ret: et.Out(0),
}
}
MethodsMap[c] = methods
MethodsMap[actor.Code()] = methods
}
}
@@ -623,7 +606,7 @@ func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, me
return reflect.New(m.Ret.Elem()).Interface().(cbg.CBORUnmarshaler), nil
}
func MinerHasMinPower(ctx context.Context, sm *StateManager, addr address.Address, ts *types.TipSet) (bool, error) {
func minerHasMinPower(ctx context.Context, sm *StateManager, addr address.Address, ts *types.TipSet) (bool, error) {
pact, err := sm.LoadActor(ctx, power.Address, ts)
if err != nil {
return false, xerrors.Errorf("loading power actor state: %w", err)
@@ -637,6 +620,70 @@ func MinerHasMinPower(ctx context.Context, sm *StateManager, addr address.Addres
return ps.MinerNominalPowerMeetsConsensusMinimum(addr)
}
func MinerEligibleToMine(ctx context.Context, sm *StateManager, addr address.Address, baseTs *types.TipSet, lookbackTs *types.TipSet) (bool, error) {
hmp, err := minerHasMinPower(ctx, sm, addr, lookbackTs)
// TODO: We're blurring the lines between a "runtime network version" and a "Lotus upgrade epoch", is that unavoidable?
if sm.GetNtwkVersion(ctx, baseTs.Height()) <= network.Version3 {
return hmp, err
}
if err != nil {
return false, err
}
if !hmp {
return false, nil
}
// Post actors v2, also check MinerEligibleForElection with base ts
pact, err := sm.LoadActor(ctx, power.Address, baseTs)
if err != nil {
return false, xerrors.Errorf("loading power actor state: %w", err)
}
pstate, err := power.Load(sm.cs.Store(ctx), pact)
if err != nil {
return false, err
}
mact, err := sm.LoadActor(ctx, addr, baseTs)
if err != nil {
return false, xerrors.Errorf("loading miner actor state: %w", err)
}
mstate, err := miner.Load(sm.cs.Store(ctx), mact)
if err != nil {
return false, err
}
// Non-empty power claim.
if claim, found, err := pstate.MinerPower(addr); err != nil {
return false, err
} else if !found {
return false, err
} else if claim.QualityAdjPower.LessThanEqual(big.Zero()) {
return false, err
}
// No fee debt.
if debt, err := mstate.FeeDebt(); err != nil {
return false, err
} else if !debt.IsZero() {
return false, err
}
// No active consensus faults.
if mInfo, err := mstate.Info(); err != nil {
return false, err
} else if baseTs.Height() <= mInfo.ConsensusFaultElapsed {
return false, nil
}
return true, nil
}
func CheckTotalFIL(ctx context.Context, sm *StateManager, ts *types.TipSet) (abi.TokenAmount, error) {
str, err := state.LoadStateTree(sm.ChainStore().Store(ctx), ts.ParentState())
if err != nil {
+1 -1
View File
@@ -46,7 +46,7 @@ func ComputeNextBaseFee(baseFee types.BigInt, gasLimitUsed int64, noOfBlocks int
}
func (cs *ChainStore) ComputeBaseFee(ctx context.Context, ts *types.TipSet) (abi.TokenAmount, error) {
if ts.Height() > build.UpgradeBreezeHeight && ts.Height() < build.UpgradeBreezeHeight+build.BreezeGasTampingDuration {
if build.UpgradeBreezeHeight >= 0 && ts.Height() > build.UpgradeBreezeHeight && ts.Height() < build.UpgradeBreezeHeight+build.BreezeGasTampingDuration {
return abi.NewTokenAmount(100), nil
}
+15 -12
View File
@@ -11,24 +11,27 @@ import (
func TestBaseFee(t *testing.T) {
tests := []struct {
basefee uint64
limitUsed int64
noOfBlocks int
output uint64
basefee uint64
limitUsed int64
noOfBlocks int
preSmoke, postSmoke uint64
}{
{100e6, 0, 1, 87.5e6},
{100e6, 0, 5, 87.5e6},
{100e6, build.BlockGasTarget, 1, 103.125e6},
{100e6, build.BlockGasTarget * 2, 2, 103.125e6},
{100e6, build.BlockGasLimit * 2, 2, 112.5e6},
{100e6, build.BlockGasLimit * 1.5, 2, 110937500},
{100e6, 0, 1, 87.5e6, 87.5e6},
{100e6, 0, 5, 87.5e6, 87.5e6},
{100e6, build.BlockGasTarget, 1, 103.125e6, 100e6},
{100e6, build.BlockGasTarget * 2, 2, 103.125e6, 100e6},
{100e6, build.BlockGasLimit * 2, 2, 112.5e6, 112.5e6},
{100e6, build.BlockGasLimit * 1.5, 2, 110937500, 106.250e6},
}
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, 0)
assert.Equal(t, fmt.Sprintf("%d", test.output), output.String())
preSmoke := ComputeNextBaseFee(types.NewInt(test.basefee), test.limitUsed, test.noOfBlocks, build.UpgradeSmokeHeight-1)
assert.Equal(t, fmt.Sprintf("%d", test.preSmoke), preSmoke.String())
postSmoke := ComputeNextBaseFee(types.NewInt(test.basefee), test.limitUsed, test.noOfBlocks, build.UpgradeSmokeHeight+1)
assert.Equal(t, fmt.Sprintf("%d", test.postSmoke), postSmoke.String())
})
}
}
+1 -1
View File
@@ -31,7 +31,7 @@ func TestIndexSeeks(t *testing.T) {
ctx := context.TODO()
nbs := blockstore.NewTemporarySync()
cs := store.NewChainStore(nbs, syncds.MutexWrap(datastore.NewMapDatastore()), nil)
cs := store.NewChainStore(nbs, syncds.MutexWrap(datastore.NewMapDatastore()), nil, nil)
_, err = cs.Import(bytes.NewReader(gencar))
if err != nil {
+141 -32
View File
@@ -8,16 +8,23 @@ import (
"io"
"os"
"strconv"
"strings"
"sync"
"golang.org/x/sync/errgroup"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/minio/blake2b-simd"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/specs-actors/actors/builtin"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/journal"
bstore "github.com/filecoin-project/lotus/lib/blockstore"
@@ -32,7 +39,9 @@ import (
lru "github.com/hashicorp/golang-lru"
block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
dstore "github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/query"
cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2"
car "github.com/ipld/go-car"
@@ -96,7 +105,7 @@ type HeadChangeEvt struct {
// 2. a block => messages references cache.
type ChainStore struct {
bs bstore.Blockstore
ds dstore.Datastore
ds dstore.Batching
heaviestLk sync.Mutex
heaviest *types.TipSet
@@ -118,11 +127,15 @@ type ChainStore struct {
vmcalls vm.SyscallBuilder
evtTypes [1]journal.EventType
journal journal.Journal
}
func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallBuilder) *ChainStore {
func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallBuilder, j journal.Journal) *ChainStore {
c, _ := lru.NewARC(DefaultMsgMetaCacheSize)
tsc, _ := lru.NewARC(DefaultTipSetCacheSize)
if j == nil {
j = journal.NilJournal()
}
cs := &ChainStore{
bs: bs,
ds: ds,
@@ -131,10 +144,11 @@ func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallB
mmCache: c,
tsCache: tsc,
vmcalls: vmcalls,
journal: j,
}
cs.evtTypes = [1]journal.EventType{
evtTypeHeadChange: journal.J.RegisterEventType("sync", "head_change"),
evtTypeHeadChange: j.RegisterEventType("sync", "head_change"),
}
ci := NewChainIndex(cs.LoadTipSet)
@@ -282,6 +296,16 @@ func (cs *ChainStore) MarkBlockAsValidated(ctx context.Context, blkid cid.Cid) e
return nil
}
func (cs *ChainStore) UnmarkBlockAsValidated(ctx context.Context, blkid cid.Cid) error {
key := blockValidationCacheKeyPrefix.Instance(blkid.String())
if err := cs.ds.Delete(key); err != nil {
return xerrors.Errorf("removing from valid block cache: %w", err)
}
return nil
}
func (cs *ChainStore) SetGenesis(b *types.BlockHeader) error {
ts, err := types.NewTipSet([]*types.BlockHeader{b})
if err != nil {
@@ -363,7 +387,7 @@ func (cs *ChainStore) reorgWorker(ctx context.Context, initialNotifees []ReorgNo
continue
}
journal.J.RecordEvent(cs.evtTypes[evtTypeHeadChange], func() interface{} {
cs.journal.RecordEvent(cs.evtTypes[evtTypeHeadChange], func() interface{} {
return HeadChangeEvt{
From: r.old.Key(),
FromHeight: r.old.Height(),
@@ -425,6 +449,53 @@ func (cs *ChainStore) takeHeaviestTipSet(ctx context.Context, ts *types.TipSet)
return nil
}
// FlushValidationCache removes all results of block validation from the
// chain metadata store. Usually the first step after a new chain import.
func (cs *ChainStore) FlushValidationCache() error {
log.Infof("clearing block validation cache...")
dsWalk, err := cs.ds.Query(query.Query{
// Potential TODO: the validation cache is not a namespace on its own
// but is rather constructed as prefixed-key `foo:bar` via .Instance(), which
// in turn does not work with the filter, which can match only on `foo/bar`
//
// If this is addressed (blockcache goes into its own sub-namespace) then
// strings.HasPrefix(...) below can be skipped
//
//Prefix: blockValidationCacheKeyPrefix.String()
KeysOnly: true,
})
if err != nil {
return xerrors.Errorf("failed to initialize key listing query: %w", err)
}
allKeys, err := dsWalk.Rest()
if err != nil {
return xerrors.Errorf("failed to run key listing query: %w", err)
}
batch, err := cs.ds.Batch()
if err != nil {
return xerrors.Errorf("failed to open a DS batch: %w", err)
}
delCnt := 0
for _, k := range allKeys {
if strings.HasPrefix(k.Key, blockValidationCacheKeyPrefix.String()) {
delCnt++
batch.Delete(datastore.RawKey(k.Key)) // nolint:errcheck
}
}
if err := batch.Commit(); err != nil {
return xerrors.Errorf("failed to commit the DS batch: %w", err)
}
log.Infof("%d block validation entries cleared.", delCnt)
return nil
}
// SetHead sets the chainstores current 'best' head node.
// This should only be called if something is broken and needs fixing
func (cs *ChainStore) SetHead(ts *types.TipSet) error {
@@ -465,14 +536,25 @@ func (cs *ChainStore) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error) {
return v.(*types.TipSet), nil
}
var blks []*types.BlockHeader
for _, c := range tsk.Cids() {
b, err := cs.GetBlock(c)
if err != nil {
return nil, xerrors.Errorf("get block %s: %w", c, err)
}
// Fetch tipset block headers from blockstore in parallel
var eg errgroup.Group
cids := tsk.Cids()
blks := make([]*types.BlockHeader, len(cids))
for i, c := range cids {
i, c := i, c
eg.Go(func() error {
b, err := cs.GetBlock(c)
if err != nil {
return xerrors.Errorf("get block %s: %w", c, err)
}
blks = append(blks, b)
blks[i] = b
return nil
})
}
err := eg.Wait()
if err != nil {
return nil, err
}
ts, err := types.NewTipSet(blks)
@@ -732,7 +814,8 @@ func (cs *ChainStore) GetSignedMessage(c cid.Cid) (*types.SignedMessage, error)
func (cs *ChainStore) readAMTCids(root cid.Cid) ([]cid.Cid, error) {
ctx := context.TODO()
a, err := adt.AsArray(cs.Store(ctx), root)
// block headers use adt0, for now.
a, err := adt0.AsArray(cs.Store(ctx), root)
if err != nil {
return nil, xerrors.Errorf("amt load: %w", err)
}
@@ -925,7 +1008,8 @@ func (cs *ChainStore) MessagesForBlock(b *types.BlockHeader) ([]*types.Message,
func (cs *ChainStore) GetParentReceipt(b *types.BlockHeader, i int) (*types.MessageReceipt, error) {
ctx := context.TODO()
a, err := adt.AsArray(cs.Store(ctx), b.ParentMessageReceipts)
// block headers use adt0, for now.
a, err := adt0.AsArray(cs.Store(ctx), b.ParentMessageReceipts)
if err != nil {
return nil, xerrors.Errorf("amt load: %w", err)
}
@@ -1166,13 +1250,6 @@ func recurseLinks(bs bstore.Blockstore, walked *cid.Set, root cid.Cid, in []cid.
}
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()
}
seen := cid.NewSet()
walked := cid.NewSet()
h := &car.CarHeader{
Roots: ts.Cids(),
Version: 1,
@@ -1182,27 +1259,57 @@ func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRo
return xerrors.Errorf("failed to write car header: %s", err)
}
return cs.WalkSnapshot(ctx, ts, inclRecentRoots, skipOldMsgs, func(c cid.Cid) error {
blk, err := cs.bs.Get(c)
if err != nil {
return xerrors.Errorf("writing object to car, bs.Get: %w", err)
}
if err := carutil.LdWrite(w, c.Bytes(), blk.RawData()); err != nil {
return xerrors.Errorf("failed to write block to car output: %w", err)
}
return nil
})
}
func (cs *ChainStore) WalkSnapshot(ctx context.Context, ts *types.TipSet, inclRecentRoots abi.ChainEpoch, skipOldMsgs bool, cb func(cid.Cid) error) error {
if ts == nil {
ts = cs.GetHeaviestTipSet()
}
seen := cid.NewSet()
walked := cid.NewSet()
blocksToWalk := ts.Cids()
currentMinHeight := ts.Height()
walkChain := func(blk cid.Cid) error {
if !seen.Visit(blk) {
return nil
}
if err := cb(blk); err != nil {
return err
}
data, err := cs.bs.Get(blk)
if err != nil {
return xerrors.Errorf("getting block: %w", err)
}
if err := carutil.LdWrite(w, blk.Bytes(), data.RawData()); err != nil {
return xerrors.Errorf("failed to write block to car output: %w", err)
}
var b types.BlockHeader
if err := b.UnmarshalCBOR(bytes.NewBuffer(data.RawData())); err != nil {
return xerrors.Errorf("unmarshaling block header (cid=%s): %w", blk, err)
}
if currentMinHeight > b.Height {
currentMinHeight = b.Height
if currentMinHeight%builtin.EpochsInDay == 0 {
log.Infow("export", "height", currentMinHeight)
}
}
var cids []cid.Cid
if !skipOldMsgs || b.Height > ts.Height()-inclRecentRoots {
mcids, err := recurseLinks(cs.bs, walked, b.Messages, []cid.Cid{b.Messages})
@@ -1237,20 +1344,20 @@ func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRo
if c.Prefix().Codec != cid.DagCBOR {
continue
}
data, err := cs.bs.Get(c)
if err != nil {
return xerrors.Errorf("writing object to car (get %s): %w", c, err)
if err := cb(c); err != nil {
return err
}
if err := carutil.LdWrite(w, c.Bytes(), data.RawData()); err != nil {
return xerrors.Errorf("failed to write out car object: %w", err)
}
}
}
return nil
}
log.Infow("export started")
exportStart := build.Clock.Now()
for len(blocksToWalk) > 0 {
next := blocksToWalk[0]
blocksToWalk = blocksToWalk[1:]
@@ -1259,6 +1366,8 @@ func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRo
}
}
log.Infow("export finished", "duration", build.Clock.Now().Sub(exportStart).Seconds())
return nil
}
@@ -1301,7 +1410,7 @@ func (cs *ChainStore) GetLatestBeaconEntry(ts *types.TipSet) (*types.BeaconEntry
}, nil
}
return nil, xerrors.Errorf("found NO beacon entries in the 20 blocks prior to given tipset")
return nil, xerrors.Errorf("found NO beacon entries in the 20 latest tipsets")
}
type chainRand struct {
+6 -11
View File
@@ -8,12 +8,9 @@ import (
datastore "github.com/ipfs/go-datastore"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
@@ -22,11 +19,9 @@ import (
)
func init() {
miner0.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
}
power0.ConsensusMinerMinPower = big.NewInt(2048)
verifreg0.MinVerifiedDealSize = big.NewInt(256)
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
}
func BenchmarkGetRandomness(b *testing.B) {
@@ -67,7 +62,7 @@ func BenchmarkGetRandomness(b *testing.B) {
bs := blockstore.NewBlockstore(bds)
cs := store.NewChainStore(bs, mds, nil)
cs := store.NewChainStore(bs, mds, nil, nil)
b.ResetTimer()
@@ -101,7 +96,7 @@ func TestChainExportImport(t *testing.T) {
}
nbs := blockstore.NewTemporary()
cs := store.NewChainStore(nbs, datastore.NewMapDatastore(), nil)
cs := store.NewChainStore(nbs, datastore.NewMapDatastore(), nil, nil)
root, err := cs.Import(buf)
if err != nil {
+54 -48
View File
@@ -10,7 +10,6 @@ import (
"golang.org/x/xerrors"
address "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/util/adt"
lru "github.com/hashicorp/golang-lru"
blocks "github.com/ipfs/go-block-format"
bserv "github.com/ipfs/go-blockservice"
@@ -24,6 +23,8 @@ import (
"go.opencensus.io/stats"
"go.opencensus.io/tag"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
@@ -43,7 +44,11 @@ var log = logging.Logger("sub")
var ErrSoftFailure = errors.New("soft validation failure")
var ErrInsufficientPower = errors.New("incoming block's miner does not have minimum power")
func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *chain.Syncer, bserv bserv.BlockService, cmgr connmgr.ConnManager) {
func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *chain.Syncer, bs bserv.BlockService, cmgr connmgr.ConnManager) {
// Timeout after (block time + propagation delay). This is useless at
// this point.
timeout := time.Duration(build.BlockDelaySecs+build.PropagationDelaySecs) * time.Second
for {
msg, err := bsub.Next(ctx)
if err != nil {
@@ -64,15 +69,22 @@ func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *cha
src := msg.GetFrom()
go func() {
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
// NOTE: we could also share a single session between
// all requests but that may have other consequences.
ses := bserv.NewSession(ctx, bs)
start := build.Clock.Now()
log.Debug("about to fetch messages for block from pubsub")
bmsgs, err := FetchMessagesByCids(context.TODO(), bserv, blk.BlsMessages)
bmsgs, err := FetchMessagesByCids(ctx, ses, blk.BlsMessages)
if err != nil {
log.Errorf("failed to fetch all bls messages for block received over pubusb: %s; source: %s", err, src)
return
}
smsgs, err := FetchSignedMessagesByCids(context.TODO(), bserv, blk.SecpkMessages)
smsgs, err := FetchSignedMessagesByCids(ctx, ses, blk.SecpkMessages)
if err != nil {
log.Errorf("failed to fetch all secpk messages for block received over pubusb: %s; source: %s", err, src)
return
@@ -97,7 +109,7 @@ func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *cha
func FetchMessagesByCids(
ctx context.Context,
bserv bserv.BlockService,
bserv bserv.BlockGetter,
cids []cid.Cid,
) ([]*types.Message, error) {
out := make([]*types.Message, len(cids))
@@ -108,12 +120,6 @@ func FetchMessagesByCids(
return err
}
// FIXME: We already sort in `fetchCids`, we are duplicating too much work,
// we don't need to pass the index.
if out[i] != nil {
return fmt.Errorf("received duplicate message")
}
out[i] = msg
return nil
})
@@ -126,7 +132,7 @@ func FetchMessagesByCids(
// FIXME: Duplicate of above.
func FetchSignedMessagesByCids(
ctx context.Context,
bserv bserv.BlockService,
bserv bserv.BlockGetter,
cids []cid.Cid,
) ([]*types.SignedMessage, error) {
out := make([]*types.SignedMessage, len(cids))
@@ -137,10 +143,6 @@ func FetchSignedMessagesByCids(
return err
}
if out[i] != nil {
return fmt.Errorf("received duplicate message")
}
out[i] = smsg
return nil
})
@@ -156,42 +158,45 @@ func FetchSignedMessagesByCids(
// blocks we did not request.
func fetchCids(
ctx context.Context,
bserv bserv.BlockService,
bserv bserv.BlockGetter,
cids []cid.Cid,
cb func(int, blocks.Block) error,
) error {
// FIXME: Why don't we use the context here?
fetchedBlocks := bserv.GetBlocks(context.TODO(), cids)
ctx, cancel := context.WithCancel(ctx)
defer cancel()
cidIndex := make(map[cid.Cid]int)
for i, c := range cids {
cidIndex[c] = i
}
if len(cids) != len(cidIndex) {
return fmt.Errorf("duplicate CIDs in fetchCids input")
}
for i := 0; i < len(cids); i++ {
select {
case block, ok := <-fetchedBlocks:
if !ok {
// Closed channel, no more blocks fetched, check if we have all
// of the CIDs requested.
// FIXME: Review this check. We don't call the callback on the
// last index?
if i == len(cids)-1 {
break
}
return fmt.Errorf("failed to fetch all messages")
}
ix, ok := cidIndex[block.Cid()]
if !ok {
return fmt.Errorf("received message we didnt ask for")
}
if err := cb(ix, block); err != nil {
return err
}
for block := range bserv.GetBlocks(ctx, cids) {
ix, ok := cidIndex[block.Cid()]
if !ok {
// Ignore duplicate/unexpected blocks. This shouldn't
// happen, but we can be safe.
log.Errorw("received duplicate/unexpected block when syncing", "cid", block.Cid())
continue
}
// Record that we've received the block.
delete(cidIndex, block.Cid())
if err := cb(ix, block); err != nil {
return err
}
}
if len(cidIndex) > 0 {
err := ctx.Err()
if err == nil {
err = fmt.Errorf("failed to fetch %d messages for unknown reasons", len(cidIndex))
}
return err
}
return nil
@@ -374,9 +379,10 @@ func (bv *BlockValidator) isChainNearSynced() bool {
func (bv *BlockValidator) validateMsgMeta(ctx context.Context, msg *types.BlockMsg) error {
// TODO there has to be a simpler way to do this without the blockstore dance
store := adt.WrapStore(ctx, cbor.NewCborStore(blockstore.NewTemporary()))
bmArr := adt.MakeEmptyArray(store)
smArr := adt.MakeEmptyArray(store)
// block headers use adt0
store := adt0.WrapStore(ctx, cbor.NewCborStore(blockstore.NewTemporary()))
bmArr := adt0.MakeEmptyArray(store)
smArr := adt0.MakeEmptyArray(store)
for i, m := range msg.BlsMessages {
c := cbg.CborCid(m)
@@ -473,14 +479,14 @@ func (bv *BlockValidator) checkPowerAndGetWorkerKey(ctx context.Context, bh *typ
return address.Undef, ErrSoftFailure
}
hmp, err := stmgr.MinerHasMinPower(ctx, bv.stmgr, bh.Miner, lbts)
eligible, err := stmgr.MinerEligibleToMine(ctx, bv.stmgr, bh.Miner, baseTs, lbts)
if err != nil {
log.Warnf("failed to determine if incoming block's miner has minimum power: %s", err)
return address.Undef, ErrSoftFailure
}
if !hmp {
log.Warnf("incoming block's miner does not have minimum power")
if !eligible {
log.Warnf("incoming block's miner is ineligible")
return address.Undef, ErrInsufficientPower
}
+63
View File
@@ -0,0 +1,63 @@
package sub
import (
"context"
"testing"
address "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
)
type getter struct {
msgs []*types.Message
}
func (g *getter) GetBlock(ctx context.Context, c cid.Cid) (blocks.Block, error) { panic("NYI") }
func (g *getter) GetBlocks(ctx context.Context, ks []cid.Cid) <-chan blocks.Block {
ch := make(chan blocks.Block, len(g.msgs))
for _, m := range g.msgs {
by, err := m.Serialize()
if err != nil {
panic(err)
}
b, err := blocks.NewBlockWithCid(by, m.Cid())
if err != nil {
panic(err)
}
ch <- b
}
close(ch)
return ch
}
func TestFetchCidsWithDedup(t *testing.T) {
msgs := []*types.Message{}
for i := 0; i < 10; i++ {
msgs = append(msgs, &types.Message{
From: address.TestAddress,
To: address.TestAddress,
Nonce: uint64(i),
})
}
cids := []cid.Cid{}
for _, m := range msgs {
cids = append(cids, m.Cid())
}
g := &getter{msgs}
// the cids have a duplicate
res, err := FetchMessagesByCids(context.TODO(), g, append(cids, cids[0]))
t.Logf("err: %+v", err)
t.Logf("res: %+v", res)
if err == nil {
t.Errorf("there should be an error")
}
if err == nil && (res[0] == nil || res[len(res)-1] == nil) {
t.Fatalf("there is a nil message: first %p, last %p", res[0], res[len(res)-1])
}
}

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