Compare commits

..
455 Commits
Author SHA1 Message Date
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
Ł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
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
Travis Person ae3691e0a2 lotus-pcr: zero refund 2020-10-07 21:53:56 +00: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
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
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
Ł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
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
273 changed files with 15077 additions and 5752 deletions
+1
View File
@@ -13,3 +13,4 @@
### Conformance testing.
conformance/ @raulk
extern/test-vectors @raulk
cmd/tvx @raulk
+216
View File
@@ -1,5 +1,221 @@
# Lotus changelog
# 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.
+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
+32 -9
View File
@@ -176,6 +176,9 @@ type FullNode interface {
// 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 +192,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 +250,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 +283,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.
@@ -385,10 +393,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)
@@ -470,6 +484,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 +536,7 @@ type DealInfo struct {
DealID abi.DealID
CreationTime time.Time
Verified bool
}
type MsgLookup struct {
@@ -725,6 +746,8 @@ type ActiveSync struct {
type SyncState struct {
ActiveSyncs []ActiveSync
VMApplied uint64
}
type SyncStateStage int
@@ -789,14 +812,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 {
+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 {
+53 -15
View File
@@ -112,6 +112,7 @@ type FullNodeStruct struct {
SyncMarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"`
SyncUnmarkBad func(ctx context.Context, bcid cid.Cid) 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 +122,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 +132,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 +158,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"`
@@ -200,7 +204,9 @@ 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"`
@@ -237,6 +243,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 +325,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"`
}
}
@@ -484,7 +494,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 +561,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 +645,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)
}
@@ -735,6 +753,10 @@ func (c *FullNodeStruct) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string
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)
}
@@ -883,10 +905,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)
}
@@ -1015,6 +1045,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 +1289,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) {
+38 -1
View File
@@ -12,15 +12,36 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node"
"github.com/filecoin-project/lotus/node/impl"
)
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, 1, OneMiner, node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
Network: build.ActorUpgradeNetworkVersion,
Height: upgradeHeight,
Migration: stmgr.UpgradeActorsV2,
}}))
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@@ -94,6 +115,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
+4 -1
View File
@@ -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)
}
}
+67 -9
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"
@@ -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)
+2 -1
View File
@@ -12,6 +12,7 @@ import (
"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 {
@@ -44,7 +45,7 @@ type StorageMiner struct {
//
// 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, nFull int, storage []StorageMiner, opts ...node.Option) ([]TestNode, []TestStorageNode)
type testSuite struct {
makeNodes APIBuilder
}
+47 -24
View File
@@ -15,9 +15,11 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/extern/sector-storage/mock"
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
"github.com/filecoin-project/lotus/node"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
bminer "github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/lotus/node/impl"
@@ -114,8 +116,29 @@ 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, 1, OneMiner, node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
Network: build.ActorUpgradeNetworkVersion,
Height: upgradeHeight,
Migration: stmgr.UpgradeActorsV2,
}}))
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@@ -129,17 +152,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 +183,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 +214,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 +237,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 +262,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 +292,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 +319,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 +344,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
+17 -8
View File
@@ -3,28 +3,37 @@
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
var UpgradeActorsV2Height = abi.ChainEpoch(10)
var UpgradeLiftoffHeight = abi.ChainEpoch(-4)
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.Version4
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
+22 -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,18 @@ 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
UpgradeActorsV2Height abi.ChainEpoch = 10
UpgradeLiftoffHeight abi.ChainEpoch = -4
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
}
NewestNetworkVersion = network.Version2
ActorUpgradeNetworkVersion = network.Version3
NewestNetworkVersion = network.Version4
ActorUpgradeNetworkVersion = network.Version4
Devnet = true
)
+32 -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,34 @@ const BreezeGasTampingDuration = 120
const UpgradeSmokeHeight = 51000
const UpgradeIgnitionHeight = 94000
const UpgradeRefuelHeight = 130800
var UpgradeActorsV2Height = abi.ChainEpoch(138720)
// 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.9.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
}
+16 -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)
}
+16 -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
}
+98
View File
@@ -0,0 +1,98 @@
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
}
+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)
}
+18 -6
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
}
@@ -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.CumsumBaseline, 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:
return Version2
default:
panic(fmt.Sprintf("unsupported network version %d", version))
}
}
+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,
+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
+5 -5
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"
@@ -121,9 +122,8 @@ var DefaultRemainderAccountActor = genesis.Actor{
}
func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
miner0.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
}
// 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)
@@ -225,7 +225,7 @@ 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()),
}
+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) {
+4 -8
View File
@@ -6,6 +6,8 @@ import (
"encoding/json"
"fmt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
cbor "github.com/ipfs/go-ipld-cbor"
@@ -24,7 +26,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 +116,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 +297,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)
}
+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)
}
+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
+44 -85
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 (
@@ -197,9 +196,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 +215,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 +251,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
}
@@ -486,7 +493,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 +560,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 +628,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 +650,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 +685,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 +722,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
@@ -795,96 +802,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) {
+155
View File
@@ -0,0 +1,155 @@
package messagesigner
import (
"bytes"
"context"
"sync"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"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"
)
const dsKeyActorNonce = "ActorNextNonce"
var log = logging.Logger("messagesigner")
type mpoolAPI 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 *wallet.Wallet
lk sync.Mutex
mpool mpoolAPI
ds datastore.Batching
}
func NewMessageSigner(wallet *wallet.Wallet, mpool *messagepool.MessagePool, ds dtypes.MetadataDS) *MessageSigner {
return newMessageSigner(wallet, mpool, ds)
}
func newMessageSigner(wallet *wallet.Wallet, mpool mpoolAPI, 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
sig, err := ms.wallet.Sign(ctx, msg.From, msg.Cid().Bytes())
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.GenerateKey(crypto.SigTypeSecp256k1)
require.NoError(t, err)
from2, err := w.GenerateKey(crypto.SigTypeSecp256k1)
require.NoError(t, err)
to1, err := w.GenerateKey(crypto.SigTypeSecp256k1)
require.NoError(t, err)
to2, err := w.GenerateKey(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)
}
+586 -40
View File
@@ -1,44 +1,172 @@
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"
states2 "github.com/filecoin-project/specs-actors/v2/actors/states"
"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.UpgradeLiftoffHeight,
Network: network.Version4,
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 +192,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 +255,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 +282,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 +324,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 +338,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 +428,438 @@ 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)
}
newStateTree, err := states2.LoadTree(store, newHamtRoot)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to load new state tree: %w", err)
}
// Check all state-tree invariants.
if msgs, err := states2.CheckStateInvariants(newStateTree, types.TotalFilecoinInt); err != nil {
return cid.Undef, xerrors.Errorf("failed to check new state tree: %w", err)
} else if !msgs.IsEmpty() {
// This error is going to be really nasty.
return cid.Undef, xerrors.Errorf("network upgrade failed: %v", msgs.Messages())
}
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
+133 -40
View File
@@ -8,37 +8,34 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/cbor"
"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"
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"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"
"github.com/ipfs/go-cid"
ipldcbor "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 +43,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 +67,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 +77,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 +110,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 +174,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)
}
@@ -222,3 +234,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())
}
}
}
+258 -64
View File
@@ -5,6 +5,8 @@ import (
"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 +26,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"
@@ -38,24 +39,83 @@ import (
var log = logging.Logger("statemgr")
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 +183,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 +194,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 +213,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 +268,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 +338,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 +354,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 +372,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)
}
@@ -837,7 +918,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 +950,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 +985,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 +993,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 +1062,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 +1152,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 +1180,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 +1270,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 +1288,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 +1312,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 +1339,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) {
+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())
})
}
}
+82 -28
View File
@@ -10,14 +10,20 @@ import (
"strconv"
"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"
@@ -282,6 +288,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 {
@@ -465,14 +481,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 +759,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 +953,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 +1195,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 +1204,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 +1289,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 +1311,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 +1355,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 {
+4 -9
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) {
+27 -15
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))
@@ -126,7 +138,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))
@@ -156,12 +168,11 @@ 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)
fetchedBlocks := bserv.GetBlocks(ctx, cids)
cidIndex := make(map[cid.Cid]int)
for i, c := range cids {
@@ -374,9 +385,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 +485,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
}
+76 -52
View File
@@ -11,12 +11,15 @@ import (
"sync"
"time"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/specs-actors/actors/runtime/proof"
"github.com/Gurpartap/async"
"github.com/hashicorp/go-multierror"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2"
@@ -32,9 +35,10 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/util/adt"
blst "github.com/supranational/blst/bindings/go"
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/builtin/power"
@@ -374,21 +378,28 @@ func (syncer *Syncer) InformNewBlock(from peer.ID, blk *types.FullBlock) bool {
return syncer.InformNewHead(from, fts)
}
func copyBlockstore(from, to bstore.Blockstore) error {
cids, err := from.AllKeysChan(context.TODO())
func copyBlockstore(ctx context.Context, from, to bstore.Blockstore) error {
ctx, span := trace.StartSpan(ctx, "copyBlockstore")
defer span.End()
cids, err := from.AllKeysChan(ctx)
if err != nil {
return err
}
// TODO: should probably expose better methods on the blockstore for this operation
var blks []blocks.Block
for c := range cids {
b, err := from.Get(c)
if err != nil {
return err
}
if err := to.Put(b); err != nil {
return err
}
blks = append(blks, b)
}
if err := to.PutMany(blks); err != nil {
return err
}
return nil
@@ -447,9 +458,10 @@ func zipTipSetAndMessages(bs cbor.IpldStore, ts *types.TipSet, allbmsgs []*types
// computeMsgMeta computes the root CID of the combined arrays of message CIDs
// of both types (BLS and Secpk).
func computeMsgMeta(bs cbor.IpldStore, bmsgCids, smsgCids []cid.Cid) (cid.Cid, error) {
store := adt.WrapStore(context.TODO(), bs)
bmArr := adt.MakeEmptyArray(store)
smArr := adt.MakeEmptyArray(store)
// block headers use adt0
store := adt0.WrapStore(context.TODO(), bs)
bmArr := adt0.MakeEmptyArray(store)
smArr := adt0.MakeEmptyArray(store)
for i, m := range bmsgCids {
c := cbg.CborCid(m)
@@ -589,7 +601,7 @@ func isPermanent(err error) bool {
return !errors.Is(err, ErrTemporal)
}
func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet) error {
func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet, useCache bool) error {
ctx, span := trace.StartSpan(ctx, "validateTipSet")
defer span.End()
@@ -605,7 +617,7 @@ func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet)
b := b // rebind to a scoped variable
futures = append(futures, async.Err(func() error {
if err := syncer.ValidateBlock(ctx, b); err != nil {
if err := syncer.ValidateBlock(ctx, b, useCache); err != nil {
if isPermanent(err) {
syncer.bad.Add(b.Cid(), NewBadBlockReason([]cid.Cid{b.Cid()}, err.Error()))
}
@@ -672,7 +684,7 @@ func blockSanityChecks(h *types.BlockHeader) error {
}
// ValidateBlock should match up with 'Semantical Validation' in validation.md in the spec
func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (err error) {
func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock, useCache bool) (err error) {
defer func() {
// b.Cid() could panic for empty blocks that are used in tests.
if rerr := recover(); rerr != nil {
@@ -681,13 +693,15 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
}
}()
isValidated, err := syncer.store.IsBlockValidated(ctx, b.Cid())
if err != nil {
return xerrors.Errorf("check block validation cache %s: %w", b.Cid(), err)
}
if useCache {
isValidated, err := syncer.store.IsBlockValidated(ctx, b.Cid())
if err != nil {
return xerrors.Errorf("check block validation cache %s: %w", b.Cid(), err)
}
if isValidated {
return nil
if isValidated {
return nil
}
}
validationStart := build.Clock.Now()
@@ -774,31 +788,35 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
b.Header.ParentWeight, pweight)
}
// Stuff that needs stateroot / worker address
stateroot, precp, err := syncer.sm.TipSetState(ctx, baseTs)
if err != nil {
return xerrors.Errorf("get tipsetstate(%d, %s) failed: %w", h.Height, h.Parents, err)
}
if stateroot != h.ParentStateRoot {
msgs, err := syncer.store.MessagesForTipset(baseTs)
stateRootCheck := async.Err(func() error {
stateroot, precp, err := syncer.sm.TipSetState(ctx, baseTs)
if err != nil {
log.Error("failed to load messages for tipset during tipset state mismatch error: ", err)
} else {
log.Warn("Messages for tipset with mismatching state:")
for i, m := range msgs {
mm := m.VMMessage()
log.Warnf("Message[%d]: from=%s to=%s method=%d params=%x", i, mm.From, mm.To, mm.Method, mm.Params)
}
return xerrors.Errorf("get tipsetstate(%d, %s) failed: %w", h.Height, h.Parents, err)
}
return xerrors.Errorf("parent state root did not match computed state (%s != %s)", stateroot, h.ParentStateRoot)
}
if stateroot != h.ParentStateRoot {
msgs, err := syncer.store.MessagesForTipset(baseTs)
if err != nil {
log.Error("failed to load messages for tipset during tipset state mismatch error: ", err)
} else {
log.Warn("Messages for tipset with mismatching state:")
for i, m := range msgs {
mm := m.VMMessage()
log.Warnf("Message[%d]: from=%s to=%s method=%d params=%x", i, mm.From, mm.To, mm.Method, mm.Params)
}
}
if precp != h.ParentMessageReceipts {
return xerrors.Errorf("parent receipts root did not match computed value (%s != %s)", precp, h.ParentMessageReceipts)
}
return xerrors.Errorf("parent state root did not match computed state (%s != %s)", stateroot, h.ParentStateRoot)
}
if precp != h.ParentMessageReceipts {
return xerrors.Errorf("parent receipts root did not match computed value (%s != %s)", precp, h.ParentMessageReceipts)
}
return nil
})
// Stuff that needs worker address
waddr, err := stmgr.GetMinerWorkerRaw(ctx, syncer.sm, lbst, h.Miner)
if err != nil {
return xerrors.Errorf("GetMinerWorkerRaw failed: %w", err)
@@ -809,13 +827,13 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
return xerrors.Errorf("block is not claiming to be a winner")
}
hp, err := stmgr.MinerHasMinPower(ctx, syncer.sm, h.Miner, lbts)
eligible, err := stmgr.MinerEligibleToMine(ctx, syncer.sm, h.Miner, baseTs, lbts)
if err != nil {
return xerrors.Errorf("determining if miner has min power failed: %w", err)
}
if !hp {
return xerrors.New("block's miner does not meet minimum power threshold")
if !eligible {
return xerrors.New("block's miner is ineligible to mine")
}
rBeacon := *prevBeacon
@@ -919,6 +937,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
winnerCheck,
msgsCheck,
baseFeeCheck,
stateRootCheck,
}
var merr error
@@ -946,8 +965,10 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
return mulErr
}
if err := syncer.store.MarkBlockAsValidated(ctx, b.Cid()); err != nil {
return xerrors.Errorf("caching block validation %s: %w", b.Cid(), err)
if useCache {
if err := syncer.store.MarkBlockAsValidated(ctx, b.Cid()); err != nil {
return xerrors.Errorf("caching block validation %s: %w", b.Cid(), err)
}
}
return nil
@@ -1070,7 +1091,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
return xerrors.Errorf("failed to get actor: %w", err)
}
if !act.IsAccountActor() {
if !builtin.IsAccountActor(act.Code) {
return xerrors.New("Sender must be an account actor")
}
nonces[m.From] = act.Nonce
@@ -1084,9 +1105,9 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
return nil
}
store := adt.WrapStore(ctx, cst)
store := adt0.WrapStore(ctx, cst)
bmArr := adt.MakeEmptyArray(store)
bmArr := adt0.MakeEmptyArray(store)
for i, m := range b.BlsMessages {
if err := checkMsg(m); err != nil {
return xerrors.Errorf("block had invalid bls message at index %d: %w", i, err)
@@ -1098,7 +1119,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
}
}
smArr := adt.MakeEmptyArray(store)
smArr := adt0.MakeEmptyArray(store)
for i, m := range b.SecpkMessages {
if err := checkMsg(m); err != nil {
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
@@ -1449,7 +1470,7 @@ func (syncer *Syncer) syncMessagesAndCheckState(ctx context.Context, headers []*
return syncer.iterFullTipsets(ctx, headers, func(ctx context.Context, fts *store.FullTipSet) error {
log.Debugw("validating tipset", "height", fts.TipSet().Height(), "size", len(fts.TipSet().Cids()))
if err := syncer.ValidateTipSet(ctx, fts); err != nil {
if err := syncer.ValidateTipSet(ctx, fts, true); err != nil {
log.Errorf("failed to validate tipset: %+v", err)
return xerrors.Errorf("message processing failed: %w", err)
}
@@ -1515,11 +1536,11 @@ func (syncer *Syncer) iterFullTipsets(ctx context.Context, headers []*types.TipS
return err
}
if err := persistMessages(bs, bstip); err != nil {
if err := persistMessages(ctx, bs, bstip); err != nil {
return err
}
if err := copyBlockstore(bs, syncer.store.Blockstore()); err != nil {
if err := copyBlockstore(ctx, bs, syncer.store.Blockstore()); err != nil {
return xerrors.Errorf("message processing failed: %w", err)
}
}
@@ -1596,7 +1617,10 @@ func (syncer *Syncer) fetchMessages(ctx context.Context, headers []*types.TipSet
return batch, nil
}
func persistMessages(bs bstore.Blockstore, bst *exchange.CompactedMessages) error {
func persistMessages(ctx context.Context, bs bstore.Blockstore, bst *exchange.CompactedMessages) error {
_, span := trace.StartSpan(ctx, "persistMessages")
defer span.End()
for _, m := range bst.Bls {
//log.Infof("putting BLS message: %s", m.Cid())
if _, err := store.PutMessage(bs, m); err != nil {
@@ -1728,7 +1752,7 @@ func (syncer *Syncer) getLatestBeaconEntry(_ context.Context, ts *types.TipSet)
cur = next
}
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")
}
func (syncer *Syncer) IsEpochBeyondCurrMax(epoch abi.ChainEpoch) bool {
+6 -11
View File
@@ -19,13 +19,10 @@ import (
"github.com/filecoin-project/go-address"
"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/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/gen/slashfilter"
"github.com/filecoin-project/lotus/chain/store"
@@ -43,11 +40,9 @@ func init() {
if err != nil {
panic(err)
}
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 source = 0
@@ -737,7 +732,7 @@ func TestSyncInputs(t *testing.T) {
err := s.ValidateBlock(context.TODO(), &types.FullBlock{
Header: &types.BlockHeader{},
})
}, false)
if err == nil {
t.Fatal("should error on empty block")
}
@@ -746,7 +741,7 @@ func TestSyncInputs(t *testing.T) {
h.ElectionProof = nil
err = s.ValidateBlock(context.TODO(), &types.FullBlock{Header: h})
err = s.ValidateBlock(context.TODO(), &types.FullBlock{Header: h}, false)
if err == nil {
t.Fatal("should error on block with nil election proof")
}
-18
View File
@@ -4,8 +4,6 @@ import (
"errors"
"github.com/ipfs/go-cid"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
)
var ErrActorNotFound = errors.New("actor not found")
@@ -17,19 +15,3 @@ type Actor struct {
Nonce uint64
Balance BigInt
}
func (a *Actor) IsAccountActor() bool {
return a.Code == builtin0.AccountActorCodeID
}
func (a *Actor) IsStorageMinerActor() bool {
return a.Code == builtin0.StorageMinerActorCodeID
}
func (a *Actor) IsMultisigActor() bool {
return a.Code == builtin0.MultisigActorCodeID
}
func (a *Actor) IsPaymentChannelActor() bool {
return a.Code == builtin0.PaymentChannelActorCodeID
}
+8 -8
View File
@@ -1648,7 +1648,7 @@ func (t *StateRoot) MarshalCBOR(w io.Writer) error {
scratch := make([]byte, 9)
// t.Version (uint64) (uint64)
// t.Version (types.StateTreeVersion) (uint64)
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Version)); err != nil {
return err
@@ -1687,7 +1687,7 @@ func (t *StateRoot) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.Version (uint64) (uint64)
// t.Version (types.StateTreeVersion) (uint64)
{
@@ -1698,7 +1698,7 @@ func (t *StateRoot) UnmarshalCBOR(r io.Reader) error {
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Version = uint64(extra)
t.Version = StateTreeVersion(extra)
}
// t.Actors (cid.Cid) (struct)
@@ -1728,22 +1728,22 @@ func (t *StateRoot) UnmarshalCBOR(r io.Reader) error {
return nil
}
var lengthBufStateInfo = []byte{128}
var lengthBufStateInfo0 = []byte{128}
func (t *StateInfo) MarshalCBOR(w io.Writer) error {
func (t *StateInfo0) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write(lengthBufStateInfo); err != nil {
if _, err := w.Write(lengthBufStateInfo0); err != nil {
return err
}
return nil
}
func (t *StateInfo) UnmarshalCBOR(r io.Reader) error {
*t = StateInfo{}
func (t *StateInfo0) UnmarshalCBOR(r io.Reader) error {
*t = StateInfo0{}
br := cbg.GetPeeker(r)
scratch := make([]byte, 8)
+14 -3
View File
@@ -2,9 +2,20 @@ package types
import "github.com/ipfs/go-cid"
// StateTreeVersion is the version of the state tree itself, independent of the
// network version or the actors version.
type StateTreeVersion uint64
const (
// StateTreeVersion0 corresponds to actors < v2.
StateTreeVersion0 StateTreeVersion = iota
// StateTreeVersion1 corresponds to actors >= v2.
StateTreeVersion1
)
type StateRoot struct {
// State root version. Versioned along with actors (for now).
Version uint64
// State tree version.
Version StateTreeVersion
// Actors tree. The structure depends on the state root version.
Actors cid.Cid
// Info. The structure depends on the state root version.
@@ -12,4 +23,4 @@ type StateRoot struct {
}
// TODO: version this.
type StateInfo struct{}
type StateInfo0 struct{}
+7 -3
View File
@@ -167,12 +167,16 @@ func (ts *TipSet) Equals(ots *TipSet) bool {
return false
}
if len(ts.blks) != len(ots.blks) {
if ts.height != ots.height {
return false
}
for i, b := range ts.blks {
if b.Cid() != ots.blks[i].Cid() {
if len(ts.cids) != len(ots.cids) {
return false
}
for i, cid := range ts.cids {
if cid != ots.cids[i] {
return false
}
}
-22
View File
@@ -1,22 +0,0 @@
package types
import (
"encoding/base64"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
cbor "github.com/ipfs/go-ipld-cbor"
)
func DecodeSignedVoucher(s string) (*paych.SignedVoucher, error) {
data, err := base64.RawURLEncoding.DecodeString(s)
if err != nil {
return nil, err
}
var sv paych.SignedVoucher
if err := cbor.DecodeInto(data, &sv); err != nil {
return nil, err
}
return &sv, nil
}
+40
View File
@@ -1,9 +1,12 @@
package chain
import (
"crypto/rand"
"encoding/json"
"testing"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
)
@@ -35,3 +38,40 @@ func TestSignedMessageJsonRoundtrip(t *testing.T) {
t.Fatal(err)
}
}
func TestAddressType(t *testing.T) {
build.SetAddressNetwork(address.Testnet)
addr, err := makeRandomAddress()
if err != nil {
t.Fatal(err)
}
if string(addr[0]) != address.TestnetPrefix {
t.Fatalf("address should start with %s", address.TestnetPrefix)
}
build.SetAddressNetwork(address.Mainnet)
addr, err = makeRandomAddress()
if err != nil {
t.Fatal(err)
}
if string(addr[0]) != address.MainnetPrefix {
t.Fatalf("address should start with %s", address.MainnetPrefix)
}
}
func makeRandomAddress() (string, error) {
bytes := make([]byte, 32)
_, err := rand.Read(bytes)
if err != nil {
return "", err
}
addr, err := address.NewActorAddress(bytes)
if err != nil {
return "", err
}
return addr.String(), nil
}
+3 -6
View File
@@ -6,28 +6,25 @@ import (
"math/rand"
"os"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/go-address"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/mock"
"github.com/filecoin-project/lotus/chain/vectors"
"github.com/filecoin-project/lotus/chain/wallet"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
)
func init() {
verifreg0.MinVerifiedDealSize = big.NewInt(2048)
power0.ConsensusMinerMinPower = big.NewInt(2048)
policy.SetMinVerifiedDealSize(abi.NewStoragePower(2048))
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
}
func MakeHeaderVectors() []vectors.HeaderVector {
+1 -2
View File
@@ -9,7 +9,6 @@ import (
addr "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/specs-actors/actors/runtime"
vmr "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/ipfs/go-cid"
)
@@ -210,7 +209,7 @@ func (ps pricedSyscalls) VerifyPoSt(vi proof.WindowPoStVerifyInfo) error {
// the "parent grinding fault", in which case it must be the sibling of h1 (same parent tipset) and one of the
// blocks in the parent of h2 (i.e. h2's grandparent).
// Returns nil and an error if the headers don't prove a fault.
func (ps pricedSyscalls) VerifyConsensusFault(h1 []byte, h2 []byte, extra []byte) (*runtime.ConsensusFault, error) {
func (ps pricedSyscalls) VerifyConsensusFault(h1 []byte, h2 []byte, extra []byte) (*vmr.ConsensusFault, error) {
ps.chargeGas(ps.pl.OnVerifyConsensusFault())
defer ps.chargeGas(gasOnActorExec)
+3 -3
View File
@@ -8,7 +8,7 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/specs-actors/actors/builtin"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
)
type scalingCost struct {
@@ -112,14 +112,14 @@ func (pl *pricelistV0) OnMethodInvocation(value abi.TokenAmount, methodNum abi.M
if big.Cmp(value, abi.NewTokenAmount(0)) != 0 {
ret += pl.sendTransferFunds
if methodNum == builtin.MethodSend {
if methodNum == builtin0.MethodSend {
// transfer only
ret += pl.sendTransferOnlyPremium
}
extra += "t"
}
if methodNum != builtin.MethodSend {
if methodNum != builtin0.MethodSend {
extra += "i"
// running actors is cheaper becase we hand over to actors
ret += pl.sendInvokeMethod
+89 -59
View File
@@ -6,91 +6,126 @@ import (
"fmt"
"reflect"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
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"
system0 "github.com/filecoin-project/specs-actors/actors/builtin/system"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
vmr "github.com/filecoin-project/specs-actors/actors/runtime"
exported0 "github.com/filecoin-project/specs-actors/actors/builtin/exported"
exported2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/exported"
vmr "github.com/filecoin-project/specs-actors/v2/actors/runtime"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/exitcode"
rtt "github.com/filecoin-project/go-state-types/rt"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
)
type Invoker struct {
builtInCode map[cid.Cid]nativeCode
builtInState map[cid.Cid]reflect.Type
type ActorRegistry struct {
actors map[cid.Cid]*actorInfo
}
// An ActorPredicate returns an error if the given actor is not valid for the given runtime environment (e.g., chain height, version, etc.).
type ActorPredicate func(vmr.Runtime, rtt.VMActor) error
func ActorsVersionPredicate(ver actors.Version) ActorPredicate {
return func(rt vmr.Runtime, v rtt.VMActor) error {
nver := actors.VersionForNetwork(rt.NetworkVersion())
if nver != ver {
return xerrors.Errorf("actor %s is a version %d actor; chain only supports actor version %d at height %d", v.Code(), ver, nver, rt.CurrEpoch())
}
return nil
}
}
type invokeFunc func(rt vmr.Runtime, params []byte) ([]byte, aerrors.ActorError)
type nativeCode []invokeFunc
func NewInvoker() *Invoker {
inv := &Invoker{
builtInCode: make(map[cid.Cid]nativeCode),
builtInState: make(map[cid.Cid]reflect.Type),
}
type actorInfo struct {
methods nativeCode
vmActor rtt.VMActor
// TODO: consider making this a network version range?
predicate ActorPredicate
}
func NewActorRegistry() *ActorRegistry {
inv := &ActorRegistry{actors: make(map[cid.Cid]*actorInfo)}
// TODO: define all these properties on the actors themselves, in specs-actors.
// add builtInCode using: register(cid, singleton)
// NETUPGRADE: register code IDs for v2, etc.
inv.Register(builtin0.SystemActorCodeID, system0.Actor{}, abi.EmptyValue{})
inv.Register(builtin0.InitActorCodeID, init0.Actor{}, init0.State{})
inv.Register(builtin0.RewardActorCodeID, reward0.Actor{}, reward0.State{})
inv.Register(builtin0.CronActorCodeID, cron0.Actor{}, cron0.State{})
inv.Register(builtin0.StoragePowerActorCodeID, power0.Actor{}, power0.State{})
inv.Register(builtin0.StorageMarketActorCodeID, market0.Actor{}, market0.State{})
inv.Register(builtin0.StorageMinerActorCodeID, miner0.Actor{}, miner0.State{})
inv.Register(builtin0.MultisigActorCodeID, msig0.Actor{}, msig0.State{})
inv.Register(builtin0.PaymentChannelActorCodeID, paych0.Actor{}, paych0.State{})
inv.Register(builtin0.VerifiedRegistryActorCodeID, verifreg0.Actor{}, verifreg0.State{})
inv.Register(builtin0.AccountActorCodeID, account0.Actor{}, account0.State{})
inv.Register(ActorsVersionPredicate(actors.Version0), exported0.BuiltinActors()...)
inv.Register(ActorsVersionPredicate(actors.Version2), exported2.BuiltinActors()...)
return inv
}
func (inv *Invoker) Invoke(codeCid cid.Cid, rt vmr.Runtime, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) {
code, ok := inv.builtInCode[codeCid]
func (ar *ActorRegistry) Invoke(codeCid cid.Cid, rt vmr.Runtime, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) {
act, ok := ar.actors[codeCid]
if !ok {
log.Errorf("no code for actor %s (Addr: %s)", codeCid, rt.Receiver())
return nil, aerrors.Newf(exitcode.SysErrorIllegalActor, "no code for actor %s(%d)(%s)", codeCid, method, hex.EncodeToString(params))
}
if method >= abi.MethodNum(len(code)) || code[method] == nil {
if err := act.predicate(rt, act.vmActor); err != nil {
return nil, aerrors.Newf(exitcode.SysErrorIllegalActor, "unsupported actor: %s", err)
}
if method >= abi.MethodNum(len(act.methods)) || act.methods[method] == nil {
return nil, aerrors.Newf(exitcode.SysErrInvalidMethod, "no method %d on actor", method)
}
return code[method](rt, params)
return act.methods[method](rt, params)
}
func (inv *Invoker) Register(c cid.Cid, instance Invokee, state interface{}) {
code, err := inv.transform(instance)
if err != nil {
panic(xerrors.Errorf("%s: %w", string(c.Hash()), err))
func (ar *ActorRegistry) Register(pred ActorPredicate, actors ...rtt.VMActor) {
if pred == nil {
pred = func(vmr.Runtime, rtt.VMActor) error { return nil }
}
for _, a := range actors {
code, err := ar.transform(a)
if err != nil {
panic(xerrors.Errorf("%s: %w", string(a.Code().Hash()), err))
}
ar.actors[a.Code()] = &actorInfo{
methods: code,
vmActor: a,
predicate: pred,
}
}
inv.builtInCode[c] = code
inv.builtInState[c] = reflect.TypeOf(state)
}
type Invokee interface {
func (ar *ActorRegistry) Create(codeCid cid.Cid, rt vmr.Runtime) (*types.Actor, aerrors.ActorError) {
act, ok := ar.actors[codeCid]
if !ok {
return nil, aerrors.Newf(exitcode.SysErrorIllegalArgument, "Can only create built-in actors.")
}
if err := act.predicate(rt, act.vmActor); err != nil {
return nil, aerrors.Newf(exitcode.SysErrorIllegalArgument, "Cannot create actor: %w", err)
}
if rtt.IsSingletonActor(act.vmActor) {
return nil, aerrors.Newf(exitcode.SysErrorIllegalArgument, "Can only have one instance of singleton actors.")
}
return &types.Actor{
Code: codeCid,
Head: EmptyObjectCid,
Nonce: 0,
Balance: abi.NewTokenAmount(0),
}, nil
}
type invokee interface {
Exports() []interface{}
}
func (*Invoker) transform(instance Invokee) (nativeCode, error) {
func (*ActorRegistry) transform(instance invokee) (nativeCode, error) {
itype := reflect.TypeOf(instance)
exports := instance.Exports()
runtimeType := reflect.TypeOf((*vmr.Runtime)(nil)).Elem()
for i, m := range exports {
i := i
newErr := func(format string, args ...interface{}) error {
@@ -111,7 +146,7 @@ func (*Invoker) transform(instance Invokee) (nativeCode, error) {
return nil, newErr("wrong number of inputs should be: " +
"vmr.Runtime, <parameter>")
}
if t.In(0) != reflect.TypeOf((*vmr.Runtime)(nil)).Elem() {
if !runtimeType.Implements(t.In(0)) {
return nil, newErr("first arguemnt should be vmr.Runtime")
}
if t.In(1).Kind() != reflect.Ptr {
@@ -176,27 +211,22 @@ func DecodeParams(b []byte, out interface{}) error {
return um.UnmarshalCBOR(bytes.NewReader(b))
}
func DumpActorState(code cid.Cid, b []byte) (interface{}, error) {
if code == builtin0.AccountActorCodeID { // Account code special case
func DumpActorState(act *types.Actor, b []byte) (interface{}, error) {
if builtin.IsAccountActor(act.Code) { // Account code special case
return nil, nil
}
i := NewInvoker() // TODO: register builtins in init block
i := NewActorRegistry() // TODO: register builtins in init block
typ, ok := i.builtInState[code]
actInfo, ok := i.actors[act.Code]
if !ok {
return nil, xerrors.Errorf("state type for actor %s not found", code)
}
rv := reflect.New(typ)
um, ok := rv.Interface().(cbg.CBORUnmarshaler)
if !ok {
return nil, xerrors.New("state type does not implement CBORUnmarshaler")
return nil, xerrors.Errorf("state type for actor %s not found", act.Code)
}
um := actInfo.vmActor.State()
if err := um.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
return nil, xerrors.Errorf("unmarshaling actor state: %w", err)
}
return rv.Elem().Interface(), nil
return um, nil
}
+1 -1
View File
@@ -77,7 +77,7 @@ func (basicContract) InvokeSomething10(rt runtime.Runtime, params *basicParams)
}
func TestInvokerBasic(t *testing.T) {
inv := Invoker{}
inv := ActorRegistry{}
code, err := inv.transform(basicContract{})
assert.NoError(t, err)
+29 -29
View File
@@ -6,11 +6,13 @@ import (
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
@@ -29,49 +31,47 @@ func init() {
var EmptyObjectCid cid.Cid
// TryCreateAccountActor creates account actors from only BLS/SECP256K1 addresses.
func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, aerrors.ActorError) {
func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, address.Address, aerrors.ActorError) {
if err := rt.chargeGasSafe(PricelistByEpoch(rt.height).OnCreateActor()); err != nil {
return nil, err
return nil, address.Undef, err
}
addrID, err := rt.state.RegisterNewAddress(addr)
if err != nil {
return nil, aerrors.Escalate(err, "registering actor address")
return nil, address.Undef, aerrors.Escalate(err, "registering actor address")
}
act, aerr := makeActor(addr)
act, aerr := makeActor(actors.VersionForNetwork(rt.NetworkVersion()), addr)
if aerr != nil {
return nil, aerr
return nil, address.Undef, aerr
}
if err := rt.state.SetActor(addrID, act); err != nil {
return nil, aerrors.Escalate(err, "creating new actor failed")
return nil, address.Undef, aerrors.Escalate(err, "creating new actor failed")
}
p, err := actors.SerializeParams(&addr)
if err != nil {
return nil, aerrors.Escalate(err, "couldn't serialize params for actor construction")
return nil, address.Undef, aerrors.Escalate(err, "couldn't serialize params for actor construction")
}
// call constructor on account
_, aerr = rt.internalSend(builtin.SystemActorAddr, addrID, builtin.MethodsAccount.Constructor, big.Zero(), p)
_, aerr = rt.internalSend(builtin0.SystemActorAddr, addrID, builtin0.MethodsAccount.Constructor, big.Zero(), p)
if aerr != nil {
return nil, aerrors.Wrap(aerr, "failed to invoke account constructor")
return nil, address.Undef, aerrors.Wrap(aerr, "failed to invoke account constructor")
}
act, err = rt.state.GetActor(addrID)
if err != nil {
return nil, aerrors.Escalate(err, "loading newly created actor failed")
return nil, address.Undef, aerrors.Escalate(err, "loading newly created actor failed")
}
return act, nil
return act, addrID, nil
}
func makeActor(addr address.Address) (*types.Actor, aerrors.ActorError) {
func makeActor(ver actors.Version, addr address.Address) (*types.Actor, aerrors.ActorError) {
switch addr.Protocol() {
case address.BLS:
return NewBLSAccountActor(), nil
case address.SECP256K1:
return NewSecp256k1AccountActor(), nil
case address.BLS, address.SECP256K1:
return newAccountActor(ver), nil
case address.ID:
return nil, aerrors.Newf(exitcode.SysErrInvalidReceiver, "no actor with given ID: %s", addr)
case address.Actor:
@@ -81,19 +81,19 @@ func makeActor(addr address.Address) (*types.Actor, aerrors.ActorError) {
}
}
func NewBLSAccountActor() *types.Actor {
func newAccountActor(ver actors.Version) *types.Actor {
// TODO: ActorsUpgrade use a global actor registry?
var code cid.Cid
switch ver {
case actors.Version0:
code = builtin0.AccountActorCodeID
case actors.Version2:
code = builtin2.AccountActorCodeID
default:
panic("unsupported actors version")
}
nact := &types.Actor{
Code: builtin.AccountActorCodeID,
Balance: types.NewInt(0),
Head: EmptyObjectCid,
}
return nact
}
func NewSecp256k1AccountActor() *types.Actor {
nact := &types.Actor{
Code: builtin.AccountActorCodeID,
Code: code,
Balance: types.NewInt(0),
Head: EmptyObjectCid,
}
+67 -42
View File
@@ -5,19 +5,17 @@ import (
"context"
"encoding/binary"
"fmt"
gruntime "runtime"
"time"
"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/cbor"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-state-types/network"
rtt "github.com/filecoin-project/go-state-types/rt"
"github.com/filecoin-project/specs-actors/actors/builtin"
rt0 "github.com/filecoin-project/specs-actors/actors/runtime"
rt2 "github.com/filecoin-project/specs-actors/v2/actors/runtime"
"github.com/ipfs/go-cid"
ipldcbor "github.com/ipfs/go-ipld-cbor"
"go.opencensus.io/trace"
@@ -29,8 +27,33 @@ import (
"github.com/filecoin-project/lotus/chain/types"
)
type Message struct {
msg types.Message
}
func (m *Message) Caller() address.Address {
if m.msg.From.Protocol() != address.ID {
panic("runtime message has a non-ID caller")
}
return m.msg.From
}
func (m *Message) Receiver() address.Address {
if m.msg.To != address.Undef && m.msg.To.Protocol() != address.ID {
panic("runtime message has a non-ID receiver")
}
return m.msg.To
}
func (m *Message) ValueReceived() abi.TokenAmount {
return m.msg.Value
}
// EnableGasTracing, if true, outputs gas tracing in execution traces.
var EnableGasTracing = false
type Runtime struct {
types.Message
rt0.Message
rt0.Syscalls
ctx context.Context
@@ -111,6 +134,7 @@ func (rt *Runtime) StorePut(x cbor.Marshaler) cid.Cid {
}
var _ rt0.Runtime = (*Runtime)(nil)
var _ rt2.Runtime = (*Runtime)(nil)
func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) {
defer func() {
@@ -123,7 +147,11 @@ func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.Act
//log.Desugar().WithOptions(zap.AddStacktrace(zapcore.ErrorLevel)).
//Sugar().Errorf("spec actors failure: %s", r)
log.Errorf("spec actors failure: %s", r)
aerr = aerrors.Newf(1, "spec actors failure: %s", r)
if rt.NetworkVersion() <= network.Version3 {
aerr = aerrors.Newf(1, "spec actors failure: %s", r)
} else {
aerr = aerrors.Newf(exitcode.SysErrReserved1, "spec actors failure: %s", r)
}
}
}()
@@ -216,12 +244,9 @@ func (rt *Runtime) NewActorAddress() address.Address {
}
func (rt *Runtime) CreateActor(codeID cid.Cid, address address.Address) {
if !builtin.IsBuiltinActor(codeID) {
rt.Abortf(exitcode.SysErrorIllegalArgument, "Can only create built-in actors.")
}
if builtin.IsSingletonActor(codeID) {
rt.Abortf(exitcode.SysErrorIllegalArgument, "Can only have one instance of singleton actors.")
act, aerr := rt.vm.areg.Create(codeID, rt)
if aerr != nil {
rt.Abortf(aerr.RetCode(), aerr.Error())
}
_, err := rt.state.GetActor(address)
@@ -231,12 +256,7 @@ func (rt *Runtime) CreateActor(codeID cid.Cid, address address.Address) {
rt.chargeGas(rt.Pricelist().OnCreateActor())
err = rt.state.SetActor(address, &types.Actor{
Code: codeID,
Head: EmptyObjectCid,
Nonce: 0,
Balance: big.Zero(),
})
err = rt.state.SetActor(address, act)
if err != nil {
panic(aerrors.Fatalf("creating actor entry: %v", err))
}
@@ -460,8 +480,10 @@ func (rt *Runtime) stateCommit(oldh, newh cid.Cid) aerrors.ActorError {
}
func (rt *Runtime) finilizeGasTracing() {
if rt.lastGasCharge != nil {
rt.lastGasCharge.TimeTaken = time.Since(rt.lastGasChargeTime)
if EnableGasTracing {
if rt.lastGasCharge != nil {
rt.lastGasCharge.TimeTaken = time.Since(rt.lastGasChargeTime)
}
}
}
@@ -492,32 +514,35 @@ func (rt *Runtime) chargeGasFunc(skip int) func(GasCharge) {
func (rt *Runtime) chargeGasInternal(gas GasCharge, skip int) aerrors.ActorError {
toUse := gas.Total()
var callers [10]uintptr
cout := gruntime.Callers(2+skip, callers[:])
if EnableGasTracing {
var callers [10]uintptr
now := build.Clock.Now()
if rt.lastGasCharge != nil {
rt.lastGasCharge.TimeTaken = now.Sub(rt.lastGasChargeTime)
cout := 0 //gruntime.Callers(2+skip, callers[:])
now := build.Clock.Now()
if rt.lastGasCharge != nil {
rt.lastGasCharge.TimeTaken = now.Sub(rt.lastGasChargeTime)
}
gasTrace := types.GasTrace{
Name: gas.Name,
Extra: gas.Extra,
TotalGas: toUse,
ComputeGas: gas.ComputeGas,
StorageGas: gas.StorageGas,
TotalVirtualGas: gas.VirtualCompute*GasComputeMulti + gas.VirtualStorage*GasStorageMulti,
VirtualComputeGas: gas.VirtualCompute,
VirtualStorageGas: gas.VirtualStorage,
Callers: callers[:cout],
}
rt.executionTrace.GasCharges = append(rt.executionTrace.GasCharges, &gasTrace)
rt.lastGasChargeTime = now
rt.lastGasCharge = &gasTrace
}
gasTrace := types.GasTrace{
Name: gas.Name,
Extra: gas.Extra,
TotalGas: toUse,
ComputeGas: gas.ComputeGas,
StorageGas: gas.StorageGas,
TotalVirtualGas: gas.VirtualCompute*GasComputeMulti + gas.VirtualStorage*GasStorageMulti,
VirtualComputeGas: gas.VirtualCompute,
VirtualStorageGas: gas.VirtualStorage,
Callers: callers[:cout],
}
rt.executionTrace.GasCharges = append(rt.executionTrace.GasCharges, &gasTrace)
rt.lastGasChargeTime = now
rt.lastGasCharge = &gasTrace
// overflow safe
if rt.gasUsed > rt.gasAvailable-toUse {
rt.gasUsed = rt.gasAvailable
+20
View File
@@ -45,3 +45,23 @@ func TestRuntimePutErrors(t *testing.T) {
rt.StorePut(&NotAVeryGoodMarshaler{})
t.Error("expected panic")
}
func BenchmarkRuntime_CreateRuntimeChargeGas_TracingDisabled(b *testing.B) {
var (
cst = cbor.NewCborStore(nil)
gch = newGasCharge("foo", 1000, 1000)
)
b.ResetTimer()
EnableGasTracing = false
noop := func() bool { return EnableGasTracing }
for n := 0; n < b.N; n++ {
// flip the value and access it to make sure
// the compiler doesn't optimize away
EnableGasTracing = true
_ = noop()
EnableGasTracing = false
_ = (&Runtime{cst: cst}).chargeGasInternal(gch, 0)
}
}
+70 -16
View File
@@ -5,8 +5,11 @@ import (
"context"
"fmt"
"reflect"
"sync/atomic"
"time"
"github.com/filecoin-project/lotus/chain/actors/builtin"
block "github.com/ipfs/go-block-format"
cid "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
@@ -22,7 +25,6 @@ import (
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/adt"
@@ -40,6 +42,12 @@ var log = logging.Logger("vm")
var actorLog = logging.Logger("actors")
var gasOnActorExec = newGasCharge("OnActorExec", 0, 0)
// stat counters
var (
StatSends uint64
StatApplied uint64
)
// ResolveToKeyAddr returns the public key type of address (`BLS`/`SECP256K1`) of an account actor identified by `addr`.
func ResolveToKeyAddr(state types.StateTree, cst cbor.IpldStore, addr address.Address) (address.Address, error) {
if addr.Protocol() == address.BLS || addr.Protocol() == address.SECP256K1 {
@@ -123,7 +131,15 @@ func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin addres
rt.Abortf(exitcode.SysErrInvalidReceiver, "resolve msg.From address failed")
}
vmm.From = resF
rt.Message = vmm
if vm.ntwkVersion(ctx, vm.blockHeight) <= network.Version3 {
rt.Message = &vmm
} else {
resT, _ := rt.ResolveAddress(msg.To)
// may be set to undef if recipient doesn't exist yet
vmm.To = resT
rt.Message = &Message{msg: vmm}
}
return rt
}
@@ -145,7 +161,7 @@ type VM struct {
cst *cbor.BasicIpldStore
buf *bufbstore.BufferedBS
blockHeight abi.ChainEpoch
inv *Invoker
areg *ActorRegistry
rand Rand
circSupplyCalc CircSupplyCalculator
ntwkVersion NtwkVersionGetter
@@ -179,7 +195,7 @@ func NewVM(ctx context.Context, opts *VMOpts) (*VM, error) {
cst: cst,
buf: buf,
blockHeight: opts.Epoch,
inv: NewInvoker(),
areg: NewActorRegistry(),
rand: opts.Rand, // TODO: Probably should be a syscall
circSupplyCalc: opts.CircSupplyCalc,
ntwkVersion: opts.NtwkVersion,
@@ -204,6 +220,8 @@ type ApplyRet struct {
func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
gasCharge *GasCharge, start time.Time) ([]byte, aerrors.ActorError, *Runtime) {
defer atomic.AddUint64(&StatSends, 1)
st := vm.cstate
origin := msg.From
@@ -218,14 +236,21 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
}
rt := vm.makeRuntime(ctx, msg, origin, on, gasUsed, nac)
rt.lastGasChargeTime = start
if EnableGasTracing {
rt.lastGasChargeTime = start
if parent != nil {
rt.lastGasChargeTime = parent.lastGasChargeTime
rt.lastGasCharge = parent.lastGasCharge
defer func() {
parent.lastGasChargeTime = rt.lastGasChargeTime
parent.lastGasCharge = rt.lastGasCharge
}()
}
}
if parent != nil {
rt.lastGasChargeTime = parent.lastGasChargeTime
rt.lastGasCharge = parent.lastGasCharge
defer func() {
parent.gasUsed = rt.gasUsed
parent.lastGasChargeTime = rt.lastGasChargeTime
parent.lastGasCharge = rt.lastGasCharge
}()
}
if gasCharge != nil {
@@ -240,11 +265,24 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
toActor, err := st.GetActor(msg.To)
if err != nil {
if xerrors.Is(err, types.ErrActorNotFound) {
a, err := TryCreateAccountActor(rt, msg.To)
a, aid, err := TryCreateAccountActor(rt, msg.To)
if err != nil {
return nil, aerrors.Wrapf(err, "could not create account")
}
toActor = a
if vm.ntwkVersion(ctx, vm.blockHeight) <= network.Version3 {
// Leave the rt.Message as is
} else {
nmsg := Message{
msg: types.Message{
To: aid,
From: rt.Message.Caller(),
Value: rt.Message.ValueReceived(),
},
}
rt.Message = &nmsg
}
} else {
return nil, aerrors.Escalate(err, "getting actor")
}
@@ -312,6 +350,7 @@ func checkMessage(msg *types.Message) error {
func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) {
start := build.Clock.Now()
defer atomic.AddUint64(&StatApplied, 1)
ret, actorErr, rt := vm.send(ctx, msg, nil, nil, start)
rt.finilizeGasTracing()
return &ApplyRet{
@@ -331,6 +370,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
start := build.Clock.Now()
ctx, span := trace.StartSpan(ctx, "vm.ApplyMessage")
defer span.End()
defer atomic.AddUint64(&StatApplied, 1)
msg := cmsg.VMMessage()
if span.IsRecordingEvents() {
span.AddAttributes(
@@ -385,7 +425,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
}
// this should never happen, but is currently still exercised by some tests
if !fromActor.IsAccountActor() {
if !builtin.IsAccountActor(fromActor.Code) {
gasOutputs := ZeroGasOutputs()
gasOutputs.MinerPenalty = minerPenaltyAmount
return &ApplyRet{
@@ -546,7 +586,7 @@ func (vm *VM) Flush(ctx context.Context) (cid.Cid, error) {
return cid.Undef, xerrors.Errorf("flushing vm: %w", err)
}
if err := Copy(from, to, root); err != nil {
if err := Copy(ctx, from, to, root); err != nil {
return cid.Undef, xerrors.Errorf("copying tree: %w", err)
}
@@ -600,9 +640,18 @@ func linksForObj(blk block.Block, cb func(cid.Cid)) error {
}
}
func Copy(from, to blockstore.Blockstore, root cid.Cid) error {
func Copy(ctx context.Context, from, to blockstore.Blockstore, root cid.Cid) error {
ctx, span := trace.StartSpan(ctx, "vm.Copy") // nolint
defer span.End()
var numBlocks int
var totalCopySize int
var batch []block.Block
batchCp := func(blk block.Block) error {
numBlocks++
totalCopySize += len(blk.RawData())
batch = append(batch, blk)
if len(batch) > 100 {
if err := to.PutMany(batch); err != nil {
@@ -623,6 +672,11 @@ func Copy(from, to blockstore.Blockstore, root cid.Cid) error {
}
}
span.AddAttributes(
trace.Int64Attribute("numBlocks", int64(numBlocks)),
trace.Int64Attribute("copySize", int64(totalCopySize)),
)
return nil
}
@@ -709,15 +763,15 @@ func (vm *VM) Invoke(act *types.Actor, rt *Runtime, method abi.MethodNum, params
defer func() {
rt.ctx = oldCtx
}()
ret, err := vm.inv.Invoke(act.Code, rt, method, params)
ret, err := vm.areg.Invoke(act.Code, rt, method, params)
if err != nil {
return nil, err
}
return ret, nil
}
func (vm *VM) SetInvoker(i *Invoker) {
vm.inv = i
func (vm *VM) SetInvoker(i *ActorRegistry) {
vm.areg = i
}
func (vm *VM) GetNtwkVersion(ctx context.Context, ce abi.ChainEpoch) network.Version {
+47 -1
View File
@@ -81,7 +81,7 @@ func (w *Wallet) findKey(addr address.Address) (*Key, error) {
return nil, nil
}
ki, err := w.keystore.Get(KNamePrefix + addr.String())
ki, err := w.tryFind(addr)
if err != nil {
if xerrors.Is(err, types.ErrKeyInfoNotFound) {
return nil, nil
@@ -96,6 +96,42 @@ func (w *Wallet) findKey(addr address.Address) (*Key, error) {
return k, nil
}
func (w *Wallet) tryFind(addr address.Address) (types.KeyInfo, error) {
ki, err := w.keystore.Get(KNamePrefix + addr.String())
if err == nil {
return ki, err
}
if !xerrors.Is(err, types.ErrKeyInfoNotFound) {
return types.KeyInfo{}, err
}
// We got an ErrKeyInfoNotFound error
// Try again, this time with the testnet prefix
aChars := []rune(addr.String())
prefixRunes := []rune(address.TestnetPrefix)
if len(prefixRunes) != 1 {
return types.KeyInfo{}, xerrors.Errorf("unexpected prefix length: %d", len(prefixRunes))
}
aChars[0] = prefixRunes[0]
ki, err = w.keystore.Get(KNamePrefix + string(aChars))
if err != nil {
return types.KeyInfo{}, err
}
// We found it with the testnet prefix
// Add this KeyInfo with the mainnet prefix address string
err = w.keystore.Put(KNamePrefix+addr.String(), ki)
if err != nil {
return types.KeyInfo{}, err
}
return ki, nil
}
func (w *Wallet) Export(addr address.Address) (*types.KeyInfo, error) {
k, err := w.findKey(addr)
if err != nil {
@@ -129,6 +165,7 @@ func (w *Wallet) ListAddrs() ([]address.Address, error) {
sort.Strings(all)
seen := map[address.Address]struct{}{}
out := make([]address.Address, 0, len(all))
for _, a := range all {
if strings.HasPrefix(a, KNamePrefix) {
@@ -137,10 +174,19 @@ func (w *Wallet) ListAddrs() ([]address.Address, error) {
if err != nil {
return nil, xerrors.Errorf("converting name to address: %w", err)
}
if _, ok := seen[addr]; ok {
continue // got duplicate with a different prefix
}
seen[addr] = struct{}{}
out = append(out, addr)
}
}
sort.Slice(out, func(i, j int) bool {
return out[i].String() < out[j].String()
})
return out, nil
}

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