Compare commits

...
892 Commits
Author SHA1 Message Date
Łukasz Magiera c459a13dca Merge pull request #2593 from mgoelzer/paych_get_parse_as_fil
Parse amount as FIL in paych get
2020-07-25 09:54:54 +02:00
Mike Goelzer b409c8f2be Parse amount as FIL in paych get 2020-07-25 01:54:21 +00:00
Whyrusleeping f69cce4089 Merge pull request #2576 from filecoin-project/fix/testnet-compat
pull in specs actors fix for testnet
2020-07-24 13:17:41 -07:00
whyrusleeping cda0326cc3 go mod tidy 2020-07-24 13:09:19 -07:00
whyrusleeping 3bdcae9a59 dont update go-fil-commcid 2020-07-24 12:41:23 -07:00
whyrusleeping 1163d36b02 hardcode legacy multihash types for backward compat 2020-07-24 12:33:04 -07:00
whyrusleeping d764d86e89 pull in specs actors fix for testnet 2020-07-24 11:36:19 -07:00
Łukasz Magiera 3921623861 Merge pull request #2506 from filecoin-project/asr/null-tipset
API documentation must not tell lies
2020-07-23 22:07:36 +02:00
Łukasz Magiera 22c684deb6 Merge pull request #2534 from filecoin-project/asr/getsize
Implement buffered blocktore GetSize()
2020-07-23 10:59:28 +02:00
Łukasz Magiera df801470ca Return size in bufbs.GetSize 2020-07-23 10:23:44 +02:00
Łukasz Magiera 01685c44e4 Merge pull request #2543 from filecoin-project/asr/readme
update devnet in readme
2020-07-23 10:10:17 +02:00
Aayush Rajasekaran 2c895e8df2 update devnet in readme 2020-07-22 23:34:26 -04:00
Aayush Rajasekaran 54c0ae17f4 Implement buffered blocktore GetSize() 2020-07-22 19:58:35 -04:00
Aayush Rajasekaran d254fb228b API documentation must not tell lies 2020-07-21 13:44:05 -04:00
Łukasz Magiera 9b1d2f4c13 Merge pull request #2462 from jsign/jsign/ipfsbstore
ipfsbstore: offlinemode, and Has() fix
2020-07-18 01:52:37 +02:00
Ignacio Hagopian fd2262f51f ipbsbstore: offlinemode, and Has() fix
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-07-17 18:02:12 -03:00
Łukasz Magiera ee6269756c Merge pull request #2429 from filecoin-project/frrist/chainwatch-miner-precommit
feat: track miner precommit
2020-07-17 22:51:42 +02:00
frrist 7ff468ce85 feat: track miner precommit
- add materalized view showing all miner sector info
2020-07-17 12:25:54 -07:00
Łukasz Magiera c4de2373fd Merge pull request #2443 from filecoin-project/feat/chainwatch/capture-base-block-rewards
Capture base block rewards
2020-07-17 11:49:29 +02:00
Mike Greenberg 18d1ab0cb9 fix(chainwatch): Parallel reward persistence; Tighten rpc logging 2020-07-16 22:58:27 -04:00
Mike Greenberg 6e7f21de03 fix(chainwatch): Remove --front switch 2020-07-16 12:14:41 -04:00
Mike Greenberg c3cc2eea46 feat(chainwatch): Add miner index on top_miners_by_base_reward view 2020-07-16 11:36:52 -04:00
Mike Greenberg 7bfcff2c18 fix(chainwatch): Backoff processor when no work exists to process 2020-07-16 11:36:52 -04:00
Mike Greenberg f2f797f088 fix(log): Move metrics and stage updates to debug; Add --log-level switch 2020-07-16 11:36:52 -04:00
Mike Greenberg 033cfa8f47 fix(chainwatch): Correct index name on state_height view 2020-07-16 11:36:52 -04:00
Mike Greenberg 0cfddae711 feat(chainwatch): Capture base_block_reward per epoch; Top miner by reward view 2020-07-16 11:36:52 -04:00
Łukasz Magiera a87899ddb6 Merge pull request #2396 from filecoin-project/frrist/chainwatch-faster-sync
Improvments to Chainwatch Syncing and Processing Pipeline
2020-07-16 11:49:53 +02:00
Łukasz Magiera bbd4ffe842 Merge pull request #2430 from filecoin-project/asr/swap-signer
SwapSigner API methods
2020-07-16 11:28:51 +02:00
Aayush Rajasekaran 605560a981 SwapSigner API methods 2020-07-15 21:54:18 -04:00
frrist b4c9ba0a8b refactor: remove unused code 2020-07-15 11:43:04 -07:00
frrist 9a53bf8f83 refactor: wire up new processor and syncer 2020-07-15 11:42:19 -07:00
frrist 41f4f1fd83 refactor: implement processor and syncer
- When chainwatch is ran it will first start a Syncer that continuously collects blocks from the
ChainNotify channel and persists them to the blocks_synced table. Once the Syncer has caught the
blocks_synced table up to the lotus daemons current head a Processor is started. The Processor
selects a batch of contiguous blocks and extracts and stores their data. It attempts to do as much
work as it can in parallel. When the blocks are done being processed their corresponding
processed_at and is_processed fields in the blocks_synced table are filled out.
2020-07-15 11:42:19 -07:00
Łukasz Magiera 6b9fd74f8e Merge pull request #2419 from filecoin-project/schomatis/fix/newtipset/mismatch-lengths
fix: NewTipSet: check mismatch in number of parents
2020-07-15 17:49:39 +02:00
Łukasz Magiera ccba495840 Merge pull request #2331 from filecoin-project/chainwatch/market-state-deal-tracking
feat: add deal state and proposal tracking to cw
2020-07-15 16:19:10 +02:00
Lucas Molas 21ffe188f4 fix: NewTipSet: check mismatch in number of parents 2020-07-15 08:17:50 -03:00
Łukasz Magiera 5f1cc6cefd Merge pull request #2398 from filecoin-project/asr/msig-cli
clarify multisig create helptext
2020-07-14 10:03:37 +02:00
Łukasz Magiera 8d03a9e739 Merge pull request #2391 from jiyilanzhou/master
api/api_full.go: fix method signature
2020-07-14 10:03:17 +02:00
Aayush Rajasekaran 17642b5ecb clarify multisig create helptext 2020-07-13 19:50:18 -04:00
Whyrusleeping 62a503d686 Merge pull request #1563 from filecoin-project/feat/cache-bs
add an lru caching blockstore
2020-07-13 16:20:43 -07:00
erchuan.ma bb49546728 api/api_full.go: fix method signature
method signature not match
2020-07-13 22:35:51 +08:00
Łukasz Magiera 3f017688c7 Merge pull request #2377 from filecoin-project/asr/msig-api
API improvements
2020-07-13 13:24:09 +02:00
Łukasz Magiera bb07c0a5df Merge pull request #2378 from austinabell/zipml
Check message length before generating Cids
2020-07-13 13:20:56 +02:00
Łukasz Magiera 7ec58255bf Merge pull request #2387 from filecoin-project/asr/cli-api
CLI/API improvements
2020-07-13 13:15:43 +02:00
Aayush Rajasekaran 1a5c20ca75 CLI/API improvements 2020-07-13 01:13:56 -04:00
frrist c9cb39d5a0 polish: update deal proposal table if slashed 2020-07-12 11:39:58 -07:00
Aayush Rajasekaran 858513559b API improvements 2020-07-11 23:54:58 -04:00
Aayush Rajasekaran 12b63d59b2 Include unlock duration as a param for multisig creation 2020-07-11 23:54:58 -04:00
austinabell 2fd860324f avoid generating cids on all messages before checking message length 2020-07-10 19:59:58 -04:00
frrist f9d8b051f4 polish: track tipset height for processing 2020-07-10 15:01:55 -07:00
frrist 1e2e62bad6 polish: track unpadded piece size in deal prop 2020-07-10 15:01:55 -07:00
frrist e13a251cc8 feat: add deal state and proposal tracking to cw 2020-07-10 15:01:55 -07:00
Łukasz Magiera 39d609a661 Merge pull request #2169 from waynewyang/evnet
set called 'true' after handle be called
2020-07-10 22:28:00 +02:00
Łukasz Magiera 5530a7bef2 Merge pull request #2322 from filecoin-project/frrist/deal-state-changes
Frrist/deal state changes
2020-07-10 21:57:42 +02:00
Łukasz Magiera bc23b0ed4f Merge pull request #2278 from filecoin-project/fix/rename-vars
rename sync variables.
2020-07-10 21:36:04 +02:00
Łukasz Magiera dc9df10f5a sync: Also rename span attributes 2020-07-10 21:31:58 +02:00
Łukasz Magiera 69125f15f9 Merge pull request #2329 from filecoin-project/feat/chainwatch/capture-power
chainwatch: Capture power from miner and reward actors
2020-07-10 21:25:46 +02:00
Łukasz Magiera 3f0312a728 Merge pull request #2370 from filecoin-project/disable-call-StatePledgeCollateral
disable call to StatePledgeCollateral
2020-07-10 21:08:03 +02:00
Mike Greenberg ebd0e93a99 chainwatch: app exit with non-zero on error 2020-07-10 11:58:41 -04:00
Mike Greenberg 3332290626 fix: Logic bug; Schema column update stateroot -> state_root 2020-07-10 11:54:11 -04:00
Anton Evangelatov 0dbca1377a disable call to StatePledgeCollateral 2020-07-10 17:52:44 +02:00
Łukasz Magiera b245fd0b7d Merge pull request #2232 from filecoin-project/feat/verifreg-bitwidth
set proper bitwidth for verifreg command hamts
2020-07-10 16:19:45 +02:00
Łukasz Magiera e81f182840 Merge pull request #2330 from filecoin-project/feat/fil-units
produce and parse FIL suffix on FIL strings
2020-07-10 09:41:01 +02:00
whyrusleeping a3602d4fcf fix tests, handle parsing with suffixes properly 2020-07-09 17:26:06 -07:00
frrist bf6b76a4fb feat: add market deal state & proposal predicates
- detects changes in the market deal proposal and market deal state
amts.
2020-07-09 14:43:21 -07:00
Łukasz Magiera 2836b521f3 Merge pull request #2333 from filecoin-project/asr/temp
Correct initial setup of sector id counter
2020-07-09 21:40:30 +02:00
Łukasz Magiera f01378f83f Merge pull request #2336 from filecoin-project/mute/refresh
Mute RtRefreshManager logs as they break terminal emulation
2020-07-09 16:40:27 +02:00
Jakub Sztandera b0cf3d3228 Mute RtRefreshManager logs as they break terminal emulation
RtRefreshManager logs random binary strings, which somtimes might be
partial multi-byte Unicode or ASCI escape codes.

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-09 16:21:55 +02:00
Aayush Rajasekaran 57a1418ff8 Correct initial setup of sector id counter 2020-07-09 01:05:27 -04:00
whyrusleeping a79b31c230 produce and parse FIL suffix on FIL strings 2020-07-08 16:16:45 -07:00
Mike Greenberg 1081679360 feat(chainwatch): Capture miner_power data 2020-07-08 18:56:55 -04:00
Mike Greenberg b9effac437 feat(chainwatch): Capture baseline power in chain_power 2020-07-08 18:40:09 -04:00
Łukasz Magiera 8fbeebb86d rename sync variables. 2020-07-08 22:02:28 +02:00
Łukasz Magiera 24d8a84ad7 Merge pull request #2252 from filecoin-project/override-maddr
add `actor` flag to `lotus-storage-miner` for proving and info calls
2020-07-08 21:28:29 +02:00
Łukasz Magiera 56bf503210 Merge pull request #2303 from filecoin-project/asr/cli
correct error message
2020-07-08 21:18:34 +02:00
Łukasz Magiera 9a5b26c50c Merge pull request #2326 from filecoin-project/feat/optim-badger
Ignore log.Sync() error
2020-07-08 21:16:13 +02:00
Łukasz Magiera 4952d4be77 Merge pull request #2321 from filecoin-project/frrist/generic-adt_array-diffing
polish: genericize adt array diff & extract store
2020-07-08 21:15:36 +02:00
Jakub Sztandera 68081a7a1f Ignore log.Sync() error
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-08 21:13:22 +02:00
Łukasz Magiera 67dd5937ca Merge pull request #2324 from filecoin-project/feat/optim-badger
Fix daemon shutdown and enable compact on close
2020-07-08 21:12:57 +02:00
Jakub Sztandera ebecca64a1 Fix daemon shutdown
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-08 21:08:24 +02:00
Jakub Sztandera 0e7b7c9fdb Update go-ds-badger2
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-08 21:08:23 +02:00
Jakub Sztandera d3d4612575 Re-eanble compact on close
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-08 20:59:46 +02:00
frrist 1254f9de0c clean: go mod tidy 2020-07-08 11:21:40 -07:00
frrist d78b7e57c7 polish: include key in AdtArrayDiff interface
- some values do not contain their keys
2020-07-08 11:19:14 -07:00
frrist 509e3b653c polish: genericize adt array diff & extract store
- adds testing for adt diff
2020-07-08 11:19:14 -07:00
Łukasz Magiera 631b8b5802 Merge pull request #2319 from filecoin-project/feat/optim-badger
Use mostly defaults for badger options
2020-07-08 18:05:58 +02:00
Jakub Sztandera 40286e4192 Use mostly defaults for badger options
This options are the defults in badger `master` now.
We should update to next badger version as soon as it is stable, it has
some nice improvments.

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-08 17:54:33 +02:00
Łukasz Magiera 8e46753e38 Merge pull request #2306 from filecoin-project/fix/mark-bad
Fix bad block rason if ValidateBlock fails
2020-07-08 11:49:50 +02:00
Jakub Sztandera 74db060cdb Fix bad block rason if ValidateBlock fails
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-08 03:55:56 +02:00
whyrusleeping 0285a9741c remove debug logs 2020-07-07 16:44:57 -07:00
Aayush Rajasekaran 53b6de6c4b CLI proving info: Check sector index before reading from deadlines 2020-07-07 18:56:53 -04:00
Aayush Rajasekaran 8645839974 correct error message 2020-07-07 18:29:45 -04:00
Łukasz Magiera 683aded05c Merge pull request #2302 from filecoin-project/asr/cli
Minor CLI improvements
2020-07-08 00:01:31 +02:00
Aayush Rajasekaran 20c80f977c Rename state compute's height flag to vm-height 2020-07-07 17:40:57 -04:00
Aayush Rajasekaran eac8a909e9 Unify all sender flags in CLI under the same name 2020-07-07 17:37:43 -04:00
Łukasz Magiera 99b5ec96a2 Merge pull request #2101 from filecoin-project/feat/persistent-journal
implement a persistent journal for lotus node operations
2020-07-07 02:38:04 +02:00
Łukasz Magiera 74aa3e05fa journal: Fix panic with no journal set 2020-07-07 02:28:59 +02:00
Łukasz Magiera 66e547230d Merge pull request #2233 from filecoin-project/frrist/miner-sector-predicate
feat: add miner sector predicate and test
2020-07-07 01:43:41 +02:00
whyrusleeping 04bd56a068 log message if journal is not configured 2020-07-06 15:37:05 -07:00
frrist e1c29ca469 polish: wire up miner state predicate 2020-07-06 14:36:21 -07:00
frrist 3c6e46cd70 feat: add miner sector predicate and test
-polish: OnActorStateChanged operate over TipSetKey
    - it was calling key() interally and tipsetkeys are cheaper to get than
the full tipset
  -polish: improve predicate method names
2020-07-06 14:27:39 -07:00
Łukasz Magiera 27b5a8c3ba Merge pull request #2283 from filecoin-project/feat/better-bad-reason
Add better description to bad blocks
2020-07-06 22:56:53 +02:00
Jakub Sztandera 49800b8fec Add original tipset to the string
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-06 19:46:25 +02:00
Łukasz Magiera cf6ac44b6e Merge pull request #2277 from Leozhang404/master
if no sectors need to recovery, checkNextRecoveries will return
2020-07-06 19:24:15 +02:00
Jakub Sztandera 50c773c6a3 Add better description to bad blocks
Track original cause of blocks being marked as bad.

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-06 19:23:29 +02:00
Łukasz Magiera 41d3ac2159 Merge pull request #2282 from filecoin-project/fix/msig-create-no-addrs
error out when trying to create multisig with no addresses
2020-07-06 18:44:22 +02:00
whyrusleeping 18f7b9bb1d use nicer timestamps 2020-07-06 09:43:19 -07:00
whyrusleeping ccf64a8534 add the real code 2020-07-06 09:42:00 -07:00
whyrusleeping 42bd4eccbe implement a persistent journal for lotus node operations 2020-07-06 09:42:00 -07:00
whyrusleeping 0964c0a8a1 error out when trying to create multisig with no addresses 2020-07-06 09:40:56 -07:00
Leo CheungandŁukasz Magiera 874cb46cb3 Update storage/wdpost_run.go
Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com>
2020-07-06 06:20:41 -05:00
Leo CheungandŁukasz Magiera ddba20ccdf Update storage/wdpost_run.go
Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com>
2020-07-06 06:19:47 -05:00
Łukasz Magiera 516e31d37c Merge pull request #2254 from filecoin-project/feat/decoded-return-values
provide decoded return values in output of StateWaitMsg
2020-07-06 11:24:12 +02:00
Łukasz Magiera 5836dfae41 Merge pull request #2259 from filecoin-project/yusef-mining-callback
add error argument to waitFunc callback in miner loop
2020-07-06 11:18:49 +02:00
Łukasz Magiera 3bb992fe6f Merge pull request #2265 from filecoin-project/misc/template-version
Use `lotus version` instead to get daemon version
2020-07-06 11:15:04 +02:00
Łukasz Magiera 2f3fc31f11 Merge pull request #2268 from chunqizhi/zcq02
Add return nil when faults == 0
2020-07-06 11:14:35 +02:00
Leo Cheung 4e12c4cb69 Update wdpost_run.go
if some unrecovered sectors can not recovered (such as cache file is missing) , miner should not send message "DeclareFaultsRecovered"
2020-07-06 15:52:58 +08:00
Leo Cheung 79e93760b7 Merge pull request #1 from filecoin-project/master
update-0706
2020-07-06 02:43:20 -05:00
chunqizhi 6c9beb9e87 Add return nil when faults == 0 2020-07-05 09:17:10 +08:00
Jakub Sztandera 1d0acf35d2 Use lotus version instead to get daemon version 2020-07-04 14:51:22 +02:00
Yusef Napora ea5dc461a1 pass error into waitFunc callback 2020-07-03 17:15:43 -04:00
Łukasz Magiera e5fdae45b7 Merge pull request #2253 from filecoin-project/extract-stats
extract stats package
2020-07-03 21:18:11 +02:00
Łukasz Magiera db50396eb5 Merge pull request #2256 from filecoin-project/feat/auto-fountains-sector-sizes
fountain: populate miner sector dropdown from specs-actors
2020-07-03 21:16:08 +02:00
Łukasz Magiera ff1cceb7bd Merge pull request #2257 from filecoin-project/fix/lotus-shed-keyinfo-switch
lotus-shed: fix secp256k1
2020-07-03 21:13:50 +02:00
Travis Person d3a007fd0a lotus-shed: fix secp256k1 2020-07-03 19:03:02 +00:00
Travis Person 4e0cf1644f fountain: populate miner sector dropdown from specs-actors 2020-07-03 19:01:56 +00:00
Anton Evangelatov fe49bcd9fa make linter happy 2020-07-03 19:52:15 +02:00
Anton Evangelatov e4d8f266c6 make linter happy 2020-07-03 19:49:21 +02:00
Anton Evangelatov faab606bd4 maddr -> actor 2020-07-03 19:45:21 +02:00
Anton Evangelatov 978ab67c73 override maddr on lotus-storage-miner info as well 2020-07-03 19:35:20 +02:00
Anton Evangelatov 4679c35e61 include headlag in func signature 2020-07-03 19:22:04 +02:00
whyrusleeping 16e493a67a provide decoded return values in output of StateWaitMsg 2020-07-03 09:57:58 -07:00
Anton Evangelatov 8b88c17503 extract stats package 2020-07-03 16:52:40 +02:00
Yusef Napora d6d68b9096 call waitFunc callback on mining error 2020-07-03 09:56:40 -04:00
Łukasz Magiera d3a1261f1e Merge pull request #2227 from filecoin-project/asr/api
Add docs comments to API
2020-07-03 15:33:07 +02:00
Łukasz Magiera 19178cca08 Merge pull request #2245 from filecoin-project/feat/fauxrep
Feat/fauxrep
2020-07-03 15:32:00 +02:00
chunqizhi 3e7654d459 Merge pull request #5 from filecoin-project/master
merge
2020-07-03 20:15:19 +08:00
Łukasz Magiera bb3758f648 seed: Support fake preseals 2020-07-03 03:29:21 +02:00
Łukasz Magiera 9d56dabb31 Merge pull request #2243 from filecoin-project/feat/buf-has-caching
check underlying datastore for objects before putting to bufbstore
2020-07-03 02:51:27 +02:00
Łukasz Magiera c3393ee185 seed: Move sector preseal to separate func 2020-07-03 02:47:33 +02:00
Łukasz Magiera 17039a5672 Update FFI 2020-07-03 02:23:45 +02:00
whyrusleeping 809a3ba07c check underlying datastore for objects before putting to bufbstore 2020-07-02 16:48:14 -07:00
Łukasz Magiera 5de7b62dbc Merge pull request #2241 from filecoin-project/fix/specs-actors-faults
Update specs actors to resolve forkiness bug
2020-07-02 22:15:11 +02:00
Jakub Sztandera 5fb76ddad2 Bump version
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 22:09:11 +02:00
Jakub Sztandera cc02092aae Go mod tidy
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 21:53:21 +02:00
Jakub Sztandera 3e4b80e7f6 Update specs actors
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 21:52:55 +02:00
Łukasz Magiera 14ae8c7272 Merge pull request #2156 from filecoin-project/fix/bench-analyze
Improve performance of bench import analyze
2020-07-02 19:35:18 +02:00
Anton Evangelatov 2a050ca326 override maddr for observability 2020-07-02 18:48:39 +02:00
Jakub Sztandera 567b8082c3 Back to 10 callers
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:35 +02:00
Jakub Sztandera f3f92ce5bc add scratchpad to gitignore
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:35 +02:00
Jakub Sztandera c4158f12f1 Include proof number as extra in OnVerifyPost
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:35 +02:00
Jakub Sztandera 3429941639 Add info about OnActorExecDone
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:34 +02:00
Jakub Sztandera 11dc902d53 Adjust OnMethodInvocation
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:34 +02:00
Jakub Sztandera 41b775fdd4 Compute time spent in actors
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:34 +02:00
Jakub Sztandera e9d2a3edd9 Limit float print precision
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:34 +02:00
Jakub Sztandera 42696372ee Progress to stderr
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:34 +02:00
Jakub Sztandera 39625eada7 Add count
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:34 +02:00
Jakub Sztandera 7a7e5a85ad Print tt from covar
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:34 +02:00
Jakub Sztandera 254295b9c3 Readd covariance
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:34 +02:00
Jakub Sztandera 4dd79ec6fa Calculate correlation
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:34 +02:00
Jakub Sztandera 9ccd25b072 Update gas values, compute correlation coefficient
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:33 +02:00
Jakub Sztandera 5e7f561133 Support complex extra, fix small bug in covariance
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:33 +02:00
Jakub Sztandera c68a8f802e Adjust gas
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:33 +02:00
Jakub Sztandera 29f5f451b3 Add covariance
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:33 +02:00
Jakub Sztandera 2caa7164a6 Midway adding covar
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:33 +02:00
Jakub Sztandera 21148033e2 Change alg for computing variance
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:33 +02:00
Jakub Sztandera bc88c632d1 Fix previous commit
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:33 +02:00
Jakub Sztandera 1e17ea3fff Adjust gas values
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:33 +02:00
Jakub Sztandera ca7e5f5e16 Set gas to 1
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:32 +02:00
Jakub Sztandera cd2595da67 Adjust gas
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:32 +02:00
Jakub Sztandera 3a9f1bf9a2 Revert "Try without recurson"
This reverts commit 76e3663b2b1f1b58f9097f45124add4fa7718199.

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:32 +02:00
Jakub Sztandera 9094405537 Try without recurson
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:32 +02:00
Jakub Sztandera 4db61e71da Reduce caller depth
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:32 +02:00
Jakub Sztandera a6417dc24b Add stats test and print observation count
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:32 +02:00
Jakub Sztandera 1bc9fbca20 Ignore virtual
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:32 +02:00
Jakub Sztandera 369ec8221f Improve edge case handling
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:32 +02:00
Jakub Sztandera 052fc35a91 Maybe avoid NaNs
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:31 +02:00
Jakub Sztandera b8ab549bcb Cleanup lint
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:31 +02:00
Jakub Sztandera 4f60c1afe7 If something costs 0 gas, make it 1.
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:31 +02:00
Jakub Sztandera 9cd34509ee Fix error handling of json
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:31 +02:00
Jakub Sztandera a2fd0aad41 More on OnActorExec
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:31 +02:00
Jakub Sztandera 01ac4e5da3 Gas on actor exec
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:47:30 +02:00
Jakub Sztandera 01e230e810 Fix ratio
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:46:42 +02:00
Jakub Sztandera 78ee64d9f8 Fix stupid mistake
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:46:42 +02:00
Jakub Sztandera e5a7cb635c Siwtch back to float64
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:46:42 +02:00
Jakub Sztandera 49ddcdb4b0 Don't pass pointers
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:46:42 +02:00
Jakub Sztandera b5ae3c055b Remove warning
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:46:41 +02:00
Jakub Sztandera 9712bbc854 Decode in workers
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:46:41 +02:00
Jakub Sztandera 3134fcb54a Streaming mean and variance
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:46:41 +02:00
Jakub Sztandera 87d668390e Use float32
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:46:41 +02:00
Jakub Sztandera 710286d6e7 Add pprof
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:46:41 +02:00
Jakub Sztandera 04edeccbf4 fix trimming
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:46:41 +02:00
Jakub Sztandera db5929f4a5 Limit size of expensiveInvocs
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:46:41 +02:00
Jakub Sztandera e65215f1b5 Make lotus-bench import analyze multithreaded and less RAM hungry
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:46:41 +02:00
Jakub Sztandera c97720e731 Fix import analyze
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-07-02 18:46:41 +02:00
Łukasz Magiera 3aaa4fb692 Merge pull request #2239 from filecoin-project/feat/upgrade-markets-0.3.1.1
Hotfix upgrade markets to 0.3.1.1 to master
2020-07-02 17:08:48 +02:00
hannahhoward 7e1e9bcd60 fix(markets): upgrade markets to 0.3.1.1
upgrade to 0.3.1.1 to get critical node restart fixes and retrieval map access fix
2020-07-02 08:03:10 -07:00
Łukasz Magiera 8c347d8764 Merge pull request #2231 from filecoin-project/feat/lotus-manage-fds
have lotus attempt to raise its own file descriptor limit
2020-07-02 10:49:34 +02:00
Łukasz Magiera f7bffdf63a Merge pull request #2230 from filecoin-project/feat/add-peer-to-hello-fail-log
add peer ID to hello protocol failure log
2020-07-02 10:49:02 +02:00
Łukasz Magiera bda43a4627 Merge pull request #2229 from filecoin-project/fix/vm-abort-log-msg
fix vm abortf log message
2020-07-02 10:48:36 +02:00
Łukasz Magiera 19195ddf96 Merge pull request #2228 from filecoin-project/feat/docgen-perms
add perms listing to docgen output
2020-07-02 10:48:04 +02:00
whyrusleeping 5fa3021a79 set proper bitwidth for verifreg command hamts 2020-07-01 17:29:11 -07:00
whyrusleeping a5935486ef have lotus attempt to raise its own file descriptor limit 2020-07-01 17:09:21 -07:00
whyrusleeping ffd012906c add peer ID to hello protocol failure log 2020-07-01 16:20:05 -07:00
whyrusleeping f8a1fb2321 fix vm abortf log message 2020-07-01 15:51:21 -07:00
Aayush Rajasekaran 605e9bbbd7 Add docs comments to API 2020-07-01 17:16:05 -04:00
whyrusleeping 168b0f8df6 add perms listing to docgen output 2020-07-01 14:01:27 -07:00
Łukasz Magiera 70d8378404 Merge pull request #2214 from filecoin-project/fix/too-high-nonce-log
miner: Fix mpool too-high-nonce-msgs log
2020-07-01 17:30:27 +02:00
Łukasz Magiera 00e38ce126 Merge pull request #2219 from filecoin-project/feat/update-paramfetch
Update paramfetch
2020-07-01 17:28:37 +02:00
Łukasz Magiera 02c3f8ed80 Update paramfetch 2020-07-01 17:23:50 +02:00
Łukasz Magiera e949a458ec miner: Fix mpool too-high-nonce-msgs log 2020-07-01 12:53:27 +02:00
Łukasz Magiera 228ff3ba57 Merge pull request #2212 from filecoin-project/fix/master-build
sync: Fix build
2020-07-01 11:26:43 +02:00
Łukasz Magiera 4c1dfd7eda sync: Fix build 2020-07-01 11:24:26 +02:00
Łukasz Magiera e1799f1524 Merge pull request #2155 from filecoin-project/feat/ffi-0.30.1
Update FFI to 0.30.1
2020-07-01 11:17:18 +02:00
Łukasz Magiera 8f0e04027e Merge pull request #2154 from laser/feat/1920-selection-commands
implement toggling of online/offline storage/retrieval deals
2020-07-01 11:06:32 +02:00
Łukasz Magiera abdafc8ee4 Merge pull request #2140 from filecoin-project/chainwatch/sector-info-schema
feat: define miner sector schema
2020-07-01 11:02:57 +02:00
Łukasz Magiera 9030b559e8 Merge pull request #1470 from hunjixin/hunjixin/test/bls_benchmarks
add bench mark for bls sign and verify
2020-07-01 10:57:34 +02:00
Łukasz Magiera cd34d02377 Merge pull request #2209 from filecoin-project/feat/faster-winpost-sectors
use bitfields to enumerate sectors for winning post
2020-07-01 10:43:24 +02:00
Łukasz Magiera a362ef97df Merge pull request #2188 from filecoin-project/const-relaxation
make system constants configurable as vars.
2020-07-01 10:43:07 +02:00
Łukasz Magiera 92f392d422 Merge pull request #2192 from filecoin-project/fix/evnts-map-pnc
Fix concurrent map access panic in event API
2020-07-01 10:36:29 +02:00
Łukasz Magiera e8ddaab1c3 Merge pull request #2202 from jackoelv/patch-2
Update mining-troubleshooting.md
2020-07-01 10:35:56 +02:00
whyrusleeping da78ff9151 use bitfields to enumerate sectors for winning post 2020-06-30 21:57:49 -07:00
frrist e576c7a08e "feat": add logic to update miner sector table on term 2020-06-30 21:26:46 -07:00
jackoelv 2d180cdacf Update mining-troubleshooting.md
some code changed, document should be changed too. 
by default, bench is not maked by make 2k. so ,first make bench is safe.
I have checked the makefile, the bundle name is not lotus-bench but 'bench'.
2020-07-01 09:45:40 +08:00
Raúl Kripalani 77c7eb6fd9 fix lint errors. 2020-06-30 22:56:13 +01:00
Whyrusleeping 857b5962da Merge pull request #2000 from filecoin-project/asr/maxheight
Do not connect to peers with impossibly high heads
2020-06-30 14:24:50 -07:00
frrist 8c54c09ab7 pair: work from pair with placer 2020-06-30 13:22:58 -07:00
Łukasz Magiera 6927a532cf Update sector-storage with lower resource requirements 2020-06-30 21:03:44 +02:00
Dirk McCormick 49dccf4284 fix: concurrent map access panic 2020-06-30 14:24:08 -04:00
Jakub Sztandera a4751ddd01 Merge pull request #2190 from filecoin-project/chore/upd-log
Update go-log
2020-06-30 19:59:26 +02:00
Jakub Sztandera c811133aac Update go-log
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-30 19:39:13 +02:00
Frrist c16ea42fad fix: update miner_head table with new miner fields (#2142) 2020-06-30 10:26:41 -07:00
Raúl Kripalani 05e521ab03 fix test compilation issue. 2020-06-30 16:47:32 +01:00
Raúl Kripalani 1ef490feea rename build.PropagationDelay{=>Secs}. 2020-06-30 15:01:30 +01:00
Raúl Kripalani 3b826e41f6 rename build.AllowableClockDrift{=>Secs}. 2020-06-30 15:00:01 +01:00
Raúl Kripalani d232299c77 type constants on all build tags. 2020-06-30 14:58:34 +01:00
Raúl Kripalani f774d2aab1 add testground Makefile target; attach to buildall. 2020-06-30 14:48:13 +01:00
Raúl KripalaniandAnton Evangelatov 642aed93d9 remove superfluous comment.
Co-authored-by: Anton Evangelatov <anton.evangelatov@gmail.com>
2020-06-30 14:38:20 +01:00
Raúl Kripalani 4f9c907248 rename build.{BlockDelay=>BlockDelaySecs}.
Since this global is not typed as a time.Duration,
rather as an int, it makes sense to clarify the unit.
2020-06-30 14:26:49 +01:00
Raúl Kripalani 612b2fe9d7 revert changes in go.sum. 2020-06-30 14:21:39 +01:00
Raúl Kripalani 0fddf3e114 make system constants configurable as vars.
This configurability is unlocked through the `testground`
build tag, which Project Oni will uses.

Changes in the usage places of these relaxed constants
were required due to the fact that Golang constants are
untyped, but vars aren't.

Read https://blog.golang.org/constants for more info.
2020-06-30 14:18:26 +01:00
Łukasz Magiera c3898e4abf Merge pull request #2172 from filecoin-project/feat/pred-tests
Add more predicate tests
2020-06-30 11:32:13 +02:00
Łukasz Magiera 726c09618a Merge pull request #2177 from filecoin-project/feat/lotus-shed-keyinfo
lotus-shed: organize peer key generate and other key commands under keyinfo
2020-06-30 11:30:57 +02:00
Travis Person 12f10ac414 lotus-shed: organize peer key generate and other key commands under keyinfo 2020-06-29 20:07:39 +00:00
Łukasz Magiera 77b3bf8bc2 Update FFI to 0.30.1 2020-06-29 20:24:27 +02:00
Łukasz Magiera a0e1d5f567 Merge pull request #2175 from filecoin-project/feat/update-markets-0.3.1
Update to markets 0.3.1
2020-06-29 20:09:33 +02:00
hannahhoward 4e32c7edb3 feat(markets): update to markets 0.3.1
Update to markets 0.3.1 with multiaddr support for miners
2020-06-29 10:24:23 -07:00
Dirk McCormick c72def55fe test: add more predicate tests 2020-06-29 11:21:29 -04:00
Łukasz Magiera 982962ef0a Merge pull request #2171 from filecoin-project/fix/bitfield-null-marshal
Update go-bitfield with fixed empty marshaling
2020-06-29 16:14:47 +02:00
Łukasz Magiera 90a470ed78 Update go-bitfield with fixed empty marshaling 2020-06-29 16:06:57 +02:00
waynewyang 048d0e0d7a set 'true' after handle be called 2020-06-29 21:37:08 +08:00
Łukasz Magiera f812cac142 Merge pull request #2161 from waynewyang/mining
fix: mining logic
2020-06-29 15:24:45 +02:00
Łukasz Magiera aeab3a709a Merge pull request #2158 from jackoelv/patch-1
Update mining.md
2020-06-29 15:19:58 +02:00
Łukasz Magiera 7058f4eb63 Merge pull request #2153 from filecoin-project/feat/state-changes-api
Feat/state changes api
2020-06-29 15:19:18 +02:00
waynewyang 8d51a20143 fix: mining logic 2020-06-28 18:20:56 +08:00
jackoelv a4f6269724 Update mining.md
lotus-storage-miner state power should be changed to lotus state power
2020-06-27 23:16:24 +08:00
Lucas MolasandJakub Sztandera fbfe57cd63 doc: block validations (#1919)
Co-authored-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-26 20:13:14 -03:00
Łukasz Magiera 0118a78967 Merge pull request #2050 from filecoin-project/asr/api-bitfield
Return sector numbers, not bitfields from API
2020-06-27 00:51:52 +02:00
Dirk McCormick 659c723ea3 fix: embed hcEvents into events as pointer so as not to copy lock 2020-06-26 15:42:44 -04:00
Dirk McCormick bbb9a9cd1a refactor: lint fixes 2020-06-26 15:36:48 -04:00
laser 5052a87a82 bugfix: accessors should be read and writers should be admin 2020-06-26 12:33:39 -07:00
laser b9180a99d4 toggle consideration of offline storage/retrieval deal proposals 2020-06-26 12:27:41 -07:00
Dirk McCormick db1773d708 docs: add predicate docs 2020-06-26 14:59:23 -04:00
Dirk McCormick a1b009328d refactor: simplify diff 2020-06-26 14:43:46 -04:00
Dirk McCormick 393a9ca4f2 test: predicates test 2020-06-26 14:41:19 -04:00
laser e910a045d0 big rename to allow for later introducing the "consider offline" config 2020-06-26 10:50:54 -07:00
laser 5d9a775699 replace enable/disable commands with selection commands 2020-06-26 10:33:06 -07:00
Łukasz Magiera 8233143578 Merge pull request #2144 from Alexey-N-Chernyshov/patch-1
Fix to addresses in paychmgr channel creation
2020-06-26 19:14:30 +02:00
Łukasz Magiera 950cb8bc03 Merge pull request #1970 from RobQuistNL/patch-3
Update Ubuntu installation documentation + bump required go version to 1.14
2020-06-26 19:12:08 +02:00
Alexey eafb04004e Fix to addresses in paychmgr channel creation 2020-06-26 09:06:01 +03:00
Rob Quist 3d3e384d5c Merge pull request #2 from RobQuistNL/patch-2
Update makefile
2020-06-26 02:10:53 +02:00
Rob Quist 38533631bf Bump to Go v. 1.14 as requirement 2020-06-26 02:09:39 +02:00
frrist 6fe39ef065 fixup! feat: define miner sector schema 2020-06-25 17:03:28 -07:00
frrist 47c3e14d4b fixup! feat: define miner sector schema 2020-06-25 17:00:22 -07:00
frrist d8b647cc3a fixup! feat: define miner sector schema 2020-06-25 16:07:43 -07:00
Dirk McCormick abad4a3941 refactor: modify predicates API 2020-06-25 17:43:37 -04:00
frrist 2c0a4914cf feat: define miner sector schema
- define a miner sector schema to store miner sector details at each tipset the miner experiences a
state change. This solution stores redundant data since a miner state change (head cid changes)
does not necessarily indicate its sectors changes.

- makes progress towards sentinel/issues/10
2020-06-25 13:16:50 -07:00
Aayush Rajasekaran e54b49b442 Bump API version 2020-06-25 13:49:15 -04:00
Aayush Rajasekaran 50aa1e6baa Update bitfield 2020-06-25 13:49:15 -04:00
Aayush Rajasekaran e3c897fb68 Change StateReadState to take an address, not an actor 2020-06-25 13:49:15 -04:00
Dirk McCormick 728afc0587 refactor: remove state API example 2020-06-25 12:46:43 -04:00
Dirk McCormick 95a9dc9db0 refactor: use struct instead of array for state change 2020-06-25 12:43:06 -04:00
Dirk McCormick b62fef7541 feat: include previous TS in StateChangedHandler 2020-06-25 12:43:06 -04:00
Dirk McCormick dd490220d7 refactor: Extract message-specific code from calledEvents
This allows us to create a general purpose head change events manager that can be used for call events and also for state change events.
2020-06-25 12:43:06 -04:00
hannahhoward 7f932b96ae WIP 2020-06-25 12:41:50 -04:00
Łukasz Magiera 4af9a20903 Merge pull request #2132 from filecoin-project/feat/deal-sechd-prio
sealing: Give priority to sectors with deals
2020-06-25 18:27:35 +02:00
Łukasz Magiera f9cb549fbe Merge pull request #2137 from filecoin-project/feat/compact-trace
Make gas traces smaller, strip callers in import-bench
2020-06-25 18:25:38 +02:00
Łukasz Magiera 7e342e60d1 sealing: Give priority to sectors with deals 2020-06-25 18:13:45 +02:00
Jakub Sztandera f98063d604 In this case I want it to be not really safe
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-25 16:58:55 +02:00
Jakub Sztandera 10c4fae8c0 Make gas traces smaller, strip callers in import-bench
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-25 16:46:50 +02:00
Łukasz Magiera cae24a226b Merge pull request #2119 from laser/feat/1920-toggle-retrieval
allow retrieval miner to enable/disable consideration of retrieval deal proposals
2020-06-24 21:19:19 +02:00
Łukasz Magiera 0162322833 Merge pull request #2126 from filecoin-project/fix/events-race
Fix two races in events
2020-06-24 21:09:14 +02:00
Łukasz Magiera 06dfe3c5ae Merge pull request #2131 from filecoin-project/fix/chainwatch-tipset-api-access
fix: use tipset corresponding to stateroot
2020-06-24 20:04:18 +02:00
frrist a98c4038f4 fix: use tipset corresponding to stateroot
- Use te tipsetkey corresponding to the stateroot when fetching actor
data from the lotus api.
2020-06-24 11:01:25 -07:00
laser 4c760ec1b1 lint: update comments to match type declarations 2020-06-24 08:08:10 -07:00
laser 176d0bb7c0 add "lotus-storage-miner retrieval-deals" subcommands
- enable retrieval
- disable retrieval
2020-06-24 08:08:10 -07:00
laser bc90b857c9 change "lotus-storage-miner deals" to "lotus-storage-miner storage-deals" 2020-06-24 08:08:10 -07:00
laser ef0abf2b98 disable/enable retrieval deal consideration via config 2020-06-24 08:07:12 -07:00
Jakub Sztandera 008a2969b2 Fix two races in events
Also race fix: depends on https://github.com/ipfs/go-blockservice/pull/65
Resolves #2092, #2099, #2108, #1930, #2110

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-24 17:05:24 +02:00
Łukasz Magiera 7d9f9ba756 Merge pull request #2125 from filecoin-project/fix/cw-state-heights-index
chainwatch: state_heights_uindex is not unique
2020-06-24 14:55:42 +02:00
Łukasz Magiera 358b36bc66 chainwatch: state_heights_uindex is not unique 2020-06-24 14:34:53 +02:00
Łukasz Magiera f1e686f706 Merge pull request #2107 from chunqizhi/zc
An incorrect sector was detected, but also run windowPoSt
2020-06-24 12:40:16 +02:00
Łukasz Magiera 0b1fa54a4d wdpost: Remove commented code 2020-06-24 12:38:46 +02:00
chunqizhi 49281ef599 Merge pull request #4 from filecoin-project/master
merge
2020-06-24 13:55:29 +08:00
24c7f47566 Modify print faulty sectors in provingFaultsCmd 2020-06-24 10:14:20 +08:00
Łukasz Magiera 4037d707c9 Merge pull request #2120 from filecoin-project/feat/change-addrs-cmd
add command to change registered multiaddrs for miner
2020-06-24 01:02:35 +02:00
Łukasz Magiera 001d4ab002 Appease the linter 2020-06-24 01:00:32 +02:00
Łukasz Magiera f115603093 Merge pull request #2121 from filecoin-project/fix/1917
Update sector-storage to fix #2080 and #1917
2020-06-24 00:56:59 +02:00
Łukasz Magiera d7bb284e57 miner: Move set-addrs command to a new 'actor' namespace 2020-06-24 00:54:28 +02:00
Łukasz Magiera 11c53c26ff Update sector-storage to fix #2080 and #1917 2020-06-24 00:47:47 +02:00
Łukasz Magiera d28bbf4674 Merge pull request #2095 from filecoin-project/feat/sector-remove
Update specs-storage; Support for removing sectors
2020-06-24 00:32:33 +02:00
Łukasz Magiera a7d662a7d8 Update to actually working sector-storage 2020-06-24 00:23:39 +02:00
Łukasz Magiera 6f8c464393 Merge remote-tracking branch 'origin/master' into feat/sector-remove 2020-06-23 23:54:27 +02:00
Raúl Kripalani c8104a03e6 some initial godocs. (#2118) 2020-06-23 18:51:25 -03:00
Łukasz Magiera 69559bcf4f Use fsm, sector-storage master 2020-06-23 23:32:12 +02:00
whyrusleeping d524821c86 add command to change registered multiaddrs for miner 2020-06-23 14:25:45 -07:00
Jakub Sztandera e864244226 Merge pull request #2117 from filecoin-project/fix/drand-config-di
improve DrandConfig dependency injection
2020-06-23 23:14:58 +02:00
Yusef Napora 5074cf8beb import DrandConfig from dtypes 2020-06-23 16:23:06 -04:00
Yusef Napora b448de422e improve DrandConfig dependency injection 2020-06-23 16:01:10 -04:00
Łukasz Magiera 99d3571772 Merge pull request #2115 from filecoin-project/feat/drand-config-override
allow overriding drand config
2020-06-23 21:59:05 +02:00
Łukasz Magiera 0354275b39 Merge pull request #2112 from laser/bugs/2111-hanging-client-retrieve
return error if retrieval deal rejected
2020-06-23 21:56:02 +02:00
laser 309fbc15b2 import aliasing, for legibility 2020-06-23 12:22:33 -07:00
Łukasz Magiera 28e3c863bf Merge pull request #2114 from filecoin-project/fix/state-mkt-participants
state: Get correct locked table in StateMarketParticipants
2020-06-23 21:21:43 +02:00
laser 06162290af explicitly handle each deal status, as per PR feedback 2020-06-23 12:14:41 -07:00
Yusef Napora 628872d0e4 forgot my go fmt hook 2020-06-23 15:10:27 -04:00
Yusef Napora 960523f45f fix drand test 2020-06-23 15:09:28 -04:00
Łukasz Magiera fb04b17fad state: Get correct locked table in StateMarketParticipants 2020-06-23 20:55:59 +02:00
laser 8adc831a31 return error if retrieval deal rejected 2020-06-23 11:08:04 -07:00
Yusef Napora 566a99240d allow overriding drand config 2020-06-23 13:33:18 -04:00
Łukasz Magiera 7b2241f051 Merge pull request #2102 from filecoin-project/feat/parallel-block-val
run block validation for tipsets in parallel
2020-06-23 17:59:14 +02:00
55ed45f108 Get the good sectors to run windowPost 2020-06-23 20:46:41 +08:00
Łukasz Magiera f8e7901b89 Address review 2020-06-23 14:44:34 +02:00
Łukasz Magiera 9e70e95242 sync: Correctly pass blocks to ValidateBlock 2020-06-23 14:10:47 +02:00
Łukasz Magiera 68d38eff33 Merge pull request #2103 from filecoin-project/deps/libp2p-0.10.0
update to latest libp2p release
2020-06-23 12:44:42 +02:00
Łukasz Magiera abd400801c mod tidy 2020-06-23 11:46:20 +02:00
Łukasz Magiera d24a750ba4 Merge pull request #2106 from filecoin-project/feat/streaming-bench-results
stream bench import results to disk
2020-06-23 11:42:18 +02:00
whyrusleeping 9903eba7fb stream bench import results to disk 2020-06-22 20:08:19 -07:00
whyrusleeping 3752311f44 update to latest libp2p release 2020-06-22 16:25:41 -07:00
whyrusleeping b71f771acb run block validation for tipsets in parallel 2020-06-22 16:09:05 -07:00
Łukasz Magiera 9f3145aec0 Merge pull request #2093 from filecoin-project/asr/clarify
Clarify expected block win when below minimum power threshold
2020-06-22 22:32:08 +02:00
Łukasz Magiera 8638076ecb Merge pull request #1894 from filecoin-project/feat/chainwatch-usage
Add chainwatch systemd svc config
2020-06-22 22:25:48 +02:00
Mike Greenberg 8649baccf7 Remove dev values from chainwatch.service 2020-06-22 16:17:07 -04:00
Aayush Rajasekaran c33d9e9668 Merge pull request #2094 from filecoin-project/schomatis/doc/security-policy
doc: report a vulnerability
2020-06-22 15:39:52 -04:00
Łukasz Magiera 03d70e1513 Merge pull request #2097 from filecoin-project/feat/disable-builtin-assets
provide an option to disable loading of built-in assets.
2020-06-22 21:35:58 +02:00
Raúl Kripalani d20255b1b4 provide an option to disable loading of built-in assets. 2020-06-22 19:42:04 +01:00
Łukasz Magiera cd91e42a56 ci: lint-changes based on master 2020-06-22 19:39:08 +02:00
Łukasz Magiera e2435be0b9 build: Bump API version 2020-06-22 19:36:26 +02:00
Łukasz Magiera 5adc188466 miner: Command to remove sectors 2020-06-22 19:35:14 +02:00
Łukasz Magiera 101ba0b796 Update deps to support removing sectors 2020-06-22 19:03:35 +02:00
Lucas Molas 8cd2012d27 doc: report a vulnerability 2020-06-22 12:45:24 -03:00
Aayush Rajasekaran 4959596527 Clarify expected block win when below minimum power threshold 2020-06-22 11:42:26 -04:00
956c397c3c Add provingFaultsCmd for getting sectors information for the currently known faults 2020-06-22 16:00:29 +08:00
chunqizhi 1249ede2b7 Merge pull request #3 from filecoin-project/master
merge
2020-06-22 15:47:43 +08:00
Łukasz Magiera 596ed330dd Merge pull request #2069 from laser/feat/1920-blocklist-cids
allow storage miners to manage a blocklist of piece CIDs
2020-06-19 21:19:15 +02:00
Łukasz Magiera b4c1594d99 Merge pull request #2073 from mitchwagner/patch-1
Remove redundant glossary item
2020-06-19 21:05:29 +02:00
Łukasz Magiera 98cb08d853 Merge pull request #2077 from laser/bugs/1993-problems-with-sizestr
bump from 3 to 4 digits in format-string used by types.SizeStr
2020-06-19 21:04:30 +02:00
Nathaniel Jensen 6b86dcde4a doc: Fix architecture broken link 2020-06-19 13:33:19 -03:00
laser fbeaab466a obey the linter 2020-06-19 09:20:20 -07:00
laser 5e77b5da9f bump from 3 to 4 digits in format-string
Fixes #1993
2020-06-19 08:51:06 -07:00
Mitch Wagner 7c4225d01c Remove redundant glossary item
The excised entry previously rendered twice in the glossary under two different keys. This commit removes one of those KV pairs to avoid that.
2020-06-18 21:31:26 -04:00
Łukasz Magiera ffa7be86fe Merge pull request #2070 from filecoin-project/feat/reset-genesis
New Genesis
2020-06-19 01:29:01 +02:00
Łukasz Magiera c41c210ced New Genesis 2020-06-19 01:24:04 +02:00
laser de7d6c255c blacklist -> blocklist 2020-06-18 15:51:01 -07:00
laser 99060fbb64 eliminate errant debug line 2020-06-18 14:05:59 -07:00
laser 0c8d648998 specify which CID is being blacklisted (it's the piece) 2020-06-18 14:02:22 -07:00
laser aa18d1985e reject storage deal proposals containing blacklisted piece CIDs 2020-06-18 13:32:20 -07:00
laser b0edf924b4 add commands for manipulating storage deal CID blacklist 2020-06-18 13:15:18 -07:00
laser 997a46a90f wombat 2020-06-18 10:32:32 -07:00
Łukasz Magiera b99b8f55f6 Merge pull request #2065 from filecoin-project/docs/docgen-fixes
docgen improvements
2020-06-18 16:20:19 +02:00
Łukasz Magiera c0a50a2143 api: Add a bunch of donstrings 2020-06-18 15:44:47 +02:00
Łukasz Magiera 382734b057 docgen: Generate simple index 2020-06-18 14:56:00 +02:00
Łukasz Magiera 90fbbea372 docgen: Make larger inputs/outputs more readable 2020-06-18 14:37:41 +02:00
Łukasz Magiera 55d9ad0b55 Fix docgen 2020-06-18 14:30:00 +02:00
Łukasz Magiera e5e5d0d9e4 Merge pull request #2064 from filecoin-project/deps/sectorstorage-d9de9b7cb4
Update sector-storage with 32G checkFiles fix
2020-06-18 12:44:29 +02:00
Łukasz Magiera 324b659d33 Update sector-storage with 32G checkFiles fix 2020-06-18 09:34:28 +02:00
Aayush Rajasekaran edcf899be1 Merge pull request #2060 from filecoin-project/jimpick/fix-lotus-bench-link
Fix bad link in hardware mining docs
2020-06-17 21:19:58 -04:00
Jim Pick 2bf781d591 Fix bad link in hardware mining docs
This fixes a bad link.

There's also a link to the Github issue thread for results that still works, but
is a bit stale (for proofs before v20). I didn't attempt to fix that as there
doesn't appear to be a thread for v27 proofs.
2020-06-17 18:04:46 -07:00
Łukasz Magiera cc179c5270 Merge pull request #2047 from filecoin-project/feat/parallel-sealing-bench
allow sealing bench to run parallel seals
2020-06-18 01:28:56 +02:00
Łukasz Magiera b417725e3e Merge pull request #2059 from filecoin-project/feat/testnet-peers
Bootstrap peers
2020-06-18 01:15:49 +02:00
Travis Person c02d8225a8 Bootstrap peers 2020-06-17 23:01:26 +00:00
Łukasz Magiera 659f570cfc Merge pull request #2058 from filecoin-project/jimpick/spelling
Spelling: s/winnnig/winning/
2020-06-17 22:09:17 +02:00
Jim Pick c7e470bd5e Spelling: s/winnnig/winning/
It was bugging me. :-)
2020-06-17 12:49:23 -07:00
Łukasz Magiera fe4efa0e0e Merge pull request #1842 from filecoin-project/next
Next network staging
2020-06-17 20:58:21 +02:00
Łukasz Magiera 02234d00b7 Merge remote-tracking branch 'origin/master' into next 2020-06-17 20:50:42 +02:00
Łukasz Magiera bef5bfcbb6 Merge pull request #2057 from filecoin-project/deps/fsm-fixes
Update storage FSM with a bunch of fixes
2020-06-17 20:48:50 +02:00
Łukasz Magiera 290512ee68 Update storage FSM with a bunch of fixes 2020-06-17 20:42:08 +02:00
Łukasz Magiera d129d6eada Merge pull request #2056 from filecoin-project/upd/specs-ac-chargegas
Update to specs actors with ChargeGas interface
2020-06-17 20:18:10 +02:00
Jakub Sztandera 5c5a3f2264 go mod tidy
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-17 20:04:28 +02:00
Łukasz Magiera d4644a28c1 Merge pull request #2046 from laser/feat/2027-manipulate-ask
add ask-manipulating (and printing) deal subcommands
2020-06-17 20:03:51 +02:00
Jeromy d66c70d1e6 add configurable paralellism for sub portions of the sealing process 2020-06-17 11:02:48 -07:00
Jakub Sztandera b91e7a9860 Update to specs actors with ChargeGas interface
Based on `lotus-0.6.1-chargegas` in specs-actors.

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-17 20:00:30 +02:00
laser fcdfda8ba2 use chain head instead of mining base 2020-06-17 10:56:42 -07:00
Łukasz Magiera 2800fd919b Merge pull request #2053 from filecoin-project/feat/worker-reconnect
seal-worker: Auto-restart if miner dies
2020-06-17 19:48:29 +02:00
Łukasz Magiera 512bbb99ca Merge pull request #2054 from filecoin-project/fix/wdpost-panic
wdpost: Don't return nil from checkSectors
2020-06-17 19:48:09 +02:00
laser ed5b74b1ae tidy up 2020-06-17 10:42:09 -07:00
laser 791dff5a87 don't go into negative remaining time 2020-06-17 10:30:16 -07:00
laser 402cd8be19 get-ask output should use durations, too 2020-06-17 10:20:42 -07:00
Łukasz Magiera bdcb1e3592 Merge pull request #2029 from filecoin-project/feat/gas-delta-output
add some smartness to bench analyze gas output
2020-06-17 18:44:10 +02:00
Łukasz Magiera e60dd219dc wdpost: Don't return nil from checkSectors 2020-06-17 18:21:40 +02:00
laser 9d7be5dcbf modify set-ask to work with human-readable clock time/duration 2020-06-17 09:20:43 -07:00
Łukasz Magiera 70e964d9f9 Merge pull request #2039 from filecoin-project/feat/testnet-params
Set build params for testnet
2020-06-17 18:01:31 +02:00
laser 673a643184 use xerrors, as per feedback in PR 2020-06-17 08:57:18 -07:00
Łukasz Magiera 2761872ea7 seal-worker: Auto-restart when API connection is lost 2020-06-17 17:47:18 +02:00
Łukasz Magiera fc7195f19a seal-worker: Wait for miner API on start 2020-06-17 17:47:18 +02:00
Łukasz Magiera 8b8bb5e833 rpc: add Closing method 2020-06-17 17:47:18 +02:00
laser 5d4f1bb3f1 work with bit-padded byte quantities, as per PR feedback 2020-06-17 08:42:30 -07:00
laser 139c3297ab change "duration" help text 2020-06-17 08:34:50 -07:00
RobQuistNL 20503de3ba Merge branch 'next' of github.com:filecoin-project/lotus into patch-3 2020-06-17 09:08:16 +02:00
laser 2676892886 go mod tidy 2020-06-16 17:47:04 -07:00
laser 5acf5bf102 upper and lower bounds checking 2020-06-16 17:45:11 -07:00
Jeromy ec693008d7 allow sealing bench to run parallel seals 2020-06-16 17:39:51 -07:00
laser 4ba1846c11 format the piece sizes 2020-06-16 17:32:45 -07:00
laser 5eceed81e1 add "get-ask" command 2020-06-16 17:23:03 -07:00
Whyrusleeping 8b725b4b8c Merge pull request #2045 from filecoin-project/feat/seed-rm-unsealed
seed: Cleanup unsealed sectors
2020-06-16 16:58:44 -07:00
laser 6253c39100 replace "set-price" with "set-ask"
Fixes #2027
2020-06-16 16:13:21 -07:00
Łukasz Magiera b845013836 Set build params for testnet 2020-06-17 00:37:40 +02:00
Łukasz Magiera 9690bc9c63 seed: Cleanup unsealed sectors 2020-06-17 00:35:51 +02:00
Whyrusleeping c6a8fe16c6 Merge pull request #2042 from jsign/jsign/considerstatus
Consider QueryOffer Error & Status
2020-06-16 13:58:37 -07:00
Ignacio Hagopian ec9a334f93 append message on unavailable and error status
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-06-16 17:52:47 -03:00
Ignacio Hagopian 35d9de6b6e consider response status and err
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-06-16 17:32:03 -03:00
Aayush Rajasekaran 4d0df5d599 Merge pull request #2040 from jsign/jsign/minerretrieval
Miner QueryOffer API & non local-discovery retrieval CLI support
2020-06-16 16:00:40 -04:00
Ignacio Hagopian 7fd082e941 resolve peerid
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-06-16 12:22:44 -03:00
Ignacio Hagopian 9d17e0be9d ClientMinerQueryOfer API & CLI support
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-06-16 11:14:49 -03:00
Rob Quist 030472d61c Remove Rust installation and remove Go installation guide 2020-06-16 15:30:41 +02:00
Łukasz Magiera 6bff52483b Merge pull request #1973 from filecoin-project/feat/drand-upd
Update to new drand
2020-06-16 15:30:40 +02:00
Łukasz Magiera 32d8ca2f21 Merge pull request #2037 from filecoin-project/feat/testnet-reset-updates
Pre-testnet reset updates
2020-06-16 15:29:33 +02:00
Jakub Sztandera fd6c8769dd Update to new drand
WIP

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-16 14:46:30 +02:00
Łukasz Magiera bac6a47c67 specs-actors v0.6.1 2020-06-16 12:30:54 +02:00
Łukasz Magiera 18dd1c277b Update ffi 2020-06-16 12:28:28 +02:00
Łukasz Magiera ab4c11c096 Merge remote-tracking branch 'origin/master' into next 2020-06-16 12:04:29 +02:00
Łukasz Magiera 6bbea74a7d Merge pull request #1961 from RobQuistNL/patch-2
Update documentation about Lotus Seal Worker
2020-06-16 11:58:38 +02:00
chunqizhi 4f1efbe38f Merge pull request #2 from filecoin-project/master
merge
2020-06-16 17:57:52 +08:00
Łukasz Magiera eeb5053919 Merge pull request #2031 from filecoin-project/feat/stats-power-lookup
stats: increase miner power lookup perf
2020-06-16 11:53:09 +02:00
Aayush Rajasekaran d8a517f992 Syncer::InformNewHead can quickly fail if height is impossibly large 2020-06-16 00:51:00 -04:00
Aayush Rajasekaran aa513d920e Merge pull request #1705 from hayeah/cache-tipset-validation-progress
Cache tipset validation progress
2020-06-16 00:14:11 -04:00
Whyrusleeping 3327ed50a8 Merge pull request #2033 from filecoin-project/asr/advance-block
Make advance-block work
2020-06-15 19:49:19 -07:00
Travis Person f31fcdae08 stats: increase miner power lookup perf 2020-06-16 02:48:27 +00:00
Whyrusleeping 66b15b7076 Merge pull request #2032 from filecoin-project/deps/go-fil-markets-0.3.0
Update to fil-markets 0.3.0
2020-06-15 19:46:24 -07:00
chunqizhi c5a9f180af Merge pull request #1 from filecoin-project/master
merge
2020-06-16 09:47:20 +08:00
Aayush Rajasekaran a9abf3ceb2 extract the fake Wpost used for testing 2020-06-15 21:02:53 -04:00
Aayush Rajasekaran ed3b2716af Don't verify ElectionPostVRF when insecure validation enabled 2020-06-15 21:02:25 -04:00
Aayush Rajasekaran 69948cd09c WalletSign should resolve ID addresses 2020-06-15 21:00:22 -04:00
Jeromy f8c4b64782 improve chain import analyze output, add some rough virtual gas charges 2020-06-15 16:05:29 -07:00
hannahhoward a422647819 fix(lint): fix lint error
fix lint error and update to tagged package
2020-06-15 15:53:39 -07:00
hannahhoward 9262661135 chore(deps): update to fil-markets 0.3.0
Updates to latest fil markets with resumability and other fixes
2020-06-15 15:43:47 -07:00
Jeromy 01c4726fd5 add some smartness to bench analyze gas output 2020-06-15 13:02:57 -07:00
Łukasz Magiera 0230362d33 Merge pull request #2025 from filecoin-project/deps/specs-actors-v0.6
specs-actors v0.6
2020-06-15 21:30:37 +02:00
Łukasz Magiera f8669d4e95 Update chain-val and sector-storage 2020-06-15 21:21:40 +02:00
Łukasz Magiera 12298f8953 Merge pull request #2026 from filecoin-project/feat/gas-extra
Use extra field in gastrace
2020-06-15 19:57:30 +02:00
Łukasz Magiera daca8651f4 Fix bench 2020-06-15 19:53:21 +02:00
Jakub Sztandera 8039701f9e Use extra field in gastrace
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-15 19:52:04 +02:00
Łukasz Magiera 01f0bb3124 Merge pull request #1994 from laser/feat/1920-toggle-accepting-storage-deals
allow miner to disable/enable consideration of received storage deal proposals
2020-06-15 19:05:39 +02:00
Łukasz Magiera 58a79773ee fix debug build 2020-06-15 18:34:36 +02:00
Łukasz Magiera c832c0bf3f mod tidy 2020-06-15 18:31:59 +02:00
Łukasz Magiera 907364ce67 Update deps, fix more tests 2020-06-15 18:30:49 +02:00
Jakub Sztandera 18cf7b046e Merge pull request #2024 from filecoin-project/feat/virtual-gas
Add virtual gas
2020-06-15 18:27:24 +02:00
Whyrusleeping 87e5c38e32 Merge pull request #1952 from laser/feat/805-warn-lotus-balance
display a little inline warning if balance is zero
2020-06-15 09:19:00 -07:00
Jakub Sztandera c98972ab23 Merge pull request #1555 from filecoin-project/feat/hashverify
Use HashVerify
2020-06-15 17:47:42 +02:00
Jakub Sztandera 2a78ebabd9 Use HashVerify
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-15 17:39:16 +02:00
Jakub Sztandera a23a87a17f Add virtual gas
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-15 16:18:05 +02:00
Łukasz Magiera 49b1acba43 Merge pull request #1992 from filecoin-project/fix/correct-recov-deadlines
wdpost: Submit recoveries for sectors within a deadline
2020-06-15 15:09:22 +02:00
Łukasz Magiera 464f6a6b08 Update specs-actors to v0.6 2020-06-15 14:49:18 +02:00
Łukasz Magiera 7e7fac05e0 Merge pull request #1989 from filecoin-project/feat/merge-master
Merge in master into the next
2020-06-15 14:45:00 +02:00
Łukasz Magiera 7296ce7287 Merge remote-tracking branch 'origin/next' into feat/merge-master 2020-06-15 14:40:29 +02:00
Łukasz Magiera 70c8f7b1ee Merge remote-tracking branch 'origin/master' into feat/merge-master 2020-06-15 14:38:38 +02:00
Łukasz Magiera 50b04d6b2b Merge pull request #2019 from chunqizhi/zcq
Add usage information for provingInfoCmd
2020-06-15 12:19:38 +02:00
chunqizhi 12056c8904 go fmt 2020-06-15 17:43:42 +08:00
Łukasz Magiera fdbda6f608 Merge pull request #2017 from jsign/jsign/nits
nit: unchecked errors
2020-06-15 11:31:57 +02:00
Howard Yeh c822816f8e Cache tipset validation progress 2020-06-14 18:41:17 +08:00
chunqizhi 6d36c030e0 Add usage information for provingInfoCmd 2020-06-13 18:05:30 +08:00
Ignacio Hagopian 82c6be14f4 unchecked errs
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-06-12 22:34:00 -03:00
Łukasz Magiera fb4ad043dd Merge pull request #2011 from filecoin-project/feat/more-callers
Expose more callers, ellipsis unimportant ones
2020-06-13 01:55:26 +02:00
Jakub Sztandera 91ea039077 Change ellipsis, more accurate timing
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-12 20:46:04 +02:00
Łukasz Magiera 8e025db656 Merge pull request #2014 from filecoin-project/fix/chain-reorgs-race
fix a potential race with chain reorgs notifees.
2020-06-12 20:35:16 +02:00
Raúl Kripalani 4e9293ba04 fix a potential race with chain reorgs notifees. 2020-06-12 19:18:23 +01:00
Łukasz Magiera 19afb57ac7 Merge pull request #1953 from jimpick/feat/libp2p-announce-addresses
Make libp2p swarm Announce / NoAnnounce addresses configurable
2020-06-12 19:28:13 +02:00
Jakub Sztandera a032bbe087 Merge pull request #2012 from filecoin-project/schomatis/feat/doc/README/branches
doc: active development branches
2020-06-12 19:27:51 +02:00
Lucas Molas a2943a6b7f doc: active development branches 2020-06-12 13:59:03 -03:00
Jakub Sztandera 8ad2b3c3d9 Removed commented out code
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-12 18:58:55 +02:00
Jakub Sztandera cd69e57a33 Expose more callers, ellipsis unimportant ones
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-12 18:49:29 +02:00
Rob Quist ca8a00f8a1 Update hardware-mining.md 2020-06-12 18:19:04 +02:00
Rob Quist 9077dea0cd Update install-lotus-ubuntu.md 2020-06-12 17:40:47 +02:00
Rob Quist d670257402 Add back installation of Go and Rust 2020-06-12 17:30:43 +02:00
Łukasz Magiera 3460fb0d47 Merge pull request #2005 from filecoin-project/feat/comp-state-template
compute-state html: Convert to templates
2020-06-12 16:47:05 +02:00
Jakub Sztandera 82eb7786d4 Cleanup lint warnings
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-12 16:25:55 +02:00
Jakub Sztandera 00385acc1d Remove htmlSafeAttr
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-12 15:26:58 +02:00
Jakub Sztandera 813940762c Use html/template
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-12 14:46:50 +02:00
Łukasz Magiera bd25d6db06 compute-state html: Convert to templates 2020-06-12 13:30:35 +02:00
Łukasz Magiera 9fbc7aafb4 Merge pull request #2001 from filecoin-project/asr/fetch-params-cli
Improve UX of fetch-params
2020-06-12 10:04:26 +02:00
Łukasz Magiera 227819dc1e docs: Update local-dev-net 2020-06-12 10:03:31 +02:00
Aayush Rajasekaran 2c401f9041 Improve UX of fetch-params 2020-06-12 01:17:10 -04:00
Jeromy c7e3a5cff4 fix null incrementing 2020-06-12 02:28:17 +02:00
Łukasz Magiera 5469df7dd1 Merge pull request #1991 from filecoin-project/feat/split-gas
Add gas tracing
2020-06-11 22:33:22 +02:00
Jakub Sztandera 071ddf6563 Add aggregate number, add number of bytes for storage calls
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-11 22:25:24 +02:00
laser 36b327b57b various symbol renames 2020-06-11 13:18:18 -07:00
laser 7587e6c08b get and set storage deal acceptance through CLI 2020-06-11 12:59:50 -07:00
Jakub Sztandera c90d35869b Add gas tracing
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-11 21:59:39 +02:00
laser 67110ce739 stub enable/disable storage deal commands 2020-06-11 12:20:11 -07:00
laser 5421d0d1c5 better field and struct names + set default appropriately
Storage miners, by default, should be configured to accept storage deals.
2020-06-11 12:15:28 -07:00
laser c458b4712a better rejection messages 2020-06-11 12:06:38 -07:00
Łukasz Magiera 0200e3def5 wdpost: Submit recoveries for sectors within a deadline 2020-06-11 20:38:29 +02:00
Jakub Sztandera 6acc9a62f8 Split gas internally into compute gas and storage gas
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-11 20:37:14 +02:00
laser d6b2519843 config-driven IsAcceptingStorageDeals flag
Makes incremental progress towards #1920.
2020-06-11 11:29:59 -07:00
Łukasz Magiera c8046f4597 Merge branch 'next' of github.com:filecoin-project/go-lotus into next 2020-06-11 18:24:51 +02:00
Łukasz Magiera 1c583ab487 Merge pull request #1966 from laser/feat/reload-config
expose config-setting through Repo interface
2020-06-11 18:15:06 +02:00
Łukasz Magiera 936f84dfa6 Merge pull request #1988 from waynewyang/VerifyConsensusFault
fix:the condition of time-offset mining fault
2020-06-11 18:11:48 +02:00
Jakub Sztandera 491f080a37 Merge remote-tracking branch 'origin/master' into feat/merge-master
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-11 17:59:27 +02:00
waynewyang 8354bd91db fix:the condition of time-offset mining fault 2020-06-11 23:52:44 +08:00
laser fb1d5197fa pass SetConfig a mutator func, as per PR feedback
- fsLockedRepo.config gets a mutex
- add missing checkToken call to lockedMemRepo#GetStorage and lockedMemRepo#SetStorage
- LockedRepo#SetConfig accepts a mutating function as per @magik
2020-06-11 08:49:19 -07:00
laser cf321f7667 add support for replacing config after node starts
- TODO: does a "locked repo" need fine-grained (i.e. field-level) locking?
2020-06-11 08:49:19 -07:00
laser 2d6b2e3811 fix a spelling error 2020-06-11 08:49:19 -07:00
laser d4dbfdbe91 rename Config to GetConfig 2020-06-11 08:49:19 -07:00
Łukasz Magiera c9a845d3aa Merge remote-tracking branch 'origin/master' into next 2020-06-11 16:29:26 +02:00
Łukasz Magiera 1e41ca125d Merge pull request #1975 from filecoin-project/feat/ex-trace
Refactor ExecutionResult to ExecutionTrace
2020-06-11 16:24:17 +02:00
Jakub Sztandera 500ddd6585 go mod tidy
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-11 16:07:04 +02:00
Łukasz Magiera 9457df9ddd Merge pull request #1985 from filecoin-project/fix/chain-idx-nulls
chainstore index: Drop wrong check
2020-06-11 16:01:05 +02:00
Jakub Sztandera c3f23ddce8 Refactor ExecutionResult to ExecutionTrace
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-11 15:53:47 +02:00
Łukasz Magiera 8b308972a4 chainstore index: Drop wrong check 2020-06-11 15:43:24 +02:00
Łukasz Magiera 4f632c893c Merge pull request #1983 from waynewyang/ConsensusFault
Add flag for cli slash-consensus
2020-06-11 14:27:33 +02:00
waynewyang 41066bd45e Add flag for cli slash-consensus 2020-06-11 19:20:11 +08:00
Jeromy ac1048fcd7 test a few more cases 2020-06-11 12:31:32 +02:00
Jeromy 14ea847ef6 fix chain index seeking through long ranges of null rounds 2020-06-11 12:31:32 +02:00
Anton Evangelatov 2ce3a5f887 docs: add a note about open files limit 2020-06-11 12:31:32 +02:00
waynewyang 27858506ff error check 2020-06-11 12:31:32 +02:00
Aayush Rajasekaran 6ba5c5d0e1 Doc fix: use correct file name 2020-06-11 12:31:32 +02:00
Lucas MolasandAayush Rajasekaran dc112a5a00 Lotus architecture notes (#1768)
Co-authored-by: Aayush Rajasekaran <arajasek94@gmail.com>
2020-06-11 12:31:32 +02:00
laser fe60ffb6ff display quantities of bytes in human-readable format
- client commP
- client local
- client find
- client query-ask
- client list-deals
- state sector-size
2020-06-11 12:31:32 +02:00
Jeromy 512270593b clean up some of the more spammy logs 2020-06-11 12:31:29 +02:00
Mike Greenberg 2cd6347a13 Express block validation, cpu/mem usage via OpenCensus 2020-06-11 12:31:04 +02:00
Łukasz Magiera b1f66b181c Merge pull request #1980 from yaohcn/fix/bench-prove
bench prove need miner-addr flag
2020-06-11 12:10:49 +02:00
Łukasz Magiera d5dae844bd Merge pull request #1978 from filecoin-project/fix/chain-index-seek-nulls
Fix/chain index seek nulls
2020-06-11 12:08:53 +02:00
yaohcn e0a8e993bc bench prove nedd miner-addr flag 2020-06-11 16:35:46 +08:00
Jeromy 1aff04faab test a few more cases 2020-06-10 22:17:29 -07:00
Jeromy 295c0861c4 fix chain index seeking through long ranges of null rounds 2020-06-10 22:15:46 -07:00
Whyrusleeping ba3f73acb8 Merge pull request #1974 from nonsense/docs-open-files-limit
docs: add a note about open files limit
2020-06-10 17:37:25 -07:00
Anton Evangelatov 68959582b9 docs: add a note about open files limit 2020-06-11 00:15:46 +02:00
Łukasz Magiera 1f9b563412 Merge pull request #1954 from filecoin-project/asr/peerid
Create an api.MinerInfo that has peerID as a Peer ID
2020-06-10 19:32:42 +02:00
Łukasz Magiera 99bc46b8b8 Merge pull request #1971 from waynewyang/err-check
error check
2020-06-10 14:38:38 +02:00
waynewyang e2d2af3afa error check 2020-06-10 20:34:04 +08:00
RobQuistNL af4c4d4f1f Prevent words from being marked as glossary links 2020-06-10 11:44:35 +02:00
RobQuistNL 6d06bfb452 Update documentation 2020-06-10 11:41:58 +02:00
RobQuistNL 159a1a4645 Update other docs + bump go.mod version 2020-06-10 10:29:57 +02:00
Rob Quist d4b230c137 Update Ubuntu installation documentation + bump required go version to 1.14 2020-06-10 10:24:38 +02:00
Łukasz Magiera 6f501119bf Merge pull request #1957 from filecoin-project/feat/v27
v27 parameters
2020-06-10 02:04:59 +02:00
Łukasz Magiera a00df0da90 FFI v27 2020-06-10 01:44:14 +02:00
Aayush Rajasekaran 6d90f12bb6 Doc fix: use correct file name 2020-06-09 20:22:51 -03:00
Lucas MolasandAayush Rajasekaran 469eef8231 Lotus architecture notes (#1768)
Co-authored-by: Aayush Rajasekaran <arajasek94@gmail.com>
2020-06-09 20:17:28 -03:00
Aayush Rajasekaran 1ccad22227 Move api.MinerInfo to api/types 2020-06-09 19:08:43 -04:00
Aayush Rajasekaran 5cf76ba8b3 Create an api.MinerInfo that has peerID as a Peer ID 2020-06-09 19:07:53 -04:00
Jakub Sztandera 81bc8471e3 Merge pull request #1963 from filecoin-project/chore/upd-log
Update go-log to master
2020-06-09 23:27:02 +02:00
Jakub Sztandera 5feea2e0f8 Update go-log to master
It restores line informations in log messages

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-09 23:06:40 +02:00
Łukasz Magiera 79b35c59a5 Merge pull request #1959 from laser/feat/human-readable-bytes-display
display quantities of bytes in human-readable format
2020-06-09 22:09:30 +02:00
Łukasz Magiera 35749f0330 Merge pull request #1962 from filecoin-project/fix/log-spammy
clean up some of the more spammy logs
2020-06-09 22:04:26 +02:00
laser 2889efb608 display quantities of bytes in human-readable format
- client commP
- client local
- client find
- client query-ask
- client list-deals
- state sector-size
2020-06-09 12:53:44 -07:00
Jeromy 686c543778 clean up some of the more spammy logs 2020-06-09 12:49:31 -07:00
Rob Quist 093dc907b3 Update documentation about Lotus Seal Worker
Running the initial command `lotus-seal-worker run` gave an error about `--address` being a required parameter.
After setting that to `127.0.0.1:2345` the miner started to freak out and sectors broke as the mining process locked up.

It seems like in the mean time the sealing work has already been moved into the `lotus-storage-miner` and thus doesn't need to run alongside the miner. 

Changed the docs to what I think is correct now - but please check, I could be horribly wrong :)
2020-06-09 20:57:21 +02:00
Jakub Sztandera 1144049c66 Merge pull request #1927 from filecoin-project/feat/opencensus_report_validation_time
Express block validation time via OpenCensus
2020-06-09 10:03:46 +02:00
Jim Pick 6e11ff3796 Make libp2p swarm Announce / NoAnnounce addresses configurable
In go-ipfs, it is possible to manually configure addresses to announce
or not announce to the swarm.

https://github.com/ipfs/go-ipfs/blob/master/docs/config.md#addressesannounce

This PR adds the same feature to Lotus. It can be configured from the [libp2p]
section of either the .lotus or .lotusstorage config.toml file. Example:

[Libp2p]
  ListenAddresses = ["/ip4/0.0.0.0/tcp/34515", "/ip6/::/tcp/34515"]
  AnnounceAddresses = ["/ip4/52.13.91.110/tcp/34515"]
2020-06-08 17:03:11 -07:00
Łukasz Magiera 19013b09e0 v27 parameters 2020-06-08 23:48:31 +02:00
Łukasz Magiera 7539d88f54 Merge pull request #1951 from filecoin-project/feat/sstor-post-better
Update sector-storage with better post faults
2020-06-08 23:48:13 +02:00
Łukasz Magiera 28f895cec2 Update sector-storage with better post faults 2020-06-08 23:20:19 +02:00
laser 751bc45bef display a little inline warning if balance is zero 2020-06-08 12:20:44 -07:00
Mike Greenberg ae83ca6893 Express block validation, cpu/mem usage via OpenCensus 2020-06-08 14:15:01 -04:00
Łukasz Magiera 5f4efedbdd Merge pull request #1949 from filecoin-project/feat/no-mbase-update-err
don't update the mining base if mining fails for some reason
2020-06-08 18:56:48 +02:00
Jeromy 9d49c6861f don't update the mining base if mining fails for some reason 2020-06-08 09:51:47 -07:00
Łukasz Magiera 3b56288a5e Merge remote-tracking branch 'origin/master' into next 2020-06-08 18:29:36 +02:00
Jakub Sztandera f257f4febb Merge pull request #1911 from filecoin-project/feat/drand-score
Score drand topic
2020-06-08 15:12:25 +02:00
Łukasz Magiera df867f3349 Merge pull request #1946 from filecoin-project/asr/walletdelete
Add delete functionality to the wallet
2020-06-08 13:27:42 +02:00
Łukasz Magiera 5270c20263 Merge pull request #1947 from filecoin-project/asr/mineravailablebalance
Correct double-counting in StateMinerAvailableBalance
2020-06-08 13:24:54 +02:00
Jakub Sztandera 7762cd0a68 Assign positive scores to drand bootstrappers
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-08 11:34:46 +02:00
Jakub Sztandera e91cc9cd08 Add drand topic scores
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-08 11:34:46 +02:00
Aayush Rajasekaran 741825a04e Correct double-counting in StateMinerAvailableBalance 2020-06-07 20:49:50 -04:00
Aayush Rajasekaran 49b27da426 Add delete functionality to the wallet 2020-06-07 19:36:01 -04:00
Łukasz Magiera bf4bbd15e5 Merge pull request #1945 from filecoin-project/feat/specs-actors-v0.5.6
Update specs-actors to v0.5.6
2020-06-06 20:53:58 +02:00
Łukasz Magiera baa69c3c81 Update specs-actors to v0.5.6 2020-06-06 19:51:10 +02:00
Whyrusleeping ac644605f2 Merge pull request #1942 from filecoin-project/fix/proto-panic
Fix protobuf panic by updating protobuf to 1.4.2
2020-06-05 18:04:20 -07:00
Jakub Sztandera 94da339622 Fix protobuf panic by updating protobuf to 1.4.2
The panic is caused by usage of internal protobuf interface.
It was changed in protobuf 1.4.0 and reluctantly fixed in 1.4.2

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-06 02:47:29 +02:00
Whyrusleeping 366359803a Merge pull request #1903 from filecoin-project/feat/reuse-get-tipset-by-height
reuse GetTipsetByHeight in GetRandomness
2020-06-05 16:06:28 -07:00
Łukasz Magiera 3b13397165 gofmt 2020-06-06 00:59:01 +02:00
Łukasz Magiera 163c2b2544 Merge remote-tracking branch 'origin/master' into next 2020-06-06 00:58:24 +02:00
Łukasz Magiera 9e2603c1bf Merge pull request #1937 from laser/bugs/916-standardize-cid-base32
print "client"-command CIDs as base32-encoded strs
2020-06-06 00:53:07 +02:00
Łukasz Magiera d27750590a Merge pull request #1928 from filecoin-project/fix/lsm-prov-deadlines
Make lotus-storage-miner deadlines correct
2020-06-06 00:37:09 +02:00
Łukasz Magiera 33a00ab9e5 Merge pull request #1938 from filecoin-project/deps/spect-actors-upd
Update specs-actors
2020-06-06 00:31:09 +02:00
Łukasz Magiera f765fe36d7 Make lotus-storage-miner deadlines correct 2020-06-06 00:28:32 +02:00
Whyrusleeping be7a95c9a5 Merge pull request #1915 from filecoin-project/feat/chain-index
implement chain index to make lookbacks faster
2020-06-05 15:13:47 -07:00
Aayush Rajasekaran 2571480bb6 Update chain-val, use tagged specs-actors 2020-06-05 18:13:30 -04:00
Jeromy 73d928751d disallow sourcing randomness from future epochs 2020-06-05 15:12:13 -07:00
Whyrusleeping 0c19544d94 Merge pull request #1941 from filecoin-project/deps/update-hamt
update to new hamt code with improved perf
2020-06-05 14:54:21 -07:00
laser a80dce2e3b move to client command 2020-06-05 14:22:29 -07:00
Jeromy fb09d1ad2b update to new hamt code with improved perf 2020-06-05 14:13:08 -07:00
laser 963e4dd2fc set a Base32 default explicitly 2020-06-05 13:52:36 -07:00
Łukasz Magiera a5d81c6cc9 Merge pull request #1932 from filecoin-project/feat/chainget-state
chain get: @state selector to prettify actor state
2020-06-05 22:42:36 +02:00
laser b167e73acb allow CLI consumer to specify CID encoding for output 2020-06-05 13:33:45 -07:00
Łukasz Magiera e7af464033 Merge pull request #1931 from filecoin-project/feat/compute-state-sub-links
compute-state html: Allow linking to internal executions
2020-06-05 22:29:23 +02:00
laser 28e454fd4a go mod tidy 2020-06-05 13:13:53 -07:00
laser 55a9c9ae0a client deal command outputs Base32-encoded CID 2020-06-05 13:13:33 -07:00
laser b3eef76cdd client commP outputs Base32-encoded string 2020-06-05 13:13:16 -07:00
Łukasz Magiera 3f81ff3507 Update specs-actors 2020-06-05 22:06:11 +02:00
laser 2347ba6f39 print "client"-command CIDs as base32-encoded strs
Fixes #916
2020-06-05 13:04:28 -07:00
Łukasz Magiera b9d3c26eae Merge pull request #1924 from filecoin-project/fix/sealing-betterering
Sealing Improvements
2020-06-05 21:58:31 +02:00
Łukasz Magiera cd6670205c Update sector-storage 2020-06-05 21:31:57 +02:00
Whyrusleeping 9f4ac4f4f3 Merge pull request #1934 from filecoin-project/bugs/return-on-error-#1611
fix unhandled nil return
2020-06-05 12:26:27 -07:00
shannonwells e4bed4d963 return on all err conditions 2020-06-05 11:20:07 -07:00
shannonwells 76b5c8b145 fix unhandled nil return 2020-06-05 11:20:07 -07:00
Łukasz Magiera 9836c45e03 Merge pull request #1935 from filecoin-project/feat/cap-batch-verify-threads
add a simple semaphore to batch verify seals
2020-06-05 20:19:45 +02:00
Jeromy 51f1712564 add a simple semaphore to batch verify seals 2020-06-05 10:47:49 -07:00
Łukasz Magiera e9eff8be5c Merge pull request #1933 from laser/bugs/1209-paramfetch-sigterm
pass context to paramfetch.GetParams
2020-06-05 19:46:23 +02:00
laser 4855045ea2 pass context to paramfetch.GetParams
Fixes #1209
2020-06-05 10:28:00 -07:00
Łukasz Magiera 6b06ae528c chain get: @state selector to prettify actor state 2020-06-05 17:41:21 +02:00
Łukasz Magiera 813961b458 compute-state html: Allow linking to internal executions 2020-06-05 14:57:37 +02:00
Łukasz Magiera 7ae9d26cd1 Merge remote-tracking branch 'origin/next' into fix/sealing-betterering 2020-06-05 14:00:47 +02:00
Łukasz Magiera 9e5cc7c910 Update fsm, sector-storage 2020-06-05 10:46:45 +02:00
Łukasz Magiera 7d166fd730 Merge pull request #1908 from filecoin-project/docs/cpu-choice
add a doc on amd vs intel cpus
2020-06-05 01:21:50 +02:00
Łukasz Magiera 60101fd97b Merge pull request #1926 from filecoin-project/chore/merge-master
Merge in master into next
2020-06-05 01:13:12 +02:00
Jakub Sztandera 0bc174697a Fix WindowPoStScheduler
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-05 00:52:45 +02:00
Jakub Sztandera 7bee5b3abc Merge remote-tracking branch 'origin/master' into next
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-05 00:33:43 +02:00
Aayush Rajasekaran 656b285195 Bugfix: Begin walkback when lookback target's height is too low 2020-06-04 18:17:54 -04:00
whyrusleeping 86083531c6 a couple bugfixes 2020-06-04 18:17:54 -04:00
Jeromy c01f70105f implement chain index to make lookbacks faster 2020-06-04 18:17:54 -04:00
Łukasz Magiera 5aafa91e22 Merge pull request #1898 from filecoin-project/deps/update
Update CLI lib
2020-06-04 23:45:39 +02:00
Łukasz Magiera bada564c10 Merge pull request #1912 from filecoin-project/asr/statesearch
search for a message should stop if we reach sender nonce of 0
2020-06-04 23:42:16 +02:00
Łukasz Magiera f9f0d86ddf Merge pull request #1913 from acruikshank/feat/1853-confirmations-in-StateWaitMsg2
Add confidence and timeout to message wait
2020-06-04 23:23:15 +02:00
vyzo 6beabb5e8a Merge pull request #1914 from filecoin-project/feat/update-pubsub
update libp2p dependencies
2020-06-04 22:50:48 +03:00
vyzo 3719938849 gomod: update go-maddr-filter 2020-06-04 22:35:33 +03:00
vyzo 6420990007 gomod: update go-libp2p-quic-transport 2020-06-04 22:34:07 +03:00
vyzo 1fab24b9bc gomod: update go-libp2p-kad-dht 2020-06-04 22:32:11 +03:00
Łukasz Magiera 8bbe63bd9d Add expected win rate to miner-info 2020-06-04 21:26:29 +02:00
Łukasz Magiera fa3b1552cf Update sector-storage intefraces 2020-06-04 21:26:29 +02:00
Łukasz Magiera c625b30781 Update fsm adapter 2020-06-04 21:26:29 +02:00
vyzo b339750757 gomod: update go-libp2p-yamux 2020-06-04 21:34:01 +03:00
acruikshank da960a9de4 more import rearrangement 2020-06-04 09:54:37 -04:00
Mike Greenberg ce30162907 Fix documentation link for new systemd page 2020-06-04 08:10:08 -04:00
Mike Greenberg c0cdcbb9e0 Adjust service logging and startup settings 2020-06-04 08:09:01 -04:00
vyzo 954a20ff4c gomod: update go-libp2p to v0.9.4 2020-06-04 14:25:17 +03:00
vyzo 8057b994cf go.mod: remove unecessary (and harmful) replace directive for go-systemd 2020-06-04 14:23:59 +03:00
acruikshank ea111b058e imports 2020-06-03 22:34:57 -04:00
acruikshank ce33074626 go fmt 2020-06-03 22:30:09 -04:00
acruikshank 5f95a92135 fix race (sort of) by increasing confidence 2020-06-03 22:18:38 -04:00
Jeromy cd817906b2 handle sourcing randomness from a future block 2020-06-03 18:30:43 -07:00
Jakub Sztandera 29dbc26dbd Update cli
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-04 01:01:41 +02:00
acruikshank 04f0130530 remove timeout 2020-06-03 17:42:06 -04:00
vyzo f210a6e91a pubsub: set Dout parameter to 3 (from the default of 2)
we are using a higher D value than the default, so this can be safely increased.
2020-06-04 00:03:31 +03:00
vyzo aded0706be gomod: update go-libp2p@v0.9.3 and go-libp2p-pubsub@v0.3.2 2020-06-04 00:02:54 +03:00
acruikshank 57567db017 tidy 2020-06-03 15:51:11 -04:00
acruikshank 5574e4f11b add confidence and timeout to message wait 2020-06-03 15:38:37 -04:00
Aayush Rajasekaran 4b01b666f6 Bugfix: searchback for a message should stop if we reach sender nonce of 0 2020-06-03 14:08:05 -04:00
Łukasz Magiera 35740895ed Merge pull request #1899 from filecoin-project/feat/1827-lotus-daemon-stop-cmd
add (sub)commands which shut down lotus daemon and storage miner
2020-06-03 19:15:20 +02:00
Jakub Sztandera 4c5d84d106 Merge pull request #1904 from filecoin-project/feat/peer-scores
Add `lotus net scores` for pubsub score visibility
2020-06-03 18:04:16 +02:00
Jeromy a8915f0331 add a doc on amd vs intel cpus 2020-06-03 08:45:53 -07:00
Jakub Sztandera 7f962e19c2 Fix lint
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-03 03:19:18 +02:00
Jakub Sztandera 186fd4da74 Add lotus net scores for pubsub score visibility
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-03 03:13:49 +02:00
Jeromy 2fdcf5347b reuse GetTipsetByHeight in GetRandomness 2020-06-02 17:35:23 -07:00
Jakub Sztandera 4a983995a8 Merge pull request #1901 from acruikshank/bugs/1893-chain-import-home-directory
Expand tilde before passing file name into chain import
2020-06-02 23:53:04 +02:00
Jakub Sztandera 263bdc9687 Merge pull request #1902 from filecoin-project/chore/merge-master
Merge in master into next
2020-06-02 23:23:41 +02:00
Jakub Sztandera 42c76aaebc Remove mod-download
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-02 23:11:17 +02:00
Jakub Sztandera 9326cb5411 Update golangci-lint, increase its timeout
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-02 23:07:48 +02:00
Jakub Sztandera 415b69155b Disable caches
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-02 23:02:37 +02:00
Jakub Sztandera 3423d29815 Prune go mod cache
Circle reports 1.9GB, should be closer to 300MB

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-02 22:54:29 +02:00
Jakub Sztandera 673a972fe9 Merge remote-tracking branch 'origin/master' into next
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-02 22:49:27 +02:00
acruikshank 1fd20b636b tidy 2020-06-02 16:48:50 -04:00
acruikshank d7a2556292 expand tilda before passing file name into chain import 2020-06-02 16:43:39 -04:00
Łukasz Magiera 8aa158d4e6 Merge pull request #1900 from filecoin-project/feat/subcall-timing-compute-state
add subcall timing to compute state output
2020-06-02 22:23:25 +02:00
Łukasz Magiera 3595b1f8e9 compute-state html: Add timing for internal executions 2020-06-02 22:06:03 +02:00
Jeromy 9b867a221a add subcall timing to compute state output 2020-06-02 12:53:24 -07:00
laser 46a016cdce name change, for consistency 2020-06-02 12:38:21 -07:00
laser bea9cd2fe2 rename to better convey intent + document 2020-06-02 12:35:11 -07:00
laser ee9d9a52a9 first take at a "lotus-storage-miner stop" command
Fixes #1827
2020-06-02 12:31:21 -07:00
laser 1e8a875edb shutdownChan instead of shutdownCh, for consistency 2020-06-02 12:31:01 -07:00
laser 36a93c90eb use a real ellipsis, kinda 2020-06-02 12:30:45 -07:00
laser 38d714a28a first take at "daemon stop" command
Fixes #1827

TODO: plumb the daemon-stopping into lotus-storage-miner, too
2020-06-02 12:29:58 -07:00
Whyrusleeping bbb954afc5 Merge pull request #1896 from filecoin-project/chore/lint-2
Fix even more lint warnings
2020-06-02 11:40:57 -07:00
Whyrusleeping de5d16eeac Merge pull request #1897 from filecoin-project/deps/update-json-rpc
update to fixed jsonrpc library
2020-06-02 11:36:31 -07:00
Jeromy 1968195da9 update to fixed jsonrpc library 2020-06-02 11:21:54 -07:00
Jakub Sztandera 22851df145 Undo change in events_test
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-02 18:46:43 +02:00
Jakub Sztandera 96ade5f2dd Cleanup more lint warnings
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-02 18:38:41 +02:00
laser 5e727819ad stub the "daemon stop" command 2020-06-02 08:09:18 -07:00
Jakub Sztandera 5605aae269 Fix even more lint warnings
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-06-02 16:29:39 +02:00
Łukasz Magiera c6b6c2990c Merge pull request #1888 from filecoin-project/feat/build-typ-version
Include build type in version
2020-06-01 21:18:30 +02:00
Łukasz Magiera a49dc90386 Fix version test 2020-06-01 21:11:37 +02:00
Łukasz Magiera 64f4e80446 Include build type in version 2020-06-01 20:49:39 +02:00
Łukasz Magiera e67253b6a8 Merge pull request #1887 from filecoin-project/feat/improve-datastore
fsrepo: Use LevelDB for metadata datastore
2020-06-01 20:21:15 +02:00
Łukasz Magiera c73326e96d fsrepo: Use LevelDB for metadata datastore 2020-06-01 20:13:07 +02:00
Łukasz Magiera 7003960fdd Merge remote-tracking branch 'origin/master' into next 2020-06-01 18:52:06 +02:00
Łukasz Magiera 0acc2a2a63 Merge pull request #1880 from filecoin-project/asr/minerfaults
Add an API method to list all faults occuring in a certain range
2020-06-01 18:47:09 +02:00
Łukasz Magiera 596f78f9e6 Merge pull request #1885 from filecoin-project/bugs/sector-size-usage-in-scripts
update scripts and docs to use human-readable sector size
2020-06-01 18:45:20 +02:00
Łukasz Magiera 17f1eec81f Merge pull request #1886 from filecoin-project/feat/1829-repo-already-locked
error message to tell user why repo is already locked
2020-06-01 18:43:05 +02:00
Łukasz Magiera f0d44ea396 Merge pull request #1884 from filecoin-project/feat/fountain-maddr-link
fountain/miner: Add a link to docs about creating owner address
2020-06-01 18:41:57 +02:00
Łukasz Magiera ad4712b593 Merge pull request #1873 from filecoin-project/feat/better-post-faults
wdpost: Better fault handling
2020-06-01 18:39:00 +02:00
laser 92b8d9ad17 tell user why repo is already locked
Fixes #1829
2020-06-01 09:37:10 -07:00
laser 12ff9fd76b update scripts and docs to use human-readable sector size
Commit #fa863595 modified various CLI commands to accept a 
human-readable sector size. We should update docs and scripts, too.
2020-06-01 09:20:44 -07:00
Łukasz Magiera e26cf4e003 fountain/miner: Add a link to docs about creating owner address 2020-06-01 17:49:15 +02:00
Łukasz Magiera b753cd4503 Run window post test on circle 2020-06-01 15:06:10 +02:00
Łukasz Magiera ee29a92021 Add a test for Window Post 2020-06-01 14:49:48 +02:00
Łukasz Magiera c3916e3a7f Merge pull request #1875 from filecoin-project/feat/check-verifreg-cmds
add commands to check individual balances for verifiers and clients
2020-06-01 13:00:08 +02:00
Aayush Rajasekaran ec0baefc48 Add an API method to list all faults occuring in a certain range 2020-05-31 00:57:52 -04:00
Jeromy bac1e3f901 put blocks in cache after get 2020-05-29 15:15:59 -07:00
Jeromy 94555ea8c1 delete block should delete from cache too 2020-05-29 15:13:18 -07:00
Jeromy cc233c6956 add an lru caching blockstore 2020-05-29 15:13:18 -07:00
Jeromy 2a3d79f055 add commands to check individual balances for verifiers and clients 2020-05-29 14:47:17 -07:00
Whyrusleeping 1c01799a4b Merge pull request #1855 from filecoin-project/feat/systemd-usage
Add systemd documention to table of contents
2020-05-29 14:07:09 -07:00
WhyrusleepingandJakub Sztandera 4ef330ba8b Update scripts/lotus-daemon.service
Co-authored-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-29 14:02:07 -07:00
Łukasz Magiera cd2bf04a6b wdpost: Better fault handling 2020-05-29 21:36:11 +02:00
Łukasz Magiera f7a71f4be7 Merge pull request #1837 from filecoin-project/feat/secstor-unseal
Update sector-storage with ReadPiece impl
2020-05-29 20:36:40 +02:00
Łukasz Magiera e5c24ff32b Update sector-storage with ReadPiece impl 2020-05-29 19:53:35 +02:00
Whyrusleeping f87054bde4 Merge pull request #1858 from hayeah/fix-miner-stale-tipset
Fix block production timing to avoid mining old tipset
2020-05-29 10:41:25 -07:00
Łukasz Magiera e954cc0d67 Merge pull request #1872 from filecoin-project/asr/docs
Fix broken link
2020-05-29 18:44:00 +02:00
Aayush Rajasekaran 43c887f2b6 Fix broken link 2020-05-29 12:35:21 -04:00
Aayush Rajasekaran 1cf9b9a67f Merge pull request #1861 from filecoin-project/asr/printmoney
Correctly handle transfers with sender = receiver
2020-05-29 12:27:56 -04:00
Aayush Rajasekaran 7dd25c3ac5 Correctly handle transfers with sender = receiver 2020-05-29 12:15:41 -04:00
Jakub Sztandera 241c3fa673 Merge pull request #1869 from filecoin-project/feat/drand-pubsub
Add pubsub support to drand beacon
2020-05-29 18:06:38 +02:00
Łukasz Magiera 785eeb1eee Merge pull request #1850 from filecoin-project/chore/lint
Cleanup many lint warnings
2020-05-29 18:06:06 +02:00
Jakub Sztandera 30d82ba962 Explicity Watch for randomness
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-29 17:55:24 +02:00
Jakub Sztandera 002d021eb7 Enable HashMsgId
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-29 17:55:24 +02:00
Jakub Sztandera 71eb41b9aa Add pubsub support to drand beacon
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-29 17:55:17 +02:00
Łukasz Magiera f06369166e Merge pull request #1868 from filecoin-project/feat/pond-regen-methods
pond: rerun method-gen
2020-05-29 15:14:20 +02:00
Łukasz Magiera 5129fed7c8 pond: rerun method-gen 2020-05-29 14:36:56 +02:00
Łukasz Magiera f06794ae84 Merge pull request #1856 from filecoin-project/deps/specs-actors-batch-porep
update specs actors to version with batch porep verification
2020-05-29 14:13:04 +02:00
Howard Yeh 1cabecedee Fix block production timing to avoid mining old tipset 2020-05-29 18:13:58 +08:00
Whyrusleeping f17c32c593 Merge pull request #1749 from filecoin-project/feat/shed-verifreg
add some commands for interacting with verified registry actor to lot…
2020-05-28 17:41:28 -07:00
Whyrusleeping b59f88324c Merge pull request #1865 from filecoin-project/fix/missing-err-check-stored-ask
Add missing err check in storage ask initialization
2020-05-28 17:17:50 -07:00
hannahhoward 0c4db8cf6b fix(storageminer): add missing err check
Missing an err check in storage miner initialization in the stored ask
2020-05-28 17:05:17 -07:00
Jeromy 9c020e54b5 Add more verifreg commands to list verifiers and clients 2020-05-28 17:01:01 -07:00
Jeromy 9811375d18 add some commands for interacting with verified registry actor to lotus-shed 2020-05-28 17:01:00 -07:00
Whyrusleeping 2632621f7e Merge pull request #1862 from filecoin-project/mod-tidy/master
Mod-tidy on master
2020-05-28 14:52:00 -07:00
Jakub Sztandera d742efe165 Mod-tidy on master
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-28 23:50:29 +02:00
Jakub Sztandera 492ffac913 Merge pull request #1853 from shepf/master
update struct.go github url
2020-05-28 23:50:05 +02:00
Mike Greenberg 21415a9847 add chainwatch systemd svc config; make install-chainwatch-service 2020-05-28 16:53:00 -04:00
Mike Greenberg 4acf0c7ec0 install service files in suitable path; tweak lotus svc restarting 2020-05-28 16:26:07 -04:00
Aayush Rajasekaran fa69adf45c update chain-validation 2020-05-28 13:21:12 -07:00
Aayush Rajasekaran fa04da2995 Update specs-actors and storage-fsm 2020-05-28 13:19:36 -07:00
Jeromy e2a554c2e6 update specs actors to version with batch porep verification 2020-05-28 13:19:18 -07:00
Jeromy 91da81c8bc mod tidy 2020-05-28 13:17:55 -07:00
Jeromy 7bd18290db Merge branch 'master' into next 2020-05-28 13:16:47 -07:00
Jeromy 8e55c91cd2 check neq zero exit code 2020-05-28 22:11:49 +02:00
Mike Greenberg 514339e855 update systemd services; include make directives and docs for use 2020-05-28 22:11:49 +02:00
frrist 9f8ecb0ac4 update chain-validation
- has new syscalls
2020-05-28 22:11:49 +02:00
frrist be1bbe88b0 update chain-val syscalls interface 2020-05-28 22:11:49 +02:00
Łukasz Magiera f1ccbe496a cli: Trim spaces from token file 2020-05-28 22:11:49 +02:00
vyzo 495554e565 gomod: update go-libp2p-pubsub@v0.3.1 2020-05-28 22:11:49 +02:00
Ignacio Hagopian 17c378c18a fix
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-05-28 22:11:49 +02:00
Ignacio Hagopian 6e63ea6cce revert file
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-05-28 22:11:49 +02:00
Ignacio Hagopian 10753f14d0 retrieve: make fileref optional
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-05-28 22:11:49 +02:00
Ignacio Hagopian 0af7cd1448 allow using ipfs for retrieval
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-05-28 22:11:49 +02:00
Ignacio Hagopian de3edc2ec7 remote ipfs support & automatic env
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-05-28 22:11:49 +02:00
Whyrusleeping d0eb4278ae Merge pull request #1860 from filecoin-project/fix/recovery-exit-code-check
check neq zero exit code
2020-05-28 12:59:29 -07:00
Jeromy b807bdbea0 check neq zero exit code 2020-05-28 08:45:34 -07:00
Mike Greenberg 386b818d16 add systemd documention to table of contents 2020-05-27 19:28:31 -04:00
Jakub Sztandera 8639409f74 go mod tidy
,
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-28 01:16:01 +02:00
Jakub Sztandera b372881e91 Fix more lint warnings
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-28 01:15:19 +02:00
Whyrusleeping fc351d08b0 Merge pull request #1849 from filecoin-project/feat/remove-drand-on-miner
Remove drand on miner side, MinerGetBaseInfo provides the same info
2020-05-27 16:06:08 -07:00
shepf eb325e6814 update struct.go github url 2020-05-28 07:05:53 +08:00
Jakub Sztandera 7232e5481c Use origin/next for linting
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-28 00:49:52 +02:00
Jakub Sztandera f26a336afb Use git.base_revision
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-28 00:45:17 +02:00
Whyrusleeping 70e690dac0 Merge pull request #1852 from filecoin-project/feat/systemd-usage
Update systemd usage and docs
2020-05-27 15:23:45 -07:00
Mike Greenberg 78e0c96f22 update systemd services; include make directives and docs for use 2020-05-27 17:17:18 -04:00
Jakub Sztandera d6615b6286 Cleanup many lint warnings
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-27 22:53:20 +02:00
Jakub Sztandera 4604b60fb1 Remove drand on miner side, MinerGetBaseInfo provides the same info
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-27 20:24:26 +02:00
Whyrusleeping 75041b96e4 Merge pull request #1815 from filecoin-project/frrist/new-chainval-syscalls
update chain-val syscalls interface
2020-05-27 11:00:16 -07:00
Whyrusleeping 8544bda14a Merge pull request #1846 from filecoin-project/feat/trim-token-file
cli: Trim spaces from token file
2020-05-27 10:58:09 -07:00
Whyrusleeping 745fba7d1f Merge pull request #1841 from filecoin-project/gomod/update-pubsub
Update go-libp2p-pubsub to v0.3.1
2020-05-27 10:50:19 -07:00
Łukasz Magiera 6986204657 Merge pull request #1848 from filecoin-project/feat/new-drand-client
Update go-log, reduce drand entry log level, add TAG env for dev scripts
2020-05-27 16:22:13 +02:00
Jakub Sztandera 3f9cde28fc Update go-log, reduce drand entry log level, add TAG env for dev scripts
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-27 16:19:21 +02:00
Jakub Sztandera aa682a377d Partially fix pond spawn
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-27 16:19:21 +02:00
Łukasz Magiera af1d54501f Merge pull request #1843 from jsign/jsign/2stackedprs
Allow remote IPFS node support & IPFS for data retrieval & automatic env wiring
2020-05-27 14:59:18 +02:00
Ignacio Hagopian 009cd92010 fix
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-05-27 09:50:32 -03:00
Łukasz Magiera 6386107b80 Merge pull request #1819 from filecoin-project/feat/new-drand-client
Switch to new drand client
2020-05-27 14:35:01 +02:00
Jakub Sztandera 218b2b82c1 Update drand chain info
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-27 14:09:04 +02:00
Jakub Sztandera b06b0147a9 Switch to new drand client
This is a preview of a change to new drand client.

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-27 13:52:33 +02:00
Łukasz Magiera b74e8f5922 Merge pull request #1847 from waynewyang/Deadline-Index
fix: add deadline index for wdpost
2020-05-27 11:40:31 +02:00
waynewyang 94a7ef1c10 add deadline index for wdpost 2020-05-27 17:01:48 +08:00
Łukasz Magiera 02afd7d71f cli: Trim spaces from token file 2020-05-27 10:13:06 +02:00
Ignacio Hagopian a10690359c revert file
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-05-26 15:35:20 -03:00
Łukasz Magiera fa4ff89dca Set devnet params 2020-05-26 19:58:09 +02:00
Ignacio Hagopian bcd84cbe9d retrieve: make fileref optional
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-05-26 14:52:52 -03:00
Ignacio Hagopian 61daaa774b allow using ipfs for retrieval
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-05-26 14:52:52 -03:00
Ignacio Hagopian d5346f8326 remote ipfs support & automatic env
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
2020-05-26 14:52:51 -03:00
frrist 8ce6921b18 update chain-validation
- has new syscalls
2020-05-26 10:51:19 -07:00
frrist c8f28103f3 update chain-val syscalls interface 2020-05-26 10:49:39 -07:00
vyzo 3cd3785385 gomod: update go-libp2p-pubsub@v0.3.1 2020-05-26 20:47:00 +03:00
Łukasz Magiera 9089aadbbf Merge pull request #1821 from filecoin-project/deps/update-ffi
update to latest ffi
2020-05-26 19:34:02 +02:00
Łukasz Magiera 02ca1937f8 mod tidy 2020-05-26 19:07:21 +02:00
Łukasz Magiera 6897110fe5 Merge pull request #1838 from waynewyang/wdpost-input-correct
Fix:the input sectors of wpost  must match with the minerActor
2020-05-26 15:00:58 +02:00
waynewyang b799af3e9a Fix:the input sectors of wpost must match with the minerActor 2020-05-26 17:58:20 +08:00
Łukasz Magiera 9641d93615 Merge pull request #1836 from waynewyang/Wdpost-Gaslimit
Set largest gaslimit for wdpost
2020-05-26 08:53:59 +02:00
waynewyang da6768c94d Set largest gaslimit for wdpost 2020-05-26 11:43:17 +08:00
Lucas Molas 54a8b88d6c Merge pull request #1832 from filecoin-project/fix/disable-relay
Unconditionally disable relay
2020-05-25 10:38:48 -03:00
vyzo ba6217cc2c go mod tidy 2020-05-25 13:46:53 +03:00
vyzo 314da26da3 unconditionally disable relay 2020-05-25 13:39:50 +03:00
Jeromy 646800b8a8 update to latest ffi 2020-05-22 09:26:14 -07:00
Lucas Molas 92d58ab191 Merge pull request #1820 from filecoin-project/fix/sink-message-topic-deliveries
sink message topic deliveries
2020-05-22 11:33:43 -03:00
vyzo 5531f27798 sink the FirstMessageDeliveries boost for the messages topic 2020-05-22 17:25:56 +03:00
vyzo cc98117df2 log block validation time 2020-05-22 17:21:37 +03:00
Whyrusleeping ffd340086e Merge pull request #1817 from filecoin-project/feat/sort-miners-by-deal-count
Add command to sort miners by deal counts
2020-05-21 16:06:44 -07:00
Jeromy 805686be2e Add command to sort miners by deal counts 2020-05-21 15:52:20 -07:00
Whyrusleeping 0d3f602d58 Merge pull request #1804 from filecoin-project/feat/seal-verify-shed
put a command for verifying seals into the shed
2020-05-21 10:07:19 -07:00
Whyrusleeping 83436842c5 Merge pull request #1802 from filecoin-project/feat/gfm-v0.2.7
Use latest go-fil-markets
2020-05-21 10:05:54 -07:00
Whyrusleeping bafb922ff7 Merge pull request #1811 from filecoin-project/feat/update-pubsub
Update pubsub and libp2p
2020-05-21 09:51:00 -07:00
Jeromy 6e024d9994 parse ticket and seal randomness flags 2020-05-21 08:26:32 -07:00
vyzo d597c3fb0d increase OpportunisticGraftThreshold to 5 2020-05-21 14:38:11 +03:00
vyzo 24cebb8b2f gomod: update go-libp2p@v0.9.2 2020-05-21 12:13:14 +03:00
vyzo 0cc8446a79 configure Dout=0 for bootstrappers, turn off Mesh Failure Penalty for messages as well 2020-05-21 12:11:22 +03:00
vyzo 3e383d909a gomod: update go-libp2p-pubsub@v0.3.0 2020-05-21 12:08:13 +03:00
hannahhoward 3264a9faad feat(deps): update to latest go-fil-markets
update to go-fil-markets v0.2.7 with latest changes, modify constructors as needed to accomodate new
DS Prefix customization
2020-05-20 16:01:03 -07:00
hannahhoward c52b75d59e fix(deps): update to new 0.2.7 2020-05-20 16:00:03 -07:00
shannonwells 652c257763 passing w/ new namespace wraps 2020-05-20 15:58:59 -07:00
shannonwells 060f23d748 mod tidy 2020-05-20 15:56:58 -07:00
shannonwells e68ab286f6 upgrade lotus to go-fil-markets v0.2.5 2020-05-20 15:56:58 -07:00
Jeromy 92e5cc5ad7 add args usage 2020-05-20 15:28:19 -07:00
Łukasz Magiera 6831ca9e03 Merge pull request #1808 from filecoin-project/feat/extract-jsonrpc-auth
Extract auth utils to go-jsonrpc
2020-05-20 22:22:53 +02:00
Łukasz Magiera f7325a69c1 Extract auth utils to go-jsonrpc 2020-05-20 20:37:45 +02:00
Łukasz Magiera bb78292faf Merge pull request #1807 from filecoin-project/feat/extract-jsonrpc
Extract lib/jsonrpc to go-jsonrpc
2020-05-20 19:58:50 +02:00
Łukasz Magiera eeca031525 extract lib/jsonrpc to go-jsonrpc 2020-05-20 19:49:09 +02:00
Jeromy f82e0e61e1 put a command for verifying seals into the shed 2020-05-20 10:10:35 -07:00
Łukasz Magiera 75e47db520 Merge pull request #1771 from filecoin-project/feat/post-recover
post: Handle Recovering sectors
2020-05-20 19:08:09 +02:00
Łukasz Magiera 3da1a0d8cc post: Declare recoveries for the next deadline 2020-05-20 19:07:31 +02:00
Travis Person a293bd798f init map 2020-05-20 18:41:22 +02:00
Łukasz Magiera ae60001dcc post: Handle Recovering sectors 2020-05-20 18:41:20 +02:00
Łukasz Magiera cea7c41023 Merge pull request #1761 from dtynn/fix/dtynn/use_abs_path_for_client_filestore
use abs path to construct FileManager
2020-05-20 12:49:53 +02:00
Łukasz Magiera 0fe7a0b2e3 Merge pull request #1764 from filecoin-project/feat/has-cache-bs
add blockstore 'Has' caching
2020-05-20 12:48:50 +02:00
Łukasz Magiera 267368d56c Merge pull request #1767 from filecoin-project/feat/html-trace-improvements
add tipset key and height to html trace output
2020-05-20 12:48:05 +02:00
Łukasz Magiera f5451ad455 Merge pull request #1795 from shannon-6block/master
Pset represents the proving sectors, and Sset repensents all sectors
2020-05-20 12:46:22 +02:00
Łukasz Magiera 555537c528 Merge pull request #1791 from filecoin-project/feat/api-gen-2
improving the autogenerated api docs
2020-05-20 12:40:49 +02:00
shannon cc5875c6bd Pset represents the proving sectors, and Sset repensents all sectors 2020-05-20 12:12:13 +08:00
Jeromy c54d050cb7 slightly better methodgroup parsing, and more group docs 2020-05-19 09:49:47 -07:00
Jeromy cb88237305 improving the autogenerated api docs 2020-05-19 08:48:58 -07:00
Whyrusleeping cc44167f2c Merge pull request #1564 from filecoin-project/feat/api-doc-gen
working on api documentation autogeneration
2020-05-18 19:24:31 -07:00
Whyrusleeping 78c656e4c1 Merge pull request #1788 from filecoin-project/asr/issuetemplate
Create an issue template for mining issues
2020-05-18 17:27:55 -07:00
Jeromy 607bcc401c very basic api documentation autogeneration 2020-05-18 17:20:54 -07:00
Whyrusleeping 7fd481ea6f Merge pull request #1766 from filecoin-project/feat/chain-get-decoders
Feat/chain get decoders
2020-05-18 16:06:41 -07:00
Whyrusleeping 9c91daf19a Merge pull request #1787 from filecoin-project/fix/dont-mine-below-min
having power below the minimum means not having power
2020-05-18 16:05:06 -07:00
Aayush Rajasekaran c1ef9d1731 Create an issue template for mining issues 2020-05-18 18:31:53 -04:00
Jeromy eaf69b160c having power below the minimum means not having power 2020-05-18 14:51:42 -07:00
Łukasz Magiera 269286e587 Merge pull request #1785 from filecoin-project/frrist/chain-val-update
update chain-validation
2020-05-18 23:49:11 +02:00
Łukasz Magiera f99c5416ce Merge pull request #1786 from filecoin-project/asr/clideal
Prevent client list-deals from crashing
2020-05-18 23:48:33 +02:00
Aayush Rajasekaran 8f6c3c2cc7 prevent client list-deals from crashing 2020-05-18 17:44:00 -04:00
frrist a2e25897e9 go mod tidy 2020-05-18 14:35:47 -07:00
frrist fc9e046ca7 update chain-validation 2020-05-18 12:50:36 -07:00
Travis Person 5730d46179 Merge pull request #1728 from filecoin-project/frrist/vm-transfer-exitcodes
return correct exit codes from vm transfer
2020-05-18 19:28:48 +00:00
frrist 9165f14693 feedback: fatal errors in vm.transfer 2020-05-18 12:00:52 -07:00
frrist 9305eca97c don't ignore transfer error in delete actor 2020-05-18 12:00:52 -07:00
frrist 0c2e4e2d4f return correct exitcodes from vm transfer 2020-05-18 12:00:52 -07:00
Łukasz Magiera 59725b3af3 Merge pull request #1784 from filecoin-project/feat/update-serialization-vectors
update serialization vectors
2020-05-18 20:34:44 +02:00
Whyrusleeping a0ab3483ed Merge pull request #1770 from filecoin-project/asr/test
Add an interop test for block header serialisation
2020-05-18 11:28:06 -07:00
Jeromy e6f3b79b23 update serialization vectors 2020-05-18 11:02:34 -07:00
Whyrusleeping 1ed6183344 Merge pull request #1782 from filecoin-project/fix/no-metrics-drand
Change drand to one without metrics
2020-05-18 10:24:15 -07:00
Jakub Sztandera 29b1ac964b mod tidy
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-18 19:09:19 +02:00
Jakub Sztandera 8d637c515a Change drand to one without metrics
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-05-18 19:00:30 +02:00
Aayush Rajasekaran 5220a61fc5 Add an interop test for block header serialisation 2020-05-16 17:27:04 -04:00
Jeromy d9502693f0 add tipset key and height to html trace output 2020-05-16 12:53:51 -07:00
Whyrusleeping 9a0d0511c7 Merge pull request #1765 from filecoin-project/fix/miner-info-div-zero
avoid dividing by zero if pset is empty
2020-05-16 12:48:53 -07:00
Jeromy 72eb32ae3c add additional chain get decoders 2020-05-16 12:41:04 -07:00
Jeromy cf9e576028 avoid dividing by zero if pset is empty 2020-05-16 11:35:24 -07:00
Jeromy 9804bd3c4c add blockstore 'Has' caching 2020-05-16 11:31:14 -07:00
dtynn 30e2642f4d use abs path to construct FileManager 2020-05-16 09:36:38 +08:00
Whyrusleeping 54b3eafd6d Merge pull request #1758 from filecoin-project/fix/lotus-bench-secp
register secp signatures for lotus bench usage
2020-05-15 13:05:27 -07:00
Jeromy f6589407c1 register secp signatures for lotus bench usage 2020-05-15 13:01:45 -07:00
Łukasz Magiera 5c73602d24 Merge pull request #1757 from filecoin-project/feat/faster-mpool-add
cache signatures, and dont check them in a lock
2020-05-15 20:27:31 +02:00
Whyrusleeping 70657e35ba Merge pull request #1708 from filecoin-project/feat/block-validator
Improved pubsub block validator
2020-05-15 11:26:26 -07:00
Łukasz Magiera 908053015b Merge pull request #1753 from filecoin-project/feat/less-res-comm2
Update sector-storage with relaxed commit2 resource numbers
2020-05-15 20:17:41 +02:00
Whyrusleeping 8bae22ef61 Merge pull request #1746 from filecoin-project/bug/circleci-mac
install jq in /usr/local/bin
2020-05-15 11:17:12 -07:00
Łukasz Magiera 1012a64110 Merge pull request #1756 from filecoin-project/feat/ffi-88555ec98
Update FFI
2020-05-15 20:16:27 +02:00
Łukasz Magiera 9eb2399539 Merge pull request #1754 from filecoin-project/fix/initial-pledge
state: Calculate slightly larger initial pledge
2020-05-15 20:15:36 +02:00
Łukasz Magiera d539be4875 Merge pull request #1741 from filecoin-project/fix/json-out-chan-closing
properly select channel ID to close for handleOutChans
2020-05-15 20:10:10 +02:00
Jeromy 13fc3f2f54 remove stress test (not really a real test) 2020-05-15 11:00:13 -07:00
Jeromy 33ec4d332b cache signatures, and dont check them in a lock 2020-05-15 10:56:38 -07:00
Whyrusleeping d6bb0500df Merge pull request #1752 from filecoin-project/fix/mpool-slowness
miner: Optimize SelectMessages
2020-05-15 10:48:06 -07:00
Łukasz Magiera b90666b293 miner: optimize SelectMessages 2020-05-15 19:30:31 +02:00
Łukasz Magiera 173a72f374 Merge pull request #1755 from filecoin-project/fix/cw-tkt-crash
chainwatch: Don't crash with nil ticket
2020-05-15 19:17:45 +02:00
Łukasz Magiera 0ae0e89ddd Update FFI 2020-05-15 19:16:06 +02:00
Łukasz Magiera c4d01c04a4 chainwatch: don't crash with nil ticket 2020-05-15 19:06:52 +02:00
Łukasz Magiera 0b56ca3c21 Merge pull request #1751 from filecoin-project/fix/turnoff-block-mesh-penalty
Turn off Mesh Delivery Failure penalty
2020-05-15 19:02:46 +02:00
Łukasz Magiera 022348f426 state: Calculate slightly larger initial pledge 2020-05-15 16:53:35 +02:00
Łukasz Magiera ad108d6051 Update sector-storage with relaxed commit2 resource numbers 2020-05-15 16:00:14 +02:00
vyzo dbe2a1e2cd turn off Mesh Delivery Failure penalty 2020-05-15 12:50:20 +03:00
Aayush Rajasekaran f86a2ced06 Merge pull request #1747 from filecoin-project/asr/docs
Fix 3 typos
2020-05-14 18:34:59 -04:00
Aayush Rajasekaran f7a45f6c12 Fix 3 typos 2020-05-14 18:27:47 -04:00
ognots 658f78d75f install jq in /usr/local/bin
/home/ognots/.bin not in path, causing macos test to fail
2020-05-14 17:32:05 -04:00
Aayush Rajasekaran e9eaee6ef8 Merge pull request #1745 from filecoin-project/asr/docs
Docs finishing touches
2020-05-14 17:08:33 -04:00
Aayush Rajasekaran 505e30c7b2 Docs finishing touches 2020-05-14 16:27:20 -04:00
Jeromy edae6a3ae8 fix the problem 2020-05-14 12:05:01 -07:00
Jeromy 987571dd8c add test to demonstrate failure 2020-05-14 11:48:58 -07:00
vyzo 81bc159b3e cache successful block signature validation 2020-05-14 20:48:40 +03:00
vyzo 50e05ae1ba use sigs.CheckBlockSignature 2020-05-14 20:48:40 +03:00
vyzo 432c69c616 update message validator to provide rejection signal 2020-05-14 20:48:40 +03:00
vyzo e714294273 initialize map 2020-05-14 20:48:19 +03:00
vyzo c3a144bcb6 flesh out signature validation logic 2020-05-14 20:48:19 +03:00
vyzo dd86a289ce cache miner worker keys 2020-05-14 20:48:19 +03:00
vyzo 6e0dac06f4 utility to retrieve miner worker key from the chain 2020-05-14 20:48:19 +03:00
vyzo 5bd0e92068 remove source flagging from bogus CID blocks
it's ineffective.
2020-05-14 20:48:19 +03:00
vyzo b032d3524b configure behaviour penalty for gsv1.1 2020-05-14 20:48:19 +03:00
vyzo 6933df918a gomod: update go-libp2p-pubsub@master 2020-05-14 20:45:25 +03:00
lijunlong 8c05251cce simplify code 2020-04-01 09:41:26 +08:00
lijunlong 7c15d1e8c3 add bench mark for bls sign and verify 2020-03-28 12:34:12 +08:00
306 changed files with 16506 additions and 8198 deletions
+18 -33
View File
@@ -1,6 +1,6 @@
version: 2.1
orbs:
go: gotest/tools@0.0.9
go: gotest/tools@0.0.13
executors:
golang:
@@ -45,7 +45,7 @@ commands:
- 'v25-2k-lotus-params'
paths:
- /var/tmp/filecoin-proof-parameters/
- run: ./lotus fetch-params --proving-params 2048
- run: ./lotus fetch-params 2048
- save_cache:
name: Save parameters cache
key: 'v25-2k-lotus-params'
@@ -79,7 +79,6 @@ jobs:
steps:
- install-deps
- prepare
- go/mod-download
- go/mod-tidy-check
build-all:
@@ -87,12 +86,8 @@ jobs:
steps:
- install-deps
- prepare
- go/mod-download
- run: sudo apt-get update
- run: sudo apt-get install npm
- restore_cache:
name: restore go mod cache
key: v1-go-deps-{{ arch }}-{{ checksum "/home/circleci/project/go.mod" }}
- run:
command: make buildall
- store_artifacts:
@@ -112,10 +107,6 @@ jobs:
steps:
- install-deps
- prepare
- go/mod-download
- restore_cache:
name: restore go mod cache
key: v1-go-deps-{{ arch }}-{{ checksum "/home/circleci/project/go.mod" }}
- run:
command: make debug
@@ -134,6 +125,9 @@ jobs:
type: string
default: "./..."
description: Import paths of packages to be tested.
winpost-test:
type: string
default: "0"
test-suite-name:
type: string
default: unit
@@ -156,10 +150,6 @@ jobs:
steps:
- install-deps
- prepare
- go/mod-download
- restore_cache:
name: restore go mod cache
key: v1-go-deps-{{ arch }}-{{ checksum "/home/circleci/project/go.mod" }}
- run:
command: make deps lotus
no_output_timeout: 30m
@@ -171,6 +161,7 @@ jobs:
environment:
GOTESTSUM_JUNITFILE: /tmp/test-reports/<< parameters.test-suite-name >>/junit.xml
GOTESTSUM_FORMAT: << parameters.gotestsum-format >>
LOTUS_TEST_WINDOW_POST: << parameters.winpost-test >>
command: |
mkdir -p /tmp/test-reports/<< parameters.test-suite-name >>
gotestsum -- \
@@ -189,16 +180,11 @@ jobs:
shell: /bin/bash -eo pipefail
command: |
bash <(curl -s https://codecov.io/bash)
- save_cache:
name: save go mod cache
key: v1-go-deps-{{ arch }}-{{ checksum "/home/circleci/project/go.mod" }}
paths:
- "~/go/pkg"
- "~/go/src/github.com"
- "~/go/src/golang.org"
test-short:
<<: *test
test-window-post:
<<: *test
build-macos:
description: build darwin lotus binary
@@ -225,14 +211,12 @@ jobs:
- run:
name: Install jq
command: |
mkdir $HOME/.bin
curl --location https://github.com/stedolan/jq/releases/download/jq-1.6/jq-osx-amd64 --output $HOME/.bin/jq
chmod +x $HOME/.bin/jq
curl --location https://github.com/stedolan/jq/releases/download/jq-1.6/jq-osx-amd64 --output /usr/local/bin/jq
chmod +x /usr/local/bin/jq
- restore_cache:
name: restore go mod and cargo cache
name: restore cargo cache
key: v3-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.sum" }}
- install-deps
- go/mod-download
- run:
command: make build
no_output_timeout: 30m
@@ -259,7 +243,6 @@ jobs:
steps:
- install-deps
- prepare
- go/mod-download
- run:
command: "! go fmt ./... 2>&1 | read"
@@ -272,7 +255,7 @@ jobs:
default: golang
golangci-lint-version:
type: string
default: 1.23.8
default: 1.27.0
concurrency:
type: string
default: '2'
@@ -288,7 +271,6 @@ jobs:
steps:
- install-deps
- prepare
- go/mod-download
- run:
command: make deps
no_output_timeout: 30m
@@ -298,7 +280,7 @@ jobs:
- run:
name: Lint
command: |
$HOME/.local/bin/golangci-lint run -v \
$HOME/.local/bin/golangci-lint run -v --timeout 2m \
--concurrency << parameters.concurrency >> << parameters.args >>
lint-changes:
<<: *lint
@@ -333,10 +315,13 @@ workflows:
jobs:
- lint-changes:
args: "--new-from-rev origin/master"
- test:
codecov-upload: true
- mod-tidy-check
- gofmt
- test:
codecov-upload: true
- test-window-post:
go-test-flags: "-run=TestWindowedPost"
winpost-test: "1"
- test-short:
go-test-flags: "--timeout 10m --short"
filters:
+1 -1
View File
@@ -21,7 +21,7 @@ A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Version (run `lotus --version`):**
**Version (run `lotus version`):**
**Additional context**
Add any other context about the problem here.
+34
View File
@@ -0,0 +1,34 @@
---
name: Sealing Issues
about: Create a report for help with sealing (commit) failures.
title: ''
labels: 'sealing'
assignees: ''
---
Please provide all the information requested here to help us troubleshoot "commit failed" issues.
If the information requested is missing, we will probably have to just ask you to provide it anyway,
before we can help debug.
**Describe the problem**
A brief description of the problem you encountered while proving (sealing) a sector.
Including what commands you ran, and a description of your setup, is very helpful.
**Sectors list**
The output of `./lotus-storage-miner sectors list`.
**Sectors status**
The output of `./lotus-storage-miner sectors status --log <sectorId>` for the failed sector(s).
**Lotus storage miner logs**
Please go through the logs of your storage miner, and include screenshots of any error-like messages you find.
**Version**
The output of `./lotus --version`.
+1
View File
@@ -35,3 +35,4 @@ build/paramfetch.sh
bin/ipget
bin/tmp/*
.idea
scratchpad
+15 -1
View File
@@ -22,13 +22,27 @@ issues:
- "func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this"
- "Potential file inclusion via variable"
- "should have( a package)? comment"
- "Error return value of `logging.SetLogLevel` is not checked"
exclude-use-default: false
exclude-rules:
- path: lotuspond
linters:
- errcheck
- path: node/modules/lp2p
linters:
- golint
- path: ".*_test.go"
- path: build/params_.*\.go
linters:
- golint
- path: api/apistruct/struct.go
linters:
- golint
- path: .*_test.go
linters:
- gosec
+31 -4
View File
@@ -6,7 +6,7 @@ all: build
unexport GOFLAGS
GOVERSION:=$(shell go version | cut -d' ' -f 3 | cut -d. -f 2)
ifeq ($(shell expr $(GOVERSION) \< 13), 1)
ifeq ($(shell expr $(GOVERSION) \< 14), 1)
$(warning Your Golang version is go 1.$(GOVERSION))
$(error Update Golang to version $(shell grep '^go' go.mod))
endif
@@ -17,7 +17,7 @@ MODULES:=
CLEAN:=
BINS:=
ldflags=-X=github.com/filecoin-project/lotus/build.CurrentCommit='+git$(subst -,.,$(shell git describe --always --match=NeVeRmAtCh --dirty 2>/dev/null || git rev-parse --short HEAD 2>/dev/null))'
ldflags=-X=github.com/filecoin-project/lotus/build.CurrentCommit=+git.$(subst -,.,$(shell git describe --always --match=NeVeRmAtCh --dirty 2>/dev/null || git rev-parse --short HEAD 2>/dev/null))
ifneq ($(strip $(LDFLAGS)),)
ldflags+=-extldflags=$(LDFLAGS)
endif
@@ -103,6 +103,21 @@ install:
install -C ./lotus-storage-miner /usr/local/bin/lotus-storage-miner
install -C ./lotus-seal-worker /usr/local/bin/lotus-seal-worker
install-services: install
mkdir -p /usr/local/lib/systemd/system
mkdir -p /var/log/lotus
install -C -m 0644 ./scripts/lotus-daemon.service /usr/local/lib/systemd/system/lotus-daemon.service
install -C -m 0644 ./scripts/lotus-miner.service /usr/local/lib/systemd/system/lotus-miner.service
systemctl daemon-reload
@echo
@echo "lotus-daemon and lotus-miner services installed. Don't forget to 'systemctl enable lotus-daemon|lotus-miner' for it to be enabled on startup."
clean-services:
rm -f /usr/local/lib/systemd/system/lotus-daemon.service
rm -f /usr/local/lib/systemd/system/lotus-miner.service
rm -f /usr/local/lib/systemd/system/chainwatch.service
systemctl daemon-reload
# TOOLS
lotus-seed: $(BUILD_DEPS)
@@ -119,7 +134,7 @@ benchmarks:
@curl -X POST 'http://benchmark.kittyhawk.wtf/benchmark' -d '@bench.json' -u "${benchmark_http_cred}"
.PHONY: benchmarks
pond: build
pond: 2k
go build -o pond ./lotuspond
(cd lotuspond/front && npm i && CI=false npm run build)
.PHONY: pond
@@ -143,10 +158,16 @@ BINS+=fountain
chainwatch:
rm -f chainwatch
go build -o chainwatch ./cmd/lotus-chainwatch
go run github.com/GeertJohan/go.rice/rice append --exec chainwatch -i ./cmd/lotus-chainwatch -i ./build
.PHONY: chainwatch
BINS+=chainwatch
install-chainwatch-service: chainwatch
install -C ./chainwatch /usr/local/bin/chainwatch
install -C -m 0644 ./scripts/chainwatch.service /usr/local/lib/systemd/system/chainwatch.service
systemctl daemon-reload
@echo
@echo "chainwatch installed. Don't forget to 'systemctl enable chainwatch' for it to be enabled on startup."
bench:
rm -f bench
go build -o bench ./cmd/lotus-bench
@@ -169,6 +190,12 @@ health:
.PHONY: health
BINS+=health
testground:
go build -tags testground -o /dev/null ./cmd/lotus
.PHONY: testground
BINS+=testground
# MISC
buildall: $(BINS)
+13 -4
View File
@@ -4,14 +4,23 @@
Lotus is an implementation of the Filecoin Distributed Storage Network. For more details about Filecoin, check out the [Filecoin Spec](https://github.com/filecoin-project/specs).
## Development
All work is tracked via issues. An attempt at keeping an up-to-date view on remaining work is in the [lotus testnet github project board](https://github.com/filecoin-project/lotus/projects/1).
## Building & Documentation
For instructions on how to build lotus from source, please visit [https://docs.lotu.sh](https://docs.lotu.sh) or read the source [here](https://github.com/filecoin-project/lotus/tree/master/documentation).
## Reporting a Vulnerability
Please send an email to security@filecoin.org. See our [security policy](SECURITY.md) for more details.
## Development
All work is tracked via issues. An attempt at keeping an up-to-date view on remaining work is in the [lotus testnet github project board](https://github.com/filecoin-project/lotus/projects/1).
The main branches under development at the moment are:
* [`master`](https://github.com/filecoin-project/lotus): current testnet.
* [`next`](https://github.com/filecoin-project/lotus/tree/next): working branch with chain-breaking changes.
* [`ntwk-calibration`](https://github.com/filecoin-project/lotus/tree/ntwk-calibration): devnet running one of `next` commits.
## License
Dual-licensed under [MIT](https://github.com/filecoin-project/lotus/blob/master/LICENSE-MIT) + [Apache 2.0](https://github.com/filecoin-project/lotus/blob/master/LICENSE-APACHE)
+29
View File
@@ -0,0 +1,29 @@
# Security Policy
## Reporting a Vulnerability
For *critical* bugs, please send an email to security@filecoin.org.
The bug reporting process differs between bugs that are critical and may crash the network, and others that are unlikely to cause problems if malicious parties know about it. For non-critical bugs, please simply file a GitHub [issue](https://github.com/filecoin-project/lotus/issues/new?template=bug_report.md).
Please try to provide a clear description of any bugs reported, along with how to reproduce the bug if possible. More detailed bug reports (especially those with a PoC included) will help us move forward much faster. Additionally, please avoid reporting bugs that already have open issues. Take a moment to search the issue list of the related GitHub repositories before writing up a new report.
Here are some examples of bugs we would consider 'critical':
* If you can spend from a `multisig` wallet you do not control the keys for.
* If you can cause a miner to be slashed without them actually misbehaving.
* If you can maintain power without submitting windowed posts regularly.
* If you can craft a message that causes lotus nodes to panic.
* If you can cause your miner to win significantly more blocks than it should.
* If you can craft a message that causes a persistent fork in the network.
* If you can cause the total amount of Filecoin in the network to no longer be 2 billion.
This is not an exhaustive list, but should provide some idea of what we consider 'critical'.
## Supported Versions
* TODO: This should be defined and set up by Mainnet launch.
| Version | Supported |
| ------- | ------------------ |
| Testnet | :white_check_mark: |
+18 -7
View File
@@ -4,19 +4,22 @@ import (
"context"
"fmt"
"github.com/filecoin-project/lotus/build"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/build"
)
type Permission = string
type Common interface {
// Auth
AuthVerify(ctx context.Context, token string) ([]Permission, error)
AuthNew(ctx context.Context, perms []Permission) ([]byte, error)
// network
// MethodGroup: Auth
AuthVerify(ctx context.Context, token string) ([]auth.Permission, error)
AuthNew(ctx context.Context, perms []auth.Permission) ([]byte, error)
// MethodGroup: Net
NetConnectedness(context.Context, peer.ID) (network.Connectedness, error)
NetPeers(context.Context) ([]peer.AddrInfo, error)
@@ -24,6 +27,9 @@ type Common interface {
NetAddrsListen(context.Context) (peer.AddrInfo, error)
NetDisconnect(context.Context, peer.ID) error
NetFindPeer(context.Context, peer.ID) (peer.AddrInfo, error)
NetPubsubScores(context.Context) ([]PubsubScore, error)
// MethodGroup: Common
// ID returns peerID of libp2p node backing this API
ID(context.Context) (peer.ID, error)
@@ -33,6 +39,11 @@ type Common interface {
LogList(context.Context) ([]string, error)
LogSetLevel(context.Context, string, string) error
// trigger graceful shutdown
Shutdown(context.Context) error
Closing(context.Context) (<-chan struct{}, error)
}
// Version provides various build-time information
+223 -31
View File
@@ -26,82 +26,189 @@ import (
type FullNode interface {
Common
// TODO: TipSetKeys
// MethodGroup: Chain
// The Chain method group contains methods for interacting with the
// blockchain, but that do not require any form of state computation.
// chain
// ChainNotify returns channel with chain head updates
// First message is guaranteed to be of len == 1, and type == 'current'
// ChainNotify returns channel with chain head updates.
// First message is guaranteed to be of len == 1, and type == 'current'.
ChainNotify(context.Context) (<-chan []*HeadChange, error)
// ChainHead returns the current head of the chain.
ChainHead(context.Context) (*types.TipSet, error)
// ChainGetRandomness is used to sample the chain for randomness.
ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error)
// ChainGetBlock returns the block specified by the given CID.
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error)
// ChainGetTipSet returns the tipset specified by the given TipSetKey.
ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error)
ChainGetParentMessages(context.Context, cid.Cid) ([]Message, error)
// ChainGetBlockMessages returns messages stored in the specified block.
ChainGetBlockMessages(ctx context.Context, blockCid cid.Cid) (*BlockMessages, error)
// ChainGetParentReceipts returns receipts for messages in parent tipset of
// the specified block.
ChainGetParentReceipts(ctx context.Context, blockCid cid.Cid) ([]*types.MessageReceipt, error)
// ChainGetParentMessages returns messages stored in parent tipset of the
// specified block.
ChainGetParentMessages(ctx context.Context, blockCid cid.Cid) ([]Message, error)
// ChainGetTipSetByHeight looks back for a tipset at the specified epoch.
// If there are no blocks at the specified epoch, a tipset at an earlier epoch
// will be returned.
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
// ChainReadObj reads ipld nodes referenced by the specified CID from chain
// blockstore and returns raw bytes.
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
// ChainHasObj checks if a given CID exists in the chain blockstore.
ChainHasObj(context.Context, cid.Cid) (bool, error)
ChainStatObj(context.Context, cid.Cid, cid.Cid) (ObjStat, error)
// ChainSetHead forcefully sets current chain head. Use with caution.
ChainSetHead(context.Context, types.TipSetKey) error
// ChainGetGenesis returns the genesis tipset.
ChainGetGenesis(context.Context) (*types.TipSet, error)
// ChainTipSetWeight computes weight for the specified tipset.
ChainTipSetWeight(context.Context, types.TipSetKey) (types.BigInt, error)
ChainGetNode(ctx context.Context, p string) (*IpldObject, error)
// ChainGetMessage reads a message referenced by the specified CID from the
// chain blockstore.
ChainGetMessage(context.Context, cid.Cid) (*types.Message, error)
// ChainGetPath returns a set of revert/apply operations needed to get from
// one tipset to another, for example:
//```
// to
// ^
// from tAA
// ^ ^
// tBA tAB
// ^---*--^
// ^
// tRR
//```
// Would return `[revert(tBA), apply(tAB), apply(tAA)]`
ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*HeadChange, error)
// ChainExport returns a stream of bytes with CAR dump of chain data.
ChainExport(context.Context, types.TipSetKey) (<-chan []byte, error)
// syncer
// MethodGroup: Sync
// The Sync method group contains methods for interacting with and
// observing the lotus sync service.
// SyncState returns the current status of the lotus sync system.
SyncState(context.Context) (*SyncState, error)
// SyncSubmitBlock can be used to submit a newly created block to the.
// network through this node
SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error
// SyncIncomingBlocks returns a channel streaming incoming, potentially not
// yet synced block headers.
SyncIncomingBlocks(ctx context.Context) (<-chan *types.BlockHeader, error)
// SyncMarkBad marks a blocks as bad, meaning that it won't ever by synced.
// Use with extreme caution.
SyncMarkBad(ctx context.Context, bcid cid.Cid) error
// SyncCheckBad checks if a block was marked as bad, and if it was, returns
// the reason.
SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error)
// messages
// 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.
// MpoolPending returns pending mempool messages.
MpoolPending(context.Context, types.TipSetKey) ([]*types.SignedMessage, error)
// MpoolPush pushes a signed message to mempool.
MpoolPush(context.Context, *types.SignedMessage) (cid.Cid, error)
MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error) // get nonce, sign, push
// MpoolPushMessage atomically assigns a nonce, signs, and pushes a message
// to mempool.
MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error)
// MpoolGetNonce gets next nonce for the specified sender.
// Note that this method may not be atomic. Use MpoolPushMessage instead.
MpoolGetNonce(context.Context, address.Address) (uint64, error)
MpoolSub(context.Context) (<-chan MpoolUpdate, error)
MpoolEstimateGasPrice(context.Context, uint64, address.Address, int64, types.TipSetKey) (types.BigInt, error)
// FullNodeStruct
// MpoolEstimateGasPrice estimates what gas price should be used for a
// message to have high likelihood of inclusion in `nblocksincl` epochs.
MpoolEstimateGasPrice(ctx context.Context, nblocksincl uint64, sender address.Address, gaslimit int64, tsk types.TipSetKey) (types.BigInt, error)
// miner
// MethodGroup: Miner
MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*MiningBaseInfo, error)
MinerCreateBlock(context.Context, *BlockTemplate) (*types.BlockMsg, error)
// // UX ?
// wallet
// MethodGroup: Wallet
// WalletNew creates a new address in the wallet with the given sigType.
WalletNew(context.Context, crypto.SigType) (address.Address, error)
// WalletHas indicates whether the given address is in the wallet.
WalletHas(context.Context, address.Address) (bool, error)
// WalletList lists all the addresses in the wallet.
WalletList(context.Context) ([]address.Address, error)
// WalletBalance returns the balance of the given address at the current head of the chain.
WalletBalance(context.Context, address.Address) (types.BigInt, error)
// WalletSign signs the given bytes using the given address.
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error)
// WalletSignMessage signs the given message using the given address.
WalletSignMessage(context.Context, address.Address, *types.Message) (*types.SignedMessage, error)
// WalletVerify takes an address, a signature, and some bytes, and indicates whether the signature is valid.
// The address does not have to be in the wallet.
WalletVerify(context.Context, address.Address, []byte, *crypto.Signature) bool
// WalletDefaultAddress returns the address marked as default in the wallet.
WalletDefaultAddress(context.Context) (address.Address, error)
// WalletSetDefault marks the given address as as the default one.
WalletSetDefault(context.Context, address.Address) error
// WalletExport returns the private key of an address in the wallet.
WalletExport(context.Context, address.Address) (*types.KeyInfo, error)
// WalletImport receives a KeyInfo, which includes a private key, and imports it into the wallet.
WalletImport(context.Context, *types.KeyInfo) (address.Address, error)
// WalletDelete deletes an address from the wallet.
WalletDelete(context.Context, address.Address) error
// Other
// ClientImport imports file under the specified path into filestore
// MethodGroup: Client
// The Client methods all have to do with interacting with the storage and
// retrieval markets as a client
// ClientImport imports file under the specified path into filestore.
ClientImport(ctx context.Context, ref FileRef) (cid.Cid, error)
// ClientStartDeal proposes a deal with a miner.
ClientStartDeal(ctx context.Context, params *StartDealParams) (*cid.Cid, error)
// ClientGetDealInfo returns the latest information about a given deal.
ClientGetDealInfo(context.Context, cid.Cid) (*DealInfo, error)
// ClientListDeals returns information about the deals made by the local client.
ClientListDeals(ctx context.Context) ([]DealInfo, error)
// ClientHasLocal indicates whether a certain CID is locally stored.
ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error)
// ClientFindData identifies peers that have a certain file, and returns QueryOffers (one per peer).
ClientFindData(ctx context.Context, root cid.Cid) ([]QueryOffer, error)
ClientRetrieve(ctx context.Context, order RetrievalOrder, ref FileRef) error
// ClientMinerQueryOffer returns a QueryOffer for the specific miner and file.
ClientMinerQueryOffer(ctx context.Context, root cid.Cid, miner address.Address) (QueryOffer, error)
// ClientRetrieve initiates the retrieval of a file, as specified in the order.
ClientRetrieve(ctx context.Context, order RetrievalOrder, ref *FileRef) error
// ClientQueryAsk returns a signed StorageAsk from the specified miner.
ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error)
// ClientCalcCommP calculates the CommP for a specified file, based on the sector size of the provided miner.
ClientCalcCommP(ctx context.Context, inpath string, miner address.Address) (*CommPRet, error)
// ClientGenCar generates a CAR file for the specified file.
ClientGenCar(ctx context.Context, ref FileRef, outpath string) error
// ClientUnimport removes references to the specified file from filestore
@@ -112,49 +219,127 @@ type FullNode interface {
//ClientListAsks() []Ask
// if tipset is nil, we'll use heaviest
// MethodGroup: State
// The State methods are used to query, inspect, and interact with chain state.
// All methods take a TipSetKey as a parameter. The state looked up is the state at that tipset.
// A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used.
// StateCall runs the given message and returns its result without any persisted changes.
StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error)
// StateReplay returns the result of executing the indicated message, assuming it was executed in the indicated tipset.
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error)
// StateGetActor returns the indicated actor's nonce and balance.
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
StateReadState(ctx context.Context, act *types.Actor, tsk types.TipSetKey) (*ActorState, error)
// StateReadState returns the indicated actor's state.
StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*ActorState, error)
// StateListMessages looks back and returns all messages with a matching to or from address, stopping at the given height.
StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error)
// StateNetworkName returns the name of the network the node is synced to
StateNetworkName(context.Context) (dtypes.NetworkName, error)
// StateMinerSectors returns info about the given miner's sectors. If the filter bitfield is nil, all sectors are included.
// If the filterOut boolean is set to true, any sectors in the filter are excluded.
// If false, only those sectors in the filter are included.
StateMinerSectors(context.Context, address.Address, *abi.BitField, bool, types.TipSetKey) ([]*ChainSectorInfo, error)
// StateMinerProvingSet returns info about those sectors that a given miner is actively proving.
StateMinerProvingSet(context.Context, address.Address, types.TipSetKey) ([]*ChainSectorInfo, error)
// StateMinerProvingDeadline calculates the deadline at some epoch for a proving period
// and returns the deadline-related calculations.
StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*miner.DeadlineInfo, error)
// StateMinerPower returns the power of the indicated miner
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error)
StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error)
// StateMinerInfo returns info about the indicated miner
StateMinerInfo(context.Context, address.Address, types.TipSetKey) (MinerInfo, error)
// StateMinerDeadlines returns all the proving deadlines for the given miner
StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) (*miner.Deadlines, error)
StateMinerFaults(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error)
// StateMinerFaults returns a bitfield indicating the faulty sectors of the given miner
StateMinerFaults(context.Context, address.Address, types.TipSetKey) (*abi.BitField, error)
// StateAllMinerFaults returns all non-expired Faults that occur within lookback epochs of the given tipset
StateAllMinerFaults(ctx context.Context, lookback abi.ChainEpoch, ts types.TipSetKey) ([]*Fault, error)
// StateMinerRecoveries returns a bitfield indicating the recovering sectors of the given miner
StateMinerRecoveries(context.Context, address.Address, types.TipSetKey) (*abi.BitField, error)
// StateMinerInitialPledgeCollateral returns the initial pledge collateral for the specified miner's sector
StateMinerInitialPledgeCollateral(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (types.BigInt, error)
// StateMinerAvailableBalance returns the portion of a miner's balance that can be withdrawn or spent
StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
// StateSectorPreCommitInfo returns the PreCommit info for the specified miner's sector
StateSectorPreCommitInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error)
// StateSectorGetInfo returns the on-chain info for the specified miner's sector
StateSectorGetInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error)
StatePledgeCollateral(context.Context, types.TipSetKey) (types.BigInt, error)
StateWaitMsg(context.Context, cid.Cid) (*MsgLookup, error)
// StateSearchMsg searches for a message in the chain, and returns its receipt and the tipset where it was executed
StateSearchMsg(context.Context, cid.Cid) (*MsgLookup, error)
// StateWaitMsg looks back in the chain for a message. If not found, it blocks until the
// message arrives on chain, and gets to the indicated confidence depth.
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error)
// StateListMiners returns the addresses of every miner that has claimed power in the Power Actor
StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error)
// StateListActors returns the addresses of every actor in the state
StateListActors(context.Context, types.TipSetKey) ([]address.Address, error)
// StateMarketBalance looks up the Escrow and Locked balances of the given address in the Storage Market
StateMarketBalance(context.Context, address.Address, types.TipSetKey) (MarketBalance, error)
// StateMarketParticipants returns the Escrow and Locked balances of every participant in the Storage Market
StateMarketParticipants(context.Context, types.TipSetKey) (map[string]MarketBalance, error)
// StateMarketDeals returns information about every deal in the Storage Market
StateMarketDeals(context.Context, types.TipSetKey) (map[string]MarketDeal, error)
// StateMarketStorageDeal returns information about the indicated deal
StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*MarketDeal, error)
// StateLookupID retrieves the ID address of the given address
StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error)
// StateAccountKey returns the public key address of the given ID address
StateAccountKey(context.Context, address.Address, types.TipSetKey) (address.Address, error)
// StateChangedActors returns all the actors whose states change between the two given state CIDs
// TODO: Should this take tipset keys instead?
StateChangedActors(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error)
// StateGetReceipt returns the message receipt for the given message
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
// StateMinerSectorCount returns the number of sectors in a miner's sector set and proving set
StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error)
// 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)
// MethodGroup: Msig
// The Msig methods are used to interact with multisig wallets on the
// filecoin network
// MsigGetAvailableBalance returns the portion of a multisig's balance that can be withdrawn or spent
MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
MsigCreate(context.Context, int64, []address.Address, types.BigInt, address.Address, types.BigInt) (cid.Cid, error)
// MsigCreate creates a multisig wallet
// It takes the following params: <required number of senders>, <approving addresses>, <unlock duration>
//<initial balance>, <sender address of the create msg>, <gas price>
MsigCreate(context.Context, int64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (cid.Cid, error)
// MsigPropose proposes a multisig message
// It takes the following params: <multisig address>, <recipient address>, <value to transfer>,
// <sender address of the propose msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigPropose(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
// MsigApprove approves a previously-proposed multisig message
// It takes the following params: <multisig address>, <proposed message ID>, <proposer address>, <recipient address>, <value to transfer>,
// <sender address of the approve msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigApprove(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
MsigCancel(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
// MsigCancel cancels a previously-proposed multisig message
// It takes the following params: <multisig address>, <proposed message ID>, <recipient address>, <value to transfer>,
// <sender address of the cancel msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigCancel(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
// MsigSwapPropose proposes swapping 2 signers in the multisig
// It takes the following params: <multisig address>, <sender address of the propose msg>,
// <old signer> <new signer>
MsigSwapPropose(context.Context, address.Address, address.Address, address.Address, address.Address) (cid.Cid, error)
// MsigSwapApprove approves a previously proposed SwapSigner
// It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
// <proposer address>, <old signer> <new signer>
MsigSwapApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, address.Address) (cid.Cid, error)
// MsigSwapCancel cancels a previously proposed SwapSigner message
// It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
// <old signer> <new signer>
MsigSwapCancel(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error)
MarketEnsureAvailable(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error)
// MarketFreeBalance
// MethodGroup: Paych
// The Paych methods are for interacting with and managing payment channels
PaychGet(ctx context.Context, from, to address.Address, ensureFunds types.BigInt) (*ChannelInfo, error)
PaychList(context.Context) ([]address.Address, error)
PaychStatus(context.Context, address.Address) (*PaychStatus, error)
@@ -202,8 +387,10 @@ type DealInfo struct {
}
type MsgLookup struct {
Receipt types.MessageReceipt
TipSet *types.TipSet
Receipt types.MessageReceipt
ReturnDec interface{}
TipSet types.TipSetKey
Height abi.ChainEpoch
}
type BlockMessages struct {
@@ -317,11 +504,11 @@ type RetrievalOrder struct {
}
type InvocResult struct {
Msg *types.Message
MsgRct *types.MessageReceipt
InternalExecutions []*types.ExecutionResult
Error string
Duration time.Duration
Msg *types.Message
MsgRct *types.MessageReceipt
ExecutionTrace types.ExecutionTrace
Error string
Duration time.Duration
}
type MethodCall struct {
@@ -424,3 +611,8 @@ const (
MsigApprove MsigProposeResponse = iota
MsigCancel
)
type Fault struct {
Miner address.Address
Epoch abi.ChainEpoch
}
+14 -3
View File
@@ -8,11 +8,10 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/sector-storage/stores"
"github.com/filecoin-project/sector-storage/storiface"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/lotus/chain/types"
)
// StorageMiner is a low-level interface to the Filecoin network storage miner node
@@ -37,6 +36,7 @@ type StorageMiner interface {
SectorsRefs(context.Context) (map[string][]SealedRef, error)
SectorsUpdate(context.Context, abi.SectorNumber, SectorState) error
SectorRemove(context.Context, abi.SectorNumber) error
StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error)
StorageLocal(ctx context.Context) (map[stores.ID]string, error)
@@ -51,10 +51,21 @@ type StorageMiner interface {
MarketImportDealData(ctx context.Context, propcid cid.Cid, path string) error
MarketListDeals(ctx context.Context) ([]storagemarket.StorageDeal, error)
MarketListIncompleteDeals(ctx context.Context) ([]storagemarket.MinerDeal, error)
MarketSetPrice(context.Context, types.BigInt) error
MarketSetAsk(ctx context.Context, price types.BigInt, duration abi.ChainEpoch, minPieceSize abi.PaddedPieceSize, maxPieceSize abi.PaddedPieceSize) error
MarketGetAsk(ctx context.Context) (*storagemarket.SignedStorageAsk, error)
DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error
DealsList(ctx context.Context) ([]storagemarket.StorageDeal, error)
DealsConsiderOnlineStorageDeals(context.Context) (bool, error)
DealsSetConsiderOnlineStorageDeals(context.Context, bool) error
DealsConsiderOnlineRetrievalDeals(context.Context) (bool, error)
DealsSetConsiderOnlineRetrievalDeals(context.Context, bool) error
DealsPieceCidBlocklist(context.Context) ([]cid.Cid, error)
DealsSetPieceCidBlocklist(context.Context, []cid.Cid) error
DealsConsiderOfflineStorageDeals(context.Context) (bool, error)
DealsSetConsiderOfflineStorageDeals(context.Context, bool) error
DealsConsiderOfflineRetrievalDeals(context.Context) (bool, error)
DealsSetConsiderOfflineRetrievalDeals(context.Context, bool) error
StorageAddLocal(ctx context.Context, path string) error
}
+11 -2
View File
@@ -2,6 +2,9 @@ package api
import (
"context"
"io"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/sector-storage/sealtasks"
"github.com/filecoin-project/sector-storage/stores"
@@ -12,7 +15,7 @@ import (
"github.com/filecoin-project/lotus/build"
)
type WorkerApi interface {
type WorkerAPI interface {
Version(context.Context) (build.Version, error)
// TODO: Info() (name, ...) ?
@@ -21,7 +24,13 @@ type WorkerApi interface {
Info(context.Context) (storiface.WorkerInfo, error)
storage.Sealer
Fetch(context.Context, abi.SectorID, stores.SectorFileType, bool) error
MoveStorage(ctx context.Context, sector abi.SectorID) error
UnsealPiece(context.Context, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) error
ReadPiece(context.Context, io.Writer, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) error
Fetch(context.Context, abi.SectorID, stores.SectorFileType, stores.PathType, stores.AcquireMode) error
Closing(context.Context) (<-chan struct{}, error)
}
+13 -86
View File
@@ -1,111 +1,38 @@
package apistruct
import (
"context"
"reflect"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/api"
)
type permKey int
var permCtxKey permKey
const (
// When changing these, update docs/API.md too
PermRead api.Permission = "read" // default
PermWrite api.Permission = "write"
PermSign api.Permission = "sign" // Use wallet keys for signing
PermAdmin api.Permission = "admin" // Manage permissions
PermRead auth.Permission = "read" // default
PermWrite auth.Permission = "write"
PermSign auth.Permission = "sign" // Use wallet keys for signing
PermAdmin auth.Permission = "admin" // Manage permissions
)
var AllPermissions = []api.Permission{PermRead, PermWrite, PermSign, PermAdmin}
var defaultPerms = []api.Permission{PermRead}
func WithPerm(ctx context.Context, perms []api.Permission) context.Context {
return context.WithValue(ctx, permCtxKey, perms)
}
var AllPermissions = []auth.Permission{PermRead, PermWrite, PermSign, PermAdmin}
var DefaultPerms = []auth.Permission{PermRead}
func PermissionedStorMinerAPI(a api.StorageMiner) api.StorageMiner {
var out StorageMinerStruct
permissionedAny(a, &out.Internal)
permissionedAny(a, &out.CommonStruct.Internal)
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.CommonStruct.Internal)
return &out
}
func PermissionedFullAPI(a api.FullNode) api.FullNode {
var out FullNodeStruct
permissionedAny(a, &out.Internal)
permissionedAny(a, &out.CommonStruct.Internal)
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.CommonStruct.Internal)
return &out
}
func PermissionedWorkerAPI(a api.WorkerApi) api.WorkerApi {
func PermissionedWorkerAPI(a api.WorkerAPI) api.WorkerAPI {
var out WorkerStruct
permissionedAny(a, &out.Internal)
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
return &out
}
func HasPerm(ctx context.Context, perm api.Permission) bool {
callerPerms, ok := ctx.Value(permCtxKey).([]api.Permission)
if !ok {
callerPerms = defaultPerms
}
for _, callerPerm := range callerPerms {
if callerPerm == perm {
return true
}
}
return false
}
func permissionedAny(in interface{}, out interface{}) {
rint := reflect.ValueOf(out).Elem()
ra := reflect.ValueOf(in)
for f := 0; f < rint.NumField(); f++ {
field := rint.Type().Field(f)
requiredPerm := api.Permission(field.Tag.Get("perm"))
if requiredPerm == "" {
panic("missing 'perm' tag on " + field.Name) // ok
}
// Validate perm tag
ok := false
for _, perm := range AllPermissions {
if requiredPerm == perm {
ok = true
break
}
}
if !ok {
panic("unknown 'perm' tag on " + field.Name) // ok
}
fn := ra.MethodByName(field.Name)
rint.Field(f).Set(reflect.MakeFunc(field.Type, func(args []reflect.Value) (results []reflect.Value) {
ctx := args[0].Interface().(context.Context)
if HasPerm(ctx, requiredPerm) {
return fn.Call(args)
}
err := xerrors.Errorf("missing permission to invoke '%s' (need '%s')", field.Name, requiredPerm)
rerr := reflect.ValueOf(&err).Elem()
if field.Type.NumOut() == 2 {
return []reflect.Value{
reflect.Zero(field.Type.Out(0)),
rerr,
}
} else {
return []reflect.Value{rerr}
}
}))
}
}
+220 -66
View File
@@ -2,6 +2,7 @@ package apistruct
import (
"context"
"io"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/network"
@@ -9,6 +10,8 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/sector-storage/sealtasks"
"github.com/filecoin-project/sector-storage/stores"
"github.com/filecoin-project/sector-storage/storiface"
@@ -30,8 +33,8 @@ var _ = AllPermissions
type CommonStruct struct {
Internal struct {
AuthVerify func(ctx context.Context, token string) ([]api.Permission, error) `perm:"read"`
AuthNew func(ctx context.Context, perms []api.Permission) ([]byte, error) `perm:"admin"`
AuthVerify func(ctx context.Context, token string) ([]auth.Permission, error) `perm:"read"`
AuthNew func(ctx context.Context, perms []auth.Permission) ([]byte, error) `perm:"admin"`
NetConnectedness func(context.Context, peer.ID) (network.Connectedness, error) `perm:"read"`
NetPeers func(context.Context) ([]peer.AddrInfo, error) `perm:"read"`
@@ -39,12 +42,16 @@ type CommonStruct struct {
NetAddrsListen func(context.Context) (peer.AddrInfo, error) `perm:"read"`
NetDisconnect func(context.Context, peer.ID) error `perm:"write"`
NetFindPeer func(context.Context, peer.ID) (peer.AddrInfo, error) `perm:"read"`
NetPubsubScores func(context.Context) ([]api.PubsubScore, error) `perm:"read"`
ID func(context.Context) (peer.ID, error) `perm:"read"`
Version func(context.Context) (api.Version, error) `perm:"read"`
LogList func(context.Context) ([]string, error) `perm:"write"`
LogSetLevel func(context.Context, string, string) error `perm:"write"`
Shutdown func(context.Context) error `perm:"admin"`
Closing func(context.Context) (<-chan struct{}, error) `perm:"read"`
}
}
@@ -100,36 +107,41 @@ type FullNodeStruct struct {
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"`
ClientImport func(ctx context.Context, ref api.FileRef) (cid.Cid, error) `perm:"admin"`
ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"`
ClientHasLocal func(ctx context.Context, root cid.Cid) (bool, error) `perm:"write"`
ClientFindData func(ctx context.Context, root cid.Cid) ([]api.QueryOffer, error) `perm:"read"`
ClientStartDeal func(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) `perm:"admin"`
ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"`
ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"`
ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref api.FileRef) error `perm:"admin"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) `perm:"read"`
ClientCalcCommP func(ctx context.Context, inpath string, miner address.Address) (*api.CommPRet, error) `perm:"read"`
ClientGenCar func(ctx context.Context, ref api.FileRef, outpath string) error `perm:"write"`
ClientImport func(ctx context.Context, ref api.FileRef) (cid.Cid, error) `perm:"admin"`
ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"`
ClientHasLocal func(ctx context.Context, root cid.Cid) (bool, error) `perm:"write"`
ClientFindData func(ctx context.Context, root cid.Cid) ([]api.QueryOffer, error) `perm:"read"`
ClientMinerQueryOffer func(ctx context.Context, root cid.Cid, miner address.Address) (api.QueryOffer, error) `perm:"read"`
ClientStartDeal func(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) `perm:"admin"`
ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"`
ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"`
ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error `perm:"admin"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) `perm:"read"`
ClientCalcCommP func(ctx context.Context, inpath string, miner address.Address) (*api.CommPRet, error) `perm:"read"`
ClientGenCar func(ctx context.Context, ref api.FileRef, outpath string) error `perm:"write"`
StateNetworkName func(context.Context) (dtypes.NetworkName, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address, *abi.BitField, bool, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerProvingDeadline func(context.Context, address.Address, types.TipSetKey) (*miner.DeadlineInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) `perm:"read"`
StateMinerInfo func(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) `perm:"read"`
StateMinerInfo func(context.Context, address.Address, types.TipSetKey) (api.MinerInfo, error) `perm:"read"`
StateMinerDeadlines func(context.Context, address.Address, types.TipSetKey) (*miner.Deadlines, error) `perm:"read"`
StateMinerFaults func(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error) `perm:"read"`
StateMinerFaults func(context.Context, address.Address, types.TipSetKey) (*abi.BitField, error) `perm:"read"`
StateAllMinerFaults func(context.Context, abi.ChainEpoch, types.TipSetKey) ([]*api.Fault, error) `perm:"read"`
StateMinerRecoveries func(context.Context, address.Address, types.TipSetKey) (*abi.BitField, error) `perm:"read"`
StateMinerInitialPledgeCollateral func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (types.BigInt, error) `perm:"read"`
StateMinerAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
StateSectorPreCommitInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"`
StateSectorGetInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"`
StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) `perm:"read"`
StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"`
StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"`
StateReadState func(context.Context, *types.Actor, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
StateReadState func(context.Context, address.Address, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
StatePledgeCollateral func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"`
StateWaitMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"`
StateWaitMsg func(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) `perm:"read"`
StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"`
StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
@@ -146,10 +158,13 @@ type FullNodeStruct struct {
StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"`
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
MsigCreate func(context.Context, int64, []address.Address, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
MsigCreate func(context.Context, int64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
MsigPropose func(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
MsigApprove func(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
MsigCancel func(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
MsigCancel func(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
MsigSwapPropose func(context.Context, address.Address, address.Address, address.Address, address.Address) (cid.Cid, error) `perm:"sign"`
MsigSwapApprove func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, address.Address) (cid.Cid, error) `perm:"sign"`
MsigSwapCancel func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error) `perm:"sign"`
MarketEnsureAvailable func(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
@@ -182,10 +197,11 @@ type StorageMinerStruct struct {
MiningBase func(context.Context) (*types.TipSet, error) `perm:"read"`
MarketImportDealData func(context.Context, cid.Cid, string) error `perm:"write"`
MarketListDeals func(ctx context.Context) ([]storagemarket.StorageDeal, error) `perm:"read"`
MarketListIncompleteDeals func(ctx context.Context) ([]storagemarket.MinerDeal, error) `perm:"read"`
MarketSetPrice func(context.Context, types.BigInt) error `perm:"admin"`
MarketImportDealData func(context.Context, cid.Cid, string) error `perm:"write"`
MarketListDeals func(ctx context.Context) ([]storagemarket.StorageDeal, error) `perm:"read"`
MarketListIncompleteDeals func(ctx context.Context) ([]storagemarket.MinerDeal, error) `perm:"read"`
MarketSetAsk func(ctx context.Context, price types.BigInt, duration abi.ChainEpoch, minPieceSize abi.PaddedPieceSize, maxPieceSize abi.PaddedPieceSize) error `perm:"admin"`
MarketGetAsk func(ctx context.Context) (*storagemarket.SignedStorageAsk, error) `perm:"read"`
PledgeSector func(context.Context) error `perm:"write"`
@@ -193,23 +209,36 @@ type StorageMinerStruct struct {
SectorsList func(context.Context) ([]abi.SectorNumber, error) `perm:"read"`
SectorsRefs func(context.Context) (map[string][]api.SealedRef, error) `perm:"read"`
SectorsUpdate func(context.Context, abi.SectorNumber, api.SectorState) error `perm:"write"`
SectorRemove func(context.Context, abi.SectorNumber) error `perm:"admin"`
WorkerConnect func(context.Context, string) error `perm:"admin"` // TODO: worker perm
WorkerStats func(context.Context) (map[uint64]storiface.WorkerStats, error) `perm:"admin"`
StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"`
StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"`
StorageStat func(context.Context, stores.ID) (stores.FsStat, error) `perm:"admin"`
StorageAttach func(context.Context, stores.StorageInfo, stores.FsStat) error `perm:"admin"`
StorageDeclareSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType) error `perm:"admin"`
StorageDropSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType) error `perm:"admin"`
StorageFindSector func(context.Context, abi.SectorID, stores.SectorFileType, bool) ([]stores.StorageInfo, error) `perm:"admin"`
StorageInfo func(context.Context, stores.ID) (stores.StorageInfo, error) `perm:"admin"`
StorageBestAlloc func(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredProof, sealing bool) ([]stores.StorageInfo, error) `perm:"admin"`
StorageReportHealth func(ctx context.Context, id stores.ID, report stores.HealthReport) error `perm:"admin"`
StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"`
StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"`
StorageStat func(context.Context, stores.ID) (stores.FsStat, error) `perm:"admin"`
StorageAttach func(context.Context, stores.StorageInfo, stores.FsStat) error `perm:"admin"`
StorageDeclareSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType, bool) error `perm:"admin"`
StorageDropSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType) error `perm:"admin"`
StorageFindSector func(context.Context, abi.SectorID, stores.SectorFileType, bool) ([]stores.SectorStorageInfo, error) `perm:"admin"`
StorageInfo func(context.Context, stores.ID) (stores.StorageInfo, error) `perm:"admin"`
StorageBestAlloc func(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredSealProof, sealing stores.PathType) ([]stores.StorageInfo, error) `perm:"admin"`
StorageReportHealth func(ctx context.Context, id stores.ID, report stores.HealthReport) error `perm:"admin"`
StorageLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) error `perm:"admin"`
StorageTryLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) (bool, error) `perm:"admin"`
DealsImportData func(ctx context.Context, dealPropCid cid.Cid, file string) error `perm:"write"`
DealsList func(ctx context.Context) ([]storagemarket.StorageDeal, error) `perm:"read"`
DealsImportData func(ctx context.Context, dealPropCid cid.Cid, file string) error `perm:"write"`
DealsList func(ctx context.Context) ([]storagemarket.StorageDeal, error) `perm:"read"`
DealsConsiderOnlineStorageDeals func(context.Context) (bool, error) `perm:"read"`
DealsSetConsiderOnlineStorageDeals func(context.Context, bool) error `perm:"admin"`
DealsConsiderOnlineRetrievalDeals func(context.Context) (bool, error) `perm:"read"`
DealsSetConsiderOnlineRetrievalDeals func(context.Context, bool) error `perm:"admin"`
DealsConsiderOfflineStorageDeals func(context.Context) (bool, error) `perm:"read"`
DealsSetConsiderOfflineStorageDeals func(context.Context, bool) error `perm:"admin"`
DealsConsiderOfflineRetrievalDeals func(context.Context) (bool, error) `perm:"read"`
DealsSetConsiderOfflineRetrievalDeals func(context.Context, bool) error `perm:"admin"`
DealsPieceCidBlocklist func(context.Context) ([]cid.Cid, error) `perm:"read"`
DealsSetPieceCidBlocklist func(context.Context, []cid.Cid) error `perm:"admin"`
StorageAddLocal func(ctx context.Context, path string) error `perm:"admin"`
}
@@ -225,13 +254,19 @@ type WorkerStruct struct {
Paths func(context.Context) ([]stores.StoragePath, error) `perm:"admin"`
Info func(context.Context) (storiface.WorkerInfo, error) `perm:"admin"`
SealPreCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) `perm:"admin"`
SealPreCommit2 func(context.Context, abi.SectorID, storage.PreCommit1Out) (cids storage.SectorCids, err error) `perm:"admin"`
SealCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storage.Commit1Out, error) `perm:"admin"`
SealCommit2 func(context.Context, abi.SectorID, storage.Commit1Out) (storage.Proof, error) `perm:"admin"`
FinalizeSector func(context.Context, abi.SectorID) error `perm:"admin"`
SealPreCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) `perm:"admin"`
SealPreCommit2 func(context.Context, abi.SectorID, storage.PreCommit1Out) (cids storage.SectorCids, err error) `perm:"admin"`
SealCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storage.Commit1Out, error) `perm:"admin"`
SealCommit2 func(context.Context, abi.SectorID, storage.Commit1Out) (storage.Proof, error) `perm:"admin"`
FinalizeSector func(context.Context, abi.SectorID, []storage.Range) error `perm:"admin"`
ReleaseUnsealed func(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) error `perm:"admin"`
Remove func(ctx context.Context, sector abi.SectorID) error `perm:"admin"`
MoveStorage func(ctx context.Context, sector abi.SectorID) error `perm:"admin"`
Fetch func(context.Context, abi.SectorID, stores.SectorFileType, bool) error `perm:"admin"`
UnsealPiece func(context.Context, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) error `perm:"admin"`
ReadPiece func(context.Context, io.Writer, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) error `perm:"admin"`
Fetch func(context.Context, abi.SectorID, stores.SectorFileType, stores.PathType, stores.AcquireMode) error `perm:"admin"`
Closing func(context.Context) (<-chan struct{}, error) `perm:"admin"`
}
@@ -239,14 +274,17 @@ type WorkerStruct struct {
// CommonStruct
func (c *CommonStruct) AuthVerify(ctx context.Context, token string) ([]api.Permission, error) {
func (c *CommonStruct) AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) {
return c.Internal.AuthVerify(ctx, token)
}
func (c *CommonStruct) AuthNew(ctx context.Context, perms []api.Permission) ([]byte, error) {
func (c *CommonStruct) AuthNew(ctx context.Context, perms []auth.Permission) ([]byte, error) {
return c.Internal.AuthNew(ctx, perms)
}
func (c *CommonStruct) NetPubsubScores(ctx context.Context) ([]api.PubsubScore, error) {
return c.Internal.NetPubsubScores(ctx)
}
func (c *CommonStruct) NetConnectedness(ctx context.Context, pid peer.ID) (network.Connectedness, error) {
return c.Internal.NetConnectedness(ctx, pid)
}
@@ -289,6 +327,14 @@ func (c *CommonStruct) LogSetLevel(ctx context.Context, group, level string) err
return c.Internal.LogSetLevel(ctx, group, level)
}
func (c *CommonStruct) Shutdown(ctx context.Context) error {
return c.Internal.Shutdown(ctx)
}
func (c *CommonStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
return c.Internal.Closing(ctx)
}
// FullNodeStruct
func (c *FullNodeStruct) ClientListImports(ctx context.Context) ([]api.Import, error) {
@@ -307,6 +353,10 @@ func (c *FullNodeStruct) ClientFindData(ctx context.Context, root cid.Cid) ([]ap
return c.Internal.ClientFindData(ctx, root)
}
func (c *FullNodeStruct) ClientMinerQueryOffer(ctx context.Context, root cid.Cid, miner address.Address) (api.QueryOffer, error) {
return c.Internal.ClientMinerQueryOffer(ctx, root, miner)
}
func (c *FullNodeStruct) ClientStartDeal(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) {
return c.Internal.ClientStartDeal(ctx, params)
}
@@ -318,7 +368,7 @@ func (c *FullNodeStruct) ClientListDeals(ctx context.Context) ([]api.DealInfo, e
return c.Internal.ClientListDeals(ctx)
}
func (c *FullNodeStruct) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref api.FileRef) error {
func (c *FullNodeStruct) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error {
return c.Internal.ClientRetrieve(ctx, order, ref)
}
@@ -417,6 +467,10 @@ func (c *FullNodeStruct) WalletImport(ctx context.Context, ki *types.KeyInfo) (a
return c.Internal.WalletImport(ctx, ki)
}
func (c *FullNodeStruct) WalletDelete(ctx context.Context, addr address.Address) error {
return c.Internal.WalletDelete(ctx, addr)
}
func (c *FullNodeStruct) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) {
return c.Internal.MpoolGetNonce(ctx, addr)
}
@@ -525,7 +579,7 @@ func (c *FullNodeStruct) StateMinerPower(ctx context.Context, a address.Address,
return c.Internal.StateMinerPower(ctx, a, tsk)
}
func (c *FullNodeStruct) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) {
func (c *FullNodeStruct) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (api.MinerInfo, error) {
return c.Internal.StateMinerInfo(ctx, actor, tsk)
}
@@ -533,10 +587,18 @@ func (c *FullNodeStruct) StateMinerDeadlines(ctx context.Context, m address.Addr
return c.Internal.StateMinerDeadlines(ctx, m, tsk)
}
func (c *FullNodeStruct) StateMinerFaults(ctx context.Context, actor address.Address, tsk types.TipSetKey) ([]abi.SectorNumber, error) {
func (c *FullNodeStruct) StateMinerFaults(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*abi.BitField, error) {
return c.Internal.StateMinerFaults(ctx, actor, tsk)
}
func (c *FullNodeStruct) StateAllMinerFaults(ctx context.Context, cutoff abi.ChainEpoch, endTsk types.TipSetKey) ([]*api.Fault, error) {
return c.Internal.StateAllMinerFaults(ctx, cutoff, endTsk)
}
func (c *FullNodeStruct) StateMinerRecoveries(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*abi.BitField, error) {
return c.Internal.StateMinerRecoveries(ctx, actor, tsk)
}
func (c *FullNodeStruct) StateMinerInitialPledgeCollateral(ctx context.Context, maddr address.Address, snum abi.SectorNumber, tsk types.TipSetKey) (types.BigInt, error) {
return c.Internal.StateMinerInitialPledgeCollateral(ctx, maddr, snum, tsk)
}
@@ -549,6 +611,10 @@ func (c *FullNodeStruct) StateSectorPreCommitInfo(ctx context.Context, maddr add
return c.Internal.StateSectorPreCommitInfo(ctx, maddr, n, tsk)
}
func (c *FullNodeStruct) StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) {
return c.Internal.StateSectorGetInfo(ctx, maddr, n, tsk)
}
func (c *FullNodeStruct) StateCall(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (*api.InvocResult, error) {
return c.Internal.StateCall(ctx, msg, tsk)
}
@@ -561,16 +627,16 @@ func (c *FullNodeStruct) StateGetActor(ctx context.Context, actor address.Addres
return c.Internal.StateGetActor(ctx, actor, tsk)
}
func (c *FullNodeStruct) StateReadState(ctx context.Context, act *types.Actor, tsk types.TipSetKey) (*api.ActorState, error) {
return c.Internal.StateReadState(ctx, act, tsk)
func (c *FullNodeStruct) StateReadState(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*api.ActorState, error) {
return c.Internal.StateReadState(ctx, addr, tsk)
}
func (c *FullNodeStruct) StatePledgeCollateral(ctx context.Context, tsk types.TipSetKey) (types.BigInt, error) {
return c.Internal.StatePledgeCollateral(ctx, tsk)
}
func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid) (*api.MsgLookup, error) {
return c.Internal.StateWaitMsg(ctx, msgc)
func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid, confidence uint64) (*api.MsgLookup, error) {
return c.Internal.StateWaitMsg(ctx, msgc, confidence)
}
func (c *FullNodeStruct) StateSearchMsg(ctx context.Context, msgc cid.Cid) (*api.MsgLookup, error) {
@@ -629,8 +695,8 @@ func (c *FullNodeStruct) MsigGetAvailableBalance(ctx context.Context, a address.
return c.Internal.MsigGetAvailableBalance(ctx, a, tsk)
}
func (c *FullNodeStruct) MsigCreate(ctx context.Context, req int64, addrs []address.Address, val types.BigInt, src address.Address, gp types.BigInt) (cid.Cid, error) {
return c.Internal.MsigCreate(ctx, req, addrs, val, src, gp)
func (c *FullNodeStruct) MsigCreate(ctx context.Context, req int64, addrs []address.Address, duration abi.ChainEpoch, val types.BigInt, src address.Address, gp types.BigInt) (cid.Cid, error) {
return c.Internal.MsigCreate(ctx, req, addrs, duration, val, src, gp)
}
func (c *FullNodeStruct) MsigPropose(ctx context.Context, msig address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
@@ -641,8 +707,20 @@ func (c *FullNodeStruct) MsigApprove(ctx context.Context, msig address.Address,
return c.Internal.MsigApprove(ctx, msig, txID, proposer, to, amt, src, method, params)
}
func (c *FullNodeStruct) MsigCancel(ctx context.Context, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
return c.Internal.MsigCancel(ctx, msig, txID, proposer, to, amt, src, method, params)
func (c *FullNodeStruct) MsigCancel(ctx context.Context, msig address.Address, txID uint64, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
return c.Internal.MsigCancel(ctx, msig, txID, to, amt, src, method, params)
}
func (c *FullNodeStruct) MsigSwapPropose(ctx context.Context, msig address.Address, src address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
return c.Internal.MsigSwapPropose(ctx, msig, src, oldAdd, newAdd)
}
func (c *FullNodeStruct) MsigSwapApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
return c.Internal.MsigSwapApprove(ctx, msig, src, txID, proposer, oldAdd, newAdd)
}
func (c *FullNodeStruct) MsigSwapCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
return c.Internal.MsigSwapCancel(ctx, msig, src, txID, oldAdd, newAdd)
}
func (c *FullNodeStruct) MarketEnsureAvailable(ctx context.Context, addr, wallet address.Address, amt types.BigInt) (cid.Cid, error) {
@@ -733,6 +811,10 @@ func (c *StorageMinerStruct) SectorsUpdate(ctx context.Context, id abi.SectorNum
return c.Internal.SectorsUpdate(ctx, id, state)
}
func (c *StorageMinerStruct) SectorRemove(ctx context.Context, number abi.SectorNumber) error {
return c.Internal.SectorRemove(ctx, number)
}
func (c *StorageMinerStruct) WorkerConnect(ctx context.Context, url string) error {
return c.Internal.WorkerConnect(ctx, url)
}
@@ -745,15 +827,15 @@ func (c *StorageMinerStruct) StorageAttach(ctx context.Context, si stores.Storag
return c.Internal.StorageAttach(ctx, si, st)
}
func (c *StorageMinerStruct) StorageDeclareSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft stores.SectorFileType) error {
return c.Internal.StorageDeclareSector(ctx, storageId, s, ft)
func (c *StorageMinerStruct) StorageDeclareSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft stores.SectorFileType, primary bool) error {
return c.Internal.StorageDeclareSector(ctx, storageId, s, ft, primary)
}
func (c *StorageMinerStruct) StorageDropSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft stores.SectorFileType) error {
return c.Internal.StorageDropSector(ctx, storageId, s, ft)
}
func (c *StorageMinerStruct) StorageFindSector(ctx context.Context, si abi.SectorID, types stores.SectorFileType, allowFetch bool) ([]stores.StorageInfo, error) {
func (c *StorageMinerStruct) StorageFindSector(ctx context.Context, si abi.SectorID, types stores.SectorFileType, allowFetch bool) ([]stores.SectorStorageInfo, error) {
return c.Internal.StorageFindSector(ctx, si, types, allowFetch)
}
@@ -773,14 +855,22 @@ func (c *StorageMinerStruct) StorageInfo(ctx context.Context, id stores.ID) (sto
return c.Internal.StorageInfo(ctx, id)
}
func (c *StorageMinerStruct) StorageBestAlloc(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredProof, sealing bool) ([]stores.StorageInfo, error) {
return c.Internal.StorageBestAlloc(ctx, allocate, spt, sealing)
func (c *StorageMinerStruct) StorageBestAlloc(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredSealProof, pt stores.PathType) ([]stores.StorageInfo, error) {
return c.Internal.StorageBestAlloc(ctx, allocate, spt, pt)
}
func (c *StorageMinerStruct) StorageReportHealth(ctx context.Context, id stores.ID, report stores.HealthReport) error {
return c.Internal.StorageReportHealth(ctx, id, report)
}
func (c *StorageMinerStruct) StorageLock(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) error {
return c.Internal.StorageLock(ctx, sector, read, write)
}
func (c *StorageMinerStruct) StorageTryLock(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) (bool, error) {
return c.Internal.StorageTryLock(ctx, sector, read, write)
}
func (c *StorageMinerStruct) MarketImportDealData(ctx context.Context, propcid cid.Cid, path string) error {
return c.Internal.MarketImportDealData(ctx, propcid, path)
}
@@ -793,8 +883,12 @@ func (c *StorageMinerStruct) MarketListIncompleteDeals(ctx context.Context) ([]s
return c.Internal.MarketListIncompleteDeals(ctx)
}
func (c *StorageMinerStruct) MarketSetPrice(ctx context.Context, p types.BigInt) error {
return c.Internal.MarketSetPrice(ctx, p)
func (c *StorageMinerStruct) MarketSetAsk(ctx context.Context, price types.BigInt, duration abi.ChainEpoch, minPieceSize abi.PaddedPieceSize, maxPieceSize abi.PaddedPieceSize) error {
return c.Internal.MarketSetAsk(ctx, price, duration, minPieceSize, maxPieceSize)
}
func (c *StorageMinerStruct) MarketGetAsk(ctx context.Context) (*storagemarket.SignedStorageAsk, error) {
return c.Internal.MarketGetAsk(ctx)
}
func (c *StorageMinerStruct) DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error {
@@ -805,6 +899,46 @@ func (c *StorageMinerStruct) DealsList(ctx context.Context) ([]storagemarket.Sto
return c.Internal.DealsList(ctx)
}
func (c *StorageMinerStruct) DealsConsiderOnlineStorageDeals(ctx context.Context) (bool, error) {
return c.Internal.DealsConsiderOnlineStorageDeals(ctx)
}
func (c *StorageMinerStruct) DealsSetConsiderOnlineStorageDeals(ctx context.Context, b bool) error {
return c.Internal.DealsSetConsiderOnlineStorageDeals(ctx, b)
}
func (c *StorageMinerStruct) DealsConsiderOnlineRetrievalDeals(ctx context.Context) (bool, error) {
return c.Internal.DealsConsiderOnlineRetrievalDeals(ctx)
}
func (c *StorageMinerStruct) DealsSetConsiderOnlineRetrievalDeals(ctx context.Context, b bool) error {
return c.Internal.DealsSetConsiderOnlineRetrievalDeals(ctx, b)
}
func (c *StorageMinerStruct) DealsPieceCidBlocklist(ctx context.Context) ([]cid.Cid, error) {
return c.Internal.DealsPieceCidBlocklist(ctx)
}
func (c *StorageMinerStruct) DealsSetPieceCidBlocklist(ctx context.Context, cids []cid.Cid) error {
return c.Internal.DealsSetPieceCidBlocklist(ctx, cids)
}
func (c *StorageMinerStruct) DealsConsiderOfflineStorageDeals(ctx context.Context) (bool, error) {
return c.Internal.DealsConsiderOfflineStorageDeals(ctx)
}
func (c *StorageMinerStruct) DealsSetConsiderOfflineStorageDeals(ctx context.Context, b bool) error {
return c.Internal.DealsSetConsiderOfflineStorageDeals(ctx, b)
}
func (c *StorageMinerStruct) DealsConsiderOfflineRetrievalDeals(ctx context.Context) (bool, error) {
return c.Internal.DealsConsiderOfflineRetrievalDeals(ctx)
}
func (c *StorageMinerStruct) DealsSetConsiderOfflineRetrievalDeals(ctx context.Context, b bool) error {
return c.Internal.DealsSetConsiderOfflineRetrievalDeals(ctx, b)
}
func (c *StorageMinerStruct) StorageAddLocal(ctx context.Context, path string) error {
return c.Internal.StorageAddLocal(ctx, path)
}
@@ -843,12 +977,32 @@ func (w *WorkerStruct) SealCommit2(ctx context.Context, sector abi.SectorID, c1o
return w.Internal.SealCommit2(ctx, sector, c1o)
}
func (w *WorkerStruct) FinalizeSector(ctx context.Context, sector abi.SectorID) error {
return w.Internal.FinalizeSector(ctx, sector)
func (w *WorkerStruct) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) error {
return w.Internal.FinalizeSector(ctx, sector, keepUnsealed)
}
func (w *WorkerStruct) Fetch(ctx context.Context, id abi.SectorID, fileType stores.SectorFileType, b bool) error {
return w.Internal.Fetch(ctx, id, fileType, b)
func (w *WorkerStruct) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) error {
return w.Internal.ReleaseUnsealed(ctx, sector, safeToFree)
}
func (w *WorkerStruct) Remove(ctx context.Context, sector abi.SectorID) error {
return w.Internal.Remove(ctx, sector)
}
func (w *WorkerStruct) MoveStorage(ctx context.Context, sector abi.SectorID) error {
return w.Internal.MoveStorage(ctx, sector)
}
func (w *WorkerStruct) UnsealPiece(ctx context.Context, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, c cid.Cid) error {
return w.Internal.UnsealPiece(ctx, id, index, size, randomness, c)
}
func (w *WorkerStruct) ReadPiece(ctx context.Context, writer io.Writer, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) error {
return w.Internal.ReadPiece(ctx, writer, id, index, size)
}
func (w *WorkerStruct) Fetch(ctx context.Context, id abi.SectorID, fileType stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) error {
return w.Internal.Fetch(ctx, id, fileType, ptype, am)
}
func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
@@ -858,4 +1012,4 @@ func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
var _ api.Common = &CommonStruct{}
var _ api.FullNode = &FullNodeStruct{}
var _ api.StorageMiner = &StorageMinerStruct{}
var _ api.WorkerApi = &WorkerStruct{}
var _ api.WorkerAPI = &WorkerStruct{}
+4 -3
View File
@@ -1,11 +1,12 @@
package client
import (
"github.com/filecoin-project/lotus/api/apistruct"
"net/http"
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/lib/jsonrpc"
"github.com/filecoin-project/lotus/api/apistruct"
)
// NewCommonRPC creates a new http jsonrpc client.
@@ -47,7 +48,7 @@ func NewStorageMinerRPC(addr string, requestHeader http.Header) (api.StorageMine
return &res, closer, err
}
func NewWorkerRPC(addr string, requestHeader http.Header) (api.WorkerApi, jsonrpc.ClientCloser, error) {
func NewWorkerRPC(addr string, requestHeader http.Header) (api.WorkerAPI, jsonrpc.ClientCloser, error) {
var res apistruct.WorkerStruct
closer, err := jsonrpc.NewMergeClient(addr, "Filecoin",
[]interface{}{
+379
View File
@@ -0,0 +1,379 @@
package main
import (
"encoding/json"
"fmt"
"go/ast"
"go/parser"
"go/token"
"reflect"
"sort"
"strings"
"time"
"unicode"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-filestore"
"github.com/libp2p/go-libp2p-core/network"
peer "github.com/libp2p/go-libp2p-peer"
"github.com/multiformats/go-multiaddr"
)
var ExampleValues = map[reflect.Type]interface{}{
reflect.TypeOf(auth.Permission("")): auth.Permission("write"),
reflect.TypeOf(""): "string value",
reflect.TypeOf(uint64(42)): uint64(42),
reflect.TypeOf(byte(7)): byte(7),
reflect.TypeOf([]byte{}): []byte("byte array"),
}
func addExample(v interface{}) {
ExampleValues[reflect.TypeOf(v)] = v
}
func init() {
c, err := cid.Decode("bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4")
if err != nil {
panic(err)
}
ExampleValues[reflect.TypeOf(c)] = c
c2, err := cid.Decode("bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve")
if err != nil {
panic(err)
}
tsk := types.NewTipSetKey(c, c2)
ExampleValues[reflect.TypeOf(tsk)] = tsk
addr, err := address.NewIDAddress(1234)
if err != nil {
panic(err)
}
ExampleValues[reflect.TypeOf(addr)] = addr
pid, err := peer.IDB58Decode("12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf")
if err != nil {
panic(err)
}
addExample(pid)
addExample(bitfield.NewFromSet([]uint64{5}))
addExample(abi.RegisteredSealProof_StackedDrg32GiBV1)
addExample(abi.RegisteredPoStProof_StackedDrgWindow32GiBV1)
addExample(abi.ChainEpoch(10101))
addExample(crypto.SigTypeBLS)
addExample(int64(9))
addExample(12.3)
addExample(123)
addExample(uintptr(0))
addExample(abi.MethodNum(1))
addExample(exitcode.ExitCode(0))
addExample(crypto.DomainSeparationTag_ElectionProofProduction)
addExample(true)
addExample(abi.UnpaddedPieceSize(1024))
addExample(abi.UnpaddedPieceSize(1024).Padded())
addExample(abi.DealID(5432))
addExample(filestore.StatusFileChanged)
addExample(abi.SectorNumber(9))
addExample(abi.SectorSize(32 * 1024 * 1024 * 1024))
addExample(api.MpoolChange(0))
addExample(network.Connected)
addExample(dtypes.NetworkName("lotus"))
addExample(api.SyncStateStage(1))
addExample(build.APIVersion)
addExample(api.PCHInbound)
addExample(time.Minute)
addExample(&types.ExecutionTrace{
Msg: exampleValue(reflect.TypeOf(&types.Message{}), nil).(*types.Message),
MsgRct: exampleValue(reflect.TypeOf(&types.MessageReceipt{}), nil).(*types.MessageReceipt),
})
addExample(map[string]types.Actor{
"t01236": exampleValue(reflect.TypeOf(types.Actor{}), nil).(types.Actor),
})
addExample(map[string]api.MarketDeal{
"t026363": exampleValue(reflect.TypeOf(api.MarketDeal{}), nil).(api.MarketDeal),
})
addExample(map[string]api.MarketBalance{
"t026363": exampleValue(reflect.TypeOf(api.MarketBalance{}), nil).(api.MarketBalance),
})
maddr, err := multiaddr.NewMultiaddr("/ip4/52.36.61.156/tcp/1347/p2p/12D3KooWFETiESTf1v4PGUvtnxMAcEFMzLZbJGg4tjWfGEimYior")
if err != nil {
panic(err)
}
// because reflect.TypeOf(maddr) returns the concrete type...
ExampleValues[reflect.TypeOf(struct{ A multiaddr.Multiaddr }{}).Field(0).Type] = maddr
}
func exampleValue(t, parent reflect.Type) interface{} {
v, ok := ExampleValues[t]
if ok {
return v
}
switch t.Kind() {
case reflect.Slice:
out := reflect.New(t).Elem()
reflect.Append(out, reflect.ValueOf(exampleValue(t.Elem(), t)))
return out.Interface()
case reflect.Chan:
return exampleValue(t.Elem(), nil)
case reflect.Struct:
es := exampleStruct(t, parent)
v := reflect.ValueOf(es).Elem().Interface()
ExampleValues[t] = v
return v
case reflect.Array:
out := reflect.New(t).Elem()
for i := 0; i < t.Len(); i++ {
out.Index(i).Set(reflect.ValueOf(exampleValue(t.Elem(), t)))
}
return out.Interface()
case reflect.Ptr:
if t.Elem().Kind() == reflect.Struct {
es := exampleStruct(t.Elem(), t)
//ExampleValues[t] = es
return es
}
case reflect.Interface:
return struct{}{}
}
panic(fmt.Sprintf("No example value for type: %s", t))
}
func exampleStruct(t, parent reflect.Type) interface{} {
ns := reflect.New(t)
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if f.Type == parent {
continue
}
if strings.Title(f.Name) == f.Name {
ns.Elem().Field(i).Set(reflect.ValueOf(exampleValue(f.Type, t)))
}
}
return ns.Interface()
}
type Visitor struct {
Methods map[string]ast.Node
}
func (v *Visitor) Visit(node ast.Node) ast.Visitor {
st, ok := node.(*ast.TypeSpec)
if !ok {
return v
}
if st.Name.Name != "FullNode" {
return nil
}
iface := st.Type.(*ast.InterfaceType)
for _, m := range iface.Methods.List {
if len(m.Names) > 0 {
v.Methods[m.Names[0].Name] = m
}
}
return v
}
const noComment = "There are not yet any comments for this method."
func parseApiASTInfo() (map[string]string, map[string]string) { //nolint:golint
fset := token.NewFileSet()
pkgs, err := parser.ParseDir(fset, "./api", nil, parser.AllErrors|parser.ParseComments)
if err != nil {
fmt.Println("parse error: ", err)
}
ap := pkgs["api"]
f := ap.Files["api/api_full.go"]
cmap := ast.NewCommentMap(fset, f, f.Comments)
v := &Visitor{make(map[string]ast.Node)}
ast.Walk(v, pkgs["api"])
groupDocs := make(map[string]string)
out := make(map[string]string)
for mn, node := range v.Methods {
cs := cmap.Filter(node).Comments()
if len(cs) == 0 {
out[mn] = noComment
} else {
for _, c := range cs {
if strings.HasPrefix(c.Text(), "MethodGroup:") {
parts := strings.Split(c.Text(), "\n")
groupName := strings.TrimSpace(parts[0][12:])
comment := strings.Join(parts[1:], "\n")
groupDocs[groupName] = comment
break
}
}
last := cs[len(cs)-1].Text()
if !strings.HasPrefix(last, "MethodGroup:") {
out[mn] = last
} else {
out[mn] = noComment
}
}
}
return out, groupDocs
}
type MethodGroup struct {
GroupName string
Header string
Methods []*Method
}
type Method struct {
Comment string
Name string
InputExample string
ResponseExample string
}
func methodGroupFromName(mn string) string {
i := strings.IndexFunc(mn[1:], func(r rune) bool {
return unicode.IsUpper(r)
})
if i < 0 {
return ""
}
return mn[:i+1]
}
func main() {
comments, groupComments := parseApiASTInfo()
groups := make(map[string]*MethodGroup)
var api struct{ api.FullNode }
t := reflect.TypeOf(api)
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
groupName := methodGroupFromName(m.Name)
g, ok := groups[groupName]
if !ok {
g = new(MethodGroup)
g.Header = groupComments[groupName]
g.GroupName = groupName
groups[groupName] = g
}
var args []interface{}
ft := m.Func.Type()
for j := 2; j < ft.NumIn(); j++ {
inp := ft.In(j)
args = append(args, exampleValue(inp, nil))
}
v, err := json.MarshalIndent(args, "", " ")
if err != nil {
panic(err)
}
outv := exampleValue(ft.Out(0), nil)
ov, err := json.MarshalIndent(outv, "", " ")
if err != nil {
panic(err)
}
g.Methods = append(g.Methods, &Method{
Name: m.Name,
Comment: comments[m.Name],
InputExample: string(v),
ResponseExample: string(ov),
})
}
var groupslice []*MethodGroup
for _, g := range groups {
groupslice = append(groupslice, g)
}
sort.Slice(groupslice, func(i, j int) bool {
return groupslice[i].GroupName < groupslice[j].GroupName
})
fmt.Printf("# Groups\n")
for _, g := range groupslice {
fmt.Printf("* [%s](#%s)\n", g.GroupName, g.GroupName)
for _, method := range g.Methods {
fmt.Printf(" * [%s](#%s)\n", method.Name, method.Name)
}
}
permStruct := reflect.TypeOf(apistruct.FullNodeStruct{}.Internal)
commonPermStruct := reflect.TypeOf(apistruct.CommonStruct{}.Internal)
for _, g := range groupslice {
g := g
fmt.Printf("## %s\n", g.GroupName)
fmt.Printf("%s\n\n", g.Header)
sort.Slice(g.Methods, func(i, j int) bool {
return g.Methods[i].Name < g.Methods[j].Name
})
for _, m := range g.Methods {
fmt.Printf("### %s\n", m.Name)
fmt.Printf("%s\n\n", m.Comment)
meth, ok := permStruct.FieldByName(m.Name)
if !ok {
meth, ok = commonPermStruct.FieldByName(m.Name)
if !ok {
panic("no perms for method: " + m.Name)
}
}
perms := meth.Tag.Get("perm")
fmt.Printf("Perms: %s\n\n", perms)
if strings.Count(m.InputExample, "\n") > 0 {
fmt.Printf("Inputs:\n```json\n%s\n```\n\n", m.InputExample)
} else {
fmt.Printf("Inputs: `%s`\n\n", m.InputExample)
}
if strings.Count(m.ResponseExample, "\n") > 0 {
fmt.Printf("Response:\n```json\n%s\n```\n\n", m.ResponseExample)
} else {
fmt.Printf("Response: `%s`\n\n", m.ResponseExample)
}
}
}
}
+13 -12
View File
@@ -8,6 +8,7 @@ import (
"math/rand"
"os"
"path/filepath"
"sync/atomic"
"testing"
"time"
@@ -35,7 +36,7 @@ func init() {
}
func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport bool) {
os.Setenv("BELLMAN_NO_GPU", "1")
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, oneMiner)
@@ -52,13 +53,13 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport
}
time.Sleep(time.Second)
mine := true
mine := int64(1)
done := make(chan struct{})
go func() {
defer close(done)
for mine {
for atomic.LoadInt64(&mine) == 1 {
time.Sleep(blocktime)
if err := sn[0].MineOne(ctx, func(bool) {}); err != nil {
if err := sn[0].MineOne(ctx, func(bool, error) {}); err != nil {
t.Error(err)
}
}
@@ -66,13 +67,13 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport
makeDeal(t, ctx, 6, client, miner, carExport)
mine = false
atomic.AddInt64(&mine, -1)
fmt.Println("shutting down mining")
<-done
}
func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
os.Setenv("BELLMAN_NO_GPU", "1")
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, oneMiner)
@@ -89,14 +90,14 @@ func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
}
time.Sleep(time.Second)
mine := true
mine := int64(1)
done := make(chan struct{})
go func() {
defer close(done)
for mine {
for atomic.LoadInt64(&mine) == 1 {
time.Sleep(blocktime)
if err := sn[0].MineOne(ctx, func(bool) {}); err != nil {
if err := sn[0].MineOne(ctx, func(bool, error) {}); err != nil {
t.Error(err)
}
}
@@ -105,7 +106,7 @@ func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
makeDeal(t, ctx, 6, client, miner, false)
makeDeal(t, ctx, 7, client, miner, false)
mine = false
atomic.AddInt64(&mine, -1)
fmt.Println("shutting down mining")
<-done
}
@@ -193,14 +194,14 @@ func testRetrieval(t *testing.T, ctx context.Context, err error, client *impl.Fu
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(rpath)
defer os.RemoveAll(rpath) //nolint:errcheck
caddr, err := client.WalletDefaultAddress(ctx)
if err != nil {
t.Fatal(err)
}
ref := api.FileRef{
ref := &api.FileRef{
Path: filepath.Join(rpath, "ret"),
IsCAR: carExport,
}
+8 -7
View File
@@ -34,7 +34,7 @@ func (ts *testSuite) testMining(t *testing.T) {
require.NoError(t, err)
<-newHeads
err = sn[0].MineOne(ctx, func(bool) {})
err = sn[0].MineOne(ctx, func(bool, error) {})
require.NoError(t, err)
<-newHeads
@@ -62,7 +62,7 @@ func (ts *testSuite) testMiningReal(t *testing.T) {
require.NoError(t, err)
<-newHeads
err = sn[0].MineOne(ctx, func(bool) {})
err = sn[0].MineOne(ctx, func(bool, error) {})
require.NoError(t, err)
<-newHeads
@@ -71,7 +71,7 @@ func (ts *testSuite) testMiningReal(t *testing.T) {
require.NoError(t, err)
require.Equal(t, abi.ChainEpoch(1), h2.Height())
err = sn[0].MineOne(ctx, func(bool) {})
err = sn[0].MineOne(ctx, func(bool, error) {})
require.NoError(t, err)
<-newHeads
@@ -82,7 +82,7 @@ func (ts *testSuite) testMiningReal(t *testing.T) {
}
func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExport bool) {
os.Setenv("BELLMAN_NO_GPU", "1")
_ = os.Setenv("BELLMAN_NO_GPU", "1")
// test making a deal with a fresh miner, and see if it starts to mine
@@ -126,12 +126,13 @@ func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExpo
minedTwo := make(chan struct{})
go func() {
doneMinedTwo := false
defer close(done)
prevExpect := 0
for atomic.LoadInt32(&mine) != 0 {
wait := make(chan int, 2)
mdone := func(mined bool) {
mdone := func(mined bool, err error) {
go func() {
n := 0
if mined {
@@ -175,9 +176,9 @@ func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExpo
time.Sleep(blocktime)
}
if prevExpect == 2 && expect == 2 && minedTwo != nil {
if prevExpect == 2 && expect == 2 && !doneMinedTwo {
close(minedTwo)
minedTwo = nil
doneMinedTwo = true
}
prevExpect = expect
+7 -5
View File
@@ -4,9 +4,11 @@ import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/stretchr/testify/assert"
)
type TestNode struct {
@@ -16,11 +18,13 @@ type TestNode struct {
type TestStorageNode struct {
api.StorageMiner
MineOne func(context.Context, func(bool)) error
MineOne func(context.Context, func(bool, error)) error
}
var PresealGenesis = -1
const GenesisPreseals = 2
type StorageMiner struct {
Full int
Preseal int
@@ -60,9 +64,7 @@ func (ts *testSuite) testVersion(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if v.Version != build.BuildVersion {
t.Error("Version didn't work properly")
}
require.Equal(t, v.Version, build.BuildVersion)
}
func (ts *testSuite) testID(t *testing.T) {
+169
View File
@@ -0,0 +1,169 @@
package test
import (
"context"
"fmt"
"github.com/filecoin-project/lotus/api"
"os"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/specs-actors/actors/abi"
miner2 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
sealing "github.com/filecoin-project/storage-fsm"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/impl"
)
func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, oneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
addrinfo, err := client.NetAddrsListen(ctx)
if err != nil {
t.Fatal(err)
}
if err := miner.NetConnect(ctx, addrinfo); err != nil {
t.Fatal(err)
}
time.Sleep(time.Second)
mine := true
done := make(chan struct{})
go func() {
defer close(done)
for mine {
time.Sleep(blocktime)
if err := sn[0].MineOne(ctx, func(bool, error) {}); err != nil {
t.Error(err)
}
}
}()
pledgeSectors(t, ctx, miner, nSectors)
mine = false
<-done
}
func pledgeSectors(t *testing.T, ctx context.Context, miner TestStorageNode, n int) {
for i := 0; i < n; i++ {
err := miner.PledgeSector(ctx)
require.NoError(t, err)
}
for {
s, err := miner.SectorsList(ctx) // Note - the test builder doesn't import genesis sectors into FSM
require.NoError(t, err)
fmt.Printf("Sectors: %d\n", len(s))
if len(s) >= n {
break
}
time.Sleep(100 * time.Millisecond)
}
fmt.Printf("All sectors is fsm\n")
s, err := miner.SectorsList(ctx)
require.NoError(t, err)
toCheck := map[abi.SectorNumber]struct{}{}
for _, number := range s {
toCheck[number] = struct{}{}
}
for len(toCheck) > 0 {
for n := range toCheck {
st, err := miner.SectorsStatus(ctx, n)
require.NoError(t, err)
if st.State == api.SectorState(sealing.Proving) {
delete(toCheck, n)
}
if strings.Contains(string(st.State), "Fail") {
t.Fatal("sector in a failed state", st.State)
}
}
time.Sleep(100 * time.Millisecond)
fmt.Printf("WaitSeal: %d\n", len(s))
}
}
func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, oneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
addrinfo, err := client.NetAddrsListen(ctx)
if err != nil {
t.Fatal(err)
}
if err := miner.NetConnect(ctx, addrinfo); err != nil {
t.Fatal(err)
}
time.Sleep(time.Second)
mine := true
done := make(chan struct{})
go func() {
defer close(done)
for mine {
time.Sleep(blocktime)
if err := sn[0].MineOne(ctx, func(bool, error) {}); err != nil {
t.Error(err)
}
}
}()
pledgeSectors(t, ctx, miner, nSectors)
maddr, err := miner.ActorAddress(ctx)
require.NoError(t, err)
di, err := client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
fmt.Printf("Running one proving periods\n")
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
if head.Height() > di.PeriodStart+(miner2.WPoStProvingPeriod)+2 {
break
}
if head.Height()%100 == 0 {
fmt.Printf("@%d\n", head.Height())
}
time.Sleep(blocktime)
}
p, err := client.StateMinerPower(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
ssz, err := miner.ActorSectorSize(ctx, maddr)
require.NoError(t, err)
require.Equal(t, p.MinerPower, p.TotalPower)
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)*uint64(nSectors+GenesisPreseals)))
// TODO: Inject faults here
mine = false
<-done
}
+43
View File
@@ -2,11 +2,16 @@ package api
import (
"encoding/json"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/libp2p/go-libp2p-core/peer"
ma "github.com/multiformats/go-multiaddr"
)
// TODO: check if this exists anywhere else
type MultiaddrSlice []ma.Multiaddr
func (m *MultiaddrSlice) UnmarshalJSON(raw []byte) (err error) {
@@ -32,3 +37,41 @@ type ObjStat struct {
Size uint64
Links uint64
}
type PubsubScore struct {
ID peer.ID
Score float64
}
type MinerInfo struct {
Owner address.Address // Must be an ID-address.
Worker address.Address // Must be an ID-address.
NewWorker address.Address // Must be an ID-address.
WorkerChangeEpoch abi.ChainEpoch
PeerId peer.ID
Multiaddrs []abi.Multiaddrs
SealProofType abi.RegisteredSealProof
SectorSize abi.SectorSize
WindowPoStPartitionSectors uint64
}
func NewApiMinerInfo(info miner.MinerInfo) MinerInfo {
mi := MinerInfo{
Owner: info.Owner,
Worker: info.Worker,
NewWorker: address.Undef,
WorkerChangeEpoch: -1,
PeerId: peer.ID(info.PeerId),
Multiaddrs: info.Multiaddrs,
SealProofType: info.SealProofType,
SectorSize: info.SectorSize,
WindowPoStPartitionSectors: info.WindowPoStPartitionSectors,
}
if info.PendingWorkerKey != nil {
mi.NewWorker = info.PendingWorkerKey.NewWorker
mi.WorkerChangeEpoch = info.PendingWorkerKey.EffectiveAt
}
return mi
}
+13
View File
@@ -13,6 +13,10 @@ import (
)
func BuiltinBootstrap() ([]peer.AddrInfo, error) {
if DisableBuiltinAssets {
return nil, nil
}
var out []peer.AddrInfo
b := rice.MustFindBox("bootstrap")
@@ -34,3 +38,12 @@ func BuiltinBootstrap() ([]peer.AddrInfo, error) {
})
return out, err
}
func DrandBootstrap() ([]peer.AddrInfo, error) {
addrs := []string{
"/dnsaddr/pl-eu.testnet.drand.sh/",
"/dnsaddr/pl-us.testnet.drand.sh/",
"/dnsaddr/pl-sin.testnet.drand.sh/",
}
return addrutil.ParseAddresses(context.TODO(), addrs)
}
+12 -12
View File
@@ -1,12 +1,12 @@
/dns4/bootstrap-0-sin.fil-test.net/tcp/1347/p2p/12D3KooWKNF7vNFEhnvB45E9mw2B5z6t419W3ziZPLdUDVnLLKGs
/ip4/86.109.15.57/tcp/1347/p2p/12D3KooWKNF7vNFEhnvB45E9mw2B5z6t419W3ziZPLdUDVnLLKGs
/dns4/bootstrap-0-dfw.fil-test.net/tcp/1347/p2p/12D3KooWECJTm7RUPyGfNbRwm6y2fK4wA7EB8rDJtWsq5AKi7iDr
/ip4/139.178.84.45/tcp/1347/p2p/12D3KooWECJTm7RUPyGfNbRwm6y2fK4wA7EB8rDJtWsq5AKi7iDr
/dns4/bootstrap-0-fra.fil-test.net/tcp/1347/p2p/12D3KooWC7MD6m7iNCuDsYtNr7xVtazihyVUizBbhmhEiyMAm9ym
/ip4/136.144.49.17/tcp/1347/p2p/12D3KooWC7MD6m7iNCuDsYtNr7xVtazihyVUizBbhmhEiyMAm9ym
/dns4/bootstrap-1-sin.fil-test.net/tcp/1347/p2p/12D3KooWD8eYqsKcEMFax6EbWN3rjA7qFsxCez2rmN8dWqkzgNaN
/ip4/86.109.15.55/tcp/1347/p2p/12D3KooWD8eYqsKcEMFax6EbWN3rjA7qFsxCez2rmN8dWqkzgNaN
/dns4/bootstrap-1-dfw.fil-test.net/tcp/1347/p2p/12D3KooWLB3RR8frLAmaK4ntHC2dwrAjyGzQgyUzWxAum1FxyyqD
/ip4/139.178.84.41/tcp/1347/p2p/12D3KooWLB3RR8frLAmaK4ntHC2dwrAjyGzQgyUzWxAum1FxyyqD
/dns4/bootstrap-1-fra.fil-test.net/tcp/1347/p2p/12D3KooWGPDJAw3HW4uVU3JEQBfFaZ1kdpg4HvvwRMVpUYbzhsLQ
/ip4/136.144.49.131/tcp/1347/p2p/12D3KooWGPDJAw3HW4uVU3JEQBfFaZ1kdpg4HvvwRMVpUYbzhsLQ
/dns4/bootstrap-0-sin.fil-test.net/tcp/1347/p2p/12D3KooWPdUquftaQvoQEtEdsRBAhwD6jopbF2oweVTzR59VbHEd
/ip4/86.109.15.57/tcp/1347/p2p/12D3KooWPdUquftaQvoQEtEdsRBAhwD6jopbF2oweVTzR59VbHEd
/dns4/bootstrap-0-dfw.fil-test.net/tcp/1347/p2p/12D3KooWQSCkHCzosEyrh8FgYfLejKgEPM5VB6qWzZE3yDAuXn8d
/ip4/139.178.84.45/tcp/1347/p2p/12D3KooWQSCkHCzosEyrh8FgYfLejKgEPM5VB6qWzZE3yDAuXn8d
/dns4/bootstrap-0-fra.fil-test.net/tcp/1347/p2p/12D3KooWEXN2eQmoyqnNjde9PBAQfQLHN67jcEdWU6JougWrgXJK
/ip4/136.144.49.17/tcp/1347/p2p/12D3KooWEXN2eQmoyqnNjde9PBAQfQLHN67jcEdWU6JougWrgXJK
/dns4/bootstrap-1-sin.fil-test.net/tcp/1347/p2p/12D3KooWLmJkZd33mJhjg5RrpJ6NFep9SNLXWc4uVngV4TXKwzYw
/ip4/86.109.15.123/tcp/1347/p2p/12D3KooWLmJkZd33mJhjg5RrpJ6NFep9SNLXWc4uVngV4TXKwzYw
/dns4/bootstrap-1-dfw.fil-test.net/tcp/1347/p2p/12D3KooWGXLHjiz6pTRu7x2pkgTVCoxcCiVxcNLpMnWcJ3JiNEy5
/ip4/139.178.86.3/tcp/1347/p2p/12D3KooWGXLHjiz6pTRu7x2pkgTVCoxcCiVxcNLpMnWcJ3JiNEy5
/dns4/bootstrap-1-fra.fil-test.net/tcp/1347/p2p/12D3KooW9szZmKttS9A1FafH3Zc2pxKwwmvCWCGKkRP4KmbhhC4R
/ip4/136.144.49.131/tcp/1347/p2p/12D3KooW9szZmKttS9A1FafH3Zc2pxKwwmvCWCGKkRP4KmbhhC4R
+15
View File
@@ -0,0 +1,15 @@
package build
// DisableBuiltinAssets disables the resolution of go.rice boxes that store
// built-in assets, such as proof parameters, bootstrap peers, genesis blocks,
// etc.
//
// When this value is set to true, it is expected that the user will
// provide any such configurations through the Lotus API itself.
//
// This is useful when you're using Lotus as a library, such as to orchestrate
// test scenarios, or for other purposes where you don't need to use the
// defaults shipped with the binary.
//
// For this flag to be effective, it must be enabled _before_ instantiating Lotus.
var DisableBuiltinAssets = false
Binary file not shown.
+1 -1
View File
@@ -2,6 +2,6 @@ package build
import rice "github.com/GeertJohan/go.rice"
func ParametersJson() []byte {
func ParametersJSON() []byte {
return rice.MustFindBox("proof-params").MustBytes("parameters.json")
}
+6 -5
View File
@@ -12,16 +12,17 @@ import (
func init() {
power.ConsensusMinerMinPower = big.NewInt(2048)
miner.SupportedProofTypes = map[abi.RegisteredProof]struct{}{
abi.RegisteredProof_StackedDRG2KiBSeal: {},
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
}
verifreg.MinVerifiedDealSize = big.NewInt(256)
BuildType |= Build2k
}
// Seconds
const BlockDelay = 2
const BlockDelaySecs = uint64(2)
const PropagationDelay = 3
const PropagationDelaySecs = uint64(3)
// SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after
// which the miner is slashed
+1
View File
@@ -4,6 +4,7 @@ package build
func init() {
InsecurePoStValidation = true
BuildType |= BuildDebug
}
// NOTE: Also includes settings from params_2k
+38
View File
@@ -0,0 +1,38 @@
package build
import (
"sort"
"github.com/libp2p/go-libp2p-core/protocol"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/lotus/node/modules/dtypes"
)
func DefaultSectorSize() abi.SectorSize {
szs := make([]abi.SectorSize, 0, len(miner.SupportedProofTypes))
for spt := range miner.SupportedProofTypes {
ss, err := spt.SectorSize()
if err != nil {
panic(err)
}
szs = append(szs, ss)
}
sort.Slice(szs, func(i, j int) bool {
return szs[i] < szs[j]
})
return szs[0]
}
// Core network constants
func BlocksTopic(netName dtypes.NetworkName) string { return "/fil/blocks/" + string(netName) }
func MessagesTopic(netName dtypes.NetworkName) string { return "/fil/msgs/" + string(netName) }
func DhtProtocolName(netName dtypes.NetworkName) protocol.ID {
return protocol.ID("/fil/kad/" + string(netName))
}
@@ -1,10 +1,9 @@
// +build !testground
package build
import (
"math/big"
"sort"
"github.com/libp2p/go-libp2p-core/protocol"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
@@ -13,32 +12,6 @@ import (
"github.com/filecoin-project/lotus/node/modules/dtypes"
)
func DefaultSectorSize() abi.SectorSize {
szs := make([]abi.SectorSize, 0, len(miner.SupportedProofTypes))
for spt := range miner.SupportedProofTypes {
ss, err := spt.SectorSize()
if err != nil {
panic(err)
}
szs = append(szs, ss)
}
sort.Slice(szs, func(i, j int) bool {
return szs[i] < szs[j]
})
return szs[0]
}
// Core network constants
func BlocksTopic(netName dtypes.NetworkName) string { return "/fil/blocks/" + string(netName) }
func MessagesTopic(netName dtypes.NetworkName) string { return "/fil/msgs/" + string(netName) }
func DhtProtocolName(netName dtypes.NetworkName) protocol.ID {
return protocol.ID("/fil/kad/" + string(netName))
}
// /////
// Storage
@@ -48,8 +21,7 @@ const UnixfsLinksPerLevel = 1024
// /////
// Consensus / Network
// Seconds
const AllowableClockDrift = 1
const AllowableClockDriftSecs = uint64(1)
// Epochs
const ForkLengthThreshold = Finality
@@ -59,11 +31,12 @@ var BlocksPerEpoch = uint64(builtin.ExpectedLeadersPerEpoch)
// Epochs
const Finality = miner.ChainFinalityish
const MessageConfidence = uint64(5)
// constants for Weight calculation
// The ratio of weight contributed by short-term vs long-term factors in a given round
const WRatioNum = int64(1)
const WRatioDen = 2
const WRatioDen = uint64(2)
// /////
// Proofs
@@ -81,25 +54,25 @@ const MaxSealLookback = SealRandomnessLookbackLimit + 2000 // TODO: Get from spe
// Mining
// Epochs
const TicketRandomnessLookback = 1
const TicketRandomnessLookback = abi.ChainEpoch(1)
const WinningPoStSectorSetLookback = 10
const WinningPoStSectorSetLookback = abi.ChainEpoch(10)
// /////
// Devnet settings
const TotalFilecoin = 2_000_000_000
const MiningRewardTotal = 1_400_000_000
const TotalFilecoin = uint64(2_000_000_000)
const MiningRewardTotal = uint64(1_400_000_000)
const FilecoinPrecision = 1_000_000_000_000_000_000
const FilecoinPrecision = uint64(1_000_000_000_000_000_000)
var InitialRewardBalance *big.Int
// TODO: Move other important consts here
func init() {
InitialRewardBalance = big.NewInt(MiningRewardTotal)
InitialRewardBalance = InitialRewardBalance.Mul(InitialRewardBalance, big.NewInt(FilecoinPrecision))
InitialRewardBalance = big.NewInt(int64(MiningRewardTotal))
InitialRewardBalance = InitialRewardBalance.Mul(InitialRewardBalance, big.NewInt(int64(FilecoinPrecision)))
}
// Sync
@@ -109,16 +82,22 @@ const BadBlockCacheSize = 1 << 15
// 10 block reorg.
const BlsSignatureCacheSize = 40000
// Size of signature verification cache
// 32k keeps the cache around 10MB in size, max
const VerifSigCacheSize = 32000
// ///////
// Limits
// TODO: If this is gonna stay, it should move to specs-actors
const BlockMessageLimit = 512
const BlockGasLimit = 100_000_000
const BlockGasLimit = 100_000_000_000
var DrandCoeffs = []string{
"82c279cce744450e68de98ee08f9698a01dd38f8e3be3c53f2b840fb9d09ad62a0b6b87981e179e1b14bc9a2d284c985",
"82d51308ad346c686f81b8094551597d7b963295cbf313401a93df9baf52d5ae98a87745bee70839a4d6e65c342bd15b",
"94eebfd53f4ba6a3b8304236400a12e73885e5a781509a5c8d41d2e8b476923d8ea6052649b3c17282f596217f96c5de",
"8dc4231e42b4edf39e86ef1579401692480647918275da767d3e558c520d6375ad953530610fd27daf110187877a65d0",
var DrandConfig = dtypes.DrandConfig{
Servers: []string{
"https://pl-eu.testnet.drand.sh",
"https://pl-us.testnet.drand.sh",
"https://pl-sin.testnet.drand.sh",
},
ChainInfoJSON: `{"public_key":"922a2e93828ff83345bae533f5172669a26c02dc76d6bf59c80892e12ab1455c229211886f35bb56af6d5bea981024df","period":25,"genesis_time":1590445175,"hash":"138a324aa6540f93d0dad002aa89454b1bec2b6e948682cde6bd4db40f4b7c9b"}`,
}
+73
View File
@@ -0,0 +1,73 @@
// +build testground
// This file makes hardcoded parameters (const) configurable as vars.
//
// Its purpose is to unlock various degrees of flexibility and parametrization
// when writing Testground plans for Lotus.
//
package build
import (
"math/big"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
)
var (
UnixfsChunkSize = uint64(1 << 20)
UnixfsLinksPerLevel = 1024
BlocksPerEpoch = uint64(builtin.ExpectedLeadersPerEpoch)
BlockMessageLimit = 512
BlockGasLimit = int64(100_000_000_000)
BlockDelaySecs = uint64(builtin.EpochDurationSeconds)
PropagationDelaySecs = uint64(6)
AllowableClockDriftSecs = uint64(1)
Finality = miner.ChainFinalityish
ForkLengthThreshold = Finality
SlashablePowerDelay = 20
InteractivePoRepConfidence = 6
MessageConfidence uint64 = 5
WRatioNum = int64(1)
WRatioDen = uint64(2)
BadBlockCacheSize = 1 << 15
BlsSignatureCacheSize = 40000
VerifSigCacheSize = 32000
SealRandomnessLookback = Finality
SealRandomnessLookbackLimit = SealRandomnessLookback + 2000
MaxSealLookback = SealRandomnessLookbackLimit + 2000
TicketRandomnessLookback = abi.ChainEpoch(1)
WinningPoStSectorSetLookback = abi.ChainEpoch(10)
TotalFilecoin uint64 = 2_000_000_000
MiningRewardTotal uint64 = 1_400_000_000
FilecoinPrecision uint64 = 1_000_000_000_000_000_000
InitialRewardBalance = func() *big.Int {
v := big.NewInt(int64(MiningRewardTotal))
v = v.Mul(v, big.NewInt(int64(FilecoinPrecision)))
return v
}()
DrandConfig = dtypes.DrandConfig{
Servers: []string{
"https://pl-eu.testnet.drand.sh",
"https://pl-us.testnet.drand.sh",
"https://pl-sin.testnet.drand.sh",
},
ChainInfoJSON: `{"public_key":"922a2e93828ff83345bae533f5172669a26c02dc76d6bf59c80892e12ab1455c229211886f35bb56af6d5bea981024df","period":25,"genesis_time":1590445175,"hash":"138a324aa6540f93d0dad002aa89454b1bec2b6e948682cde6bd4db40f4b7c9b"}`,
}
)
+6 -6
View File
@@ -1,5 +1,6 @@
// +build !debug
// +build !2k
// +build !testground
package build
@@ -13,13 +14,12 @@ import (
func init() {
power.ConsensusMinerMinPower = big.NewInt(1024 << 30)
miner.SupportedProofTypes = map[abi.RegisteredProof]struct{}{
abi.RegisteredProof_StackedDRG32GiBSeal: {},
abi.RegisteredProof_StackedDRG64GiBSeal: {},
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg32GiBV1: {},
abi.RegisteredSealProof_StackedDrg64GiBV1: {},
}
}
// Seconds
const BlockDelay = builtin.EpochDurationSeconds
const BlockDelaySecs = uint64(builtin.EpochDurationSeconds)
const PropagationDelay = 6
const PropagationDelaySecs = uint64(6)
+90 -90
View File
@@ -1,152 +1,152 @@
{
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-0170db1f394b35d995252228ee359194b13199d259380541dc529fb0099096b0.params": {
"cid": "QmYkygifkXnrnsN4MJsjBFHTQJHx294CyikDgDK8nYxdGh",
"digest": "df3f30442a6d6b4192f5071fb17e820c",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-0170db1f394b35d995252228ee359194b13199d259380541dc529fb0099096b0.params": {
"cid": "QmeDRyxek34F1H6xJY6AkFdWvPsy5F6dKTrebV3ZtWT4ky",
"digest": "f5827f2d8801c62c831e0f972f6dc8bb",
"sector_size": 2048
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-0170db1f394b35d995252228ee359194b13199d259380541dc529fb0099096b0.vk": {
"cid": "QmdXyqbmy2bkJA9Kyhh6z25GrTCq48LwX6c1mxPsm54wi7",
"digest": "0bea3951abf9557a3569f68e52a30c6c",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-0170db1f394b35d995252228ee359194b13199d259380541dc529fb0099096b0.vk": {
"cid": "QmUw1ZmG4BBbX19MsbH3zAEGKUc42iFJc5ZAyomDHeJTsA",
"digest": "398fecdb4b2de445125852bc3c080b35",
"sector_size": 2048
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-0cfb4f178bbb71cf2ecfcd42accce558b27199ab4fb59cb78f2483fe21ef36d9.params": {
"cid": "Qmf5XZZtP5VcYTf65MbKjLVabcS6cYMbr2rFShmfJzh5e5",
"digest": "655e6277638edc8c658094f6f0b33d54",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-0cfb4f178bbb71cf2ecfcd42accce558b27199ab4fb59cb78f2483fe21ef36d9.params": {
"cid": "QmUeNKp9YZpiAFm81RV5KuxH1FDGJx2DuwcbU2XNSZLLSv",
"digest": "2b6d2972ac9e862e8134d98fb695b0c5",
"sector_size": 536870912
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-0cfb4f178bbb71cf2ecfcd42accce558b27199ab4fb59cb78f2483fe21ef36d9.vk": {
"cid": "QmPuhdWnAXBks43emnkqi9FQzyU1gASKyz23zrD27BPGs8",
"digest": "57690e3a6a94c3f704802a674b34f36b",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-0cfb4f178bbb71cf2ecfcd42accce558b27199ab4fb59cb78f2483fe21ef36d9.vk": {
"cid": "QmQaQmTXX995Akd66ggtJY5bNx6Gkxk8P34JTdMMq8393G",
"digest": "3688c9eb256b7b17f411dad78d5ef74a",
"sector_size": 536870912
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-3ea05428c9d11689f23529cde32fd30aabd50f7d2c93657c1d3650bca3e8ea9e.params": {
"cid": "QmPNVgTN7N5vDtD5u7ERMTLcvUtrKRBfYVUDr6uW3pKhX7",
"digest": "3d390654f58e603b896ac70c653f5676",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-3ea05428c9d11689f23529cde32fd30aabd50f7d2c93657c1d3650bca3e8ea9e.params": {
"cid": "QmfEYTMSkwGJTumQx26iKXGNKiYh3mmAC4SkdybZpJCj5p",
"digest": "09bff16aed893349d94485cfae366a9c",
"sector_size": 2048
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-3ea05428c9d11689f23529cde32fd30aabd50f7d2c93657c1d3650bca3e8ea9e.vk": {
"cid": "Qmbj61Zez7v5xA7nSCnmWbyLYznWJDWeusz7Yg8EcgVdoN",
"digest": "8c170a164743c39576a7f47a1b51e6f3",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-3ea05428c9d11689f23529cde32fd30aabd50f7d2c93657c1d3650bca3e8ea9e.vk": {
"cid": "QmP4ThPieSUJyRanjibWpT5R5cCMzMAU4j8Y7kBn7CSW1Q",
"digest": "142f2f7e8f1b1779290315cabfd2c803",
"sector_size": 2048
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-50c7368dea9593ed0989e70974d28024efa9d156d585b7eea1be22b2e753f331.params": {
"cid": "QmRApb8RZoBK3cqicT7V3ydXg8yVvqPFMPrQNXP33aBihp",
"digest": "b1b58ff9a297b82885e8a7dfb035f83c",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-50c7368dea9593ed0989e70974d28024efa9d156d585b7eea1be22b2e753f331.params": {
"cid": "QmcAixrHsz29DgvtZiMc2kQjvPRvWxYUp36QYmRDZbmREm",
"digest": "8f987f64d434365562180b96ec12e299",
"sector_size": 8388608
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-50c7368dea9593ed0989e70974d28024efa9d156d585b7eea1be22b2e753f331.vk": {
"cid": "QmcytF1dTdqMFoyXi931j1RgmGtLfR9LLLaBznRt1tPQyD",
"digest": "1a09e00c641f192f55af3433a028f050",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-50c7368dea9593ed0989e70974d28024efa9d156d585b7eea1be22b2e753f331.vk": {
"cid": "QmT4iFnbL6r4txS5PXsiV7NTzbhCxHy54PvdkJJGV2VFXb",
"digest": "94b6c24ac01924f4feeecedd16b5d77d",
"sector_size": 8388608
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-5294475db5237a2e83c3e52fd6c2b03859a1831d45ed08c4f35dbf9a803165a9.params": {
"cid": "QmPvr54tWaVeP4WnekivzUAJitTqsQfvikBvAHNEaDNQSw",
"digest": "9380e41368ed4083dbc922b290d3b786",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-5294475db5237a2e83c3e52fd6c2b03859a1831d45ed08c4f35dbf9a803165a9.params": {
"cid": "QmbjFst6SFCK1KsTQrfwPdxf3VTNa1raed574tEZZ9PoyQ",
"digest": "2c245fe8179839dd6c6cdea207c67ae8",
"sector_size": 8388608
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-5294475db5237a2e83c3e52fd6c2b03859a1831d45ed08c4f35dbf9a803165a9.vk": {
"cid": "QmXyVLVDRCcxA9SjT7PeK8HFtyxZ2ZH3SHa8KoGLw8VGJt",
"digest": "f0731a7e20f90704bd38fc5d27882f6d",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-5294475db5237a2e83c3e52fd6c2b03859a1831d45ed08c4f35dbf9a803165a9.vk": {
"cid": "QmQJKmvZN1a5cQ1Nw6CDyXs3nuRPzvyU5NvCFMUL2BfcZC",
"digest": "56ae47bfda53bb8d22981ed8d8d27d72",
"sector_size": 8388608
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-7d739b8cf60f1b0709eeebee7730e297683552e4b69cab6984ec0285663c5781.params": {
"cid": "Qmf5f6ko3dqj7qauzXpZqxM9B2x2sL977K6gE2ppNwuJPv",
"digest": "273ebb8c896326b7c292bee8b775fd38",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-7d739b8cf60f1b0709eeebee7730e297683552e4b69cab6984ec0285663c5781.params": {
"cid": "QmQCABxeTpdvXTyjDyk7nPBxkQzCh7MXfGztWnSXEPKMLW",
"digest": "7e6b2eb5ecbb11ac651ad66ebbb2075a",
"sector_size": 536870912
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-7d739b8cf60f1b0709eeebee7730e297683552e4b69cab6984ec0285663c5781.vk": {
"cid": "QmfP3MQe8koW63n5MkDENENVHxib78MJYYyZvbneCsuze8",
"digest": "3dd94da9da64e51b3445bc528d84e76d",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-7d739b8cf60f1b0709eeebee7730e297683552e4b69cab6984ec0285663c5781.vk": {
"cid": "QmPBweyugh5Sx4umk8ULhgEGbjY8xmWLfU6M7EMpc8Mad6",
"digest": "94a8d9e25a9ab9674d339833664eba25",
"sector_size": 536870912
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-0-0377ded656c6f524f1618760bffe4e0a1c51d5a70c4509eedae8a27555733edc.params": {
"cid": "QmYEeeCE8uT2bsVkxcqqUYeMmMEbe6rfmo8wQCv7jFHqqm",
"digest": "c947f2021304ed43b7216f7a8436e294",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-0-0377ded656c6f524f1618760bffe4e0a1c51d5a70c4509eedae8a27555733edc.params": {
"cid": "QmY5yax1E9KymBnCeHksE9Zi8NieZbmwcpoDGoabkeeb9h",
"digest": "c909ea9e3fe25ab9b391a64593afdbba",
"sector_size": 34359738368
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-0-0377ded656c6f524f1618760bffe4e0a1c51d5a70c4509eedae8a27555733edc.vk": {
"cid": "QmXB63ExriFjB4ywWnXTnFwCcLFfCeEP3h15qtL5i7F4aX",
"digest": "ab20d7b253e7e9a0d2ccdf7599ec8ec3",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-0-0377ded656c6f524f1618760bffe4e0a1c51d5a70c4509eedae8a27555733edc.vk": {
"cid": "QmXnPo4yH5mwMguwrvqgRfduSttbmPrXtbBfbwU21wQWHt",
"digest": "caf900461e988bbf86dbcaca087b7864",
"sector_size": 34359738368
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-0-559e581f022bb4e4ec6e719e563bf0e026ad6de42e56c18714a2c692b1b88d7e.params": {
"cid": "QmW5Yxg3L1NSzuQVcRMHMbG3uvVoi4dTLzVaDpnEUPQpnA",
"digest": "079ba19645828ae42b22b0e3f4866e8d",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-0-559e581f022bb4e4ec6e719e563bf0e026ad6de42e56c18714a2c692b1b88d7e.params": {
"cid": "QmZtzzPWwmZEgR7MSMvXRbt9KVK8k4XZ5RLWHybHJW9SdE",
"digest": "a2844f0703f186d143a06146a04577d8",
"sector_size": 34359738368
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-0-559e581f022bb4e4ec6e719e563bf0e026ad6de42e56c18714a2c692b1b88d7e.vk": {
"cid": "QmQzZ5dJ11tcSBees38WX41tZLXS9BqpEti253m5QcnTNs",
"digest": "c76125a50a7de315165de359b5174ae4",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-0-559e581f022bb4e4ec6e719e563bf0e026ad6de42e56c18714a2c692b1b88d7e.vk": {
"cid": "QmWxEA7EdQCUJTzjNpxg5XTF45D2uVyYnN1QRUb5TRYU8M",
"digest": "2306247a1e616dbe07f01b88196c2044",
"sector_size": 34359738368
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-2-2627e4006b67f99cef990c0a47d5426cb7ab0a0ad58fc1061547bf2d28b09def.params": {
"cid": "QmNk3wga1tS53FUu1QnkK8ehWA2cqpCnSEAPv3KLxdJxNa",
"digest": "421e4790c0b80e0107a7ff67acf14084",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-2-2627e4006b67f99cef990c0a47d5426cb7ab0a0ad58fc1061547bf2d28b09def.params": {
"cid": "QmP676KwuvyF9Y64uJnXvLtvD1xcuWQ6wD23RzYtQ6dd4f",
"digest": "215b1c667a4f46a1d0178338df568615",
"sector_size": 68719476736
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-2-2627e4006b67f99cef990c0a47d5426cb7ab0a0ad58fc1061547bf2d28b09def.vk": {
"cid": "QmVQCHGsrUtbn9RjHs1e6GXfeXDW5m9w4ge48PSX3Z2as2",
"digest": "8b60e9cc1470a6729c687d6cf0a1f79c",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-2-2627e4006b67f99cef990c0a47d5426cb7ab0a0ad58fc1061547bf2d28b09def.vk": {
"cid": "QmPvPwbJtcSGyqB1rQJhSF5yvFbX9ZBSsHVej5F8JUyHUJ",
"digest": "0c9c423b28b1455fcbc329a1045fd4dd",
"sector_size": 68719476736
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-2-b62098629d07946e9028127e70295ed996fe3ed25b0f9f88eb610a0ab4385a3c.params": {
"cid": "QmTL3VvydaMFWKvE5VzxjgKsJYgL9JMM4JVYNtQxdj9JK1",
"digest": "2685f31124b22ea6b2857e5a5e87ffa3",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-2-b62098629d07946e9028127e70295ed996fe3ed25b0f9f88eb610a0ab4385a3c.params": {
"cid": "QmUxPQfvckzm1t6MFRdDZ1fDK5UJzAjK7pTZ97cwyachdr",
"digest": "965132f51ae445b0e6d32692b7561995",
"sector_size": 68719476736
},
"v26-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-2-b62098629d07946e9028127e70295ed996fe3ed25b0f9f88eb610a0ab4385a3c.vk": {
"cid": "QmSVWbLqQYbUbbJyfsRMzEib2rfSqMtnPks1Nw22omcBQm",
"digest": "efe703cd2839597c7ca5c2a906b74296",
"v27-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-2-b62098629d07946e9028127e70295ed996fe3ed25b0f9f88eb610a0ab4385a3c.vk": {
"cid": "QmTxq2EBnQWb5R8tS4MHdchj4vNfLYGoSXxwJFvs5xgW4K",
"digest": "fc8c3d26e0e56373ad96cb41520d55a6",
"sector_size": 68719476736
},
"v26-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-032d3138d22506ec0082ed72b2dcba18df18477904e35bafee82b3793b06832f.params": {
"cid": "QmU9dH31nZZUJnsogR4Ld4ySUcH6wm2RgmGiujwnqtbU6k",
"digest": "fcef8e87ae2afd7a28aae44347b804cf",
"v27-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-032d3138d22506ec0082ed72b2dcba18df18477904e35bafee82b3793b06832f.params": {
"cid": "QmRjgZHERgqGoRagR788Kh6ybi26csVYa8mqbqhmZm57Jx",
"digest": "cfc7b0897d1eee48c586f7beb89e67f7",
"sector_size": 2048
},
"v26-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-032d3138d22506ec0082ed72b2dcba18df18477904e35bafee82b3793b06832f.vk": {
"cid": "QmdJ15DMGPooye5NaPcRfXUdHUDibcN7hKjbmTGuu1K4AQ",
"digest": "2ee2b3518229680db15161d4f582af37",
"v27-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-032d3138d22506ec0082ed72b2dcba18df18477904e35bafee82b3793b06832f.vk": {
"cid": "QmNjvnvFP7KgovHUddULoB19fBHT81iz7NcUbzEHZUUPsm",
"digest": "fb59bd061c987eac7068008c44de346b",
"sector_size": 2048
},
"v26-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-6babf46ce344ae495d558e7770a585b2382d54f225af8ed0397b8be7c3fcd472.params": {
"cid": "QmZgtxcY3tMXXQxZTA7ZTUDXLVUnfxNcerXgeW4gG2NnfP",
"digest": "3273c7135cb75684248b475781b738ee",
"v27-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-6babf46ce344ae495d558e7770a585b2382d54f225af8ed0397b8be7c3fcd472.params": {
"cid": "QmTpRPBA4dt8fgGpcVzi4L1KA1U2eBHCE8WVmS2GUygMvT",
"digest": "36d465915b0afbf96bd08e7915e00952",
"sector_size": 536870912
},
"v26-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-6babf46ce344ae495d558e7770a585b2382d54f225af8ed0397b8be7c3fcd472.vk": {
"cid": "QmSS6ZkAV2aGZcgKgdPpEEgihXF1ryZX8PSAZDWSoeL1d4",
"digest": "1519b5f61d9044a59f2bdc57537c094b",
"v27-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-6babf46ce344ae495d558e7770a585b2382d54f225af8ed0397b8be7c3fcd472.vk": {
"cid": "QmRzDyVfQCLsxspoVsed5bcQRsG6KiktngJfcNBL3TJPZe",
"digest": "99d16df0eb6a7e227a4f4570c4f6b6f1",
"sector_size": 536870912
},
"v26-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-ecd683648512ab1765faa2a5f14bab48f676e633467f0aa8aad4b55dcb0652bb.params": {
"cid": "QmQBGXeiNn6hVwbR6qFarQqiNGDdKk4h9ucfyvcXyfYz2N",
"digest": "7d5f896f435c38e93bcda6dd168d860b",
"v27-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-ecd683648512ab1765faa2a5f14bab48f676e633467f0aa8aad4b55dcb0652bb.params": {
"cid": "QmV8ZjTSGzDUWmFvsq9NSyPBR7eDDUcvCPNgj2yE7HMAFu",
"digest": "34f3ddf1d1c9f41c0cd73b91e8b4bc27",
"sector_size": 8388608
},
"v26-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-ecd683648512ab1765faa2a5f14bab48f676e633467f0aa8aad4b55dcb0652bb.vk": {
"cid": "QmPrZgBVGMckEAeu5eSJnLmiAwcPQjKjZe5ir6VaQ5AxKs",
"digest": "fe6d2de44580a0db5a4934688899b92f",
"v27-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-ecd683648512ab1765faa2a5f14bab48f676e633467f0aa8aad4b55dcb0652bb.vk": {
"cid": "QmTa3VbjTiqJWU6r4WKayaQrUaaBsrpp5UDqYvPDd2C5hs",
"digest": "ec62d59651daa5631d3d1e9c782dd940",
"sector_size": 8388608
},
"v26-stacked-proof-of-replication-merkletree-poseidon_hasher-8-8-0-sha256_hasher-82a357d2f2ca81dc61bb45f4a762807aedee1b0a53fd6c4e77b46a01bfef7820.params": {
"cid": "QmZL2cq45XJn5BFzagAZwgFmLrcM1W6CXoiEF9C5j5tjEF",
"digest": "acdfed9f0512bc85a01a9fb871d475d5",
"v27-stacked-proof-of-replication-merkletree-poseidon_hasher-8-8-0-sha256_hasher-82a357d2f2ca81dc61bb45f4a762807aedee1b0a53fd6c4e77b46a01bfef7820.params": {
"cid": "Qmf8ngfArxrv9tFWDqBcNegdBMymvuakwyHKd1pbW3pbsb",
"digest": "a16d6f4c6424fb280236739f84b24f97",
"sector_size": 34359738368
},
"v26-stacked-proof-of-replication-merkletree-poseidon_hasher-8-8-0-sha256_hasher-82a357d2f2ca81dc61bb45f4a762807aedee1b0a53fd6c4e77b46a01bfef7820.vk": {
"cid": "QmQ4zB7nNa1tDYNifBkExRnZtwtxZw775iaqvVsZyRi6Q2",
"digest": "524a2f3e9d6826593caebc41bb545c40",
"v27-stacked-proof-of-replication-merkletree-poseidon_hasher-8-8-0-sha256_hasher-82a357d2f2ca81dc61bb45f4a762807aedee1b0a53fd6c4e77b46a01bfef7820.vk": {
"cid": "QmfQgVFerArJ6Jupwyc9tKjLD9n1J9ajLHBdpY465tRM7M",
"digest": "7a139d82b8a02e35279d657e197f5c1f",
"sector_size": 34359738368
},
"v26-stacked-proof-of-replication-merkletree-poseidon_hasher-8-8-2-sha256_hasher-96f1b4a04c5c51e4759bbf224bbc2ef5a42c7100f16ec0637123f16a845ddfb2.params": {
"cid": "QmY7DitNKXFeLQt9QoVQkfjM1EvRnprqUVxjmkTXkHDNka",
"digest": "f27271c0537ba65ade2ec045f8fbd069",
"v27-stacked-proof-of-replication-merkletree-poseidon_hasher-8-8-2-sha256_hasher-96f1b4a04c5c51e4759bbf224bbc2ef5a42c7100f16ec0637123f16a845ddfb2.params": {
"cid": "QmfDha8271nXJn14Aq3qQeghjMBWbs6HNSGa6VuzCVk4TW",
"digest": "5d3cd3f107a3bea8a96d1189efd2965c",
"sector_size": 68719476736
},
"v26-stacked-proof-of-replication-merkletree-poseidon_hasher-8-8-2-sha256_hasher-96f1b4a04c5c51e4759bbf224bbc2ef5a42c7100f16ec0637123f16a845ddfb2.vk": {
"cid": "QmUJsvoCuQ4LszPmeRVAkMYb5qY95ctz3UXKhu8xLzyFKo",
"digest": "576b292938c6c9d0a0e721bd867a543b",
"v27-stacked-proof-of-replication-merkletree-poseidon_hasher-8-8-2-sha256_hasher-96f1b4a04c5c51e4759bbf224bbc2ef5a42c7100f16ec0637123f16a845ddfb2.vk": {
"cid": "QmRVtTtiFzHJTHurYzaCvetGAchux9cktixT4aGHthN6Zt",
"digest": "62c366405404e60f171e661492740b1c",
"sector_size": 68719476736
}
}
+26 -3
View File
@@ -3,11 +3,33 @@ package build
import "fmt"
var CurrentCommit string
var BuildType int
const (
BuildDefault = 0
Build2k = 0x1
BuildDebug = 0x3
)
func buildType() string {
switch BuildType {
case BuildDefault:
return ""
case BuildDebug:
return "+debug"
case Build2k:
return "+2k"
default:
return "+huh?"
}
}
// BuildVersion is the local build version, set by build system
const BuildVersion = "0.3.0"
const BuildVersion = "0.4.1"
var UserVersion = BuildVersion + CurrentCommit
func UserVersion() string {
return BuildVersion + buildType() + CurrentCommit
}
type Version uint32
@@ -31,8 +53,9 @@ func (ve Version) EqMajorMinor(v2 Version) bool {
}
// APIVersion is a semver version of the rpc api exposed
var APIVersion Version = newVer(0, 3, 0)
var APIVersion Version = newVer(0, 6, 0)
//nolint:varcheck,deadcode
const (
majorMask = 0xff0000
minorMask = 0xffff00
+1
View File
@@ -50,6 +50,7 @@ func Newf(retCode exitcode.ExitCode, format string, args ...interface{}) ActorEr
}
// todo: bit hacky
func NewfSkip(skip int, retCode exitcode.ExitCode, format string, args ...interface{}) ActorError {
if retCode == 0 {
return &actorError{
+36 -5
View File
@@ -1,6 +1,8 @@
package chain
import (
"fmt"
"github.com/filecoin-project/lotus/build"
lru "github.com/hashicorp/golang-lru"
"github.com/ipfs/go-cid"
@@ -10,6 +12,35 @@ type BadBlockCache struct {
badBlocks *lru.ARCCache
}
type BadBlockReason struct {
Reason string
TipSet []cid.Cid
OriginalReason *BadBlockReason
}
func NewBadBlockReason(cid []cid.Cid, format string, i ...interface{}) BadBlockReason {
return BadBlockReason{
TipSet: cid,
Reason: fmt.Sprintf(format, i...),
}
}
func (bbr BadBlockReason) Linked(reason string, i ...interface{}) BadBlockReason {
or := &bbr
if bbr.OriginalReason != nil {
or = bbr.OriginalReason
}
return BadBlockReason{Reason: fmt.Sprintf(reason, i...), OriginalReason: or}
}
func (bbr BadBlockReason) String() string {
res := bbr.Reason
if bbr.OriginalReason != nil {
res += " caused by: " + fmt.Sprintf("%s %s", bbr.OriginalReason.TipSet, bbr.OriginalReason.String())
}
return res
}
func NewBadBlockCache() *BadBlockCache {
cache, err := lru.NewARC(build.BadBlockCacheSize)
if err != nil {
@@ -21,15 +52,15 @@ func NewBadBlockCache() *BadBlockCache {
}
}
func (bts *BadBlockCache) Add(c cid.Cid, reason string) {
bts.badBlocks.Add(c, reason)
func (bts *BadBlockCache) Add(c cid.Cid, bbr BadBlockReason) {
bts.badBlocks.Add(c, bbr)
}
func (bts *BadBlockCache) Has(c cid.Cid) (string, bool) {
func (bts *BadBlockCache) Has(c cid.Cid) (BadBlockReason, bool) {
rval, ok := bts.badBlocks.Get(c)
if !ok {
return "", false
return BadBlockReason{}, false
}
return rval.(string), true
return rval.(BadBlockReason), true
}
+4
View File
@@ -17,6 +17,10 @@ type Response struct {
Err error
}
// RandomBeacon represents a system that provides randomness to Lotus.
// Other components interrogate the RandomBeacon to acquire randomness that's
// valid for a specific chain epoch. Also to verify beacon entries that have
// been posted on chain.
type RandomBeacon interface {
Entry(context.Context, uint64) <-chan Response
VerifyEntry(types.BeaconEntry, types.BeaconEntry) error
+83 -125
View File
@@ -1,48 +1,33 @@
package drand
import (
"bytes"
"context"
"math/rand"
"sync"
"time"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/beacon"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/abi"
dchain "github.com/drand/drand/chain"
dclient "github.com/drand/drand/client"
hclient "github.com/drand/drand/client/http"
dlog "github.com/drand/drand/log"
gclient "github.com/drand/drand/lp2p/client"
"github.com/drand/kyber"
kzap "github.com/go-kit/kit/log/zap"
"go.uber.org/zap/zapcore"
"golang.org/x/xerrors"
logging "github.com/ipfs/go-log"
pubsub "github.com/libp2p/go-libp2p-pubsub"
dbeacon "github.com/drand/drand/beacon"
"github.com/drand/drand/core"
dkey "github.com/drand/drand/key"
dnet "github.com/drand/drand/net"
dproto "github.com/drand/drand/protobuf/drand"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/lotus/chain/beacon"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes"
)
var log = logging.Logger("drand")
var drandServers = []string{
"nicolas.drand.fil-test.net:443",
"philipp.drand.fil-test.net:443",
"mathilde.drand.fil-test.net:443",
"ludovic.drand.fil-test.net:443",
"gabbi.drand.fil-test.net:443",
"linus.drand.fil-test.net:443",
"jeff.drand.fil-test.net:443",
}
var drandPubKey *dkey.DistPublic
func init() {
drandPubKey = new(dkey.DistPublic)
err := drandPubKey.FromTOML(&dkey.DistPublicTOML{Coefficients: build.DrandCoeffs})
if err != nil {
panic(err)
}
}
type drandPeer struct {
addr string
tls bool
@@ -56,14 +41,17 @@ func (dp *drandPeer) IsTLS() bool {
return dp.tls
}
// DrandBeacon connects Lotus with a drand network in order to provide
// randomness to the system in a way that's aligned with Filecoin rounds/epochs.
//
// We connect to drand peers via their public HTTP endpoints. The peers are
// enumerated in the drandServers variable.
//
// The root trust for the Drand chain is configured from build.DrandChain.
type DrandBeacon struct {
client dnet.Client
client dclient.Client
peers []dnet.Peer
peersIndex int
peersIndexMtx sync.Mutex
pubkey *dkey.DistPublic
pubkey kyber.Point
// seconds
interval time.Duration
@@ -76,120 +64,91 @@ type DrandBeacon struct {
localCache map[uint64]types.BeaconEntry
}
func NewDrandBeacon(genesisTs, interval uint64) (*DrandBeacon, error) {
func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes.DrandConfig) (*DrandBeacon, error) {
if genesisTs == 0 {
panic("what are you doing this cant be zero")
}
drandChain, err := dchain.InfoFromJSON(bytes.NewReader([]byte(config.ChainInfoJSON)))
if err != nil {
return nil, xerrors.Errorf("unable to unmarshal drand chain info: %w", err)
}
dlogger := dlog.NewKitLoggerFrom(kzap.NewZapSugarLogger(
log.SugaredLogger.Desugar(), zapcore.InfoLevel))
var clients []dclient.Client
for _, url := range config.Servers {
hc, err := hclient.NewWithInfo(url, drandChain, nil)
if err != nil {
return nil, xerrors.Errorf("could not create http drand client: %w", err)
}
clients = append(clients, hc)
}
opts := []dclient.Option{
dclient.WithChainInfo(drandChain),
dclient.WithCacheSize(1024),
dclient.WithLogger(dlogger),
dclient.WithAutoWatch(),
}
if ps != nil {
opts = append(opts, gclient.WithPubsub(ps))
} else {
log.Info("drand beacon without pubsub")
}
client, err := dclient.Wrap(clients, opts...)
if err != nil {
return nil, xerrors.Errorf("creating drand client")
}
db := &DrandBeacon{
client: dnet.NewGrpcClient(),
client: client,
localCache: make(map[uint64]types.BeaconEntry),
}
for _, ds := range drandServers {
db.peers = append(db.peers, &drandPeer{addr: ds, tls: true})
}
db.peersIndex = rand.Intn(len(db.peers))
groupResp, err := db.client.Group(context.TODO(), db.peers[db.peersIndex], &dproto.GroupRequest{})
if err != nil {
return nil, xerrors.Errorf("failed to get group response from beacon peer: %w", err)
}
kgroup, err := core.ProtoToGroup(groupResp)
if err != nil {
return nil, xerrors.Errorf("failed to parse group response: %w", err)
}
// TODO: verify these values are what we expect them to be
if !kgroup.PublicKey.Equal(drandPubKey) {
return nil, xerrors.Errorf("public key does not match")
}
// fmt.Printf("Drand Pubkey:\n%#v\n", kgroup.PublicKey.TOML()) // use to print public key
db.pubkey = drandPubKey
db.interval = kgroup.Period
db.drandGenTime = uint64(kgroup.GenesisTime)
db.pubkey = drandChain.PublicKey
db.interval = drandChain.Period
db.drandGenTime = uint64(drandChain.GenesisTime)
db.filRoundTime = interval
db.filGenTime = genesisTs
// TODO: the stream currently gives you back *all* values since drand genesis.
// Having the stream in the background is merely an optimization, so not a big deal to disable it for now
// go db.handleStreamingUpdates()
return db, nil
}
func (db *DrandBeacon) rotatePeersIndex() {
db.peersIndexMtx.Lock()
nval := rand.Intn(len(db.peers))
db.peersIndex = nval
db.peersIndexMtx.Unlock()
log.Warnf("rotated to drand peer %d, %q", nval, db.peers[nval].Address())
}
func (db *DrandBeacon) getPeerIndex() int {
db.peersIndexMtx.Lock()
defer db.peersIndexMtx.Unlock()
return db.peersIndex
}
func (db *DrandBeacon) handleStreamingUpdates() {
for {
p := db.peers[db.getPeerIndex()]
ch, err := db.client.PublicRandStream(context.Background(), p, &dproto.PublicRandRequest{})
if err != nil {
log.Warnf("failed to get public rand stream to peer %q: %s", p.Address(), err)
log.Warnf("trying again in 10 seconds")
db.rotatePeersIndex()
time.Sleep(time.Second * 10)
continue
}
for e := range ch {
db.cacheValue(types.BeaconEntry{
Round: e.Round,
Data: e.Signature,
})
}
log.Warnf("drand beacon stream to peer %q broke, reconnecting in 10 seconds", p.Address())
db.rotatePeersIndex()
time.Sleep(time.Second * 10)
}
}
func (db *DrandBeacon) Entry(ctx context.Context, round uint64) <-chan beacon.Response {
// check cache, it it if there, otherwise query the endpoint
cres := db.getCachedValue(round)
if cres != nil {
out := make(chan beacon.Response, 1)
out <- beacon.Response{Entry: *cres}
close(out)
return out
}
out := make(chan beacon.Response, 1)
if round != 0 {
be := db.getCachedValue(round)
if be != nil {
out <- beacon.Response{Entry: *be}
close(out)
return out
}
}
go func() {
p := db.peers[db.getPeerIndex()]
resp, err := db.client.PublicRand(ctx, p, &dproto.PublicRandRequest{Round: round})
start := time.Now()
log.Infow("start fetching randomness", "round", round)
resp, err := db.client.Get(ctx, round)
var br beacon.Response
if err != nil {
db.rotatePeersIndex()
br.Err = xerrors.Errorf("drand peer %q failed publicRand request: %w", p.Address(), err)
br.Err = xerrors.Errorf("drand failed Get request: %w", err)
} else {
br.Entry.Round = resp.GetRound()
br.Entry.Data = resp.GetSignature()
br.Entry.Round = resp.Round()
br.Entry.Data = resp.Signature()
}
log.Infow("done fetching randomness", "round", round, "took", time.Since(start))
out <- br
close(out)
}()
return out
}
func (db *DrandBeacon) cacheValue(e types.BeaconEntry) {
db.cacheLk.Lock()
defer db.cacheLk.Unlock()
@@ -211,13 +170,12 @@ func (db *DrandBeacon) VerifyEntry(curr types.BeaconEntry, prev types.BeaconEntr
// TODO handle genesis better
return nil
}
b := &dbeacon.Beacon{
b := &dchain.Beacon{
PreviousSig: prev.Data,
Round: curr.Round,
Signature: curr.Data,
}
//log.Warnw("VerifyEntry", "beacon", b)
err := dbeacon.VerifyBeacon(db.pubkey.Key(), b)
err := dchain.VerifyBeacon(db.pubkey, b)
if err == nil {
db.cacheValue(curr)
}
+18 -7
View File
@@ -1,14 +1,25 @@
package drand
import (
"fmt"
"os"
"testing"
dchain "github.com/drand/drand/chain"
hclient "github.com/drand/drand/client/http"
"github.com/stretchr/testify/assert"
"github.com/filecoin-project/lotus/build"
)
func TestPrintDrandPubkey(t *testing.T) {
bc, err := NewDrandBeacon(1, 1)
if err != nil {
t.Fatal(err)
}
fmt.Printf("Drand Pubkey:\n%#v\n", bc.pubkey.TOML())
func TestPrintGroupInfo(t *testing.T) {
server := build.DrandConfig.Servers[0]
c, err := hclient.New(server, nil, nil)
assert.NoError(t, err)
cg := c.(interface {
FetchChainInfo(groupHash []byte) (*dchain.Info, error)
})
chain, err := cg.FetchChainInfo(nil)
assert.NoError(t, err)
err = chain.ToJSON(os.Stdout)
assert.NoError(t, err)
}
+21 -2
View File
@@ -10,6 +10,7 @@ import (
"golang.org/x/xerrors"
cborutil "github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
@@ -27,6 +28,24 @@ const BlockSyncProtocolID = "/fil/sync/blk/0.0.1"
const BlockSyncMaxRequestLength = 800
// BlockSyncService is the component that services BlockSync requests from
// peers.
//
// BlockSync is the basic chain synchronization protocol of Filecoin. BlockSync
// is an RPC-oriented protocol, with a single operation to request blocks.
//
// A request contains a start anchor block (referred to with a CID), and a
// amount of blocks requested beyond the anchor (including the anchor itself).
//
// A client can also pass options, encoded as a 64-bit bitfield. Lotus supports
// two options at the moment:
//
// - include block contents
// - include block messages
//
// The response will include a status code, an optional message, and the
// response payload in case of success. The payload is a slice of serialized
// tipsets.
type BlockSyncService struct {
cs *store.ChainStore
}
@@ -91,7 +110,7 @@ func (bss *BlockSyncService) HandleStream(s inet.Stream) {
ctx, span := trace.StartSpan(context.Background(), "blocksync.HandleStream")
defer span.End()
defer s.Close()
defer s.Close() //nolint:errcheck
var req BlockSyncRequest
if err := cborutil.ReadCborRPC(bufio.NewReader(s), &req); err != nil {
@@ -107,7 +126,7 @@ func (bss *BlockSyncService) HandleStream(s inet.Stream) {
}
writeDeadline := 60 * time.Second
s.SetDeadline(time.Now().Add(writeDeadline))
_ = s.SetDeadline(time.Now().Add(writeDeadline))
if err := cborutil.WriteCborRPC(s, resp); err != nil {
log.Warnw("failed to write back response for handle stream", "err", err, "peer", s.Conn().RemotePeer())
return
+24 -12
View File
@@ -64,6 +64,11 @@ func (bs *BlockSync) processStatus(req *BlockSyncRequest, res *BlockSyncResponse
}
}
// GetBlocks fetches count blocks from the network, from the provided tipset
// *backwards*, returning as many tipsets as count.
//
// {hint/usage}: This is used by the Syncer during normal chain syncing and when
// resolving forks.
func (bs *BlockSync) GetBlocks(ctx context.Context, tsk types.TipSetKey, count int) ([]*types.TipSet, error) {
ctx, span := trace.StartSpan(ctx, "bsync.GetBlocks")
defer span.End()
@@ -80,7 +85,9 @@ func (bs *BlockSync) GetBlocks(ctx context.Context, tsk types.TipSetKey, count i
Options: BSOptBlocks,
}
// this peerset is sorted by latency and failure counting.
peers := bs.getPeers()
// randomize the first few peers so we don't always pick the same peer
shufflePrefix(peers)
@@ -283,14 +290,14 @@ func (bs *BlockSync) fetchBlocksBlockSync(ctx context.Context, p peer.ID, req *B
bs.RemovePeer(p)
return nil, xerrors.Errorf("failed to open stream to peer: %w", err)
}
s.SetWriteDeadline(time.Now().Add(5 * time.Second))
_ = s.SetWriteDeadline(time.Now().Add(5 * time.Second))
if err := cborutil.WriteCborRPC(s, req); err != nil {
s.SetWriteDeadline(time.Time{})
_ = s.SetWriteDeadline(time.Time{})
bs.syncPeers.logFailure(p, time.Since(start))
return nil, err
}
s.SetWriteDeadline(time.Time{})
_ = s.SetWriteDeadline(time.Time{})
var res BlockSyncResponse
r := incrt.New(s, 50<<10, 5*time.Second)
@@ -356,6 +363,7 @@ func (bs *BlockSync) RemovePeer(p peer.ID) {
bs.syncPeers.removePeer(p)
}
// getPeers returns a preference-sorted set of peers to query.
func (bs *BlockSync) getPeers() []peer.ID {
return bs.syncPeers.prefSortedPeers()
}
@@ -561,26 +569,30 @@ func (bpt *bsPeerTracker) logSuccess(p peer.ID, dur time.Duration) {
bpt.lk.Lock()
defer bpt.lk.Unlock()
if pi, ok := bpt.peers[p]; !ok {
var pi *peerStats
var ok bool
if pi, ok = bpt.peers[p]; !ok {
log.Warnw("log success called on peer not in tracker", "peerid", p.String())
return
} else {
pi.successes++
logTime(pi, dur)
}
pi.successes++
logTime(pi, dur)
}
func (bpt *bsPeerTracker) logFailure(p peer.ID, dur time.Duration) {
bpt.lk.Lock()
defer bpt.lk.Unlock()
if pi, ok := bpt.peers[p]; !ok {
var pi *peerStats
var ok bool
if pi, ok = bpt.peers[p]; !ok {
log.Warn("log failure called on peer not in tracker", "peerid", p.String())
return
} else {
pi.failures++
logTime(pi, dur)
}
pi.failures++
logTime(pi, dur)
}
func (bpt *bsPeerTracker) removePeer(p peer.ID) {
+10 -21
View File
@@ -19,7 +19,7 @@ import (
var log = logging.Logger("events")
// `curH`-`ts.Height` = `confidence`
// HeightHandler `curH`-`ts.Height` = `confidence`
type HeightHandler func(ctx context.Context, ts *types.TipSet, curH abi.ChainEpoch) error
type RevertHandler func(ctx context.Context, ts *types.TipSet) error
@@ -31,7 +31,7 @@ type heightHandler struct {
revert RevertHandler
}
type eventApi interface {
type eventAPI interface {
ChainNotify(context.Context) (<-chan []*api.HeadChange, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
@@ -42,7 +42,7 @@ type eventApi interface {
}
type Events struct {
api eventApi
api eventAPI
tsc *tipSetCache
lk sync.Mutex
@@ -51,10 +51,10 @@ type Events struct {
readyOnce sync.Once
heightEvents
calledEvents
*hcEvents
}
func NewEvents(ctx context.Context, api eventApi) *Events {
func NewEvents(ctx context.Context, api eventAPI) *Events {
gcConfidence := 2 * build.ForkLengthThreshold
tsc := newTSCache(gcConfidence, api.ChainGetTipSetByHeight)
@@ -67,25 +67,14 @@ func NewEvents(ctx context.Context, api eventApi) *Events {
heightEvents: heightEvents{
tsc: tsc,
ctx: ctx,
gcConfidence: abi.ChainEpoch(gcConfidence),
gcConfidence: gcConfidence,
heightTriggers: map[uint64]*heightHandler{},
htTriggerHeights: map[abi.ChainEpoch][]uint64{},
htHeights: map[abi.ChainEpoch][]uint64{},
},
calledEvents: calledEvents{
cs: api,
tsc: tsc,
ctx: ctx,
gcConfidence: uint64(gcConfidence),
confQueue: map[triggerH]map[msgH][]*queuedEvent{},
revertQueue: map[msgH][]triggerH{},
triggers: map[triggerId]*callHandler{},
matchers: map[triggerId][]MatchFunc{},
timeouts: map[abi.ChainEpoch]map[triggerId]int{},
},
hcEvents: newHCEvents(ctx, api, tsc, uint64(gcConfidence)),
}
e.ready.Add(1)
@@ -143,7 +132,7 @@ func (e *Events) listenHeadChangesOnce(ctx context.Context) error {
}
e.readyOnce.Do(func() {
e.at = cur[0].Val.Height()
e.lastTs = cur[0].Val
e.ready.Done()
})
@@ -166,7 +155,7 @@ func (e *Events) listenHeadChangesOnce(ctx context.Context) error {
}
// sync with fake chainstore (for tests)
if fcs, ok := e.api.(interface{notifDone()}); ok {
if fcs, ok := e.api.(interface{ notifDone() }); ok {
fcs.notifDone()
}
}
@@ -186,5 +175,5 @@ func (e *Events) headChange(rev, app []*types.TipSet) error {
return err
}
return e.headChangeCalled(rev, app)
return e.processHeadChangeEvent(rev, app)
}
+373 -118
View File
@@ -13,8 +13,9 @@ import (
)
const NoTimeout = math.MaxInt64
const NoHeight = abi.ChainEpoch(-1)
type triggerId = uint64
type triggerID = uint64
// msgH is the block height at which a message was present / event has happened
type msgH = abi.ChainEpoch
@@ -23,53 +24,60 @@ type msgH = abi.ChainEpoch
// message (msgH+confidence)
type triggerH = abi.ChainEpoch
// `ts` is the tipset, in which the `msg` is included.
type eventData interface{}
// EventHandler arguments:
// `prevTs` is the previous tipset, eg the "from" tipset for a state change.
// `ts` is the event tipset, eg the tipset in which the `msg` is included.
// `curH`-`ts.Height` = `confidence`
type CalledHandler func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (more bool, err error)
type EventHandler func(data eventData, prevTs, ts *types.TipSet, curH abi.ChainEpoch) (more bool, err error)
// CheckFunc is used for atomicity guarantees. If the condition the callbacks
// wait for has already happened in tipset `ts`
//
// If `done` is true, timeout won't be triggered
// If `more` is false, no messages will be sent to CalledHandler (RevertHandler
// If `more` is false, no messages will be sent to EventHandler (RevertHandler
// may still be called)
type CheckFunc func(ts *types.TipSet) (done bool, more bool, err error)
type MatchFunc func(msg *types.Message) (bool, error)
type callHandler struct {
// Keep track of information for an event handler
type handlerInfo struct {
confidence int
timeout abi.ChainEpoch
disabled bool // TODO: GC after gcConfidence reached
handle CalledHandler
handle EventHandler
revert RevertHandler
}
// When a change occurs, a queuedEvent is created and put into a queue
// until the required confidence is reached
type queuedEvent struct {
trigger triggerId
trigger triggerID
h abi.ChainEpoch
msg *types.Message
prevH abi.ChainEpoch
h abi.ChainEpoch
data eventData
called bool
}
type calledEvents struct {
cs eventApi
// Manages chain head change events, which may be forward (new tipset added to
// chain) or backward (chain branch discarded in favour of heavier branch)
type hcEvents struct {
cs eventAPI
tsc *tipSetCache
ctx context.Context
gcConfidence uint64
at abi.ChainEpoch
lastTs *types.TipSet
lk sync.Mutex
ctr triggerId
ctr triggerID
triggers map[triggerId]*callHandler
matchers map[triggerId][]MatchFunc
triggers map[triggerID]*handlerInfo
// maps block heights to events
// [triggerH][msgH][event]
@@ -78,29 +86,81 @@ type calledEvents struct {
// [msgH][triggerH]
revertQueue map[msgH][]triggerH
// [timeoutH+confidence][triggerId]{calls}
timeouts map[abi.ChainEpoch]map[triggerId]int
// [timeoutH+confidence][triggerID]{calls}
timeouts map[abi.ChainEpoch]map[triggerID]int
messageEvents
watcherEvents
}
func (e *calledEvents) headChangeCalled(rev, app []*types.TipSet) error {
func newHCEvents(ctx context.Context, cs eventAPI, tsc *tipSetCache, gcConfidence uint64) *hcEvents {
e := hcEvents{
ctx: ctx,
cs: cs,
tsc: tsc,
gcConfidence: gcConfidence,
confQueue: map[triggerH]map[msgH][]*queuedEvent{},
revertQueue: map[msgH][]triggerH{},
triggers: map[triggerID]*handlerInfo{},
timeouts: map[abi.ChainEpoch]map[triggerID]int{},
}
e.messageEvents = newMessageEvents(ctx, &e, cs)
e.watcherEvents = newWatcherEvents(ctx, &e, cs)
return &e
}
// Called when there is a change to the head with tipsets to be
// reverted / applied
func (e *hcEvents) processHeadChangeEvent(rev, app []*types.TipSet) error {
e.lk.Lock()
defer e.lk.Unlock()
for _, ts := range rev {
e.handleReverts(ts)
e.at = ts.Height()
e.lastTs = ts
}
for _, ts := range app {
// called triggers
e.checkNewCalls(ts)
for ; e.at <= ts.Height(); e.at++ {
e.applyWithConfidence(ts, e.at)
// Check if the head change caused any state changes that we were
// waiting for
stateChanges := e.watcherEvents.checkStateChanges(e.lastTs, ts)
// Queue up calls until there have been enough blocks to reach
// confidence on the state changes
for tid, data := range stateChanges {
e.queueForConfidence(tid, data, e.lastTs, ts)
}
// Check if the head change included any new message calls
newCalls, err := e.messageEvents.checkNewCalls(ts)
if err != nil {
return err
}
// Queue up calls until there have been enough blocks to reach
// confidence on the message calls
for tid, data := range newCalls {
e.queueForConfidence(tid, data, nil, ts)
}
for at := e.lastTs.Height(); at <= ts.Height(); at++ {
// Apply any queued events and timeouts that were targeted at the
// current chain height
e.applyWithConfidence(ts, at)
e.applyTimeouts(ts)
}
// Update the latest known tipset
e.lastTs = ts
}
return nil
}
func (e *calledEvents) handleReverts(ts *types.TipSet) {
func (e *hcEvents) handleReverts(ts *types.TipSet) {
reverts, ok := e.revertQueue[ts.Height()]
if !ok {
return // nothing to do
@@ -116,7 +176,7 @@ func (e *calledEvents) handleReverts(ts *types.TipSet) {
trigger := e.triggers[event.trigger]
if err := trigger.revert(e.ctx, ts); err != nil {
log.Errorf("reverting chain trigger (call %s.%d() @H %d, called @ %d) failed: %s", event.msg.To, event.msg.Method, ts.Height(), triggerH, err)
log.Errorf("reverting chain trigger (@H %d, triggered @ %d) failed: %s", ts.Height(), triggerH, err)
}
}
delete(e.confQueue[triggerH], ts.Height())
@@ -124,42 +184,15 @@ func (e *calledEvents) handleReverts(ts *types.TipSet) {
delete(e.revertQueue, ts.Height())
}
func (e *calledEvents) checkNewCalls(ts *types.TipSet) {
pts, err := e.cs.ChainGetTipSet(e.ctx, ts.Parents()) // we actually care about messages in the parent tipset here
if err != nil {
log.Errorf("getting parent tipset in checkNewCalls: %s", err)
return
// Queue up events until the chain has reached a height that reflects the
// desired confidence
func (e *hcEvents) queueForConfidence(trigID uint64, data eventData, prevTs, ts *types.TipSet) {
trigger := e.triggers[trigID]
prevH := NoHeight
if prevTs != nil {
prevH = prevTs.Height()
}
e.messagesForTs(pts, func(msg *types.Message) {
// TODO: provide receipts
for tid, matchFns := range e.matchers {
var matched bool
for _, matchFn := range matchFns {
ok, err := matchFn(msg)
if err != nil {
log.Errorf("event matcher failed: %s", err)
continue
}
matched = ok
if matched {
break
}
}
if matched {
e.queueForConfidence(tid, msg, ts)
break
}
}
})
}
func (e *calledEvents) queueForConfidence(triggerId uint64, msg *types.Message, ts *types.TipSet) {
trigger := e.triggers[triggerId]
appliedH := ts.Height()
triggerH := appliedH + abi.ChainEpoch(trigger.confidence)
@@ -171,18 +204,20 @@ func (e *calledEvents) queueForConfidence(triggerId uint64, msg *types.Message,
}
byOrigH[appliedH] = append(byOrigH[appliedH], &queuedEvent{
trigger: triggerId,
trigger: trigID,
prevH: prevH,
h: appliedH,
msg: msg,
data: data,
})
e.revertQueue[appliedH] = append(e.revertQueue[appliedH], triggerH)
}
func (e *calledEvents) applyWithConfidence(ts *types.TipSet, height abi.ChainEpoch) {
// Apply any events that were waiting for this chain height for confidence
func (e *hcEvents) applyWithConfidence(ts *types.TipSet, height abi.ChainEpoch) {
byOrigH, ok := e.confQueue[height]
if !ok {
return // no triggers at thin height
return // no triggers at this height
}
for origH, events := range byOrigH {
@@ -201,15 +236,20 @@ func (e *calledEvents) applyWithConfidence(ts *types.TipSet, height abi.ChainEpo
continue
}
rec, err := e.cs.StateGetReceipt(e.ctx, event.msg.Cid(), ts.Key())
if err != nil {
log.Error(err)
return
// Previous tipset - this is relevant for example in a state change
// from one tipset to another
var prevTs *types.TipSet
if event.prevH != NoHeight {
prevTs, err = e.tsc.get(event.prevH)
if err != nil {
log.Errorf("events: applyWithConfidence didn't find tipset for previous event; wanted %d; current %d", event.prevH, height)
continue
}
}
more, err := trigger.handle(event.msg, rec, triggerTs, height)
more, err := trigger.handle(event.data, prevTs, triggerTs, height)
if err != nil {
log.Errorf("chain trigger (call %s.%d() @H %d, called @ %d) failed: %s", event.msg.To, event.msg.Method, origH, height, err)
log.Errorf("chain trigger (@H %d, triggered @ %d) failed: %s", origH, height, err)
continue // don't revert failed calls
}
@@ -225,17 +265,18 @@ func (e *calledEvents) applyWithConfidence(ts *types.TipSet, height abi.ChainEpo
}
}
func (e *calledEvents) applyTimeouts(ts *types.TipSet) {
// Apply any timeouts that expire at this height
func (e *hcEvents) applyTimeouts(ts *types.TipSet) {
triggers, ok := e.timeouts[ts.Height()]
if !ok {
return // nothing to do
}
for triggerId, calls := range triggers {
for triggerID, calls := range triggers {
if calls > 0 {
continue // don't timeout if the method was called
}
trigger := e.triggers[triggerId]
trigger := e.triggers[triggerID]
if trigger.disabled {
continue
}
@@ -255,12 +296,225 @@ func (e *calledEvents) applyTimeouts(ts *types.TipSet) {
}
}
func (e *calledEvents) messagesForTs(ts *types.TipSet, consume func(*types.Message)) {
// Listen for an event
// - CheckFunc: immediately checks if the event already occurred
// - EventHandler: called when the event has occurred, after confidence tipsets
// - RevertHandler: called if the chain head changes causing the event to revert
// - confidence: wait this many tipsets before calling EventHandler
// - timeout: at this chain height, timeout on waiting for this event
func (e *hcEvents) onHeadChanged(check CheckFunc, hnd EventHandler, rev RevertHandler, confidence int, timeout abi.ChainEpoch) (triggerID, error) {
e.lk.Lock()
defer e.lk.Unlock()
// Check if the event has already occurred
ts := e.tsc.best()
done, more, err := check(ts)
if err != nil {
return 0, xerrors.Errorf("called check error (h: %d): %w", ts.Height(), err)
}
if done {
timeout = NoTimeout
}
// Create a trigger for the event
id := e.ctr
e.ctr++
e.triggers[id] = &handlerInfo{
confidence: confidence,
timeout: timeout + abi.ChainEpoch(confidence),
disabled: !more,
handle: hnd,
revert: rev,
}
// If there's a timeout, set up a timeout check at that height
if timeout != NoTimeout {
if e.timeouts[timeout+abi.ChainEpoch(confidence)] == nil {
e.timeouts[timeout+abi.ChainEpoch(confidence)] = map[uint64]int{}
}
e.timeouts[timeout+abi.ChainEpoch(confidence)][id] = 0
}
return id, nil
}
// headChangeAPI is used to allow the composed event APIs to call back to hcEvents
// to listen for changes
type headChangeAPI interface {
onHeadChanged(check CheckFunc, hnd EventHandler, rev RevertHandler, confidence int, timeout abi.ChainEpoch) (triggerID, error)
}
// watcherEvents watches for a state change
type watcherEvents struct {
ctx context.Context
cs eventAPI
hcAPI headChangeAPI
lk sync.RWMutex
matchers map[triggerID]StateMatchFunc
}
func newWatcherEvents(ctx context.Context, hcAPI headChangeAPI, cs eventAPI) watcherEvents {
return watcherEvents{
ctx: ctx,
cs: cs,
hcAPI: hcAPI,
matchers: make(map[triggerID]StateMatchFunc),
}
}
// Run each of the matchers against the previous and current state to see if
// there's a change
func (we *watcherEvents) checkStateChanges(oldState, newState *types.TipSet) map[triggerID]eventData {
we.lk.RLock()
defer we.lk.RUnlock()
res := make(map[triggerID]eventData)
for tid, matchFn := range we.matchers {
ok, data, err := matchFn(oldState, newState)
if err != nil {
log.Errorf("event diff fn failed: %s", err)
continue
}
if ok {
res[tid] = data
}
}
return res
}
// StateChange represents a change in state
type StateChange interface{}
// StateChangeHandler arguments:
// `oldTs` is the state "from" tipset
// `newTs` is the state "to" tipset
// `states` is the change in state
// `curH`-`ts.Height` = `confidence`
type StateChangeHandler func(oldTs, newTs *types.TipSet, states StateChange, curH abi.ChainEpoch) (more bool, err error)
type StateMatchFunc func(oldTs, newTs *types.TipSet) (bool, StateChange, error)
// StateChanged registers a callback which is triggered when a specified state
// change occurs or a timeout is reached.
//
// * `CheckFunc` callback is invoked immediately with a recent tipset, it
// returns two booleans - `done`, and `more`.
//
// * `done` should be true when some on-chain state change we are waiting
// for has happened. When `done` is set to true, timeout trigger is disabled.
//
// * `more` should be false when we don't want to receive new notifications
// through StateChangeHandler. Note that notifications may still be delivered to
// RevertHandler
//
// * `StateChangeHandler` is called when the specified state change was observed
// on-chain, and a confidence threshold was reached, or the specified `timeout`
// height was reached with no state change observed. When this callback is
// invoked on a timeout, `oldState` and `newState` are set to nil.
// This callback returns a boolean specifying whether further notifications
// should be sent, like `more` return param from `CheckFunc` above.
//
// * `RevertHandler` is called after apply handler, when we drop the tipset
// containing the message. The tipset passed as the argument is the tipset
// that is being dropped. Note that the event dropped may be re-applied
// in a different tipset in small amount of time.
//
// * `StateMatchFunc` is called against each tipset state. If there is a match,
// the state change is queued up until the confidence interval has elapsed (and
// `StateChangeHandler` is called)
func (we *watcherEvents) StateChanged(check CheckFunc, scHnd StateChangeHandler, rev RevertHandler, confidence int, timeout abi.ChainEpoch, mf StateMatchFunc) error {
hnd := func(data eventData, prevTs, ts *types.TipSet, height abi.ChainEpoch) (bool, error) {
states, ok := data.(StateChange)
if data != nil && !ok {
panic("expected StateChange")
}
return scHnd(prevTs, ts, states, height)
}
id, err := we.hcAPI.onHeadChanged(check, hnd, rev, confidence, timeout)
if err != nil {
return err
}
we.lk.Lock()
defer we.lk.Unlock()
we.matchers[id] = mf
return nil
}
// messageEvents watches for message calls to actors
type messageEvents struct {
ctx context.Context
cs eventAPI
hcAPI headChangeAPI
lk sync.RWMutex
matchers map[triggerID][]MsgMatchFunc
}
func newMessageEvents(ctx context.Context, hcAPI headChangeAPI, cs eventAPI) messageEvents {
return messageEvents{
ctx: ctx,
cs: cs,
hcAPI: hcAPI,
matchers: map[triggerID][]MsgMatchFunc{},
}
}
// Check if there are any new actor calls
func (me *messageEvents) checkNewCalls(ts *types.TipSet) (map[triggerID]eventData, error) {
pts, err := me.cs.ChainGetTipSet(me.ctx, ts.Parents()) // we actually care about messages in the parent tipset here
if err != nil {
log.Errorf("getting parent tipset in checkNewCalls: %s", err)
return nil, err
}
me.lk.RLock()
defer me.lk.RUnlock()
res := make(map[triggerID]eventData)
me.messagesForTs(pts, func(msg *types.Message) {
// TODO: provide receipts
for tid, matchFns := range me.matchers {
var matched bool
for _, matchFn := range matchFns {
ok, err := matchFn(msg)
if err != nil {
log.Errorf("event matcher failed: %s", err)
continue
}
matched = ok
if matched {
break
}
}
if matched {
res[tid] = msg
break
}
}
})
return res, nil
}
// Get the messages in a tipset
func (me *messageEvents) messagesForTs(ts *types.TipSet, consume func(*types.Message)) {
seen := map[cid.Cid]struct{}{}
for _, tsb := range ts.Blocks() {
msgs, err := e.cs.ChainGetBlockMessages(context.TODO(), tsb.Cid())
msgs, err := me.cs.ChainGetBlockMessages(context.TODO(), tsb.Cid())
if err != nil {
log.Errorf("messagesForTs MessagesForBlock failed (ts.H=%d, Bcid:%s, B.Mcid:%s): %s", ts.Height(), tsb.Cid(), tsb.Messages, err)
// this is quite bad, but probably better than missing all the other updates
@@ -289,20 +543,27 @@ func (e *calledEvents) messagesForTs(ts *types.TipSet, consume func(*types.Messa
}
}
// Called registers a callbacks which are triggered when a specified method is
// MsgHandler arguments:
// `ts` is the tipset, in which the `msg` is included.
// `curH`-`ts.Height` = `confidence`
type MsgHandler func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (more bool, err error)
type MsgMatchFunc func(msg *types.Message) (bool, error)
// Called registers a callback which is triggered when a specified method is
// called on an actor, or a timeout is reached.
//
// * `CheckFunc` callback is invoked immediately with a recent tipset, it
// returns two booleans - `done`, and `more`.
//
// * `done` should be true when some on-chain action we are waiting for has
// happened. When `done` is set to true, timeout trigger is disabled.
// * `done` should be true when some on-chain action we are waiting for has
// happened. When `done` is set to true, timeout trigger is disabled.
//
// * `more` should be false when we don't want to receive new notifications
// through CalledHandler. Note that notifications may still be delivered to
// RevertHandler
// * `more` should be false when we don't want to receive new notifications
// through MsgHandler. Note that notifications may still be delivered to
// RevertHandler
//
// * `CalledHandler` is called when the specified event was observed on-chain,
// * `MsgHandler` is called when the specified event was observed on-chain,
// and a confidence threshold was reached, or the specified `timeout` height
// was reached with no events observed. When this callback is invoked on a
// timeout, `msg` is set to nil. This callback returns a boolean specifying
@@ -313,44 +574,38 @@ func (e *calledEvents) messagesForTs(ts *types.TipSet, consume func(*types.Messa
// containing the message. The tipset passed as the argument is the tipset
// that is being dropped. Note that the message dropped may be re-applied
// in a different tipset in small amount of time.
func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHandler, confidence int, timeout abi.ChainEpoch, mf MatchFunc) error {
e.lk.Lock()
defer e.lk.Unlock()
ts := e.tsc.best()
done, more, err := check(ts)
if err != nil {
return xerrors.Errorf("called check error (h: %d): %w", ts.Height(), err)
}
if done {
timeout = NoTimeout
}
id := e.ctr
e.ctr++
e.triggers[id] = &callHandler{
confidence: confidence,
timeout: timeout + abi.ChainEpoch(confidence),
disabled: !more,
handle: hnd,
revert: rev,
}
e.matchers[id] = append(e.matchers[id], mf)
if timeout != NoTimeout {
if e.timeouts[timeout+abi.ChainEpoch(confidence)] == nil {
e.timeouts[timeout+abi.ChainEpoch(confidence)] = map[uint64]int{}
//
// * `MsgMatchFunc` is called against each message. If there is a match, the
// message is queued up until the confidence interval has elapsed (and
// `MsgHandler` is called)
func (me *messageEvents) Called(check CheckFunc, msgHnd MsgHandler, rev RevertHandler, confidence int, timeout abi.ChainEpoch, mf MsgMatchFunc) error {
hnd := func(data eventData, prevTs, ts *types.TipSet, height abi.ChainEpoch) (bool, error) {
msg, ok := data.(*types.Message)
if data != nil && !ok {
panic("expected msg")
}
e.timeouts[timeout+abi.ChainEpoch(confidence)][id] = 0
rec, err := me.cs.StateGetReceipt(me.ctx, msg.Cid(), ts.Key())
if err != nil {
return false, err
}
return msgHnd(msg, rec, ts, height)
}
id, err := me.hcAPI.onHeadChanged(check, hnd, rev, confidence, timeout)
if err != nil {
return err
}
me.lk.Lock()
defer me.lk.Unlock()
me.matchers[id] = append(me.matchers[id], mf)
return nil
}
func (e *calledEvents) CalledMsg(ctx context.Context, hnd CalledHandler, rev RevertHandler, confidence int, timeout abi.ChainEpoch, msg types.ChainMsg) error {
return e.Called(e.CheckMsg(ctx, msg, hnd), hnd, rev, confidence, timeout, e.MatchMsg(msg.VMMessage()))
// Convenience function for checking and matching messages
func (me *messageEvents) CalledMsg(ctx context.Context, hnd MsgHandler, rev RevertHandler, confidence int, timeout abi.ChainEpoch, msg types.ChainMsg) error {
return me.Called(me.CheckMsg(ctx, msg, hnd), hnd, rev, confidence, timeout, me.MatchMsg(msg.VMMessage()))
}
+16 -8
View File
@@ -15,23 +15,26 @@ type heightEvents struct {
tsc *tipSetCache
gcConfidence abi.ChainEpoch
ctr triggerId
ctr triggerID
heightTriggers map[triggerId]*heightHandler
heightTriggers map[triggerID]*heightHandler
htTriggerHeights map[triggerH][]triggerId
htHeights map[msgH][]triggerId
htTriggerHeights map[triggerH][]triggerID
htHeights map[msgH][]triggerID
ctx context.Context
}
func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
ctx, span := trace.StartSpan(e.ctx, "events.HeightHeadChange")
defer span.End()
span.AddAttributes(trace.Int64Attribute("endHeight", int64(app[0].Height())))
span.AddAttributes(trace.Int64Attribute("reverts", int64(len(rev))))
span.AddAttributes(trace.Int64Attribute("applies", int64(len(app))))
e.lk.Lock()
defer e.lk.Unlock()
for _, ts := range rev {
// TODO: log error if h below gcconfidence
// revert height-based triggers
@@ -40,7 +43,10 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
for _, tid := range e.htHeights[h] {
ctx, span := trace.StartSpan(ctx, "events.HeightRevert")
err := e.heightTriggers[tid].revert(ctx, ts)
rev := e.heightTriggers[tid].revert
e.lk.Unlock()
err := rev(ctx, ts)
e.lk.Lock()
e.heightTriggers[tid].called = false
span.End()
@@ -87,7 +93,6 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
if hnd.called {
return nil
}
hnd.called = true
triggerH := h - abi.ChainEpoch(hnd.confidence)
@@ -98,8 +103,11 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
ctx, span := trace.StartSpan(ctx, "events.HeightApply")
span.AddAttributes(trace.BoolAttribute("immediate", false))
err = hnd.handle(ctx, incTs, h)
handle := hnd.handle
e.lk.Unlock()
err = handle(ctx, incTs, h)
e.lk.Lock()
hnd.called = true
span.End()
if err != nil {
+250 -6
View File
@@ -211,15 +211,14 @@ func (fcs *fakeCS) advance(rev, app int, msgs map[int]cid.Cid, nulls ...int) { /
fcs.sub(revs, apps)
fcs.sync.Lock()
fcs.sync.Unlock()
fcs.sync.Unlock() //nolint:staticcheck
}
func (fcs *fakeCS) notifDone() {
fcs.sync.Unlock()
}
var _ eventApi = &fakeCS{}
var _ eventAPI = &fakeCS{}
func TestAt(t *testing.T) {
fcs := &fakeCS{
@@ -671,7 +670,7 @@ func TestCalled(t *testing.T) {
0: n2msg,
})
require.Equal(t, true, applied) // msg from H=7, which had reverted execution
require.Equal(t, true, applied) // msg from H=7, which had reverted execution
require.Equal(t, false, reverted)
require.Equal(t, abi.ChainEpoch(10), appliedH)
applied = false
@@ -1005,8 +1004,6 @@ func TestRemoveTriggersOnMessage(t *testing.T) {
return false, true, nil
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (bool, error) {
require.Equal(t, false, applied)
fmt.Println(msg == nil)
fmt.Println(curH)
applied = true
return more, nil
}, func(_ context.Context, ts *types.TipSet) error {
@@ -1068,3 +1065,250 @@ func TestRemoveTriggersOnMessage(t *testing.T) {
require.Equal(t, true, applied)
require.Equal(t, false, reverted)
}
type testStateChange struct {
from string
to string
}
func TestStateChanged(t *testing.T) {
fcs := &fakeCS{
t: t,
h: 1,
msgs: map[cid.Cid]fakeMsg{},
blkMsgs: map[cid.Cid]cid.Cid{},
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
}
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
events := NewEvents(context.Background(), fcs)
more := true
var applied, reverted bool
var appliedData StateChange
var appliedOldTs *types.TipSet
var appliedNewTs *types.TipSet
var appliedH abi.ChainEpoch
var matchData StateChange
confidence := 3
timeout := abi.ChainEpoch(20)
err := events.StateChanged(func(ts *types.TipSet) (d bool, m bool, e error) {
return false, true, nil
}, func(oldTs, newTs *types.TipSet, data StateChange, curH abi.ChainEpoch) (bool, error) {
require.Equal(t, false, applied)
applied = true
appliedData = data
appliedOldTs = oldTs
appliedNewTs = newTs
appliedH = curH
return more, nil
}, func(_ context.Context, ts *types.TipSet) error {
reverted = true
return nil
}, confidence, timeout, func(oldTs, newTs *types.TipSet) (bool, StateChange, error) {
if matchData == nil {
return false, matchData, nil
}
d := matchData
matchData = nil
return true, d, nil
})
require.NoError(t, err)
// create few blocks to make sure nothing get's randomly called
fcs.advance(0, 4, nil) // H=5
require.Equal(t, false, applied)
require.Equal(t, false, reverted)
// create state change (but below confidence threshold)
matchData = testStateChange{from: "a", to: "b"}
fcs.advance(0, 3, nil)
require.Equal(t, false, applied)
require.Equal(t, false, reverted)
// create additional block so we are above confidence threshold
fcs.advance(0, 2, nil) // H=10 (confidence=3, apply)
require.Equal(t, true, applied)
require.Equal(t, false, reverted)
applied = false
// dip below confidence (should not apply again)
fcs.advance(2, 2, nil) // H=10 (confidence=3, apply)
require.Equal(t, false, applied)
require.Equal(t, false, reverted)
// Change happens from 5 -> 6
require.Equal(t, abi.ChainEpoch(5), appliedOldTs.Height())
require.Equal(t, abi.ChainEpoch(6), appliedNewTs.Height())
// Actually applied (with confidence) at 9
require.Equal(t, abi.ChainEpoch(9), appliedH)
// Make sure the state change was correctly passed through
rcvd := appliedData.(testStateChange)
require.Equal(t, "a", rcvd.from)
require.Equal(t, "b", rcvd.to)
}
func TestStateChangedRevert(t *testing.T) {
fcs := &fakeCS{
t: t,
h: 1,
msgs: map[cid.Cid]fakeMsg{},
blkMsgs: map[cid.Cid]cid.Cid{},
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
}
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
events := NewEvents(context.Background(), fcs)
more := true
var applied, reverted bool
var matchData StateChange
confidence := 1
timeout := abi.ChainEpoch(20)
err := events.StateChanged(func(ts *types.TipSet) (d bool, m bool, e error) {
return false, true, nil
}, func(oldTs, newTs *types.TipSet, data StateChange, curH abi.ChainEpoch) (bool, error) {
require.Equal(t, false, applied)
applied = true
return more, nil
}, func(_ context.Context, ts *types.TipSet) error {
reverted = true
return nil
}, confidence, timeout, func(oldTs, newTs *types.TipSet) (bool, StateChange, error) {
if matchData == nil {
return false, matchData, nil
}
d := matchData
matchData = nil
return true, d, nil
})
require.NoError(t, err)
fcs.advance(0, 2, nil) // H=3
// Make a state change from TS at height 3 to TS at height 4
matchData = testStateChange{from: "a", to: "b"}
fcs.advance(0, 1, nil) // H=4
// Haven't yet reached confidence
require.Equal(t, false, applied)
require.Equal(t, false, reverted)
// Advance to reach confidence level
fcs.advance(0, 1, nil) // H=5
// Should now have called the handler
require.Equal(t, true, applied)
require.Equal(t, false, reverted)
applied = false
// Advance 3 more TS
fcs.advance(0, 3, nil) // H=8
require.Equal(t, false, applied)
require.Equal(t, false, reverted)
// Regress but not so far as to cause a revert
fcs.advance(3, 1, nil) // H=6
require.Equal(t, false, applied)
require.Equal(t, false, reverted)
// Regress back to state where change happened
fcs.advance(3, 1, nil) // H=4
// Expect revert to have happened
require.Equal(t, false, applied)
require.Equal(t, true, reverted)
}
func TestStateChangedTimeout(t *testing.T) {
fcs := &fakeCS{
t: t,
h: 1,
msgs: map[cid.Cid]fakeMsg{},
blkMsgs: map[cid.Cid]cid.Cid{},
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
}
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
events := NewEvents(context.Background(), fcs)
called := false
err := events.StateChanged(func(ts *types.TipSet) (d bool, m bool, e error) {
return false, true, nil
}, func(oldTs, newTs *types.TipSet, data StateChange, curH abi.ChainEpoch) (bool, error) {
called = true
require.Nil(t, data)
require.Equal(t, abi.ChainEpoch(20), newTs.Height())
require.Equal(t, abi.ChainEpoch(23), curH)
return false, nil
}, func(_ context.Context, ts *types.TipSet) error {
t.Fatal("revert on timeout")
return nil
}, 3, 20, func(oldTs, newTs *types.TipSet) (bool, StateChange, error) {
return false, nil, nil
})
require.NoError(t, err)
fcs.advance(0, 21, nil)
require.False(t, called)
fcs.advance(0, 5, nil)
require.True(t, called)
called = false
// with check func reporting done
fcs = &fakeCS{
t: t,
h: 1,
msgs: map[cid.Cid]fakeMsg{},
blkMsgs: map[cid.Cid]cid.Cid{},
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
}
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
events = NewEvents(context.Background(), fcs)
err = events.StateChanged(func(ts *types.TipSet) (d bool, m bool, e error) {
return true, true, nil
}, func(oldTs, newTs *types.TipSet, data StateChange, curH abi.ChainEpoch) (bool, error) {
called = true
require.Nil(t, data)
require.Equal(t, abi.ChainEpoch(20), newTs.Height())
require.Equal(t, abi.ChainEpoch(23), curH)
return false, nil
}, func(_ context.Context, ts *types.TipSet) error {
t.Fatal("revert on timeout")
return nil
}, 3, 20, func(oldTs, newTs *types.TipSet) (bool, StateChange, error) {
return false, nil, nil
})
require.NoError(t, err)
fcs.advance(0, 21, nil)
require.False(t, called)
fcs.advance(0, 5, nil)
require.False(t, called)
}
+25
View File
@@ -0,0 +1,25 @@
package state
import (
"context"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
)
type contextStore struct {
ctx context.Context
cst *cbor.BasicIpldStore
}
func (cs *contextStore) Context() context.Context {
return cs.ctx
}
func (cs *contextStore) Get(ctx context.Context, c cid.Cid, out interface{}) error {
return cs.cst.Get(ctx, c, out)
}
func (cs *contextStore) Put(ctx context.Context, v interface{}) (cid.Cid, error) {
return cs.cst.Put(ctx, v)
}
+106
View File
@@ -0,0 +1,106 @@
package state
import (
"github.com/filecoin-project/specs-actors/actors/util/adt"
typegen "github.com/whyrusleeping/cbor-gen"
)
// AdtArrayDiff generalizes adt.Array diffing by accepting a Deferred type that can unmarshalled to its corresponding struct
// in an interface implantation.
// Add should be called when a new k,v is added to the array
// Modify should be called when a value is modified in the array
// Remove should be called when a value is removed from the array
type AdtArrayDiff interface {
Add(key uint64, val *typegen.Deferred) error
Modify(key uint64, from, to *typegen.Deferred) error
Remove(key uint64, val *typegen.Deferred) error
}
// TODO Performance can be improved by diffing the underlying IPLD graph, e.g. https://github.com/ipfs/go-merkledag/blob/749fd8717d46b4f34c9ce08253070079c89bc56d/dagutils/diff.go#L104
// CBOR Marshaling will likely be the largest performance bottleneck here.
// DiffAdtArray accepts two *adt.Array's and an AdtArrayDiff implementation. It does the following:
// - All values that exist in preArr and not in curArr are passed to AdtArrayDiff.Remove()
// - All values that exist in curArr nnd not in prevArr are passed to adtArrayDiff.Add()
// - All values that exist in preArr and in curArr are passed to AdtArrayDiff.Modify()
// - It is the responsibility of AdtArrayDiff.Modify() to determine if the values it was passed have been modified.
func DiffAdtArray(preArr, curArr *adt.Array, out AdtArrayDiff) error {
prevVal := new(typegen.Deferred)
if err := preArr.ForEach(prevVal, func(i int64) error {
curVal := new(typegen.Deferred)
found, err := curArr.Get(uint64(i), curVal)
if err != nil {
return err
}
if !found {
if err := out.Remove(uint64(i), prevVal); err != nil {
return err
}
return nil
}
if err := out.Modify(uint64(i), prevVal, curVal); err != nil {
return err
}
return curArr.Delete(uint64(i))
}); err != nil {
return err
}
curVal := new(typegen.Deferred)
return curArr.ForEach(curVal, func(i int64) error {
return out.Add(uint64(i), curVal)
})
}
// TODO Performance can be improved by diffing the underlying IPLD graph, e.g. https://github.com/ipfs/go-merkledag/blob/749fd8717d46b4f34c9ce08253070079c89bc56d/dagutils/diff.go#L104
// CBOR Marshaling will likely be the largest performance bottleneck here.
// AdtMapDiff generalizes adt.Map diffing by accepting a Deferred type that can unmarshalled to its corresponding struct
// in an interface implantation.
// AsKey should return the Keyer implementation specific to the map
// Add should be called when a new k,v is added to the map
// Modify should be called when a value is modified in the map
// Remove should be called when a value is removed from the map
type AdtMapDiff interface {
AsKey(key string) (adt.Keyer, error)
Add(key string, val *typegen.Deferred) error
Modify(key string, from, to *typegen.Deferred) error
Remove(key string, val *typegen.Deferred) error
}
func DiffAdtMap(preMap, curMap *adt.Map, out AdtMapDiff) error {
prevVal := new(typegen.Deferred)
if err := preMap.ForEach(prevVal, func(key string) error {
curVal := new(typegen.Deferred)
k, err := out.AsKey(key)
if err != nil {
return err
}
found, err := curMap.Get(k, curVal)
if err != nil {
return err
}
if !found {
if err := out.Remove(key, prevVal); err != nil {
return err
}
return nil
}
if err := out.Modify(key, prevVal, curVal); err != nil {
return err
}
return curMap.Delete(k)
}); err != nil {
return err
}
curVal := new(typegen.Deferred)
return curMap.ForEach(curVal, func(key string) error {
return out.Add(key, curVal)
})
}
+155
View File
@@ -0,0 +1,155 @@
package state
import (
"bytes"
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
ds "github.com/ipfs/go-datastore"
ds_sync "github.com/ipfs/go-datastore/sync"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbornode "github.com/ipfs/go-ipld-cbor"
typegen "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
)
func TestDiffAdtArray(t *testing.T) {
ctxstoreA := newContextStore()
ctxstoreB := newContextStore()
arrA := adt.MakeEmptyArray(ctxstoreA)
arrB := adt.MakeEmptyArray(ctxstoreB)
require.NoError(t, arrA.Set(0, runtime.CBORBytes([]byte{0}))) // delete
require.NoError(t, arrA.Set(1, runtime.CBORBytes([]byte{0}))) // modify
require.NoError(t, arrB.Set(1, runtime.CBORBytes([]byte{1})))
require.NoError(t, arrA.Set(2, runtime.CBORBytes([]byte{1}))) // delete
require.NoError(t, arrA.Set(3, runtime.CBORBytes([]byte{0}))) // noop
require.NoError(t, arrB.Set(3, runtime.CBORBytes([]byte{0})))
require.NoError(t, arrA.Set(4, runtime.CBORBytes([]byte{0}))) // modify
require.NoError(t, arrB.Set(4, runtime.CBORBytes([]byte{6})))
require.NoError(t, arrB.Set(5, runtime.CBORBytes{8})) // add
require.NoError(t, arrB.Set(6, runtime.CBORBytes{9})) // add
changes := new(TestAdtDiff)
assert.NoError(t, DiffAdtArray(arrA, arrB, changes))
assert.NotNil(t, changes)
assert.Equal(t, 2, len(changes.Added))
// keys 5 and 6 were added
assert.EqualValues(t, uint64(5), changes.Added[0].key)
assert.EqualValues(t, []byte{8}, changes.Added[0].val)
assert.EqualValues(t, uint64(6), changes.Added[1].key)
assert.EqualValues(t, []byte{9}, changes.Added[1].val)
assert.Equal(t, 2, len(changes.Modified))
// keys 1 and 4 were modified
assert.EqualValues(t, uint64(1), changes.Modified[0].From.key)
assert.EqualValues(t, []byte{0}, changes.Modified[0].From.val)
assert.EqualValues(t, uint64(1), changes.Modified[0].To.key)
assert.EqualValues(t, []byte{1}, changes.Modified[0].To.val)
assert.EqualValues(t, uint64(4), changes.Modified[1].From.key)
assert.EqualValues(t, []byte{0}, changes.Modified[1].From.val)
assert.EqualValues(t, uint64(4), changes.Modified[1].To.key)
assert.EqualValues(t, []byte{6}, changes.Modified[1].To.val)
assert.Equal(t, 2, len(changes.Removed))
// keys 0 and 2 were deleted
assert.EqualValues(t, uint64(0), changes.Removed[0].key)
assert.EqualValues(t, []byte{0}, changes.Removed[0].val)
assert.EqualValues(t, uint64(2), changes.Removed[1].key)
assert.EqualValues(t, []byte{1}, changes.Removed[1].val)
}
type adtDiffResult struct {
key uint64
val runtime.CBORBytes
}
type TestAdtDiff struct {
Added []adtDiffResult
Modified []TestAdtDiffModified
Removed []adtDiffResult
}
var _ AdtArrayDiff = &TestAdtDiff{}
type TestAdtDiffModified struct {
From adtDiffResult
To adtDiffResult
}
func (t *TestAdtDiff) Add(key uint64, val *typegen.Deferred) error {
v := new(runtime.CBORBytes)
err := v.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
t.Added = append(t.Added, adtDiffResult{
key: key,
val: *v,
})
return nil
}
func (t *TestAdtDiff) Modify(key uint64, from, to *typegen.Deferred) error {
vFrom := new(runtime.CBORBytes)
err := vFrom.UnmarshalCBOR(bytes.NewReader(from.Raw))
if err != nil {
return err
}
vTo := new(runtime.CBORBytes)
err = vTo.UnmarshalCBOR(bytes.NewReader(to.Raw))
if err != nil {
return err
}
if !bytes.Equal(*vFrom, *vTo) {
t.Modified = append(t.Modified, TestAdtDiffModified{
From: adtDiffResult{
key: key,
val: *vFrom,
},
To: adtDiffResult{
key: key,
val: *vTo,
},
})
}
return nil
}
func (t *TestAdtDiff) Remove(key uint64, val *typegen.Deferred) error {
v := new(runtime.CBORBytes)
err := v.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
t.Removed = append(t.Removed, adtDiffResult{
key: key,
val: *v,
})
return nil
}
func newContextStore() *contextStore {
ctx := context.Background()
bs := bstore.NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
store := cbornode.NewCborStore(bs)
return &contextStore{
ctx: ctx,
cst: store,
}
}
+490
View File
@@ -0,0 +1,490 @@
package state
import (
"bytes"
"context"
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
typegen "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/api/apibstore"
"github.com/filecoin-project/lotus/chain/types"
)
// UserData is the data returned from the DiffTipSetKeyFunc
type UserData interface{}
// ChainAPI abstracts out calls made by this class to external APIs
type ChainAPI interface {
apibstore.ChainIO
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
}
// StatePredicates has common predicates for responding to state changes
type StatePredicates struct {
api ChainAPI
cst *cbor.BasicIpldStore
}
func NewStatePredicates(api ChainAPI) *StatePredicates {
return &StatePredicates{
api: api,
cst: cbor.NewCborStore(apibstore.NewAPIBlockstore(api)),
}
}
// DiffTipSetKeyFunc check if there's a change form oldState to newState, and returns
// - changed: was there a change
// - user: user-defined data representing the state change
// - err
type DiffTipSetKeyFunc func(ctx context.Context, oldState, newState types.TipSetKey) (changed bool, user UserData, err error)
type DiffActorStateFunc func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error)
// OnActorStateChanged calls diffStateFunc when the state changes for the given actor
func (sp *StatePredicates) OnActorStateChanged(addr address.Address, diffStateFunc DiffActorStateFunc) DiffTipSetKeyFunc {
return func(ctx context.Context, oldState, newState types.TipSetKey) (changed bool, user UserData, err error) {
oldActor, err := sp.api.StateGetActor(ctx, addr, oldState)
if err != nil {
return false, nil, err
}
newActor, err := sp.api.StateGetActor(ctx, addr, newState)
if err != nil {
return false, nil, err
}
if oldActor.Head.Equals(newActor.Head) {
return false, nil, nil
}
return diffStateFunc(ctx, oldActor.Head, newActor.Head)
}
}
type DiffStorageMarketStateFunc func(ctx context.Context, oldState *market.State, newState *market.State) (changed bool, user UserData, err error)
// OnStorageMarketActorChanged calls diffStorageMarketState when the state changes for the market actor
func (sp *StatePredicates) OnStorageMarketActorChanged(diffStorageMarketState DiffStorageMarketStateFunc) DiffTipSetKeyFunc {
return sp.OnActorStateChanged(builtin.StorageMarketActorAddr, func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error) {
var oldState market.State
if err := sp.cst.Get(ctx, oldActorStateHead, &oldState); err != nil {
return false, nil, err
}
var newState market.State
if err := sp.cst.Get(ctx, newActorStateHead, &newState); err != nil {
return false, nil, err
}
return diffStorageMarketState(ctx, &oldState, &newState)
})
}
type DiffAdtArraysFunc func(ctx context.Context, oldDealStateRoot, newDealStateRoot *adt.Array) (changed bool, user UserData, err error)
// OnDealStateChanged calls diffDealStates when the market deal state changes
func (sp *StatePredicates) OnDealStateChanged(diffDealStates DiffAdtArraysFunc) DiffStorageMarketStateFunc {
return func(ctx context.Context, oldState *market.State, newState *market.State) (changed bool, user UserData, err error) {
if oldState.States.Equals(newState.States) {
return false, nil, nil
}
ctxStore := &contextStore{
ctx: ctx,
cst: sp.cst,
}
oldRoot, err := adt.AsArray(ctxStore, oldState.States)
if err != nil {
return false, nil, err
}
newRoot, err := adt.AsArray(ctxStore, newState.States)
if err != nil {
return false, nil, err
}
return diffDealStates(ctx, oldRoot, newRoot)
}
}
// OnDealProposalChanged calls diffDealProps when the market proposal state changes
func (sp *StatePredicates) OnDealProposalChanged(diffDealProps DiffAdtArraysFunc) DiffStorageMarketStateFunc {
return func(ctx context.Context, oldState *market.State, newState *market.State) (changed bool, user UserData, err error) {
if oldState.Proposals.Equals(newState.Proposals) {
return false, nil, nil
}
ctxStore := &contextStore{
ctx: ctx,
cst: sp.cst,
}
oldRoot, err := adt.AsArray(ctxStore, oldState.Proposals)
if err != nil {
return false, nil, err
}
newRoot, err := adt.AsArray(ctxStore, newState.Proposals)
if err != nil {
return false, nil, err
}
return diffDealProps(ctx, oldRoot, newRoot)
}
}
var _ AdtArrayDiff = &MarketDealProposalChanges{}
type MarketDealProposalChanges struct {
Added []ProposalIDState
Removed []ProposalIDState
}
type ProposalIDState struct {
ID abi.DealID
Proposal market.DealProposal
}
func (m *MarketDealProposalChanges) Add(key uint64, val *typegen.Deferred) error {
dp := new(market.DealProposal)
err := dp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Added = append(m.Added, ProposalIDState{abi.DealID(key), *dp})
return nil
}
func (m *MarketDealProposalChanges) Modify(key uint64, from, to *typegen.Deferred) error {
// short circuit, DealProposals are static
return nil
}
func (m *MarketDealProposalChanges) Remove(key uint64, val *typegen.Deferred) error {
dp := new(market.DealProposal)
err := dp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Removed = append(m.Removed, ProposalIDState{abi.DealID(key), *dp})
return nil
}
// OnDealProposalAmtChanged detects changes in the deal proposal AMT for all deal proposals and returns a MarketProposalsChanges structure containing:
// - Added Proposals
// - Modified Proposals
// - Removed Proposals
func (sp *StatePredicates) OnDealProposalAmtChanged() DiffAdtArraysFunc {
return func(ctx context.Context, oldDealProps, newDealProps *adt.Array) (changed bool, user UserData, err error) {
proposalChanges := new(MarketDealProposalChanges)
if err := DiffAdtArray(oldDealProps, newDealProps, proposalChanges); err != nil {
return false, nil, err
}
if len(proposalChanges.Added)+len(proposalChanges.Removed) == 0 {
return false, nil, nil
}
return true, proposalChanges, nil
}
}
var _ AdtArrayDiff = &MarketDealStateChanges{}
type MarketDealStateChanges struct {
Added []DealIDState
Modified []DealStateChange
Removed []DealIDState
}
type DealIDState struct {
ID abi.DealID
Deal market.DealState
}
func (m *MarketDealStateChanges) Add(key uint64, val *typegen.Deferred) error {
ds := new(market.DealState)
err := ds.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Added = append(m.Added, DealIDState{abi.DealID(key), *ds})
return nil
}
func (m *MarketDealStateChanges) Modify(key uint64, from, to *typegen.Deferred) error {
dsFrom := new(market.DealState)
if err := dsFrom.UnmarshalCBOR(bytes.NewReader(from.Raw)); err != nil {
return err
}
dsTo := new(market.DealState)
if err := dsTo.UnmarshalCBOR(bytes.NewReader(to.Raw)); err != nil {
return err
}
if *dsFrom != *dsTo {
m.Modified = append(m.Modified, DealStateChange{abi.DealID(key), dsFrom, dsTo})
}
return nil
}
func (m *MarketDealStateChanges) Remove(key uint64, val *typegen.Deferred) error {
ds := new(market.DealState)
err := ds.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Removed = append(m.Removed, DealIDState{abi.DealID(key), *ds})
return nil
}
// OnDealStateAmtChanged detects changes in the deal state AMT for all deal states and returns a MarketDealStateChanges structure containing:
// - Added Deals
// - Modified Deals
// - Removed Deals
func (sp *StatePredicates) OnDealStateAmtChanged() DiffAdtArraysFunc {
return func(ctx context.Context, oldDealStates, newDealStates *adt.Array) (changed bool, user UserData, err error) {
dealStateChanges := new(MarketDealStateChanges)
if err := DiffAdtArray(oldDealStates, newDealStates, dealStateChanges); err != nil {
return false, nil, err
}
if len(dealStateChanges.Added)+len(dealStateChanges.Modified)+len(dealStateChanges.Removed) == 0 {
return false, nil, nil
}
return true, dealStateChanges, nil
}
}
// ChangedDeals is a set of changes to deal state
type ChangedDeals map[abi.DealID]DealStateChange
// DealStateChange is a change in deal state from -> to
type DealStateChange struct {
ID abi.DealID
From *market.DealState
To *market.DealState
}
// DealStateChangedForIDs detects changes in the deal state AMT for the given deal IDs
func (sp *StatePredicates) DealStateChangedForIDs(dealIds []abi.DealID) DiffAdtArraysFunc {
return func(ctx context.Context, oldDealStateArray, newDealStateArray *adt.Array) (changed bool, user UserData, err error) {
changedDeals := make(ChangedDeals)
for _, dealID := range dealIds {
var oldDealPtr, newDealPtr *market.DealState
var oldDeal, newDeal market.DealState
_, err := oldDealStateArray.Get(uint64(dealID), &oldDeal)
if err != nil {
return false, nil, err
}
oldDealPtr = &oldDeal
_, err = newDealStateArray.Get(uint64(dealID), &newDeal)
if err != nil {
return false, nil, err
}
newDealPtr = &newDeal
if oldDeal != newDeal {
changedDeals[dealID] = DealStateChange{dealID, oldDealPtr, newDealPtr}
}
}
if len(changedDeals) > 0 {
return true, changedDeals, nil
}
return false, nil, nil
}
}
type DiffMinerActorStateFunc func(ctx context.Context, oldState *miner.State, newState *miner.State) (changed bool, user UserData, err error)
func (sp *StatePredicates) OnMinerActorChange(minerAddr address.Address, diffMinerActorState DiffMinerActorStateFunc) DiffTipSetKeyFunc {
return sp.OnActorStateChanged(minerAddr, func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error) {
var oldState miner.State
if err := sp.cst.Get(ctx, oldActorStateHead, &oldState); err != nil {
return false, nil, err
}
var newState miner.State
if err := sp.cst.Get(ctx, newActorStateHead, &newState); err != nil {
return false, nil, err
}
return diffMinerActorState(ctx, &oldState, &newState)
})
}
type MinerSectorChanges struct {
Added []miner.SectorOnChainInfo
Extended []SectorExtensions
Removed []miner.SectorOnChainInfo
}
var _ AdtArrayDiff = &MinerSectorChanges{}
type SectorExtensions struct {
From miner.SectorOnChainInfo
To miner.SectorOnChainInfo
}
func (m *MinerSectorChanges) Add(key uint64, val *typegen.Deferred) error {
si := new(miner.SectorOnChainInfo)
err := si.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Added = append(m.Added, *si)
return nil
}
func (m *MinerSectorChanges) Modify(key uint64, from, to *typegen.Deferred) error {
siFrom := new(miner.SectorOnChainInfo)
err := siFrom.UnmarshalCBOR(bytes.NewReader(from.Raw))
if err != nil {
return err
}
siTo := new(miner.SectorOnChainInfo)
err = siTo.UnmarshalCBOR(bytes.NewReader(to.Raw))
if err != nil {
return err
}
if siFrom.Info.Expiration != siTo.Info.Expiration {
m.Extended = append(m.Extended, SectorExtensions{
From: *siFrom,
To: *siTo,
})
}
return nil
}
func (m *MinerSectorChanges) Remove(key uint64, val *typegen.Deferred) error {
si := new(miner.SectorOnChainInfo)
err := si.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Removed = append(m.Removed, *si)
return nil
}
func (sp *StatePredicates) OnMinerSectorChange() DiffMinerActorStateFunc {
return func(ctx context.Context, oldState, newState *miner.State) (changed bool, user UserData, err error) {
ctxStore := &contextStore{
ctx: ctx,
cst: sp.cst,
}
sectorChanges := &MinerSectorChanges{
Added: []miner.SectorOnChainInfo{},
Extended: []SectorExtensions{},
Removed: []miner.SectorOnChainInfo{},
}
// no sector changes
if oldState.Sectors.Equals(newState.Sectors) {
return false, nil, nil
}
oldSectors, err := adt.AsArray(ctxStore, oldState.Sectors)
if err != nil {
return false, nil, err
}
newSectors, err := adt.AsArray(ctxStore, newState.Sectors)
if err != nil {
return false, nil, err
}
if err := DiffAdtArray(oldSectors, newSectors, sectorChanges); err != nil {
return false, nil, err
}
// nothing changed
if len(sectorChanges.Added)+len(sectorChanges.Extended)+len(sectorChanges.Removed) == 0 {
return false, nil, nil
}
return true, sectorChanges, nil
}
}
type MinerPreCommitChanges struct {
Added []miner.SectorPreCommitOnChainInfo
Removed []miner.SectorPreCommitOnChainInfo
}
func (m *MinerPreCommitChanges) AsKey(key string) (adt.Keyer, error) {
sector, err := adt.ParseUIntKey(key)
if err != nil {
return nil, err
}
return miner.SectorKey(abi.SectorNumber(sector)), nil
}
func (m *MinerPreCommitChanges) Add(key string, val *typegen.Deferred) error {
sp := new(miner.SectorPreCommitOnChainInfo)
err := sp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Added = append(m.Added, *sp)
return nil
}
func (m *MinerPreCommitChanges) Modify(key string, from, to *typegen.Deferred) error {
return nil
}
func (m *MinerPreCommitChanges) Remove(key string, val *typegen.Deferred) error {
sp := new(miner.SectorPreCommitOnChainInfo)
err := sp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Removed = append(m.Removed, *sp)
return nil
}
func (sp *StatePredicates) OnMinerPreCommitChange() DiffMinerActorStateFunc {
return func(ctx context.Context, oldState, newState *miner.State) (changed bool, user UserData, err error) {
ctxStore := &contextStore{
ctx: ctx,
cst: sp.cst,
}
precommitChanges := &MinerPreCommitChanges{
Added: []miner.SectorPreCommitOnChainInfo{},
Removed: []miner.SectorPreCommitOnChainInfo{},
}
if oldState.PreCommittedSectors.Equals(newState.PreCommittedSectors) {
return false, nil, nil
}
oldPrecommits, err := adt.AsMap(ctxStore, oldState.PreCommittedSectors)
if err != nil {
return false, nil, err
}
newPrecommits, err := adt.AsMap(ctxStore, newState.PreCommittedSectors)
if err != nil {
return false, nil, err
}
if err := DiffAdtMap(oldPrecommits, newPrecommits, precommitChanges); err != nil {
return false, nil, err
}
if len(precommitChanges.Added)+len(precommitChanges.Removed) == 0 {
return false, nil, nil
}
return true, precommitChanges, nil
}
}
+483
View File
@@ -0,0 +1,483 @@
package state
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"github.com/ipfs/go-cid"
ds "github.com/ipfs/go-datastore"
ds_sync "github.com/ipfs/go-datastore/sync"
"github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbornode "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/util/adt"
tutils "github.com/filecoin-project/specs-actors/support/testing"
"github.com/filecoin-project/lotus/chain/types"
)
var dummyCid cid.Cid
func init() {
dummyCid, _ = cid.Parse("bafkqaaa")
}
type mockAPI struct {
ts map[types.TipSetKey]*types.Actor
bs bstore.Blockstore
}
func newMockAPI(bs bstore.Blockstore) *mockAPI {
return &mockAPI{
bs: bs,
ts: make(map[types.TipSetKey]*types.Actor),
}
}
func (m mockAPI) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) {
return m.bs.Has(c)
}
func (m mockAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
blk, err := m.bs.Get(c)
if err != nil {
return nil, xerrors.Errorf("blockstore get: %w", err)
}
return blk.RawData(), nil
}
func (m mockAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
return m.ts[tsk], nil
}
func (m mockAPI) setActor(tsk types.TipSetKey, act *types.Actor) {
m.ts[tsk] = act
}
func TestMarketPredicates(t *testing.T) {
ctx := context.Background()
bs := bstore.NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
store := cbornode.NewCborStore(bs)
oldDeal1 := &market.DealState{
SectorStartEpoch: 1,
LastUpdatedEpoch: 2,
SlashEpoch: 0,
}
oldDeal2 := &market.DealState{
SectorStartEpoch: 4,
LastUpdatedEpoch: 5,
SlashEpoch: 0,
}
oldDeals := map[abi.DealID]*market.DealState{
abi.DealID(1): oldDeal1,
abi.DealID(2): oldDeal2,
}
oldProp1 := &market.DealProposal{
PieceCID: dummyCid,
PieceSize: 0,
VerifiedDeal: false,
Client: tutils.NewIDAddr(t, 1),
Provider: tutils.NewIDAddr(t, 1),
StartEpoch: 1,
EndEpoch: 2,
StoragePricePerEpoch: big.Zero(),
ProviderCollateral: big.Zero(),
ClientCollateral: big.Zero(),
}
oldProp2 := &market.DealProposal{
PieceCID: dummyCid,
PieceSize: 0,
VerifiedDeal: false,
Client: tutils.NewIDAddr(t, 1),
Provider: tutils.NewIDAddr(t, 1),
StartEpoch: 2,
EndEpoch: 3,
StoragePricePerEpoch: big.Zero(),
ProviderCollateral: big.Zero(),
ClientCollateral: big.Zero(),
}
oldProps := map[abi.DealID]*market.DealProposal{
abi.DealID(1): oldProp1,
abi.DealID(2): oldProp2,
}
oldStateC := createMarketState(ctx, t, store, oldDeals, oldProps)
newDeal1 := &market.DealState{
SectorStartEpoch: 1,
LastUpdatedEpoch: 3,
SlashEpoch: 0,
}
newDeal2 := &market.DealState{
SectorStartEpoch: 4,
LastUpdatedEpoch: 6,
SlashEpoch: 6,
}
// added
newDeal3 := &market.DealState{
SectorStartEpoch: 1,
LastUpdatedEpoch: 2,
SlashEpoch: 3,
}
newDeals := map[abi.DealID]*market.DealState{
abi.DealID(1): newDeal1,
abi.DealID(2): newDeal2,
abi.DealID(3): newDeal3,
}
// added
newProp3 := &market.DealProposal{
PieceCID: dummyCid,
PieceSize: 0,
VerifiedDeal: false,
Client: tutils.NewIDAddr(t, 1),
Provider: tutils.NewIDAddr(t, 1),
StartEpoch: 4,
EndEpoch: 4,
StoragePricePerEpoch: big.Zero(),
ProviderCollateral: big.Zero(),
ClientCollateral: big.Zero(),
}
newProps := map[abi.DealID]*market.DealProposal{
abi.DealID(1): oldProp1, // 1 was persisted
// prop 2 was removed
abi.DealID(3): newProp3, // new
// NB: DealProposals cannot be modified, so don't test that case.
}
newStateC := createMarketState(ctx, t, store, newDeals, newProps)
minerAddr, err := address.NewFromString("t00")
require.NoError(t, err)
oldState, err := mockTipset(minerAddr, 1)
require.NoError(t, err)
newState, err := mockTipset(minerAddr, 2)
require.NoError(t, err)
api := newMockAPI(bs)
api.setActor(oldState.Key(), &types.Actor{Head: oldStateC})
api.setActor(newState.Key(), &types.Actor{Head: newStateC})
t.Run("deal ID predicate", func(t *testing.T) {
preds := NewStatePredicates(api)
dealIds := []abi.DealID{abi.DealID(1), abi.DealID(2)}
diffIDFn := preds.OnStorageMarketActorChanged(preds.OnDealStateChanged(preds.DealStateChangedForIDs(dealIds)))
// Diff a state against itself: expect no change
changed, _, err := diffIDFn(ctx, oldState.Key(), oldState.Key())
require.NoError(t, err)
require.False(t, changed)
// Diff old state against new state
changed, valIDs, err := diffIDFn(ctx, oldState.Key(), newState.Key())
require.NoError(t, err)
require.True(t, changed)
changedDealIDs, ok := valIDs.(ChangedDeals)
require.True(t, ok)
require.Len(t, changedDealIDs, 2)
require.Contains(t, changedDealIDs, abi.DealID(1))
require.Contains(t, changedDealIDs, abi.DealID(2))
deal1 := changedDealIDs[abi.DealID(1)]
if deal1.From.LastUpdatedEpoch != 2 || deal1.To.LastUpdatedEpoch != 3 {
t.Fatal("Unexpected change to LastUpdatedEpoch")
}
deal2 := changedDealIDs[abi.DealID(2)]
if deal2.From.SlashEpoch != 0 || deal2.To.SlashEpoch != 6 {
t.Fatal("Unexpected change to SlashEpoch")
}
// Test that OnActorStateChanged does not call the callback if the state has not changed
mockAddr, err := address.NewFromString("t01")
require.NoError(t, err)
actorDiffFn := preds.OnActorStateChanged(mockAddr, func(context.Context, cid.Cid, cid.Cid) (bool, UserData, error) {
t.Fatal("No state change so this should not be called")
return false, nil, nil
})
changed, _, err = actorDiffFn(ctx, oldState.Key(), oldState.Key())
require.NoError(t, err)
require.False(t, changed)
// Test that OnDealStateChanged does not call the callback if the state has not changed
diffDealStateFn := preds.OnDealStateChanged(func(context.Context, *adt.Array, *adt.Array) (bool, UserData, error) {
t.Fatal("No state change so this should not be called")
return false, nil, nil
})
marketState := createEmptyMarketState(t, store)
changed, _, err = diffDealStateFn(ctx, marketState, marketState)
require.NoError(t, err)
require.False(t, changed)
})
t.Run("deal state array predicate", func(t *testing.T) {
preds := NewStatePredicates(api)
diffArrFn := preds.OnStorageMarketActorChanged(preds.OnDealStateChanged(preds.OnDealStateAmtChanged()))
changed, _, err := diffArrFn(ctx, oldState.Key(), oldState.Key())
require.NoError(t, err)
require.False(t, changed)
changed, valArr, err := diffArrFn(ctx, oldState.Key(), newState.Key())
require.NoError(t, err)
require.True(t, changed)
changedDeals, ok := valArr.(*MarketDealStateChanges)
require.True(t, ok)
require.Len(t, changedDeals.Added, 1)
require.Equal(t, abi.DealID(3), changedDeals.Added[0].ID)
require.Equal(t, *newDeal3, changedDeals.Added[0].Deal)
require.Len(t, changedDeals.Removed, 0)
require.Len(t, changedDeals.Modified, 2)
require.Equal(t, abi.DealID(1), changedDeals.Modified[0].ID)
require.Equal(t, newDeal1, changedDeals.Modified[0].To)
require.Equal(t, oldDeal1, changedDeals.Modified[0].From)
require.Equal(t, abi.DealID(2), changedDeals.Modified[1].ID)
require.Equal(t, oldDeal2, changedDeals.Modified[1].From)
require.Equal(t, newDeal2, changedDeals.Modified[1].To)
})
t.Run("deal proposal array predicate", func(t *testing.T) {
preds := NewStatePredicates(api)
diffArrFn := preds.OnStorageMarketActorChanged(preds.OnDealProposalChanged(preds.OnDealProposalAmtChanged()))
changed, _, err := diffArrFn(ctx, oldState.Key(), oldState.Key())
require.NoError(t, err)
require.False(t, changed)
changed, valArr, err := diffArrFn(ctx, oldState.Key(), newState.Key())
require.NoError(t, err)
require.True(t, changed)
changedProps, ok := valArr.(*MarketDealProposalChanges)
require.True(t, ok)
require.Len(t, changedProps.Added, 1)
require.Equal(t, abi.DealID(3), changedProps.Added[0].ID)
require.Equal(t, *newProp3, changedProps.Added[0].Proposal)
// proposals cannot be modified -- no modified testing
require.Len(t, changedProps.Removed, 1)
require.Equal(t, abi.DealID(2), changedProps.Removed[0].ID)
require.Equal(t, *oldProp2, changedProps.Removed[0].Proposal)
})
}
func TestMinerSectorChange(t *testing.T) {
ctx := context.Background()
bs := bstore.NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
store := cbornode.NewCborStore(bs)
nextID := uint64(0)
nextIDAddrF := func() address.Address {
defer func() { nextID++ }()
return tutils.NewIDAddr(t, nextID)
}
owner, worker := nextIDAddrF(), nextIDAddrF()
si0 := newSectorOnChainInfo(0, tutils.MakeCID("0"), big.NewInt(0), abi.ChainEpoch(0), abi.ChainEpoch(10))
si1 := newSectorOnChainInfo(1, tutils.MakeCID("1"), big.NewInt(1), abi.ChainEpoch(1), abi.ChainEpoch(11))
si2 := newSectorOnChainInfo(2, tutils.MakeCID("2"), big.NewInt(2), abi.ChainEpoch(2), abi.ChainEpoch(11))
oldMinerC := createMinerState(ctx, t, store, owner, worker, []miner.SectorOnChainInfo{si0, si1, si2})
si3 := newSectorOnChainInfo(3, tutils.MakeCID("3"), big.NewInt(3), abi.ChainEpoch(3), abi.ChainEpoch(12))
// 0 delete
// 1 extend
// 2 same
// 3 added
si1Ext := si1
si1Ext.Info.Expiration++
newMinerC := createMinerState(ctx, t, store, owner, worker, []miner.SectorOnChainInfo{si1Ext, si2, si3})
minerAddr := nextIDAddrF()
oldState, err := mockTipset(minerAddr, 1)
require.NoError(t, err)
newState, err := mockTipset(minerAddr, 2)
require.NoError(t, err)
api := newMockAPI(bs)
api.setActor(oldState.Key(), &types.Actor{Head: oldMinerC})
api.setActor(newState.Key(), &types.Actor{Head: newMinerC})
preds := NewStatePredicates(api)
minerDiffFn := preds.OnMinerActorChange(minerAddr, preds.OnMinerSectorChange())
change, val, err := minerDiffFn(ctx, oldState.Key(), newState.Key())
require.NoError(t, err)
require.True(t, change)
require.NotNil(t, val)
sectorChanges, ok := val.(*MinerSectorChanges)
require.True(t, ok)
require.Equal(t, len(sectorChanges.Added), 1)
require.Equal(t, 1, len(sectorChanges.Added))
require.Equal(t, si3, sectorChanges.Added[0])
require.Equal(t, 1, len(sectorChanges.Removed))
require.Equal(t, si0, sectorChanges.Removed[0])
require.Equal(t, 1, len(sectorChanges.Extended))
require.Equal(t, si1, sectorChanges.Extended[0].From)
require.Equal(t, si1Ext, sectorChanges.Extended[0].To)
change, val, err = minerDiffFn(ctx, oldState.Key(), oldState.Key())
require.NoError(t, err)
require.False(t, change)
require.Nil(t, val)
change, val, err = minerDiffFn(ctx, newState.Key(), oldState.Key())
require.NoError(t, err)
require.True(t, change)
require.NotNil(t, val)
sectorChanges, ok = val.(*MinerSectorChanges)
require.True(t, ok)
require.Equal(t, 1, len(sectorChanges.Added))
require.Equal(t, si0, sectorChanges.Added[0])
require.Equal(t, 1, len(sectorChanges.Removed))
require.Equal(t, si3, sectorChanges.Removed[0])
require.Equal(t, 1, len(sectorChanges.Extended))
require.Equal(t, si1, sectorChanges.Extended[0].To)
require.Equal(t, si1Ext, sectorChanges.Extended[0].From)
}
func mockTipset(minerAddr address.Address, timestamp uint64) (*types.TipSet, error) {
return types.NewTipSet([]*types.BlockHeader{{
Miner: minerAddr,
Height: 5,
ParentStateRoot: dummyCid,
Messages: dummyCid,
ParentMessageReceipts: dummyCid,
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS},
BLSAggregate: &crypto.Signature{Type: crypto.SigTypeBLS},
Timestamp: timestamp,
}})
}
func createMarketState(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, deals map[abi.DealID]*market.DealState, props map[abi.DealID]*market.DealProposal) cid.Cid {
dealRootCid := createDealAMT(ctx, t, store, deals)
propRootCid := createProposalAMT(ctx, t, store, props)
state := createEmptyMarketState(t, store)
state.States = dealRootCid
state.Proposals = propRootCid
stateC, err := store.Put(ctx, state)
require.NoError(t, err)
return stateC
}
func createEmptyMarketState(t *testing.T, store *cbornode.BasicIpldStore) *market.State {
emptyArrayCid, err := amt.NewAMT(store).Flush(context.TODO())
require.NoError(t, err)
emptyMap, err := store.Put(context.TODO(), hamt.NewNode(store, hamt.UseTreeBitWidth(5)))
require.NoError(t, err)
return market.ConstructState(emptyArrayCid, emptyMap, emptyMap)
}
func createDealAMT(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, deals map[abi.DealID]*market.DealState) cid.Cid {
root := amt.NewAMT(store)
for dealID, dealState := range deals {
err := root.Set(ctx, uint64(dealID), dealState)
require.NoError(t, err)
}
rootCid, err := root.Flush(ctx)
require.NoError(t, err)
return rootCid
}
func createProposalAMT(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, props map[abi.DealID]*market.DealProposal) cid.Cid {
root := amt.NewAMT(store)
for dealID, prop := range props {
err := root.Set(ctx, uint64(dealID), prop)
require.NoError(t, err)
}
rootCid, err := root.Flush(ctx)
require.NoError(t, err)
return rootCid
}
func createMinerState(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, owner, worker address.Address, sectors []miner.SectorOnChainInfo) cid.Cid {
rootCid := createSectorsAMT(ctx, t, store, sectors)
state := createEmptyMinerState(ctx, t, store, owner, worker)
state.Sectors = rootCid
stateC, err := store.Put(ctx, state)
require.NoError(t, err)
return stateC
}
func createEmptyMinerState(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, owner, worker address.Address) *miner.State {
emptyArrayCid, err := amt.NewAMT(store).Flush(context.TODO())
require.NoError(t, err)
emptyMap, err := store.Put(context.TODO(), hamt.NewNode(store, hamt.UseTreeBitWidth(5)))
require.NoError(t, err)
emptyDeadlines := miner.ConstructDeadlines()
emptyDeadlinesCid, err := store.Put(context.Background(), emptyDeadlines)
require.NoError(t, err)
state, err := miner.ConstructState(emptyArrayCid, emptyMap, emptyDeadlinesCid, owner, worker, abi.PeerID{'1'}, nil, abi.RegisteredSealProof_StackedDrg64GiBV1, 0)
require.NoError(t, err)
return state
}
func createSectorsAMT(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, sectors []miner.SectorOnChainInfo) cid.Cid {
root := amt.NewAMT(store)
for _, sector := range sectors {
sector := sector
err := root.Set(ctx, uint64(sector.Info.SectorNumber), &sector)
require.NoError(t, err)
}
rootCid, err := root.Flush(ctx)
require.NoError(t, err)
return rootCid
}
// returns a unique SectorOnChainInfo with each invocation with SectorNumber set to `sectorNo`.
func newSectorOnChainInfo(sectorNo abi.SectorNumber, sealed cid.Cid, weight big.Int, activation, expiration abi.ChainEpoch) miner.SectorOnChainInfo {
info := newSectorPreCommitInfo(sectorNo, sealed, expiration)
return miner.SectorOnChainInfo{
Info: *info,
ActivationEpoch: activation,
DealWeight: weight,
VerifiedDealWeight: weight,
}
}
const (
sectorSealRandEpochValue = abi.ChainEpoch(1)
)
// 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{
SealProof: abi.RegisteredSealProof_StackedDrg32GiBV1,
SectorNumber: sectorNo,
SealedCID: sealed,
SealRandEpoch: sectorSealRandEpochValue,
DealIDs: nil,
Expiration: expiration,
}
}
+5 -5
View File
@@ -8,11 +8,11 @@ import (
"github.com/filecoin-project/lotus/chain/types"
)
func (e *calledEvents) CheckMsg(ctx context.Context, smsg types.ChainMsg, hnd CalledHandler) CheckFunc {
func (me *messageEvents) CheckMsg(ctx context.Context, smsg types.ChainMsg, hnd MsgHandler) CheckFunc {
msg := smsg.VMMessage()
return func(ts *types.TipSet) (done bool, more bool, err error) {
fa, err := e.cs.StateGetActor(ctx, msg.From, ts.Key())
fa, err := me.cs.StateGetActor(ctx, msg.From, ts.Key())
if err != nil {
return false, true, err
}
@@ -22,7 +22,7 @@ func (e *calledEvents) CheckMsg(ctx context.Context, smsg types.ChainMsg, hnd Ca
return false, true, nil
}
rec, err := e.cs.StateGetReceipt(ctx, smsg.VMMessage().Cid(), ts.Key())
rec, err := me.cs.StateGetReceipt(ctx, smsg.VMMessage().Cid(), ts.Key())
if err != nil {
return false, true, xerrors.Errorf("getting receipt in CheckMsg: %w", err)
}
@@ -33,10 +33,10 @@ func (e *calledEvents) CheckMsg(ctx context.Context, smsg types.ChainMsg, hnd Ca
}
}
func (e *calledEvents) MatchMsg(inmsg *types.Message) MatchFunc {
func (me *messageEvents) MatchMsg(inmsg *types.Message) MsgMatchFunc {
return func(msg *types.Message) (bool, error) {
if msg.From == inmsg.From && msg.Nonce == inmsg.Nonce && !inmsg.Equals(msg) {
return false, xerrors.Errorf("matching msg %s from %s, nonce %d: got duplicate origin/nonce msg %s", inmsg.Cid(), inmsg.From, inmsg.Nonce, msg.Nonce)
return false, xerrors.Errorf("matching msg %s from %s, nonce %d: got duplicate origin/nonce msg %d", inmsg.Cid(), inmsg.From, inmsg.Nonce, msg.Nonce)
}
return inmsg.Equals(msg), nil
+18 -19
View File
@@ -45,6 +45,10 @@ var log = logging.Logger("gen")
const msgsPerBlock = 20
var ValidWpostForTesting = []abi.PoStProof{{
ProofBytes: []byte("valid proof"),
}}
type ChainGen struct {
msgsPerBlock int
@@ -89,8 +93,8 @@ func (m mybs) Get(c cid.Cid) (block.Block, error) {
}
func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
saminer.SupportedProofTypes = map[abi.RegisteredProof]struct{}{
abi.RegisteredProof_StackedDRG2KiBSeal: {},
saminer.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
}
mr := repo.NewMemory(nil)
@@ -104,7 +108,7 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
return nil, xerrors.Errorf("failed to get metadata datastore: %w", err)
}
bds, err := lr.Datastore("/blocks")
bds, err := lr.Datastore("/chain")
if err != nil {
return nil, xerrors.Errorf("failed to get blocks datastore: %w", err)
}
@@ -141,7 +145,7 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
return nil, err
}
genm1, k1, err := seed.PreSeal(maddr1, abi.RegisteredProof_StackedDRG2KiBPoSt, 0, numSectors, m1temp, []byte("some randomness"), nil)
genm1, k1, err := seed.PreSeal(maddr1, abi.RegisteredSealProof_StackedDrg2KiBV1, 0, numSectors, m1temp, []byte("some randomness"), nil, true)
if err != nil {
return nil, err
}
@@ -153,7 +157,7 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
return nil, err
}
genm2, k2, err := seed.PreSeal(maddr2, abi.RegisteredProof_StackedDRG2KiBPoSt, 0, numSectors, m2temp, []byte("some randomness"), nil)
genm2, k2, err := seed.PreSeal(maddr2, abi.RegisteredSealProof_StackedDrg2KiBV1, 0, numSectors, m2temp, []byte("some randomness"), nil, true)
if err != nil {
return nil, err
}
@@ -192,7 +196,7 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
*genm2,
},
NetworkName: "",
Timestamp: uint64(time.Now().Add(-500 * build.BlockDelay * time.Second).Unix()),
Timestamp: uint64(time.Now().Add(-500 * time.Duration(build.BlockDelaySecs) * time.Second).Unix()),
}
genb, err := genesis2.MakeGenesisBlock(context.TODO(), bs, sys, tpl)
@@ -219,6 +223,10 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
miners := []address.Address{maddr1, maddr2}
beac := beacon.NewMockBeacon(time.Second)
//beac, err := drand.NewDrandBeacon(tpl.Timestamp, build.BlockDelaySecs)
//if err != nil {
//return nil, xerrors.Errorf("creating drand beacon: %w", err)
//}
gen := &ChainGen{
bs: bs,
@@ -406,7 +414,7 @@ func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, vrfticke
if cg.Timestamper != nil {
ts = cg.Timestamper(parents, height-parents.Height())
} else {
ts = parents.MinTimestamp() + uint64((height-parents.Height())*build.BlockDelay)
ts = parents.MinTimestamp() + uint64(height-parents.Height())*build.BlockDelaySecs
}
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, &api.BlockTemplate{
@@ -427,7 +435,7 @@ func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, vrfticke
return fblk, err
}
// This function is awkward. It's used to deal with messages made when
// ResyncBankerNonce is used for dealing with messages made when
// simulating forks
func (cg *ChainGen) ResyncBankerNonce(ts *types.TipSet) error {
act, err := cg.sm.GetActor(cg.banker, ts)
@@ -529,16 +537,7 @@ func (wpp *wppProvider) GenerateCandidates(ctx context.Context, _ abi.PoStRandom
}
func (wpp *wppProvider) ComputeProof(context.Context, []abi.SectorInfo, abi.PoStRandomness) ([]abi.PoStProof, error) {
return []abi.PoStProof{{
ProofBytes: []byte("valid proof"),
}}, nil
}
type ProofInput struct {
sectors []abi.SectorInfo
hvrf []byte
challengedSectors []uint64
vrfout []byte
return ValidWpostForTesting, nil
}
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round abi.ChainEpoch,
@@ -614,6 +613,6 @@ func (m genFakeVerifier) VerifyWindowPoSt(ctx context.Context, info abi.WindowPo
panic("not supported")
}
func (m genFakeVerifier) GenerateWinningPoStSectorChallenge(ctx context.Context, proof abi.RegisteredProof, id abi.ActorID, randomness abi.PoStRandomness, u uint64) ([]uint64, error) {
func (m genFakeVerifier) GenerateWinningPoStSectorChallenge(ctx context.Context, proof abi.RegisteredPoStProof, id abi.ActorID, randomness abi.PoStRandomness, u uint64) ([]uint64, error) {
panic("not supported")
}
+2 -2
View File
@@ -14,8 +14,8 @@ import (
)
func init() {
miner.SupportedProofTypes = map[abi.RegisteredProof]struct{}{
abi.RegisteredProof_StackedDRG2KiBSeal: {},
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
}
power.ConsensusMinerMinPower = big.NewInt(2048)
verifreg.MinVerifiedDealSize = big.NewInt(256)
+13 -7
View File
@@ -58,6 +58,8 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
for i, m := range miners {
// Create miner through power actor
i := i
m := m
spt, err := ffiwrapper.SealProofTypeFromSectorSize(m.SectorSize)
if err != nil {
@@ -69,7 +71,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
constructorParams := &power.CreateMinerParams{
Owner: m.Worker,
Worker: m.Worker,
Peer: m.PeerId,
Peer: []byte(m.PeerId),
SealProofType: spt,
}
@@ -154,6 +156,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
// Commit sectors
for pi, preseal := range m.Sectors {
preseal := preseal
// TODO: Maybe check seal (Can just be snark inputs, doesn't go into the genesis file)
// check deals, get dealWeight
@@ -201,12 +204,12 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
{
newSectorInfo := &miner.SectorOnChainInfo{
Info: miner.SectorPreCommitInfo{
RegisteredProof: preseal.ProofType,
SectorNumber: preseal.SectorID,
SealedCID: preseal.CommR,
SealRandEpoch: 0,
DealIDs: []abi.DealID{dealIDs[pi]},
Expiration: preseal.Deal.EndEpoch,
SealProof: preseal.ProofType,
SectorNumber: preseal.SectorID,
SealedCID: preseal.CommR,
SealRandEpoch: 0,
DealIDs: []abi.DealID{dealIDs[pi]},
Expiration: preseal.Deal.EndEpoch,
},
ActivationEpoch: 0,
DealWeight: dealWeight.DealWeight,
@@ -239,6 +242,9 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
st.TotalQualityAdjPower = big.Sub(st.TotalQualityAdjPower, big.NewInt(1))
return nil
})
if err != nil {
return cid.Undef, xerrors.Errorf("mutating state: %w", err)
}
c, err := vm.Flush(ctx)
if err != nil {
+11
View File
@@ -150,6 +150,17 @@ func aggregateSignatures(sigs []crypto.Signature) (*crypto.Signature, error) {
}
aggSig := bls.Aggregate(blsSigs)
if aggSig == nil {
if len(sigs) > 0 {
return nil, xerrors.Errorf("bls.Aggregate returned nil with %d signatures", len(sigs))
}
return &crypto.Signature{
Type: crypto.SigTypeBLS,
Data: new(bls.Signature)[:],
}, nil
}
return &crypto.Signature{
Type: crypto.SigTypeBLS,
Data: aggSig[:],
+50 -8
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"context"
"errors"
"fmt"
"math"
"sort"
"sync"
@@ -87,6 +88,8 @@ type MessagePool struct {
localMsgs datastore.Datastore
netName dtypes.NetworkName
sigValCache *lru.TwoQueueCache
}
type msgSet struct {
@@ -180,14 +183,17 @@ func (mpp *mpoolProvider) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error)
func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*MessagePool, error) {
cache, _ := lru.New2Q(build.BlsSignatureCacheSize)
verifcache, _ := lru.New2Q(build.VerifSigCacheSize)
mp := &MessagePool{
closer: make(chan struct{}),
repubTk: time.NewTicker(build.BlockDelay * 10 * time.Second),
repubTk: time.NewTicker(time.Duration(build.BlockDelaySecs) * 10 * time.Second),
localAddrs: make(map[address.Address]struct{}),
pending: make(map[address.Address]*msgSet),
minGasPrice: types.NewInt(0),
maxTxPoolSize: 5000,
blsSigCache: cache,
sigValCache: verifcache,
changes: lps.New(50),
localMsgs: namespace.Wrap(ds, datastore.NewKey(localMsgsDs)),
api: api,
@@ -313,12 +319,6 @@ func (mp *MessagePool) Push(m *types.SignedMessage) (cid.Cid, error) {
}
func (mp *MessagePool) Add(m *types.SignedMessage) error {
mp.curTsLk.Lock()
defer mp.curTsLk.Unlock()
return mp.addTs(m, mp.curTs)
}
func (mp *MessagePool) addTs(m *types.SignedMessage, curTs *types.TipSet) error {
// big messages are bad, anti DOS
if m.Size() > 32*1024 {
return xerrors.Errorf("mpool message too large (%dB): %w", m.Size(), ErrMessageTooBig)
@@ -332,11 +332,53 @@ func (mp *MessagePool) addTs(m *types.SignedMessage, curTs *types.TipSet) error
return ErrMessageValueTooHigh
}
if err := sigs.Verify(&m.Signature, m.Message.From, m.Message.Cid().Bytes()); err != nil {
if err := mp.VerifyMsgSig(m); err != nil {
log.Warnf("mpooladd signature verification failed: %s", err)
return err
}
mp.curTsLk.Lock()
defer mp.curTsLk.Unlock()
return mp.addTs(m, mp.curTs)
}
func sigCacheKey(m *types.SignedMessage) (string, error) {
switch m.Signature.Type {
case crypto.SigTypeBLS:
if len(m.Signature.Data) < 90 {
return "", fmt.Errorf("bls signature too short")
}
return string(m.Cid().Bytes()) + string(m.Signature.Data[64:]), nil
case crypto.SigTypeSecp256k1:
return string(m.Cid().Bytes()), nil
default:
return "", xerrors.Errorf("unrecognized signature type: %d", m.Signature.Type)
}
}
func (mp *MessagePool) VerifyMsgSig(m *types.SignedMessage) error {
sck, err := sigCacheKey(m)
if err != nil {
return err
}
_, ok := mp.sigValCache.Get(sck)
if ok {
// already validated, great
return nil
}
if err := sigs.Verify(&m.Signature, m.Message.From, m.Message.Cid().Bytes()); err != nil {
return err
}
mp.sigValCache.Add(sck, struct{}{})
return nil
}
func (mp *MessagePool) addTs(m *types.SignedMessage, curTs *types.TipSet) error {
snonce, err := mp.getStateNonce(m.Message.From, curTs)
if err != nil {
return xerrors.Errorf("failed to look up actor state nonce: %s: %w", err, ErrBroadcastAnyway)
+17 -17
View File
@@ -16,7 +16,7 @@ import (
"github.com/ipfs/go-datastore"
)
type testMpoolApi struct {
type testMpoolAPI struct {
cb func(rev, app []*types.TipSet) error
bmsgs map[cid.Cid][]*types.SignedMessage
@@ -25,68 +25,68 @@ type testMpoolApi struct {
tipsets []*types.TipSet
}
func newTestMpoolApi() *testMpoolApi {
return &testMpoolApi{
func newTestMpoolAPI() *testMpoolAPI {
return &testMpoolAPI{
bmsgs: make(map[cid.Cid][]*types.SignedMessage),
statenonce: make(map[address.Address]uint64),
}
}
func (tma *testMpoolApi) applyBlock(t *testing.T, b *types.BlockHeader) {
func (tma *testMpoolAPI) applyBlock(t *testing.T, b *types.BlockHeader) {
t.Helper()
if err := tma.cb(nil, []*types.TipSet{mock.TipSet(b)}); err != nil {
t.Fatal(err)
}
}
func (tma *testMpoolApi) revertBlock(t *testing.T, b *types.BlockHeader) {
func (tma *testMpoolAPI) revertBlock(t *testing.T, b *types.BlockHeader) {
t.Helper()
if err := tma.cb([]*types.TipSet{mock.TipSet(b)}, nil); err != nil {
t.Fatal(err)
}
}
func (tma *testMpoolApi) setStateNonce(addr address.Address, v uint64) {
func (tma *testMpoolAPI) setStateNonce(addr address.Address, v uint64) {
tma.statenonce[addr] = v
}
func (tma *testMpoolApi) setBlockMessages(h *types.BlockHeader, msgs ...*types.SignedMessage) {
func (tma *testMpoolAPI) setBlockMessages(h *types.BlockHeader, msgs ...*types.SignedMessage) {
tma.bmsgs[h.Cid()] = msgs
tma.tipsets = append(tma.tipsets, mock.TipSet(h))
}
func (tma *testMpoolApi) SubscribeHeadChanges(cb func(rev, app []*types.TipSet) error) *types.TipSet {
func (tma *testMpoolAPI) SubscribeHeadChanges(cb func(rev, app []*types.TipSet) error) *types.TipSet {
tma.cb = cb
return nil
}
func (tma *testMpoolApi) PutMessage(m types.ChainMsg) (cid.Cid, error) {
func (tma *testMpoolAPI) PutMessage(m types.ChainMsg) (cid.Cid, error) {
return cid.Undef, nil
}
func (tma *testMpoolApi) PubSubPublish(string, []byte) error {
func (tma *testMpoolAPI) PubSubPublish(string, []byte) error {
return nil
}
func (tma *testMpoolApi) StateGetActor(addr address.Address, ts *types.TipSet) (*types.Actor, error) {
func (tma *testMpoolAPI) StateGetActor(addr address.Address, ts *types.TipSet) (*types.Actor, error) {
return &types.Actor{
Nonce: tma.statenonce[addr],
Balance: types.NewInt(90000000),
}, nil
}
func (tma *testMpoolApi) StateAccountKey(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
func (tma *testMpoolAPI) StateAccountKey(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
if addr.Protocol() != address.BLS && addr.Protocol() != address.SECP256K1 {
return address.Undef, fmt.Errorf("given address was not a key addr")
}
return addr, nil
}
func (tma *testMpoolApi) MessagesForBlock(h *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error) {
func (tma *testMpoolAPI) MessagesForBlock(h *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error) {
return nil, tma.bmsgs[h.Cid()], nil
}
func (tma *testMpoolApi) MessagesForTipset(ts *types.TipSet) ([]types.ChainMsg, error) {
func (tma *testMpoolAPI) MessagesForTipset(ts *types.TipSet) ([]types.ChainMsg, error) {
if len(ts.Blocks()) != 1 {
panic("cant deal with multiblock tipsets in this test")
}
@@ -108,7 +108,7 @@ func (tma *testMpoolApi) MessagesForTipset(ts *types.TipSet) ([]types.ChainMsg,
return out, nil
}
func (tma *testMpoolApi) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error) {
func (tma *testMpoolAPI) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error) {
for _, ts := range tma.tipsets {
if types.CidArrsEqual(tsk.Cids(), ts.Cids()) {
return ts, nil
@@ -138,7 +138,7 @@ func mustAdd(t *testing.T, mp *MessagePool, msg *types.SignedMessage) {
}
func TestMessagePool(t *testing.T) {
tma := newTestMpoolApi()
tma := newTestMpoolAPI()
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
if err != nil {
@@ -179,7 +179,7 @@ func TestMessagePool(t *testing.T) {
}
func TestRevertMessages(t *testing.T) {
tma := newTestMpoolApi()
tma := newTestMpoolAPI()
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
if err != nil {
+2 -2
View File
@@ -21,7 +21,7 @@ import (
var log = logging.Logger("statetree")
// Stores actors state by their ID.
// StateTree stores actors state by their ID.
type StateTree struct {
root *hamt.Node
Store cbor.IpldStore
@@ -149,7 +149,7 @@ func (st *StateTree) SetActor(addr address.Address, act *types.Actor) error {
return nil
}
// `LookupID` gets the ID address of this actor's `addr` stored in the `InitActor`.
// LookupID gets the ID address of this actor's `addr` stored in the `InitActor`.
func (st *StateTree) LookupID(addr address.Address) (address.Address, error) {
if addr.Protocol() == address.ID {
return addr, nil
+4 -1
View File
@@ -255,12 +255,15 @@ func TestStateTreeConsistency(t *testing.T) {
}
for i, a := range addrs {
st.SetActor(a, &types.Actor{
err := st.SetActor(a, &types.Actor{
Code: randomCid,
Head: randomCid,
Balance: types.NewInt(uint64(10000 + i)),
Nonce: uint64(1000 - i),
})
if err != nil {
t.Fatalf("while setting actor: %+v", err)
}
}
root, err := st.Flush(context.TODO())
+5 -5
View File
@@ -62,11 +62,11 @@ func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate
}
return &api.InvocResult{
Msg: msg,
MsgRct: &ret.MessageReceipt,
InternalExecutions: ret.InternalExecutions,
Error: errs,
Duration: ret.Duration,
Msg: msg,
MsgRct: &ret.MessageReceipt,
ExecutionTrace: ret.ExecutionTrace,
Error: errs,
Duration: ret.Duration,
}, nil
}
+2 -2
View File
@@ -37,8 +37,8 @@ import (
)
func init() {
miner.SupportedProofTypes = map[abi.RegisteredProof]struct{}{
abi.RegisteredProof_StackedDRG2KiBSeal: {},
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
}
power.ConsensusMinerMinPower = big.NewInt(2048)
verifreg.MinVerifiedDealSize = big.NewInt(256)
+51 -21
View File
@@ -121,10 +121,10 @@ func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (c
var trace []*api.InvocResult
st, _, err := sm.computeTipSetState(ctx, ts.Blocks(), func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
ir := &api.InvocResult{
Msg: msg,
MsgRct: &ret.MessageReceipt,
InternalExecutions: ret.InternalExecutions,
Duration: ret.Duration,
Msg: msg,
MsgRct: &ret.MessageReceipt,
ExecutionTrace: ret.ExecutionTrace,
Duration: ret.Duration,
}
if ret.ActorErr != nil {
ir.Error = ret.ActorErr.Error()
@@ -184,10 +184,9 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, pstate cid.Cid, bms []B
var err error
params, err := actors.SerializeParams(&reward.AwardBlockRewardParams{
Miner: b.Miner,
Penalty: penalty,
GasReward: gasReward,
TicketCount: 1, // TODO: no longer need ticket count here.
Miner: b.Miner,
Penalty: penalty,
GasReward: gasReward,
})
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to serialize award params: %w", err)
@@ -326,7 +325,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
blkmsgs = append(blkmsgs, bm)
}
return sm.ApplyBlocks(ctx, pstate, blkmsgs, abi.ChainEpoch(blks[0].Height), r, cb)
return sm.ApplyBlocks(ctx, pstate, blkmsgs, blks[0].Height, r, cb)
}
func (sm *StateManager) parentState(ts *types.TipSet) cid.Cid {
@@ -382,8 +381,8 @@ func (sm *StateManager) LoadActorState(ctx context.Context, a address.Address, o
cst := cbor.NewCborStore(sm.cs.Blockstore())
if err := cst.Get(ctx, act.Head, out); err != nil {
var r cbg.Deferred
cst.Get(ctx, act.Head, &r)
fmt.Printf("badhead %x\n", r.Raw)
_ = cst.Get(ctx, act.Head, &r)
log.Errorw("bad actor head", "error", err, "raw", r.Raw, "address", a)
return nil, err
}
@@ -405,8 +404,8 @@ func (sm *StateManager) LoadActorStateRaw(ctx context.Context, a address.Address
return act, nil
}
// Similar to `vm.ResolveToKeyAddr` but does not allow `Actor` type of addresses. Uses the `TipSet` `ts`
// to generate the VM state.
// ResolveToKeyAddress is similar to `vm.ResolveToKeyAddr` but does not allow `Actor` type of addresses.
// Uses the `TipSet` `ts` to generate the VM state.
func (sm *StateManager) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
switch addr.Protocol() {
case address.BLS, address.SECP256K1:
@@ -480,7 +479,10 @@ func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.T
return r, nil
}
func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid) (*types.TipSet, *types.MessageReceipt, error) {
// WaitForMessage blocks until a message appears on chain. It looks backwards in the chain to see if this has already
// happened. It guarantees that the message has been on chain for at least confidence epochs without being reverted
// before returning.
func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confidence uint64) (*types.TipSet, *types.MessageReceipt, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
@@ -528,6 +530,11 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid) (*type
close(backSearchWait)
}()
var candidateTs *types.TipSet
var candidateRcp *types.MessageReceipt
heightOfHead := head[0].Val.Height()
reverts := map[types.TipSetKey]bool{}
for {
select {
case notif, ok := <-tsub:
@@ -537,21 +544,44 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid) (*type
for _, val := range notif {
switch val.Type {
case store.HCRevert:
continue
if val.Val.Equals(candidateTs) {
candidateTs = nil
candidateRcp = nil
}
if backSearchWait != nil {
reverts[val.Val.Key()] = true
}
case store.HCApply:
if candidateTs != nil && val.Val.Height() >= candidateTs.Height()+abi.ChainEpoch(confidence) {
return candidateTs, candidateRcp, nil
}
r, err := sm.tipsetExecutedMessage(val.Val, mcid, msg.VMMessage())
if err != nil {
return nil, nil, err
}
if r != nil {
return val.Val, r, nil
if confidence == 0 {
return val.Val, r, err
}
candidateTs = val.Val
candidateRcp = r
}
heightOfHead = val.Val.Height()
}
}
case <-backSearchWait:
if backTs != nil {
return backTs, backRcp, nil
// check if we found the message in the chain and that is hasn't been reverted since we started searching
if backTs != nil && !reverts[backTs.Key()] {
// if head is at or past confidence interval, return immediately
if heightOfHead >= backTs.Height()+abi.ChainEpoch(confidence) {
return backTs, backRcp, nil
}
// wait for confidence interval
candidateTs = backTs
candidateRcp = backRcp
}
reverts = nil
backSearchWait = nil
case <-ctx.Done():
return nil, nil, ctx.Err()
@@ -610,9 +640,9 @@ func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet
return nil, nil, err
}
if act.Nonce < m.VMMessage().Nonce {
// nonce on chain is before message nonce we're looking for, its
// not going to be here
// we either have no messages from the sender, or the latest message we found has a lower nonce than the one being searched for,
// either way, no reason to lookback, it ain't there
if act.Nonce == 0 || act.Nonce < m.VMMessage().Nonce {
return nil, nil, nil
}
+147 -26
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"context"
"os"
"reflect"
cid "github.com/ipfs/go-cid"
blockstore "github.com/ipfs/go-ipfs-blockstore"
@@ -13,13 +14,20 @@ import (
"github.com/filecoin-project/go-address"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/account"
"github.com/filecoin-project/specs-actors/actors/builtin/cron"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/util/adt"
@@ -37,7 +45,7 @@ func GetNetworkName(ctx context.Context, sm *StateManager, st cid.Cid) (dtypes.N
var state init_.State
_, err := sm.LoadActorStateRaw(ctx, builtin.InitActorAddr, &state, st)
if err != nil {
return "", xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
return "", xerrors.Errorf("(get sset) failed to load init actor state: %w", err)
}
return dtypes.NetworkName(state.NetworkName), nil
@@ -138,6 +146,24 @@ func PreCommitInfo(ctx context.Context, sm *StateManager, maddr address.Address,
return *i, nil
}
func MinerSectorInfo(ctx context.Context, sm *StateManager, maddr address.Address, sid abi.SectorNumber, ts *types.TipSet) (*miner.SectorOnChainInfo, error) {
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
}
sectorInfo, ok, err := mas.GetSector(sm.cs.Store(ctx), sid)
if err != nil {
return nil, err
}
if !ok {
return nil, xerrors.New("sector not found")
}
return sectorInfo, nil
}
func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address, filter *abi.BitField, filterOut bool) ([]*api.ChainSectorInfo, error) {
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
@@ -155,13 +181,34 @@ func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *S
return nil, xerrors.Errorf("(get sectors) failed to load miner actor state: %w", err)
}
// TODO: Optimization: we could avoid loaditg the whole proving set here if we had AMT.GetNth with bitfield filtering
sectorSet, err := GetProvingSetRaw(ctx, sm, mas)
if err != nil {
return nil, xerrors.Errorf("getting proving set: %w", err)
cst := cbor.NewCborStore(sm.cs.Blockstore())
var deadlines miner.Deadlines
if err := cst.Get(ctx, mas.Deadlines, &deadlines); err != nil {
return nil, xerrors.Errorf("failed to load deadlines: %w", err)
}
if len(sectorSet) == 0 {
notProving, err := abi.BitFieldUnion(mas.Faults, mas.Recoveries)
if err != nil {
return nil, xerrors.Errorf("failed to union faults and recoveries: %w", err)
}
allSectors, err := bitfield.MultiMerge(append(deadlines.Due[:], mas.NewSectors)...)
if err != nil {
return nil, xerrors.Errorf("merging deadline bitfields failed: %w", err)
}
provingSectors, err := bitfield.SubtractBitField(allSectors, notProving)
if err != nil {
return nil, xerrors.Errorf("failed to subtract non-proving sectors from set: %w", err)
}
numProvSect, err := provingSectors.Count()
if err != nil {
return nil, xerrors.Errorf("failed to count bits: %w", err)
}
// TODO(review): is this right? feels fishy to me
if numProvSect == 0 {
return nil, nil
}
@@ -180,17 +227,34 @@ func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *S
return nil, xerrors.Errorf("getting miner ID: %w", err)
}
ids, err := pv.GenerateWinningPoStSectorChallenge(ctx, wpt, abi.ActorID(mid), rand, uint64(len(sectorSet)))
ids, err := pv.GenerateWinningPoStSectorChallenge(ctx, wpt, abi.ActorID(mid), rand, numProvSect)
if err != nil {
return nil, xerrors.Errorf("generating winning post challenges: %w", err)
}
sectors, err := provingSectors.All(miner.SectorsMax)
if err != nil {
return nil, xerrors.Errorf("failed to enumerate all sector IDs: %w", err)
}
sectorAmt, err := amt.LoadAMT(ctx, cst, mas.Sectors)
if err != nil {
return nil, xerrors.Errorf("failed to load sectors amt: %w", err)
}
out := make([]abi.SectorInfo, len(ids))
for i, n := range ids {
sid := sectors[n]
var sinfo miner.SectorOnChainInfo
if err := sectorAmt.Get(ctx, sid, &sinfo); err != nil {
return nil, xerrors.Errorf("failed to get sector %d: %w", sid, err)
}
out[i] = abi.SectorInfo{
RegisteredProof: wpt,
SectorNumber: sectorSet[n].ID,
SealedCID: sectorSet[n].Info.Info.SealedCID,
SealProof: spt,
SectorNumber: sinfo.Info.SectorNumber,
SealedCID: sinfo.Info.SealedCID,
}
}
@@ -248,27 +312,27 @@ func GetMinerDeadlines(ctx context.Context, sm *StateManager, ts *types.TipSet,
return mas.LoadDeadlines(sm.cs.Store(ctx))
}
func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]abi.SectorNumber, error) {
func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*abi.BitField, error) {
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return nil, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
return nil, xerrors.Errorf("(get faults) failed to load miner actor state: %w", err)
}
faults, err := mas.Faults.All(miner.SectorsMax)
if err != nil {
return nil, xerrors.Errorf("reading fault bit set: %w", err)
}
out := make([]abi.SectorNumber, len(faults))
for i, fault := range faults {
out[i] = abi.SectorNumber(fault)
}
return out, nil
return mas.Faults, nil
}
func GetStorageDeal(ctx context.Context, sm *StateManager, dealId abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) {
func GetMinerRecoveries(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*abi.BitField, error) {
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return nil, xerrors.Errorf("(get recoveries) failed to load miner actor state: %w", err)
}
return mas.Recoveries, nil
}
func GetStorageDeal(ctx context.Context, sm *StateManager, dealID abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) {
var state market.State
if _, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts); err != nil {
return nil, err
@@ -280,7 +344,7 @@ func GetStorageDeal(ctx context.Context, sm *StateManager, dealId abi.DealID, ts
}
var dp market.DealProposal
if err := da.Get(ctx, uint64(dealId), &dp); err != nil {
if err := da.Get(ctx, uint64(dealID), &dp); err != nil {
return nil, err
}
@@ -289,7 +353,7 @@ func GetStorageDeal(ctx context.Context, sm *StateManager, dealId abi.DealID, ts
return nil, err
}
st, found, err := sa.Get(dealId)
st, found, err := sa.Get(dealID)
if err != nil {
return nil, err
}
@@ -521,3 +585,60 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcn beacon.RandomBe
BeaconEntries: entries,
}, nil
}
type methodMeta struct {
Name string
Params reflect.Type
Ret reflect.Type
}
var MethodsMap = map[cid.Cid][]methodMeta{}
func init() {
cidToMethods := map[cid.Cid][2]interface{}{
// builtin.SystemActorCodeID: {builtin.MethodsSystem, system.Actor{} }- apparently it doesn't have methods
builtin.InitActorCodeID: {builtin.MethodsInit, init_.Actor{}},
builtin.CronActorCodeID: {builtin.MethodsCron, cron.Actor{}},
builtin.AccountActorCodeID: {builtin.MethodsAccount, account.Actor{}},
builtin.StoragePowerActorCodeID: {builtin.MethodsPower, power.Actor{}},
builtin.StorageMinerActorCodeID: {builtin.MethodsMiner, miner.Actor{}},
builtin.StorageMarketActorCodeID: {builtin.MethodsMarket, market.Actor{}},
builtin.PaymentChannelActorCodeID: {builtin.MethodsPaych, paych.Actor{}},
builtin.MultisigActorCodeID: {builtin.MethodsMultisig, multisig.Actor{}},
builtin.RewardActorCodeID: {builtin.MethodsReward, reward.Actor{}},
builtin.VerifiedRegistryActorCodeID: {builtin.MethodsVerifiedRegistry, verifreg.Actor{}},
}
for c, m := range cidToMethods {
rt := reflect.TypeOf(m[0])
nf := rt.NumField()
MethodsMap[c] = append(MethodsMap[c], methodMeta{
Name: "Send",
Params: reflect.TypeOf(new(adt.EmptyValue)),
Ret: reflect.TypeOf(new(adt.EmptyValue)),
})
exports := m[1].(abi.Invokee).Exports()
for i := 0; i < nf; i++ {
export := reflect.TypeOf(exports[i+1])
MethodsMap[c] = append(MethodsMap[c], methodMeta{
Name: rt.Field(i).Name,
Params: export.In(1),
Ret: export.Out(0),
})
}
}
}
func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, method abi.MethodNum, ts *types.TipSet) (cbg.CBORUnmarshaler, error) {
act, err := sm.GetActor(to, ts)
if err != nil {
return nil, err
}
m := MethodsMap[act.Code][method]
return reflect.New(m.Ret.Elem()).Interface().(cbg.CBORUnmarshaler), nil
}
+3
View File
@@ -32,8 +32,11 @@ func (fts *FullTipSet) Cids() []cid.Cid {
return cids
}
// TipSet returns a narrower view of this FullTipSet elliding the block
// messages.
func (fts *FullTipSet) TipSet() *types.TipSet {
if fts.tipset != nil {
// FIXME: fts.tipset is actually never set. Should it memoize?
return fts.tipset
}
+161
View File
@@ -0,0 +1,161 @@
package store
import (
"context"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/abi"
lru "github.com/hashicorp/golang-lru"
"golang.org/x/xerrors"
)
type ChainIndex struct {
skipCache *lru.ARCCache
loadTipSet loadTipSetFunc
skipLength abi.ChainEpoch
}
type loadTipSetFunc func(types.TipSetKey) (*types.TipSet, error)
func NewChainIndex(lts loadTipSetFunc) *ChainIndex {
sc, _ := lru.NewARC(8192)
return &ChainIndex{
skipCache: sc,
loadTipSet: lts,
skipLength: 20,
}
}
type lbEntry struct {
ts *types.TipSet
parentHeight abi.ChainEpoch
targetHeight abi.ChainEpoch
target types.TipSetKey
}
func (ci *ChainIndex) GetTipsetByHeight(_ context.Context, from *types.TipSet, to abi.ChainEpoch) (*types.TipSet, error) {
if from.Height()-to <= ci.skipLength {
return ci.walkBack(from, to)
}
rounded, err := ci.roundDown(from)
if err != nil {
return nil, err
}
cur := rounded.Key()
for {
cval, ok := ci.skipCache.Get(cur)
if !ok {
fc, err := ci.fillCache(cur)
if err != nil {
return nil, err
}
cval = fc
}
lbe := cval.(*lbEntry)
if lbe.ts.Height() == to || lbe.parentHeight < to {
return lbe.ts, nil
} else if to > lbe.targetHeight {
return ci.walkBack(lbe.ts, to)
}
cur = lbe.target
}
}
func (ci *ChainIndex) GetTipsetByHeightWithoutCache(from *types.TipSet, to abi.ChainEpoch) (*types.TipSet, error) {
return ci.walkBack(from, to)
}
func (ci *ChainIndex) fillCache(tsk types.TipSetKey) (*lbEntry, error) {
ts, err := ci.loadTipSet(tsk)
if err != nil {
return nil, err
}
if ts.Height() == 0 {
return &lbEntry{
ts: ts,
parentHeight: 0,
}, nil
}
// will either be equal to ts.Height, or at least > ts.Parent.Height()
rheight := ci.roundHeight(ts.Height())
parent, err := ci.loadTipSet(ts.Parents())
if err != nil {
return nil, err
}
rheight -= ci.skipLength
var skipTarget *types.TipSet
if parent.Height() < rheight {
skipTarget = parent
} else {
skipTarget, err = ci.walkBack(parent, rheight)
if err != nil {
return nil, xerrors.Errorf("fillCache walkback: %w", err)
}
}
lbe := &lbEntry{
ts: ts,
parentHeight: parent.Height(),
targetHeight: skipTarget.Height(),
target: skipTarget.Key(),
}
ci.skipCache.Add(tsk, lbe)
return lbe, nil
}
// floors to nearest skipLength multiple
func (ci *ChainIndex) roundHeight(h abi.ChainEpoch) abi.ChainEpoch {
return (h / ci.skipLength) * ci.skipLength
}
func (ci *ChainIndex) roundDown(ts *types.TipSet) (*types.TipSet, error) {
target := ci.roundHeight(ts.Height())
rounded, err := ci.walkBack(ts, target)
if err != nil {
return nil, err
}
return rounded, nil
}
func (ci *ChainIndex) walkBack(from *types.TipSet, to abi.ChainEpoch) (*types.TipSet, error) {
if to > from.Height() {
return nil, xerrors.Errorf("looking for tipset with height greater than start point")
}
if to == from.Height() {
return from, nil
}
ts := from
for {
pts, err := ci.loadTipSet(ts.Parents())
if err != nil {
return nil, err
}
if to > pts.Height() {
// in case pts is lower than the epoch we're looking for (null blocks)
// return a tipset above that height
return ts, nil
}
if to == pts.Height() {
return pts, nil
}
ts = pts
}
}
+80
View File
@@ -0,0 +1,80 @@
package store_test
import (
"bytes"
"context"
"testing"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types/mock"
"github.com/filecoin-project/specs-actors/actors/abi"
datastore "github.com/ipfs/go-datastore"
syncds "github.com/ipfs/go-datastore/sync"
blockstore "github.com/ipfs/go-ipfs-blockstore"
"github.com/stretchr/testify/assert"
)
func TestIndexSeeks(t *testing.T) {
cg, err := gen.NewGenerator()
if err != nil {
t.Fatal(err)
}
gencar, err := cg.GenesisCar()
if err != nil {
t.Fatal(err)
}
gen := cg.Genesis()
ctx := context.TODO()
nbs := blockstore.NewBlockstore(syncds.MutexWrap(datastore.NewMapDatastore()))
cs := store.NewChainStore(nbs, syncds.MutexWrap(datastore.NewMapDatastore()), nil)
_, err = cs.Import(bytes.NewReader(gencar))
if err != nil {
t.Fatal(err)
}
cur := mock.TipSet(gen)
if err := cs.PutTipSet(ctx, mock.TipSet(gen)); err != nil {
t.Fatal(err)
}
cs.SetGenesis(gen)
// Put 113 blocks from genesis
for i := 0; i < 113; i++ {
nextts := mock.TipSet(mock.MkBlock(cur, 1, 1))
if err := cs.PutTipSet(ctx, nextts); err != nil {
t.Fatal(err)
}
cur = nextts
}
// Put 50 null epochs + 1 block
skip := mock.MkBlock(cur, 1, 1)
skip.Height += 50
skipts := mock.TipSet(skip)
if err := cs.PutTipSet(ctx, skipts); err != nil {
t.Fatal(err)
}
ts, err := cs.GetTipsetByHeight(ctx, skip.Height-10, skipts, false)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, abi.ChainEpoch(164), ts.Height())
for i := 0; i <= 113; i++ {
ts3, err := cs.GetTipsetByHeight(ctx, abi.ChainEpoch(i), skipts, false)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, abi.ChainEpoch(i), ts3.Height())
}
}
+114 -50
View File
@@ -18,9 +18,9 @@ import (
"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/state"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/journal"
"github.com/filecoin-project/lotus/metrics"
"go.opencensus.io/stats"
"go.opencensus.io/trace"
@@ -48,7 +48,20 @@ import (
var log = logging.Logger("chainstore")
var chainHeadKey = dstore.NewKey("head")
var blockValidationCacheKeyPrefix = dstore.NewKey("blockValidation")
// ReorgNotifee represents a callback that gets called upon reorgs.
type ReorgNotifee func(rev, app []*types.TipSet) error
// ChainStore is the main point of access to chain data.
//
// Raw chain data is stored in the Blockstore, with relevant markers (genesis,
// latest head tipset references) being tracked in the Datastore (key-value
// store).
//
// To alleviate disk access, the ChainStore has two ARC caches:
// 1. a tipset cache
// 2. a block => messages references cache.
type ChainStore struct {
bs bstore.Blockstore
ds dstore.Datastore
@@ -62,8 +75,10 @@ type ChainStore struct {
tstLk sync.Mutex
tipsets map[abi.ChainEpoch][]cid.Cid
reorgCh chan<- reorg
headChangeNotifs []func(rev, app []*types.TipSet) error
cindex *ChainIndex
reorgCh chan<- reorg
reorgNotifeeCh chan ReorgNotifee
mmCache *lru.ARCCache
tsCache *lru.ARCCache
@@ -84,7 +99,9 @@ func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls runtime.Sys
vmcalls: vmcalls,
}
cs.reorgCh = cs.reorgWorker(context.TODO())
ci := NewChainIndex(cs.LoadTipSet)
cs.cindex = ci
hcnf := func(rev, app []*types.TipSet) error {
cs.pubLk.Lock()
@@ -117,7 +134,8 @@ func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls runtime.Sys
return nil
}
cs.headChangeNotifs = append(cs.headChangeNotifs, hcnf, hcmetric)
cs.reorgNotifeeCh = make(chan ReorgNotifee)
cs.reorgCh = cs.reorgWorker(context.TODO(), []ReorgNotifee{hcnf, hcmetric})
return cs
}
@@ -206,8 +224,24 @@ func (cs *ChainStore) SubHeadChanges(ctx context.Context) chan []*api.HeadChange
return out
}
func (cs *ChainStore) SubscribeHeadChanges(f func(rev, app []*types.TipSet) error) {
cs.headChangeNotifs = append(cs.headChangeNotifs, f)
func (cs *ChainStore) SubscribeHeadChanges(f ReorgNotifee) {
cs.reorgNotifeeCh <- f
}
func (cs *ChainStore) IsBlockValidated(ctx context.Context, blkid cid.Cid) (bool, error) {
key := blockValidationCacheKeyPrefix.Instance(blkid.String())
return cs.ds.Has(key)
}
func (cs *ChainStore) MarkBlockAsValidated(ctx context.Context, blkid cid.Cid) error {
key := blockValidationCacheKeyPrefix.Instance(blkid.String())
if err := cs.ds.Put(key, []byte{0}); err != nil {
return xerrors.Errorf("cache block validation: %w", err)
}
return nil
}
func (cs *ChainStore) SetGenesis(b *types.BlockHeader) error {
@@ -242,6 +276,9 @@ func (cs *ChainStore) PutTipSet(ctx context.Context, ts *types.TipSet) error {
return nil
}
// MaybeTakeHeavierTipSet evaluates the incoming tipset and locks it in our
// internal state as our new head, if and only if it is heavier than the current
// head.
func (cs *ChainStore) MaybeTakeHeavierTipSet(ctx context.Context, ts *types.TipSet) error {
cs.heaviestLk.Lock()
defer cs.heaviestLk.Unlock()
@@ -268,13 +305,19 @@ type reorg struct {
new *types.TipSet
}
func (cs *ChainStore) reorgWorker(ctx context.Context) chan<- reorg {
func (cs *ChainStore) reorgWorker(ctx context.Context, initialNotifees []ReorgNotifee) chan<- reorg {
out := make(chan reorg, 32)
notifees := make([]ReorgNotifee, len(initialNotifees))
copy(notifees, initialNotifees)
go func() {
defer log.Warn("reorgWorker quit")
for {
select {
case n := <-cs.reorgNotifeeCh:
notifees = append(notifees, n)
case r := <-out:
revert, apply, err := cs.ReorgOps(r.old, r.new)
if err != nil {
@@ -282,13 +325,21 @@ func (cs *ChainStore) reorgWorker(ctx context.Context) chan<- reorg {
continue
}
journal.Add("sync", map[string]interface{}{
"op": "headChange",
"from": r.old.Key(),
"to": r.new.Key(),
"rev": len(revert),
"apply": len(apply),
})
// reverse the apply array
for i := len(apply)/2 - 1; i >= 0; i-- {
opp := len(apply) - 1 - i
apply[i], apply[opp] = apply[opp], apply[i]
}
for _, hcf := range cs.headChangeNotifs {
for _, hcf := range notifees {
if err := hcf(revert, apply); err != nil {
log.Error("head change func errored (BAD): ", err)
}
@@ -301,6 +352,9 @@ func (cs *ChainStore) reorgWorker(ctx context.Context) chan<- reorg {
return out
}
// takeHeaviestTipSet actually sets the incoming tipset as our head both in
// memory and in the ChainStore. It also sends a notification to deliver to
// ReorgNotifees.
func (cs *ChainStore) takeHeaviestTipSet(ctx context.Context, ts *types.TipSet) error {
_, span := trace.StartSpan(ctx, "takeHeaviestTipSet")
defer span.End()
@@ -338,6 +392,7 @@ func (cs *ChainStore) SetHead(ts *types.TipSet) error {
return cs.takeHeaviestTipSet(context.TODO(), ts)
}
// Contains returns whether our BlockStore has all blocks in the supplied TipSet.
func (cs *ChainStore) Contains(ts *types.TipSet) (bool, error) {
for _, c := range ts.Cids() {
has, err := cs.bs.Has(c)
@@ -352,6 +407,8 @@ func (cs *ChainStore) Contains(ts *types.TipSet) (bool, error) {
return true, nil
}
// GetBlock fetches a BlockHeader with the supplied CID. It returns
// blockstore.ErrNotFound if the block was not found in the BlockStore.
func (cs *ChainStore) GetBlock(c cid.Cid) (*types.BlockHeader, error) {
sb, err := cs.bs.Get(c)
if err != nil {
@@ -387,7 +444,7 @@ func (cs *ChainStore) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error) {
return ts, nil
}
// returns true if 'a' is an ancestor of 'b'
// IsAncestorOf returns true if 'a' is an ancestor of 'b'
func (cs *ChainStore) IsAncestorOf(a, b *types.TipSet) (bool, error) {
if b.Height() <= a.Height() {
return false, nil
@@ -444,6 +501,7 @@ func (cs *ChainStore) ReorgOps(a, b *types.TipSet) ([]*types.TipSet, []*types.Ti
return leftChain, rightChain, nil
}
// GetHeaviestTipSet returns the current heaviest tipset known (i.e. our head).
func (cs *ChainStore) GetHeaviestTipSet() *types.TipSet {
cs.heaviestLk.Lock()
defer cs.heaviestLk.Unlock()
@@ -895,39 +953,50 @@ func DrawRandomness(rbase []byte, pers crypto.DomainSeparationTag, round abi.Cha
return nil, xerrors.Errorf("deriving randomness: %w", err)
}
VRFDigest := blake2b.Sum256(rbase)
h.Write(VRFDigest[:])
_, err := h.Write(VRFDigest[:])
if err != nil {
return nil, xerrors.Errorf("hashing VRFDigest: %w", err)
}
if err := binary.Write(h, binary.BigEndian, round); err != nil {
return nil, xerrors.Errorf("deriving randomness: %w", err)
}
h.Write(entropy)
_, err = h.Write(entropy)
if err != nil {
return nil, xerrors.Errorf("hashing entropy: %w", err)
}
return h.Sum(nil), nil
}
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) (out []byte, err error) {
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
_, span := trace.StartSpan(ctx, "store.GetRandomness")
defer span.End()
span.AddAttributes(trace.Int64Attribute("round", int64(round)))
//defer func() {
//log.Infof("getRand %v %d %d %x -> %x", blks, pers, round, entropy, out)
//}()
for {
nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
if err != nil {
return nil, err
}
mtb := nts.MinTicketBlock()
// if at (or just past -- for null epochs) appropriate epoch
// or at genesis (works for negative epochs)
if nts.Height() <= round || mtb.Height == 0 {
return DrawRandomness(nts.MinTicketBlock().Ticket.VRFProof, pers, round, entropy)
}
blks = mtb.Parents
ts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
if err != nil {
return nil, err
}
if round > ts.Height() {
return nil, xerrors.Errorf("cannot draw randomness from the future")
}
searchHeight := round
if searchHeight < 0 {
searchHeight = 0
}
randTs, err := cs.GetTipsetByHeight(ctx, searchHeight, ts, true)
if err != nil {
return nil, err
}
mtb := randTs.MinTicketBlock()
// if at (or just past -- for null epochs) appropriate epoch
// or at genesis (works for negative epochs)
return DrawRandomness(mtb.Ticket.VRFProof, pers, round, entropy)
}
// GetTipsetByHeight returns the tipset on the chain behind 'ts' at the given
@@ -940,35 +1009,31 @@ func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h abi.ChainEpoch, t
}
if h > ts.Height() {
return nil, xerrors.Errorf("looking for tipset with height less than start point")
return nil, xerrors.Errorf("looking for tipset with height greater than start point")
}
if h == ts.Height() {
return ts, nil
}
if ts.Height()-h > build.ForkLengthThreshold {
log.Warnf("expensive call to GetTipsetByHeight, seeking %d levels", ts.Height()-h)
lbts, err := cs.cindex.GetTipsetByHeight(ctx, ts, h)
if err != nil {
return nil, err
}
for {
pts, err := cs.LoadTipSet(ts.Parents())
if lbts.Height() < h {
log.Warnf("chain index returned the wrong tipset at height %d, using slow retrieval", h)
lbts, err = cs.cindex.GetTipsetByHeightWithoutCache(ts, h)
if err != nil {
return nil, err
}
if h > pts.Height() {
if prev {
return pts, nil
}
return ts, nil
}
if h == pts.Height() {
return pts, nil
}
ts = pts
}
if lbts.Height() == h || !prev {
return lbts, nil
}
return cs.LoadTipSet(lbts.Parents())
}
func recurseLinks(bs blockstore.Blockstore, root cid.Cid, in []cid.Cid) ([]cid.Cid, error) {
@@ -1148,7 +1213,6 @@ func (cr *chainRand) GetRandomness(ctx context.Context, pers crypto.DomainSepara
func (cs *ChainStore) GetTipSetFromKey(tsk types.TipSetKey) (*types.TipSet, error) {
if tsk.IsEmpty() {
return cs.GetHeaviestTipSet(), nil
} else {
return cs.LoadTipSet(tsk)
}
return cs.LoadTipSet(tsk)
}
+3 -3
View File
@@ -22,8 +22,8 @@ import (
)
func init() {
miner.SupportedProofTypes = map[abi.RegisteredProof]struct{}{
abi.RegisteredProof_StackedDRG2KiBSeal: {},
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
}
power.ConsensusMinerMinPower = big.NewInt(2048)
verifreg.MinVerifiedDealSize = big.NewInt(256)
@@ -55,7 +55,7 @@ func BenchmarkGetRandomness(b *testing.B) {
b.Fatal(err)
}
bds, err := lr.Datastore("/blocks")
bds, err := lr.Datastore("/chain")
if err != nil {
b.Fatal(err)
}
+196 -19
View File
@@ -1,30 +1,45 @@
package sub
import (
"bytes"
"context"
"fmt"
"sync"
"time"
"golang.org/x/xerrors"
address "github.com/filecoin-project/go-address"
amt "github.com/filecoin-project/go-amt-ipld/v2"
miner "github.com/filecoin-project/specs-actors/actors/builtin/miner"
lru "github.com/hashicorp/golang-lru"
"github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2"
connmgr "github.com/libp2p/go-libp2p-core/connmgr"
"github.com/libp2p/go-libp2p-core/peer"
pubsub "github.com/libp2p/go-libp2p-pubsub"
cbg "github.com/whyrusleeping/cbor-gen"
"go.opencensus.io/stats"
"go.opencensus.io/tag"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain"
"github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/bufbstore"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/metrics"
)
var log = logging.Logger("sub")
func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *chain.Syncer, cmgr connmgr.ConnManager, bv *BlockValidator) {
func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *chain.Syncer, cmgr connmgr.ConnManager) {
for {
msg, err := bsub.Next(ctx)
if err != nil {
@@ -42,25 +57,20 @@ func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *cha
return
}
//nolint:golint
src := peer.ID(msg.GetFrom())
src := msg.GetFrom()
go func() {
log.Infof("New block over pubsub: %s", blk.Cid())
start := time.Now()
log.Debug("about to fetch messages for block from pubsub")
bmsgs, err := s.Bsync.FetchMessagesByCids(context.TODO(), blk.BlsMessages)
if err != nil {
log.Errorf("failed to fetch all bls messages for block received over pubusb: %s; flagging source %s", err, src)
bv.flagPeer(src)
log.Errorf("failed to fetch all bls messages for block received over pubusb: %s; source: %s", err, src)
return
}
smsgs, err := s.Bsync.FetchSignedMessagesByCids(context.TODO(), blk.SecpkMessages)
if err != nil {
log.Errorf("failed to fetch all secpk messages for block received over pubusb: %s; flagging source %s", err, src)
bv.flagPeer(src)
log.Errorf("failed to fetch all secpk messages for block received over pubusb: %s; source: %s", err, src)
return
}
@@ -89,15 +99,25 @@ type BlockValidator struct {
recvBlocks *blockReceiptCache
blacklist func(peer.ID)
// necessary for block validation
chain *store.ChainStore
stmgr *stmgr.StateManager
mx sync.Mutex
keycache map[string]address.Address
}
func NewBlockValidator(blacklist func(peer.ID)) *BlockValidator {
func NewBlockValidator(chain *store.ChainStore, stmgr *stmgr.StateManager, blacklist func(peer.ID)) *BlockValidator {
p, _ := lru.New2Q(4096)
return &BlockValidator{
peers: p,
killThresh: 10,
blacklist: blacklist,
recvBlocks: newBlockReceiptCache(),
chain: chain,
stmgr: stmgr,
keycache: make(map[string]address.Address),
}
}
@@ -120,35 +140,190 @@ func (bv *BlockValidator) flagPeer(p peer.ID) {
}
func (bv *BlockValidator) Validate(ctx context.Context, pid peer.ID, msg *pubsub.Message) pubsub.ValidationResult {
// track validation time
begin := time.Now()
defer func() {
log.Debugf("block validation time: %s", time.Since(begin))
}()
stats.Record(ctx, metrics.BlockReceived.M(1))
recordFailure := func(what string) {
ctx, _ = tag.New(ctx, tag.Insert(metrics.FailureType, what))
stats.Record(ctx, metrics.BlockValidationFailure.M(1))
bv.flagPeer(pid)
}
// make sure the block can be decoded
blk, err := types.DecodeBlockMsg(msg.GetData())
if err != nil {
log.Error("got invalid block over pubsub: ", err)
ctx, _ = tag.New(ctx, tag.Insert(metrics.FailureType, "invalid"))
stats.Record(ctx, metrics.BlockValidationFailure.M(1))
bv.flagPeer(pid)
recordFailure("invalid")
return pubsub.ValidationReject
}
// check the message limit constraints
if len(blk.BlsMessages)+len(blk.SecpkMessages) > build.BlockMessageLimit {
log.Warnf("received block with too many messages over pubsub")
ctx, _ = tag.New(ctx, tag.Insert(metrics.FailureType, "too_many_messages"))
stats.Record(ctx, metrics.BlockValidationFailure.M(1))
bv.flagPeer(pid)
recordFailure("too_many_messages")
return pubsub.ValidationReject
}
// make sure we have a signature
if blk.Header.BlockSig == nil {
log.Warnf("received block without a signature over pubsub")
recordFailure("missing_signature")
return pubsub.ValidationReject
}
// validate the block meta: the Message CID in the header must match the included messages
err = bv.validateMsgMeta(ctx, blk)
if err != nil {
log.Warnf("error validating message metadata: %s", err)
recordFailure("invalid_block_meta")
return pubsub.ValidationReject
}
// we want to ensure that it is a block from a known miner; we reject blocks from unknown miners
// to prevent spam attacks.
// the logic works as follows: we lookup the miner in the chain for its key.
// if we can find it then it's a known miner and we can validate the signature.
// if we can't find it, we check whether we are (near) synced in the chain.
// if we are not synced we cannot validate the block and we must ignore it.
// if we are synced and the miner is unknown, then the block is rejcected.
key, err := bv.getMinerWorkerKey(ctx, blk)
if err != nil {
if bv.isChainNearSynced() {
log.Warnf("received block message from unknown miner over pubsub; rejecting message")
recordFailure("unknown_miner")
return pubsub.ValidationReject
} else {
log.Warnf("cannot validate block message; unknown miner in unsynced chain")
return pubsub.ValidationIgnore
}
}
err = sigs.CheckBlockSignature(ctx, blk.Header, key)
if err != nil {
log.Errorf("block signature verification failed: %s", err)
recordFailure("signature_verification_failed")
return pubsub.ValidationReject
}
// it's a good block! make sure we've only seen it once
if bv.recvBlocks.add(blk.Header.Cid()) > 0 {
// TODO: once these changes propagate to the network, we can consider
// dropping peers who send us the same block multiple times
return pubsub.ValidationIgnore
}
// all good, accept the block
msg.ValidatorData = blk
stats.Record(ctx, metrics.BlockValidationSuccess.M(1))
return pubsub.ValidationAccept
}
func (bv *BlockValidator) isChainNearSynced() bool {
ts := bv.chain.GetHeaviestTipSet()
timestamp := ts.MinTimestamp()
now := time.Now().UnixNano()
cutoff := uint64(now) - uint64(6*time.Hour)
return timestamp > cutoff
}
func (bv *BlockValidator) validateMsgMeta(ctx context.Context, msg *types.BlockMsg) error {
var bcids, scids []cbg.CBORMarshaler
for _, m := range msg.BlsMessages {
c := cbg.CborCid(m)
bcids = append(bcids, &c)
}
for _, m := range msg.SecpkMessages {
c := cbg.CborCid(m)
scids = append(scids, &c)
}
// TODO there has to be a simpler way to do this without the blockstore dance
bs := cbor.NewCborStore(bstore.NewBlockstore(dstore.NewMapDatastore()))
bmroot, err := amt.FromArray(ctx, bs, bcids)
if err != nil {
return err
}
smroot, err := amt.FromArray(ctx, bs, scids)
if err != nil {
return err
}
mrcid, err := bs.Put(ctx, &types.MsgMeta{
BlsMessages: bmroot,
SecpkMessages: smroot,
})
if err != nil {
return err
}
if msg.Header.Messages != mrcid {
return fmt.Errorf("messages didn't match root cid in header")
}
return nil
}
func (bv *BlockValidator) getMinerWorkerKey(ctx context.Context, msg *types.BlockMsg) (address.Address, error) {
addr := msg.Header.Miner
bv.mx.Lock()
key, ok := bv.keycache[addr.String()]
bv.mx.Unlock()
if ok {
return key, nil
}
// TODO I have a feeling all this can be simplified by cleverer DI to use the API
ts := bv.chain.GetHeaviestTipSet()
st, _, err := bv.stmgr.TipSetState(ctx, ts)
if err != nil {
return address.Undef, err
}
buf := bufbstore.NewBufferedBstore(bv.chain.Blockstore())
cst := cbor.NewCborStore(buf)
state, err := state.LoadStateTree(cst, st)
if err != nil {
return address.Undef, err
}
act, err := state.GetActor(addr)
if err != nil {
return address.Undef, err
}
blk, err := bv.chain.Blockstore().Get(act.Head)
if err != nil {
return address.Undef, err
}
aso := blk.RawData()
var mst miner.State
err = mst.UnmarshalCBOR(bytes.NewReader(aso))
if err != nil {
return address.Undef, err
}
worker := mst.Info.Worker
key, err = bv.stmgr.ResolveToKeyAddress(ctx, worker, ts)
if err != nil {
return address.Undef, err
}
bv.mx.Lock()
bv.keycache[addr.String()] = key
bv.mx.Unlock()
return key, nil
}
type blockReceiptCache struct {
blocks *lru.TwoQueueCache
}
@@ -197,10 +372,12 @@ func (mv *MessageValidator) Validate(ctx context.Context, pid peer.ID, msg *pubs
tag.Insert(metrics.FailureType, "add"),
)
stats.Record(ctx, metrics.MessageValidationFailure.M(1))
if xerrors.Is(err, messagepool.ErrBroadcastAnyway) {
return pubsub.ValidationAccept
switch {
case xerrors.Is(err, messagepool.ErrBroadcastAnyway):
return pubsub.ValidationIgnore
default:
return pubsub.ValidationReject
}
return pubsub.ValidationIgnore
}
stats.Record(ctx, metrics.MessageValidationSuccess.M(1))
return pubsub.ValidationAccept
+246 -81
View File
@@ -8,7 +8,6 @@ import (
"os"
"sort"
"strings"
"sync"
"time"
"github.com/Gurpartap/async"
@@ -50,10 +49,37 @@ import (
"github.com/filecoin-project/lotus/metrics"
)
// Blocks that are more than MaxHeightDrift epochs above
//the theoretical max height based on systime are quickly rejected
const MaxHeightDrift = 5
var log = logging.Logger("chain")
var LocalIncoming = "incoming"
// Syncer is in charge of running the chain synchronization logic. As such, it
// is tasked with these functions, amongst others:
//
// * Fast-forwards the chain as it learns of new TipSets from the network via
// the SyncManager.
// * Applies the fork choice rule to select the correct side when confronted
// with a fork in the network.
// * Requests block headers and messages from other peers when not available
// in our BlockStore.
// * Tracks blocks marked as bad in a cache.
// * Keeps the BlockStore and ChainStore consistent with our view of the world,
// the latter of which in turn informs other components when a reorg has been
// committed.
//
// The Syncer does not run workers itself. It's mainly concerned with
// ensuring a consistent state of chain consensus. The reactive and network-
// interfacing processes are part of other components, such as the SyncManager
// (which owns the sync scheduler and sync workers), BlockSync, the HELLO
// protocol, and the gossipsub block propagation layer.
//
// {hint/concept} The fork-choice rule as it currently stands is: "pick the
// chain with the heaviest weight, so long as it hasnt deviated one finality
// threshold from our head (900 epochs, parameter determined by spec-actors)".
type Syncer struct {
// The interface for accessing and putting tipsets into local storage
store *store.ChainStore
@@ -86,6 +112,7 @@ type Syncer struct {
verifier ffiwrapper.Verifier
}
// NewSyncer creates a new Syncer object.
func NewSyncer(sm *stmgr.StateManager, bsync *blocksync.BlockSync, connmgr connmgr.ConnManager, self peer.ID, beacon beacon.RandomBeacon, verifier ffiwrapper.Verifier) (*Syncer, error) {
gen, err := sm.ChainStore().GetGenesis()
if err != nil {
@@ -134,6 +161,11 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) bool {
return false
}
if syncer.IsEpochBeyondCurrMax(fts.TipSet().Height()) {
log.Errorf("Received block with impossibly large height %d", fts.TipSet().Height())
return false
}
for _, b := range fts.Blocks {
if reason, ok := syncer.bad.Has(b.Cid()); ok {
log.Warnf("InformNewHead called on block marked as bad: %s (reason: %s)", b.Cid(), reason)
@@ -183,6 +215,11 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) bool {
return true
}
// IncomingBlocks spawns a goroutine that subscribes to the local eventbus to
// receive new block headers as they arrive from the network, and sends them to
// the returned channel.
//
// These blocks have not necessarily been incorporated to our view of the chain.
func (syncer *Syncer) IncomingBlocks(ctx context.Context) (<-chan *types.BlockHeader, error) {
sub := syncer.incoming.Sub(LocalIncoming)
out := make(chan *types.BlockHeader, 10)
@@ -210,11 +247,15 @@ func (syncer *Syncer) IncomingBlocks(ctx context.Context) (<-chan *types.BlockHe
return out, nil
}
// ValidateMsgMeta performs structural and content hash validation of the
// messages within this block. If validation passes, it stores the messages in
// the underlying IPLD block store.
func (syncer *Syncer) ValidateMsgMeta(fblk *types.FullBlock) error {
if msgc := len(fblk.BlsMessages) + len(fblk.SecpkMessages); msgc > build.BlockMessageLimit {
return xerrors.Errorf("block %s has too many messages (%d)", fblk.Header.Cid(), msgc)
}
// Collect the CIDs of both types of messages separately: BLS and Secpk.
var bcids, scids []cbg.CBORMarshaler
for _, m := range fblk.BlsMessages {
c := cbg.CborCid(m.Cid())
@@ -232,11 +273,14 @@ func (syncer *Syncer) ValidateMsgMeta(fblk *types.FullBlock) error {
blockstore := syncer.store.Blockstore()
bs := cbor.NewCborStore(blockstore)
// Compute the root CID of the combined message trie.
smroot, err := computeMsgMeta(bs, bcids, scids)
if err != nil {
return xerrors.Errorf("validating msgmeta, compute failed: %w", err)
}
// Check that the message trie root matches with what's in the block.
if fblk.Header.Messages != smroot {
return xerrors.Errorf("messages in full block did not match msgmeta root in header (%s != %s)", fblk.Header.Messages, smroot)
}
@@ -305,6 +349,10 @@ func zipTipSetAndMessages(bs cbor.IpldStore, ts *types.TipSet, allbmsgs []*types
fts := &store.FullTipSet{}
for bi, b := range ts.Blocks() {
if msgc := len(bmi[bi]) + len(smi[bi]); msgc > build.BlockMessageLimit {
return nil, fmt.Errorf("block %q has too many messages (%d)", b.Cid(), msgc)
}
var smsgs []*types.SignedMessage
var smsgCids []cbg.CBORMarshaler
for _, m := range smi[bi] {
@@ -321,10 +369,6 @@ func zipTipSetAndMessages(bs cbor.IpldStore, ts *types.TipSet, allbmsgs []*types
bmsgCids = append(bmsgCids, &c)
}
if msgc := len(bmsgCids) + len(smsgCids); msgc > build.BlockMessageLimit {
return nil, fmt.Errorf("block %q has too many messages (%d)", b.Cid(), msgc)
}
mrcid, err := computeMsgMeta(bs, bmsgCids, smsgCids)
if err != nil {
return nil, err
@@ -346,6 +390,8 @@ func zipTipSetAndMessages(bs cbor.IpldStore, ts *types.TipSet, allbmsgs []*types
return fts, nil
}
// 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 []cbg.CBORMarshaler) (cid.Cid, error) {
ctx := context.TODO()
bmroot, err := amt.FromArray(ctx, bs, bmsgCids)
@@ -369,14 +415,24 @@ func computeMsgMeta(bs cbor.IpldStore, bmsgCids, smsgCids []cbg.CBORMarshaler) (
return mrcid, nil
}
// FetchTipSet tries to load the provided tipset from the store, and falls back
// to the network (BlockSync) by querying the supplied peer if not found
// locally.
//
// {hint/usage} This is used from the HELLO protocol, to fetch the greeting
// peer's heaviest tipset if we don't have it.
func (syncer *Syncer) FetchTipSet(ctx context.Context, p peer.ID, tsk types.TipSetKey) (*store.FullTipSet, error) {
if fts, err := syncer.tryLoadFullTipSet(tsk); err == nil {
return fts, nil
}
// fall back to the network.
return syncer.Bsync.GetFullTipSet(ctx, p, tsk)
}
// tryLoadFullTipSet queries the tipset in the ChainStore, and returns a full
// representation of it containing FullBlocks. If ALL blocks are not found
// locally, it errors entirely with blockstore.ErrNotFound.
func (syncer *Syncer) tryLoadFullTipSet(tsk types.TipSetKey) (*store.FullTipSet, error) {
ts, err := syncer.store.LoadTipSet(tsk)
if err != nil {
@@ -401,6 +457,12 @@ func (syncer *Syncer) tryLoadFullTipSet(tsk types.TipSetKey) (*store.FullTipSet,
return fts, nil
}
// Sync tries to advance our view of the chain to `maybeHead`. It does nothing
// if our current head is heavier than the requested tipset, or if we're already
// at the requested head, or if the head is the genesis.
//
// Most of the heavy-lifting logic happens in syncer#collectChain. Refer to the
// godocs on that method for a more detailed view.
func (syncer *Syncer) Sync(ctx context.Context, maybeHead *types.TipSet) error {
ctx, span := trace.StartSpan(ctx, "chain.Sync")
defer span.End()
@@ -429,6 +491,8 @@ func (syncer *Syncer) Sync(ctx context.Context, maybeHead *types.TipSet) error {
return xerrors.Errorf("collectChain failed: %w", err)
}
// At this point we have accepted and synced to the new `maybeHead`
// (`StageSyncComplete`).
if err := syncer.store.PutTipSet(ctx, maybeHead); err != nil {
span.AddAttributes(trace.StringAttribute("put_error", err.Error()))
span.SetStatus(trace.Status{
@@ -465,16 +529,27 @@ func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet)
return nil
}
var futures []async.ErrorFuture
for _, b := range fts.Blocks {
if err := syncer.ValidateBlock(ctx, b); err != nil {
if isPermanent(err) {
syncer.bad.Add(b.Cid(), err.Error())
}
return xerrors.Errorf("validating block %s: %w", b.Cid(), err)
}
b := b // rebind to a scoped variable
if err := syncer.sm.ChainStore().AddToTipSetTracker(b.Header); err != nil {
return xerrors.Errorf("failed to add validated header to tipset tracker: %w", err)
futures = append(futures, async.Err(func() error {
if err := syncer.ValidateBlock(ctx, b); err != nil {
if isPermanent(err) {
syncer.bad.Add(b.Cid(), NewBadBlockReason([]cid.Cid{b.Cid()}, err.Error()))
}
return xerrors.Errorf("validating block %s: %w", b.Cid(), err)
}
if err := syncer.sm.ChainStore().AddToTipSetTracker(b.Header); err != nil {
return xerrors.Errorf("failed to add validated header to tipset tracker: %w", err)
}
return nil
}))
}
for _, f := range futures {
if err := f.AwaitContext(ctx); err != nil {
return err
}
}
return nil
@@ -526,10 +601,36 @@ func blockSanityChecks(h *types.BlockHeader) error {
return nil
}
// Should match up with 'Semantical Validation' in validation.md in the spec
func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) 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) {
defer func() {
// b.Cid() could panic for empty blocks that are used in tests.
if rerr := recover(); rerr != nil {
err = xerrors.Errorf("validate block panic: %w", rerr)
return
}
}()
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
}
validationStart := time.Now()
defer func() {
dur := time.Since(validationStart)
durMilli := dur.Seconds() * float64(1000)
stats.Record(ctx, metrics.BlockValidationDurationMilliseconds.M(durMilli))
log.Infow("block validation", "took", dur, "height", b.Header.Height)
}()
ctx, span := trace.StartSpan(ctx, "validateBlock")
defer span.End()
if build.InsecurePoStValidation {
log.Warn("insecure test validation is enabled, if you see this outside of a test, it is a severe bug!")
}
@@ -565,18 +666,18 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
// fast checks first
now := uint64(time.Now().Unix())
if h.Timestamp > now+build.AllowableClockDrift {
if h.Timestamp > now+build.AllowableClockDriftSecs {
return xerrors.Errorf("block was from the future (now=%d, blk=%d): %w", now, h.Timestamp, ErrTemporal)
}
if h.Timestamp > now {
log.Warn("Got block from the future, but within threshold", h.Timestamp, time.Now().Unix())
}
if h.Timestamp < baseTs.MinTimestamp()+(build.BlockDelay*uint64(h.Height-baseTs.Height())) {
if h.Timestamp < baseTs.MinTimestamp()+(build.BlockDelaySecs*uint64(h.Height-baseTs.Height())) {
log.Warn("timestamp funtimes: ", h.Timestamp, baseTs.MinTimestamp(), h.Height, baseTs.Height())
diff := (baseTs.MinTimestamp() + (build.BlockDelay * uint64(h.Height-baseTs.Height()))) - h.Timestamp
diff := (baseTs.MinTimestamp() + (build.BlockDelaySecs * uint64(h.Height-baseTs.Height()))) - h.Timestamp
return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * deltaH:%d; diff %d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelay, h.Height-baseTs.Height(), diff)
return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * deltaH:%d; diff %d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelaySecs, h.Height-baseTs.Height(), diff)
}
msgsCheck := async.Err(func() error {
@@ -639,7 +740,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return xerrors.Errorf("could not draw randomness: %w", err)
}
if err := gen.VerifyVRF(ctx, waddr, vrfBase, h.ElectionProof.VRFProof); err != nil {
if err := VerifyElectionPoStVRF(ctx, waddr, vrfBase, h.ElectionProof.VRFProof); err != nil {
return xerrors.Errorf("validating block election proof failed: %w", err)
}
@@ -665,7 +766,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
})
blockSigCheck := async.Err(func() error {
if err := sigs.CheckBlockSignature(h, ctx, waddr); err != nil {
if err := sigs.CheckBlockSignature(ctx, h, waddr); err != nil {
return xerrors.Errorf("check block signature failed: %w", err)
}
return nil
@@ -700,7 +801,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return xerrors.Errorf("failed to compute vrf base for ticket: %w", err)
}
err = gen.VerifyVRF(ctx, waddr, vrfBase, h.Ticket.VRFProof)
err = VerifyElectionPoStVRF(ctx, waddr, vrfBase, h.Ticket.VRFProof)
if err != nil {
return xerrors.Errorf("validating block tickets failed: %w", err)
}
@@ -748,7 +849,11 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
}
}
return merr
if err := syncer.store.MarkBlockAsValidated(ctx, b.Cid()); err != nil {
return xerrors.Errorf("caching block validation %s: %w", b.Cid(), err)
}
return nil
}
func (syncer *Syncer) VerifyWinningPoStProof(ctx context.Context, h *types.BlockHeader, prevBeacon types.BeaconEntry, lbst cid.Cid, waddr address.Address) error {
@@ -846,7 +951,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
// Phase 1: syntactic validation, as defined in the spec
minGas := vm.PricelistByEpoch(baseTs.Height()).OnChainMessage(msg.ChainLength())
if err := m.ValidForBlockInclusion(minGas); err != nil {
if err := m.ValidForBlockInclusion(minGas.Total()); err != nil {
return err
}
@@ -938,23 +1043,14 @@ func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig *crypto.Signat
trace.Int64Attribute("msgCount", int64(len(msgs))),
)
var wg sync.WaitGroup
digests := make([]bls.Digest, len(msgs))
for i := 0; i < 10; i++ {
wg.Add(1)
go func(w int) {
defer wg.Done()
for j := 0; (j*10)+w < len(msgs); j++ {
digests[j*10+w] = bls.Hash(bls.Message(msgs[j*10+w].Bytes()))
}
}(i)
bmsgs := make([]bls.Message, len(msgs))
for i, m := range msgs {
bmsgs[i] = m.Bytes()
}
wg.Wait()
var bsig bls.Signature
copy(bsig[:], sig.Data)
if !bls.Verify(&bsig, digests, pubks) {
if !bls.HashVerify(&bsig, bmsgs, pubks) {
return xerrors.New("bls aggregate signature failed to verify")
}
@@ -971,41 +1067,70 @@ func extractSyncState(ctx context.Context) *SyncerState {
return nil
}
func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to *types.TipSet) ([]*types.TipSet, error) {
// collectHeaders collects the headers from the blocks between any two tipsets.
//
// `incoming` is the heaviest/projected/target tipset we have learned about, and
// `known` is usually an anchor tipset we already have in our view of the chain
// (which could be the genesis).
//
// collectHeaders checks if portions of the chain are in our ChainStore; falling
// down to the network to retrieve the missing parts. If during the process, any
// portion we receive is in our denylist (bad list), we short-circuit.
//
// {hint/usage}: This is used by collectChain, which is in turn called from the
// main Sync method (Syncer#Sync), so it's a pretty central method.
//
// {hint/logic}: The logic of this method is as follows:
//
// 1. Check that the from tipset is not linked to a parent block known to be
// bad.
// 2. Check the consistency of beacon entries in the from tipset. We check
// total equality of the BeaconEntries in each block.
// 3. Traverse the chain backwards, for each tipset:
// 3a. Load it from the chainstore; if found, it move on to its parent.
// 3b. Query our peers via BlockSync in batches, requesting up to a
// maximum of 500 tipsets every time.
//
// Once we've concluded, if we find a mismatching tipset at the height where the
// anchor tipset should be, we are facing a fork, and we invoke Syncer#syncFork
// to resolve it. Refer to the godocs there.
//
// All throughout the process, we keep checking if the received blocks are in
// the deny list, and short-circuit the process if so.
func (syncer *Syncer) collectHeaders(ctx context.Context, incoming *types.TipSet, known *types.TipSet) ([]*types.TipSet, error) {
ctx, span := trace.StartSpan(ctx, "collectHeaders")
defer span.End()
ss := extractSyncState(ctx)
span.AddAttributes(
trace.Int64Attribute("fromHeight", int64(from.Height())),
trace.Int64Attribute("toHeight", int64(to.Height())),
trace.Int64Attribute("incomingHeight", int64(incoming.Height())),
trace.Int64Attribute("knownHeight", int64(known.Height())),
)
markBad := func(fmts string, args ...interface{}) {
for _, b := range from.Cids() {
syncer.bad.Add(b, fmt.Sprintf(fmts, args...))
}
}
for _, pcid := range from.Parents().Cids() {
// Check if the parents of the from block are in the denylist.
// i.e. if a fork of the chain has been requested that we know to be bad.
for _, pcid := range incoming.Parents().Cids() {
if reason, ok := syncer.bad.Has(pcid); ok {
markBad("linked to %s", pcid)
return nil, xerrors.Errorf("chain linked to block marked previously as bad (%s, %s) (reason: %s)", from.Cids(), pcid, reason)
newReason := reason.Linked("linked to %s", pcid)
for _, b := range incoming.Cids() {
syncer.bad.Add(b, newReason)
}
return nil, xerrors.Errorf("chain linked to block marked previously as bad (%s, %s) (reason: %s)", incoming.Cids(), pcid, reason)
}
}
{
// ensure consistency of beacon entires
targetBE := from.Blocks()[0].BeaconEntries
targetBE := incoming.Blocks()[0].BeaconEntries
sorted := sort.SliceIsSorted(targetBE, func(i, j int) bool {
return targetBE[i].Round < targetBE[j].Round
})
if !sorted {
syncer.bad.Add(from.Cids()[0], "wrong order of beacon entires")
syncer.bad.Add(incoming.Cids()[0], NewBadBlockReason(incoming.Cids(), "wrong order of beacon entires"))
return nil, xerrors.Errorf("wrong order of beacon entires")
}
for _, bh := range from.Blocks()[1:] {
for _, bh := range incoming.Blocks()[1:] {
if len(targetBE) != len(bh.BeaconEntries) {
// cannot mark bad, I think @Kubuxu
return nil, xerrors.Errorf("tipset contained different number for beacon entires")
@@ -1020,12 +1145,12 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to
}
}
blockSet := []*types.TipSet{from}
blockSet := []*types.TipSet{incoming}
at := from.Parents()
at := incoming.Parents()
// we want to sync all the blocks until the height above the block we have
untilHeight := to.Height() + 1
untilHeight := known.Height() + 1
ss.SetHeight(blockSet[len(blockSet)-1].Height())
@@ -1035,11 +1160,12 @@ loop:
for blockSet[len(blockSet)-1].Height() > untilHeight {
for _, bc := range at.Cids() {
if reason, ok := syncer.bad.Has(bc); ok {
newReason := reason.Linked("change contained %s", bc)
for _, b := range acceptedBlocks {
syncer.bad.Add(b, fmt.Sprintf("chain contained %s", bc))
syncer.bad.Add(b, newReason)
}
return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s) (reason: %s)", from.Cids(), bc, reason)
return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s) (reason: %s)", incoming.Cids(), bc, reason)
}
}
@@ -1057,8 +1183,8 @@ loop:
}
// NB: GetBlocks validates that the blocks are in-fact the ones we
// requested, and that they are correctly linked to eachother. It does
// not validate any state transitions
// requested, and that they are correctly linked to one another. It does
// not validate any state transitions.
window := 500
if gap := int(blockSet[len(blockSet)-1].Height() - untilHeight); gap < window {
window = gap
@@ -1083,11 +1209,12 @@ loop:
}
for _, bc := range b.Cids() {
if reason, ok := syncer.bad.Has(bc); ok {
newReason := reason.Linked("change contained %s", bc)
for _, b := range acceptedBlocks {
syncer.bad.Add(b, fmt.Sprintf("chain contained %s", bc))
syncer.bad.Add(b, newReason)
}
return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s) (reason: %s)", from.Cids(), bc, reason)
return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s) (reason: %s)", incoming.Cids(), bc, reason)
}
}
blockSet = append(blockSet, b)
@@ -1099,22 +1226,23 @@ loop:
at = blks[len(blks)-1].Parents()
}
// We have now ascertained that this is *not* a 'fast forward'
if !types.CidArrsEqual(blockSet[len(blockSet)-1].Parents().Cids(), to.Cids()) {
last := blockSet[len(blockSet)-1]
if last.Parents() == to.Parents() {
// base is the tipset in the candidate chain at the height equal to our known tipset height.
if base := blockSet[len(blockSet)-1]; !types.CidArrsEqual(base.Parents().Cids(), known.Cids()) {
if base.Parents() == known.Parents() {
// common case: receiving a block thats potentially part of the same tipset as our best block
return blockSet, nil
}
log.Warnf("(fork detected) synced header chain (%s - %d) does not link to our best block (%s - %d)", from.Cids(), from.Height(), to.Cids(), to.Height())
fork, err := syncer.syncFork(ctx, last, to)
// We have now ascertained that this is *not* a 'fast forward'
log.Warnf("(fork detected) synced header chain (%s - %d) does not link to our best block (%s - %d)", incoming.Cids(), incoming.Height(), known.Cids(), known.Height())
fork, err := syncer.syncFork(ctx, base, known)
if err != nil {
if xerrors.Is(err, ErrForkTooLong) {
// TODO: we're marking this block bad in the same way that we mark invalid blocks bad. Maybe distinguish?
log.Warn("adding forked chain to our bad tipset cache")
for _, b := range from.Blocks() {
syncer.bad.Add(b.Cid(), "fork past finality")
for _, b := range incoming.Blocks() {
syncer.bad.Add(b.Cid(), NewBadBlockReason(incoming.Cids(), "fork past finality"))
}
}
return nil, xerrors.Errorf("failed to sync fork: %w", err)
@@ -1128,13 +1256,19 @@ loop:
var ErrForkTooLong = fmt.Errorf("fork longer than threshold")
func (syncer *Syncer) syncFork(ctx context.Context, from *types.TipSet, to *types.TipSet) ([]*types.TipSet, error) {
tips, err := syncer.Bsync.GetBlocks(ctx, from.Parents(), int(build.ForkLengthThreshold))
// syncFork tries to obtain the chain fragment that links a fork into a common
// ancestor in our view of the chain.
//
// If the fork is too long (build.ForkLengthThreshold), we add the entire subchain to the
// denylist. Else, we find the common ancestor, and add the missing chain
// fragment until the fork point to the returned []TipSet.
func (syncer *Syncer) syncFork(ctx context.Context, incoming *types.TipSet, known *types.TipSet) ([]*types.TipSet, error) {
tips, err := syncer.Bsync.GetBlocks(ctx, incoming.Parents(), int(build.ForkLengthThreshold))
if err != nil {
return nil, err
}
nts, err := syncer.store.LoadTipSet(to.Parents())
nts, err := syncer.store.LoadTipSet(known.Parents())
if err != nil {
return nil, xerrors.Errorf("failed to load next local tipset: %w", err)
}
@@ -1144,7 +1278,7 @@ func (syncer *Syncer) syncFork(ctx context.Context, from *types.TipSet, to *type
if !syncer.Genesis.Equals(nts) {
return nil, xerrors.Errorf("somehow synced chain that linked back to a different genesis (bad genesis: %s)", nts.Key())
}
return nil, xerrors.Errorf("synced chain forked at genesis, refusing to sync")
return nil, xerrors.Errorf("synced chain forked at genesis, refusing to sync; incoming: %s")
}
if nts.Equals(tips[cur]) {
@@ -1279,6 +1413,25 @@ func persistMessages(bs bstore.Blockstore, bst *blocksync.BSTipSet) error {
return nil
}
// collectChain tries to advance our view of the chain to the purported head.
//
// It goes through various stages:
//
// 1. StageHeaders: we proceed in the sync process by requesting block headers
// from our peers, moving back from their heads, until we reach a tipset
// that we have in common (such a common tipset must exist, thought it may
// simply be the genesis block).
//
// If the common tipset is our head, we treat the sync as a "fast-forward",
// else we must drop part of our chain to connect to the peer's head
// (referred to as "forking").
//
// 2. StagePersistHeaders: now that we've collected the missing headers,
// augmented by those on the other side of a fork, we persist them to the
// BlockStore.
//
// 3. StageMessages: having acquired the headers and found a common tipset,
// we then move forward, requesting the full blocks, including the messages.
func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet) error {
ctx, span := trace.StartSpan(ctx, "collectChain")
defer span.End()
@@ -1325,12 +1478,11 @@ func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet) error
return nil
}
func VerifyElectionPoStVRF(ctx context.Context, evrf []byte, rand []byte, worker address.Address) error {
if err := gen.VerifyVRF(ctx, worker, rand, evrf); err != nil {
return xerrors.Errorf("failed to verify post_randomness vrf: %w", err)
func VerifyElectionPoStVRF(ctx context.Context, worker address.Address, rand []byte, evrf []byte) error {
if build.InsecurePoStValidation {
return nil
}
return nil
return gen.VerifyVRF(ctx, worker, rand, evrf)
}
func (syncer *Syncer) State() []SyncerState {
@@ -1341,14 +1493,17 @@ func (syncer *Syncer) State() []SyncerState {
return out
}
// MarkBad manually adds a block to the "bad blocks" cache.
func (syncer *Syncer) MarkBad(blk cid.Cid) {
syncer.bad.Add(blk, "manually marked bad")
syncer.bad.Add(blk, NewBadBlockReason([]cid.Cid{blk}, "manually marked bad"))
}
func (syncer *Syncer) CheckBadBlockCache(blk cid.Cid) (string, bool) {
return syncer.bad.Has(blk)
bbr, ok := syncer.bad.Has(blk)
return bbr.String(), ok
}
func (syncer *Syncer) getLatestBeaconEntry(ctx context.Context, ts *types.TipSet) (*types.BeaconEntry, error) {
func (syncer *Syncer) getLatestBeaconEntry(_ context.Context, ts *types.TipSet) (*types.BeaconEntry, error) {
cur := ts
for i := 0; i < 20; i++ {
cbe := cur.Blocks()[0].BeaconEntries
@@ -1369,3 +1524,13 @@ func (syncer *Syncer) getLatestBeaconEntry(ctx context.Context, ts *types.TipSet
return nil, xerrors.Errorf("found NO beacon entries in the 20 blocks prior to given tipset")
}
func (syncer *Syncer) IsEpochBeyondCurrMax(epoch abi.ChainEpoch) bool {
g, err := syncer.store.GetGenesis()
if err != nil {
return false
}
now := uint64(time.Now().Unix())
return epoch > (abi.ChainEpoch((now-g.Timestamp)/build.BlockDelaySecs) + MaxHeightDrift)
}
+2 -1
View File
@@ -35,6 +35,7 @@ type SyncManager struct {
syncStates []*SyncerState
// Normally this handler is set to `(*Syncer).Sync()`.
doSync func(context.Context, *types.TipSet) error
stop chan struct{}
@@ -280,7 +281,7 @@ func (sm *SyncManager) syncScheduler() {
}
func (sm *SyncManager) scheduleIncoming(ts *types.TipSet) {
log.Info("scheduling incoming tipset sync: ", ts.Cids())
log.Debug("scheduling incoming tipset sync: ", ts.Cids())
if sm.getBootstrapState() == BSStateSelected {
sm.setBootstrapState(BSStateScheduled)
sm.syncTargets <- ts
+5 -5
View File
@@ -34,8 +34,8 @@ import (
func init() {
build.InsecurePoStValidation = true
os.Setenv("TRUST_PARAMS", "1")
miner.SupportedProofTypes = map[abi.RegisteredProof]struct{}{
abi.RegisteredProof_StackedDRG2KiBSeal: {},
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
}
power.ConsensusMinerMinPower = big.NewInt(2048)
verifreg.MinVerifiedDealSize = big.NewInt(256)
@@ -408,7 +408,7 @@ func TestSyncBadTimestamp(t *testing.T) {
base := tu.g.CurTipset
tu.g.Timestamper = func(pts *types.TipSet, tl abi.ChainEpoch) uint64 {
return pts.MinTimestamp() + (build.BlockDelay / 2)
return pts.MinTimestamp() + (build.BlockDelaySecs / 2)
}
fmt.Println("BASE: ", base.Cids())
@@ -417,7 +417,7 @@ func TestSyncBadTimestamp(t *testing.T) {
a1 := tu.mineOnBlock(base, 0, nil, false, true)
tu.g.Timestamper = nil
tu.g.ResyncBankerNonce(a1.TipSet())
require.NoError(t, tu.g.ResyncBankerNonce(a1.TipSet()))
fmt.Println("After mine bad block!")
tu.printHeads()
@@ -479,7 +479,7 @@ func TestSyncFork(t *testing.T) {
a := tu.mineOnBlock(a1, p1, []int{0}, true, false)
a = tu.mineOnBlock(a, p1, []int{0}, true, false)
tu.g.ResyncBankerNonce(a1.TipSet())
require.NoError(t, tu.g.ResyncBankerNonce(a1.TipSet()))
// chain B will now be heaviest
b := tu.mineOnBlock(base, p2, []int{1}, true, false)
b = tu.mineOnBlock(b, p2, []int{1}, true, false)
+1 -1
View File
@@ -76,7 +76,7 @@ func SizeStr(bi BigInt) string {
}
f, _ := r.Float64()
return fmt.Sprintf("%.3g %s", f, byteSizeUnits[i])
return fmt.Sprintf("%.4g %s", f, byteSizeUnits[i])
}
var deciUnits = []string{"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"}
+25 -2
View File
@@ -3,7 +3,12 @@ package types
import (
"bytes"
"math/big"
"math/rand"
"strings"
"testing"
"time"
"github.com/docker/go-units"
"github.com/stretchr/testify/assert"
)
@@ -38,7 +43,7 @@ func TestBigIntSerializationRoundTrip(t *testing.T) {
func TestFilRoundTrip(t *testing.T) {
testValues := []string{
"0", "1", "1.001", "100.10001", "101100", "5000.01", "5000",
"0 FIL", "1 FIL", "1.001 FIL", "100.10001 FIL", "101100 FIL", "5000.01 FIL", "5000 FIL",
}
for _, v := range testValues {
@@ -60,8 +65,10 @@ func TestSizeStr(t *testing.T) {
}{
{0, "0 B"},
{1, "1 B"},
{1016, "1016 B"},
{1024, "1 KiB"},
{2000, "1.95 KiB"},
{1000 * 1024, "1000 KiB"},
{2000, "1.953 KiB"},
{5 << 20, "5 MiB"},
{11 << 60, "11 EiB"},
}
@@ -71,6 +78,22 @@ func TestSizeStr(t *testing.T) {
}
}
func TestSizeStrUnitsSymmetry(t *testing.T) {
s := rand.NewSource(time.Now().UnixNano())
r := rand.New(s)
for i := 0; i < 1000000; i++ {
n := r.Uint64()
l := strings.ReplaceAll(units.BytesSize(float64(n)), " ", "")
r := strings.ReplaceAll(SizeStr(NewInt(n)), " ", "")
assert.NotContains(t, l, "e+")
assert.NotContains(t, r, "e+")
assert.Equal(t, l, r, "wrong formatting for %d", n)
}
}
func TestSizeStrBig(t *testing.T) {
ZiB := big.NewInt(50000)
ZiB = ZiB.Lsh(ZiB, 70)
+15 -4
View File
@@ -69,10 +69,13 @@ type BlockHeader struct {
BlockSig *crypto.Signature // 13
ForkSignaling uint64 // 14
// internal
validated bool // true if the signature has been validated
}
func (b *BlockHeader) ToStorageBlock() (block.Block, error) {
data, err := b.Serialize()
func (blk *BlockHeader) ToStorageBlock() (block.Block, error) {
data, err := blk.Serialize()
if err != nil {
return nil, err
}
@@ -86,8 +89,8 @@ func (b *BlockHeader) ToStorageBlock() (block.Block, error) {
return block.NewBlockWithCid(data, c)
}
func (b *BlockHeader) Cid() cid.Cid {
sb, err := b.ToStorageBlock()
func (blk *BlockHeader) Cid() cid.Cid {
sb, err := blk.ToStorageBlock()
if err != nil {
panic(err) // Not sure i'm entirely comfortable with this one, needs to be checked
}
@@ -124,6 +127,14 @@ func (blk *BlockHeader) SigningBytes() ([]byte, error) {
return blkcopy.Serialize()
}
func (blk *BlockHeader) SetValidated() {
blk.validated = true
}
func (blk *BlockHeader) IsValidated() bool {
return blk.validated
}
type MsgMeta struct {
BlsMessages cid.Cid
SecpkMessages cid.Cid
+60 -2
View File
@@ -2,13 +2,17 @@ package types
import (
"bytes"
"encoding/hex"
"fmt"
"github.com/stretchr/testify/require"
"reflect"
"testing"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/crypto"
cid "github.com/ipfs/go-cid"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
)
func testBlockHeader(t testing.TB) *BlockHeader {
@@ -63,6 +67,60 @@ func TestBlockHeaderSerialization(t *testing.T) {
}
}
func TestInteropBH(t *testing.T) {
newAddr, err := address.NewSecp256k1Address([]byte("address0"))
if err != nil {
t.Fatal(err)
}
mcid, err := cid.Parse("bafy2bzaceaxyj7xq27gc2747adjcirpxx52tt7owqx6z6kckun7tqivvoym4y")
if err != nil {
t.Fatal(err)
}
posts := []abi.PoStProof{
{abi.RegisteredPoStProof_StackedDrgWinning2KiBV1, []byte{0x07}},
}
bh := &BlockHeader{
Miner: newAddr,
Ticket: &Ticket{[]byte{0x01, 0x02, 0x03}},
ElectionProof: &ElectionProof{[]byte{0x0a, 0x0b}},
BeaconEntries: []BeaconEntry{
{
Round: 5,
Data: []byte{0x0c},
//prevRound: 0,
},
},
Height: 2,
Messages: mcid,
ParentMessageReceipts: mcid,
Parents: []cid.Cid{mcid},
ParentWeight: NewInt(1000),
ForkSignaling: 3,
ParentStateRoot: mcid,
Timestamp: 1,
WinPoStProof: posts,
BlockSig: &crypto.Signature{
Type: crypto.SigTypeBLS,
Data: []byte{0x3},
},
BLSAggregate: &crypto.Signature{},
}
bhsb, err := bh.SigningBytes()
if err != nil {
t.Fatal(err)
}
// acquired from go-filecoin
gfc := "8f5501d04cb15021bf6bd003073d79e2238d4e61f1ad22814301020381420a0b818205410c818200410781d82a5827000171a0e402202f84fef0d7cc2d7f9f00d22445f7bf7539fdd685fd9f284aa37f3822b57619cc430003e802d82a5827000171a0e402202f84fef0d7cc2d7f9f00d22445f7bf7539fdd685fd9f284aa37f3822b57619ccd82a5827000171a0e402202f84fef0d7cc2d7f9f00d22445f7bf7539fdd685fd9f284aa37f3822b57619ccd82a5827000171a0e402202f84fef0d7cc2d7f9f00d22445f7bf7539fdd685fd9f284aa37f3822b57619cc410001f603"
require.Equal(t, gfc, hex.EncodeToString(bhsb))
}
func BenchmarkBlockHeaderMarshal(b *testing.B) {
bh := testBlockHeader(b)
+99 -5
View File
@@ -1,9 +1,103 @@
package types
type ExecutionResult struct {
Msg *Message
MsgRct *MessageReceipt
Error string
import (
"encoding/json"
"fmt"
"runtime"
"strings"
"time"
)
Subcalls []*ExecutionResult
type ExecutionTrace struct {
Msg *Message
MsgRct *MessageReceipt
Error string
Duration time.Duration
GasCharges []*GasTrace
Subcalls []ExecutionTrace
}
type GasTrace struct {
Name string
Location []Loc `json:"loc"`
TotalGas int64 `json:"tg"`
ComputeGas int64 `json:"cg"`
StorageGas int64 `json:"sg"`
TotalVirtualGas int64 `json:"vtg"`
VirtualComputeGas int64 `json:"vcg"`
VirtualStorageGas int64 `json:"vsg"`
TimeTaken time.Duration `json:"tt"`
Extra interface{} `json:"ex,omitempty"`
Callers []uintptr `json:"-"`
}
type Loc struct {
File string
Line int
Function string
}
func (l Loc) Show() bool {
ignorePrefix := []string{
"reflect.",
"github.com/filecoin-project/lotus/chain/vm.(*Invoker).transform",
"github.com/filecoin-project/go-amt-ipld/",
}
for _, pre := range ignorePrefix {
if strings.HasPrefix(l.Function, pre) {
return false
}
}
return true
}
func (l Loc) String() string {
file := strings.Split(l.File, "/")
fn := strings.Split(l.Function, "/")
var fnpkg string
if len(fn) > 2 {
fnpkg = strings.Join(fn[len(fn)-2:], "/")
} else {
fnpkg = l.Function
}
return fmt.Sprintf("%s@%s:%d", fnpkg, file[len(file)-1], l.Line)
}
func (l Loc) Important() bool {
if strings.HasPrefix(l.Function, "github.com/filecoin-project/specs-actors/actors/builtin") {
return true
}
return false
}
func (gt *GasTrace) MarshalJSON() ([]byte, error) {
type GasTraceCopy GasTrace
if len(gt.Location) == 0 {
if len(gt.Callers) != 0 {
frames := runtime.CallersFrames(gt.Callers)
for {
frame, more := frames.Next()
if frame.Function == "github.com/filecoin-project/lotus/chain/vm.(*VM).ApplyMessage" {
break
}
l := Loc{
File: frame.File,
Line: frame.Line,
Function: frame.Function,
}
gt.Location = append(gt.Location, l)
if !more {
break
}
}
}
}
cpy := (*GasTraceCopy)(gt)
return json.Marshal(cpy)
}
+26 -5
View File
@@ -11,11 +11,11 @@ import (
type FIL BigInt
func (f FIL) String() string {
r := new(big.Rat).SetFrac(f.Int, big.NewInt(build.FilecoinPrecision))
r := new(big.Rat).SetFrac(f.Int, big.NewInt(int64(build.FilecoinPrecision)))
if r.Sign() == 0 {
return "0"
return "0 FIL"
}
return strings.TrimRight(strings.TrimRight(r.FloatString(18), "0"), ".")
return strings.TrimRight(strings.TrimRight(r.FloatString(18), "0"), ".") + " FIL"
}
func (f FIL) Format(s fmt.State, ch rune) {
@@ -28,14 +28,35 @@ func (f FIL) Format(s fmt.State, ch rune) {
}
func ParseFIL(s string) (FIL, error) {
suffix := strings.TrimLeft(s, ".1234567890")
s = s[:len(s)-len(suffix)]
var attofil bool
if suffix != "" {
norm := strings.ToLower(strings.TrimSpace(suffix))
switch norm {
case "", "fil":
case "attofil", "afil":
attofil = true
default:
return FIL{}, fmt.Errorf("unrecognized suffix: %q", suffix)
}
}
r, ok := new(big.Rat).SetString(s)
if !ok {
return FIL{}, fmt.Errorf("failed to parse %q as a decimal number", s)
}
r = r.Mul(r, big.NewRat(build.FilecoinPrecision, 1))
if !attofil {
r = r.Mul(r, big.NewRat(int64(build.FilecoinPrecision), 1))
}
if !r.IsInt() {
return FIL{}, fmt.Errorf("invalid FIL value: %q", s)
var pref string
if attofil {
pref = "atto"
}
return FIL{}, fmt.Errorf("invalid %sFIL value: %q", pref, s)
}
return FIL{r.Num()}, nil
+7 -10
View File
@@ -21,6 +21,7 @@ type ChainMsg interface {
Cid() cid.Cid
VMMessage() *Message
ToStorageBlock() (block.Block, error)
// FIXME: This is the *message* length, this name is misleading.
ChainLength() int
}
@@ -41,20 +42,16 @@ type Message struct {
Params []byte
}
func (t *Message) BlockMiner() address.Address {
panic("implement me")
func (m *Message) Caller() address.Address {
return m.From
}
func (t *Message) Caller() address.Address {
return t.From
func (m *Message) Receiver() address.Address {
return m.To
}
func (t *Message) Receiver() address.Address {
return t.To
}
func (t *Message) ValueReceived() abi.TokenAmount {
return t.Value
func (m *Message) ValueReceived() abi.TokenAmount {
return m.Value
}
func DecodeMessage(b []byte) (*Message, error) {
+6 -1
View File
@@ -49,6 +49,11 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
panic(err)
}
pstateRoot := c
if parents != nil {
pstateRoot = parents.Blocks()[0].ParentStateRoot
}
var pcids []cid.Cid
var height abi.ChainEpoch
weight := types.NewInt(weightInc)
@@ -72,7 +77,7 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
ParentWeight: weight,
Messages: c,
Height: height,
ParentStateRoot: c,
ParentStateRoot: pstateRoot,
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")},
}
}
+8 -8
View File
@@ -9,12 +9,12 @@ import (
"github.com/multiformats/go-multihash"
)
func (m *SignedMessage) ToStorageBlock() (block.Block, error) {
if m.Signature.Type == crypto.SigTypeBLS {
return m.Message.ToStorageBlock()
func (sm *SignedMessage) ToStorageBlock() (block.Block, error) {
if sm.Signature.Type == crypto.SigTypeBLS {
return sm.Message.ToStorageBlock()
}
data, err := m.Serialize()
data, err := sm.Serialize()
if err != nil {
return nil, err
}
@@ -28,12 +28,12 @@ func (m *SignedMessage) ToStorageBlock() (block.Block, error) {
return block.NewBlockWithCid(data, c)
}
func (m *SignedMessage) Cid() cid.Cid {
if m.Signature.Type == crypto.SigTypeBLS {
return m.Message.Cid()
func (sm *SignedMessage) Cid() cid.Cid {
if sm.Signature.Type == crypto.SigTypeBLS {
return sm.Message.Cid()
}
sb, err := m.ToStorageBlock()
sb, err := sm.ToStorageBlock()
if err != nil {
panic(err)
}
+6 -2
View File
@@ -23,8 +23,6 @@ type TipSet struct {
height abi.ChainEpoch
}
// why didnt i just export the fields? Because the struct has methods with the
// same names already
type ExpTipSet struct {
Cids []cid.Cid
Blocks []*BlockHeader
@@ -32,6 +30,8 @@ type ExpTipSet struct {
}
func (ts *TipSet) MarshalJSON() ([]byte, error) {
// why didnt i just export the fields? Because the struct has methods with the
// same names already
return json.Marshal(ExpTipSet{
Cids: ts.cids,
Blocks: ts.blks,
@@ -112,6 +112,10 @@ func NewTipSet(blks []*BlockHeader) (*TipSet, error) {
return nil, fmt.Errorf("cannot create tipset with mismatching heights")
}
if len(blks[0].Parents) != len(b.Parents) {
return nil, fmt.Errorf("cannot create tipset with mismatching number of parents")
}
for i, cid := range b.Parents {
if cid != blks[0].Parents[i] {
return nil, fmt.Errorf("cannot create tipset with mismatching parents")
+3 -3
View File
@@ -61,9 +61,9 @@ func TestTipSetKey(t *testing.T) {
t.Run("JSON", func(t *testing.T) {
k0 := NewTipSetKey()
verifyJson(t, "[]", k0)
verifyJSON(t, "[]", k0)
k3 := NewTipSetKey(c1, c2, c3)
verifyJson(t, `[`+
verifyJSON(t, `[`+
`{"/":"bafy2bzacecesrkxghscnq7vatble2hqdvwat6ed23vdu4vvo3uuggsoaya7ki"},`+
`{"/":"bafy2bzacebxfyh2fzoxrt6kcgc5dkaodpcstgwxxdizrww225vrhsizsfcg4g"},`+
`{"/":"bafy2bzacedwviarjtjraqakob5pslltmuo5n3xev3nt5zylezofkbbv5jclyu"}`+
@@ -71,7 +71,7 @@ func TestTipSetKey(t *testing.T) {
})
}
func verifyJson(t *testing.T, expected string, k TipSetKey) {
func verifyJSON(t *testing.T, expected string, k TipSetKey) {
bytes, err := json.Marshal(k)
require.NoError(t, err)
assert.Equal(t, expected, string(bytes))
+6 -5
View File
@@ -9,10 +9,10 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/puppet"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/ipfs/go-cid"
vtypes "github.com/filecoin-project/chain-validation/chain/types"
vdrivers "github.com/filecoin-project/chain-validation/drivers"
vstate "github.com/filecoin-project/chain-validation/state"
"github.com/filecoin-project/lotus/chain/stmgr"
@@ -24,12 +24,13 @@ import (
// Applier applies messages to state trees and storage.
type Applier struct {
stateWrapper *StateWrapper
syscalls runtime.Syscalls
}
var _ vstate.Applier = &Applier{}
func NewApplier(sw *StateWrapper) *Applier {
return &Applier{sw}
func NewApplier(sw *StateWrapper, syscalls runtime.Syscalls) *Applier {
return &Applier{sw, syscalls}
}
func (a *Applier) ApplyMessage(epoch abi.ChainEpoch, message *vtypes.Message) (vtypes.ApplyMessageResult, error) {
@@ -65,7 +66,7 @@ func (a *Applier) ApplySignedMessage(epoch abi.ChainEpoch, msg *vtypes.SignedMes
}
func (a *Applier) ApplyTipSetMessages(epoch abi.ChainEpoch, blocks []vtypes.BlockMessagesInfo, rnd vstate.RandomnessSource) (vtypes.ApplyTipSetResult, error) {
cs := store.NewChainStore(a.stateWrapper.bs, a.stateWrapper.ds, vdrivers.NewChainValidationSyscalls())
cs := store.NewChainStore(a.stateWrapper.bs, a.stateWrapper.ds, a.syscalls)
sm := stmgr.NewStateManager(cs)
var bms []stmgr.BlockMessages
@@ -134,7 +135,7 @@ func (a *Applier) applyMessage(epoch abi.ChainEpoch, lm types.ChainMsg) (vtypes.
ctx := context.TODO()
base := a.stateWrapper.Root()
lotusVM, err := vm.NewVM(base, epoch, &vmRand{}, a.stateWrapper.bs, vdrivers.NewChainValidationSyscalls())
lotusVM, err := vm.NewVM(base, epoch, &vmRand{}, a.stateWrapper.bs, a.syscalls)
// need to modify the VM invoker to add the puppet actor
chainValInvoker := vm.NewInvoker()
chainValInvoker.Register(puppet.PuppetActorCodeID, puppet.Actor{}, puppet.State{})
+3 -16
View File
@@ -1,11 +1,9 @@
package validation
import (
"context"
"github.com/filecoin-project/specs-actors/actors/runtime"
vstate "github.com/filecoin-project/chain-validation/state"
"github.com/filecoin-project/specs-actors/actors/abi"
acrypto "github.com/filecoin-project/specs-actors/actors/crypto"
)
type Factories struct {
@@ -18,26 +16,15 @@ func NewFactories() *Factories {
return &Factories{}
}
func (f *Factories) NewStateAndApplier() (vstate.VMWrapper, vstate.Applier) {
func (f *Factories) NewStateAndApplier(syscalls runtime.Syscalls) (vstate.VMWrapper, vstate.Applier) {
st := NewState()
return st, NewApplier(st)
return st, NewApplier(st, syscalls)
}
func (f *Factories) NewKeyManager() vstate.KeyManager {
return newKeyManager()
}
type fakeRandSrc struct {
}
func (r fakeRandSrc) Randomness(_ context.Context, _ acrypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) (abi.Randomness, error) {
return abi.Randomness("sausages"), nil
}
func (f *Factories) NewRandomnessSource() vstate.RandomnessSource {
return &fakeRandSrc{}
}
func (f *Factories) NewValidationConfig() vstate.ValidationConfig {
trackGas := true
checkExit := true
+7 -2
View File
@@ -7,6 +7,7 @@ import (
"os"
"github.com/filecoin-project/go-address"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/types"
@@ -173,14 +174,18 @@ func WriteJsonToFile(fname string, obj interface{}) error {
if err != nil {
return err
}
defer fi.Close()
defer fi.Close() //nolint:errcheck
out, err := json.MarshalIndent(obj, "", " ")
if err != nil {
return err
}
fi.Write(out)
_, err = fi.Write(out)
if err != nil {
return xerrors.Errorf("writing json: %w", err)
}
return nil
}
+40 -1
View File
@@ -1,11 +1,15 @@
package vectors
import (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"path/filepath"
"testing"
"github.com/filecoin-project/lotus/chain/types"
)
func LoadVector(t *testing.T, f string, out interface{}) {
@@ -42,5 +46,40 @@ func TestBlockHeaderVectors(t *testing.T) {
}
func TestMessageSigningVectors(t *testing.T) {
// TODO:
var msvs []MessageSigningVector
LoadVector(t, "message_signing.json", &msvs)
for i, msv := range msvs {
smsg := &types.SignedMessage{
Message: *msv.Unsigned,
Signature: *msv.Signature,
}
if smsg.Cid().String() != msv.Cid {
t.Fatalf("cid of message in vector %d mismatches", i)
}
// TODO: check signature
}
}
func TestUnsignedMessageVectors(t *testing.T) {
var msvs []UnsignedMessageVector
LoadVector(t, "unsigned_messages.json", &msvs)
for i, msv := range msvs {
b, err := msv.Message.Serialize()
if err != nil {
t.Fatal(err)
}
dec, err := hex.DecodeString(msv.HexCbor)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(b, dec) {
t.Fatalf("serialization vector %d mismatches bytes", i)
}
}
}
+82 -15
View File
@@ -3,6 +3,7 @@ package vm
import (
"fmt"
"github.com/filecoin-project/go-address"
addr "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
@@ -11,34 +12,74 @@ import (
"github.com/ipfs/go-cid"
)
const (
GasStorageMulti = 1
GasComputeMulti = 1
)
type GasCharge struct {
Name string
Extra interface{}
ComputeGas int64
StorageGas int64
VirtualCompute int64
VirtualStorage int64
}
func (g GasCharge) Total() int64 {
return g.ComputeGas*GasComputeMulti + g.StorageGas*GasStorageMulti
}
func (g GasCharge) WithVirtual(compute, storage int64) GasCharge {
out := g
out.VirtualCompute = compute
out.VirtualStorage = storage
return out
}
func (g GasCharge) WithExtra(extra interface{}) GasCharge {
out := g
out.Extra = extra
return out
}
func newGasCharge(name string, computeGas int64, storageGas int64) GasCharge {
return GasCharge{
Name: name,
ComputeGas: computeGas,
StorageGas: storageGas,
}
}
// Pricelist provides prices for operations in the VM.
//
// Note: this interface should be APPEND ONLY since last chain checkpoint
type Pricelist interface {
// OnChainMessage returns the gas used for storing a message of a given size in the chain.
OnChainMessage(msgSize int) int64
OnChainMessage(msgSize int) GasCharge
// OnChainReturnValue returns the gas used for storing the response of a message in the chain.
OnChainReturnValue(dataSize int) int64
OnChainReturnValue(dataSize int) GasCharge
// OnMethodInvocation returns the gas used when invoking a method.
OnMethodInvocation(value abi.TokenAmount, methodNum abi.MethodNum) int64
OnMethodInvocation(value abi.TokenAmount, methodNum abi.MethodNum) GasCharge
// OnIpldGet returns the gas used for storing an object
OnIpldGet(dataSize int) int64
OnIpldGet(dataSize int) GasCharge
// OnIpldPut returns the gas used for storing an object
OnIpldPut(dataSize int) int64
OnIpldPut(dataSize int) GasCharge
// OnCreateActor returns the gas used for creating an actor
OnCreateActor() int64
OnCreateActor() GasCharge
// OnDeleteActor returns the gas used for deleting an actor
OnDeleteActor() int64
OnDeleteActor() GasCharge
OnVerifySignature(sigType crypto.SigType, planTextSize int) (int64, error)
OnHashing(dataSize int) int64
OnComputeUnsealedSectorCid(proofType abi.RegisteredProof, pieces []abi.PieceInfo) int64
OnVerifySeal(info abi.SealVerifyInfo) int64
OnVerifyPost(info abi.WindowPoStVerifyInfo) int64
OnVerifyConsensusFault() int64
OnVerifySignature(sigType crypto.SigType, planTextSize int) (GasCharge, error)
OnHashing(dataSize int) GasCharge
OnComputeUnsealedSectorCid(proofType abi.RegisteredSealProof, pieces []abi.PieceInfo) GasCharge
OnVerifySeal(info abi.SealVerifyInfo) GasCharge
OnVerifyPost(info abi.WindowPoStVerifyInfo) GasCharge
OnVerifyConsensusFault() GasCharge
}
var prices = map[abi.ChainEpoch]Pricelist{
@@ -92,7 +133,7 @@ func PricelistByEpoch(epoch abi.ChainEpoch) Pricelist {
type pricedSyscalls struct {
under vmr.Syscalls
pl Pricelist
chargeGas func(int64)
chargeGas func(GasCharge)
}
// Verifies that a signature is valid for an address and plaintext.
@@ -102,30 +143,40 @@ func (ps pricedSyscalls) VerifySignature(signature crypto.Signature, signer addr
return err
}
ps.chargeGas(c)
defer ps.chargeGas(gasOnActorExec)
return ps.under.VerifySignature(signature, signer, plaintext)
}
// Hashes input data using blake2b with 256 bit output.
func (ps pricedSyscalls) HashBlake2b(data []byte) [32]byte {
ps.chargeGas(ps.pl.OnHashing(len(data)))
defer ps.chargeGas(gasOnActorExec)
return ps.under.HashBlake2b(data)
}
// Computes an unsealed sector CID (CommD) from its constituent piece CIDs (CommPs) and sizes.
func (ps pricedSyscalls) ComputeUnsealedSectorCID(reg abi.RegisteredProof, pieces []abi.PieceInfo) (cid.Cid, error) {
func (ps pricedSyscalls) ComputeUnsealedSectorCID(reg abi.RegisteredSealProof, pieces []abi.PieceInfo) (cid.Cid, error) {
ps.chargeGas(ps.pl.OnComputeUnsealedSectorCid(reg, pieces))
defer ps.chargeGas(gasOnActorExec)
return ps.under.ComputeUnsealedSectorCID(reg, pieces)
}
// Verifies a sector seal proof.
func (ps pricedSyscalls) VerifySeal(vi abi.SealVerifyInfo) error {
ps.chargeGas(ps.pl.OnVerifySeal(vi))
defer ps.chargeGas(gasOnActorExec)
return ps.under.VerifySeal(vi)
}
// Verifies a proof of spacetime.
func (ps pricedSyscalls) VerifyPoSt(vi abi.WindowPoStVerifyInfo) error {
ps.chargeGas(ps.pl.OnVerifyPost(vi))
defer ps.chargeGas(gasOnActorExec)
return ps.under.VerifyPoSt(vi)
}
@@ -141,5 +192,21 @@ func (ps pricedSyscalls) VerifyPoSt(vi abi.WindowPoStVerifyInfo) error {
// 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) {
ps.chargeGas(ps.pl.OnVerifyConsensusFault())
defer ps.chargeGas(gasOnActorExec)
return ps.under.VerifyConsensusFault(h1, h2, extra)
}
func (ps pricedSyscalls) BatchVerifySeals(inp map[address.Address][]abi.SealVerifyInfo) (map[address.Address][]bool, error) {
var gasChargeSum GasCharge
gasChargeSum.Name = "BatchVerifySeals"
count := int64(0)
for _, svis := range inp {
count += int64(len(svis))
}
gasChargeSum = gasChargeSum.WithExtra(count).WithVirtual(129778623*count+716683250, 0)
ps.chargeGas(gasChargeSum) // TODO: this is only called by the cron actor. Should we even charge gas?
defer ps.chargeGas(gasOnActorExec)
return ps.under.BatchVerifySeals(inp)
}
+61 -27
View File
@@ -2,7 +2,9 @@ package vm
import (
"fmt"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/crypto"
)
@@ -84,80 +86,112 @@ type pricelistV0 struct {
var _ Pricelist = (*pricelistV0)(nil)
// OnChainMessage returns the gas used for storing a message of a given size in the chain.
func (pl *pricelistV0) OnChainMessage(msgSize int) int64 {
return pl.onChainMessageBase + pl.onChainMessagePerByte*int64(msgSize)
func (pl *pricelistV0) OnChainMessage(msgSize int) GasCharge {
return newGasCharge("OnChainMessage", 0, pl.onChainMessageBase+pl.onChainMessagePerByte*int64(msgSize)).WithVirtual(77302, 0)
}
// OnChainReturnValue returns the gas used for storing the response of a message in the chain.
func (pl *pricelistV0) OnChainReturnValue(dataSize int) int64 {
return int64(dataSize) * pl.onChainReturnValuePerByte
func (pl *pricelistV0) OnChainReturnValue(dataSize int) GasCharge {
return newGasCharge("OnChainReturnValue", 0, int64(dataSize)*pl.onChainReturnValuePerByte).WithVirtual(107294, 0)
}
// OnMethodInvocation returns the gas used when invoking a method.
func (pl *pricelistV0) OnMethodInvocation(value abi.TokenAmount, methodNum abi.MethodNum) int64 {
func (pl *pricelistV0) OnMethodInvocation(value abi.TokenAmount, methodNum abi.MethodNum) GasCharge {
ret := pl.sendBase
extra := ""
virtGas := int64(1072944)
if value != abi.NewTokenAmount(0) {
// TODO: fix this, it is comparing pointers instead of values
// see vv
ret += pl.sendTransferFunds
}
if big.Cmp(value, abi.NewTokenAmount(0)) != 0 {
virtGas += 497495
if methodNum == builtin.MethodSend {
// transfer only
virtGas += 973940
}
extra += "t"
}
if methodNum != builtin.MethodSend {
ret += pl.sendInvokeMethod
extra += "i"
// running actors is cheaper becase we hand over to actors
virtGas += -295779
}
return ret
return newGasCharge("OnMethodInvocation", ret, 0).WithVirtual(virtGas, 0).WithExtra(extra)
}
// OnIpldGet returns the gas used for storing an object
func (pl *pricelistV0) OnIpldGet(dataSize int) int64 {
return pl.ipldGetBase + int64(dataSize)*pl.ipldGetPerByte
func (pl *pricelistV0) OnIpldGet(dataSize int) GasCharge {
return newGasCharge("OnIpldGet", pl.ipldGetBase+int64(dataSize)*pl.ipldGetPerByte, 0).
WithExtra(dataSize).WithVirtual(433685, 0)
}
// OnIpldPut returns the gas used for storing an object
func (pl *pricelistV0) OnIpldPut(dataSize int) int64 {
return pl.ipldPutBase + int64(dataSize)*pl.ipldPutPerByte
func (pl *pricelistV0) OnIpldPut(dataSize int) GasCharge {
return newGasCharge("OnIpldPut", pl.ipldPutBase, int64(dataSize)*pl.ipldPutPerByte).
WithExtra(dataSize).WithVirtual(88970, 0)
}
// OnCreateActor returns the gas used for creating an actor
func (pl *pricelistV0) OnCreateActor() int64 {
return pl.createActorBase + pl.createActorExtra
func (pl *pricelistV0) OnCreateActor() GasCharge {
return newGasCharge("OnCreateActor", pl.createActorBase, pl.createActorExtra).WithVirtual(65636, 0)
}
// OnDeleteActor returns the gas used for deleting an actor
func (pl *pricelistV0) OnDeleteActor() int64 {
return pl.deleteActor
func (pl *pricelistV0) OnDeleteActor() GasCharge {
return newGasCharge("OnDeleteActor", 0, pl.deleteActor)
}
// OnVerifySignature
func (pl *pricelistV0) OnVerifySignature(sigType crypto.SigType, planTextSize int) (int64, error) {
func (pl *pricelistV0) OnVerifySignature(sigType crypto.SigType, planTextSize int) (GasCharge, error) {
costFn, ok := pl.verifySignature[sigType]
if !ok {
return 0, fmt.Errorf("cost function for signature type %d not supported", sigType)
return GasCharge{}, fmt.Errorf("cost function for signature type %d not supported", sigType)
}
return costFn(int64(planTextSize)), nil
sigName, _ := sigType.Name()
virtGas := int64(0)
switch sigType {
case crypto.SigTypeBLS:
virtGas = 220138570
case crypto.SigTypeSecp256k1:
virtGas = 7053730
}
return newGasCharge("OnVerifySignature", costFn(int64(planTextSize)), 0).
WithExtra(map[string]interface{}{
"type": sigName,
"size": planTextSize,
}).WithVirtual(virtGas, 0), nil
}
// OnHashing
func (pl *pricelistV0) OnHashing(dataSize int) int64 {
return pl.hashingBase + int64(dataSize)*pl.hashingPerByte
func (pl *pricelistV0) OnHashing(dataSize int) GasCharge {
return newGasCharge("OnHashing", pl.hashingBase+int64(dataSize)*pl.hashingPerByte, 0).WithExtra(dataSize).WithVirtual(77300, 0)
}
// OnComputeUnsealedSectorCid
func (pl *pricelistV0) OnComputeUnsealedSectorCid(proofType abi.RegisteredProof, pieces []abi.PieceInfo) int64 {
func (pl *pricelistV0) OnComputeUnsealedSectorCid(proofType abi.RegisteredSealProof, pieces []abi.PieceInfo) GasCharge {
// TODO: this needs more cost tunning, check with @lotus
return pl.computeUnsealedSectorCidBase
return newGasCharge("OnComputeUnsealedSectorCid", pl.computeUnsealedSectorCidBase, 0).WithVirtual(382370, 0)
}
// OnVerifySeal
func (pl *pricelistV0) OnVerifySeal(info abi.SealVerifyInfo) int64 {
func (pl *pricelistV0) OnVerifySeal(info abi.SealVerifyInfo) GasCharge {
// TODO: this needs more cost tunning, check with @lotus
return pl.verifySealBase
return newGasCharge("OnVerifySeal", pl.verifySealBase, 0).WithVirtual(199954003, 0)
}
// OnVerifyPost
func (pl *pricelistV0) OnVerifyPost(info abi.WindowPoStVerifyInfo) int64 {
func (pl *pricelistV0) OnVerifyPost(info abi.WindowPoStVerifyInfo) GasCharge {
// TODO: this needs more cost tunning, check with @lotus
return pl.verifyPostBase
return newGasCharge("OnVerifyPost", pl.verifyPostBase, 0).WithVirtual(2629471704, 0).WithExtra(len(info.ChallengedSectors))
}
// OnVerifyConsensusFault
func (pl *pricelistV0) OnVerifyConsensusFault() int64 {
return pl.verifyConsensusFault
func (pl *pricelistV0) OnVerifyConsensusFault() GasCharge {
return newGasCharge("OnVerifyConsensusFault", pl.verifyConsensusFault, 0).WithVirtual(551935, 0)
}
+6 -8
View File
@@ -32,7 +32,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors/aerrors"
)
type invoker struct {
type Invoker struct {
builtInCode map[cid.Cid]nativeCode
builtInState map[cid.Cid]reflect.Type
}
@@ -40,8 +40,8 @@ type invoker struct {
type invokeFunc func(rt runtime.Runtime, params []byte) ([]byte, aerrors.ActorError)
type nativeCode []invokeFunc
func NewInvoker() *invoker {
inv := &invoker{
func NewInvoker() *Invoker {
inv := &Invoker{
builtInCode: make(map[cid.Cid]nativeCode),
builtInState: make(map[cid.Cid]reflect.Type),
}
@@ -62,7 +62,7 @@ func NewInvoker() *invoker {
return inv
}
func (inv *invoker) Invoke(codeCid cid.Cid, rt runtime.Runtime, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) {
func (inv *Invoker) Invoke(codeCid cid.Cid, rt runtime.Runtime, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) {
code, ok := inv.builtInCode[codeCid]
if !ok {
@@ -76,7 +76,7 @@ func (inv *invoker) Invoke(codeCid cid.Cid, rt runtime.Runtime, method abi.Metho
}
func (inv *invoker) Register(c cid.Cid, instance Invokee, state interface{}) {
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))
@@ -89,9 +89,7 @@ type Invokee interface {
Exports() []interface{}
}
var tAError = reflect.TypeOf((*aerrors.ActorError)(nil)).Elem()
func (*invoker) transform(instance Invokee) (nativeCode, error) {
func (*Invoker) transform(instance Invokee) (nativeCode, error) {
itype := reflect.TypeOf(instance)
exports := instance.Exports()
for i, m := range exports {
+1 -1
View File
@@ -76,7 +76,7 @@ func (basicContract) InvokeSomething10(rt runtime.Runtime, params *basicParams)
}
func TestInvokerBasic(t *testing.T) {
inv := invoker{}
inv := Invoker{}
code, err := inv.transform(basicContract{})
assert.NoError(t, err)
+2 -1
View File
@@ -2,6 +2,7 @@ package vm
import (
"context"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin"
@@ -27,7 +28,7 @@ func init() {
var EmptyObjectCid cid.Cid
// Creates account actors from only BLS/SECP256K1 addresses.
// TryCreateAccountActor creates account actors from only BLS/SECP256K1 addresses.
func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, aerrors.ActorError) {
addrID, err := rt.state.RegisterNewAddress(addr)
if err != nil {
+136 -83
View File
@@ -5,6 +5,9 @@ import (
"context"
"encoding/binary"
"fmt"
gruntime "runtime"
"time"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
@@ -49,10 +52,12 @@ type Runtime struct {
origin address.Address
originNonce uint64
internalExecutions []*types.ExecutionResult
numActorsCreated uint64
allowInternal bool
callerValidated bool
executionTrace types.ExecutionTrace
numActorsCreated uint64
allowInternal bool
callerValidated bool
lastGasChargeTime time.Time
lastGasCharge *types.GasTrace
}
func (rt *Runtime) TotalFilCircSupply() abi.TokenAmount {
@@ -105,8 +110,8 @@ type notFoundErr interface {
IsNotFound() bool
}
func (rs *Runtime) Get(c cid.Cid, o vmr.CBORUnmarshaler) bool {
if err := rs.cst.Get(context.TODO(), c, o); err != nil {
func (rt *Runtime) Get(c cid.Cid, o vmr.CBORUnmarshaler) bool {
if err := rt.cst.Get(context.TODO(), c, o); err != nil {
var nfe notFoundErr
if xerrors.As(err, &nfe) && nfe.IsNotFound() {
if xerrors.As(err, new(cbor.SerializationError)) {
@@ -120,8 +125,8 @@ func (rs *Runtime) Get(c cid.Cid, o vmr.CBORUnmarshaler) bool {
return true
}
func (rs *Runtime) Put(x vmr.CBORMarshaler) cid.Cid {
c, err := rs.cst.Put(context.TODO(), x)
func (rt *Runtime) Put(x vmr.CBORMarshaler) cid.Cid {
c, err := rt.cst.Put(context.TODO(), x)
if err != nil {
if xerrors.As(err, new(cbor.SerializationError)) {
panic(aerrors.Newf(exitcode.ErrSerialization, "failed to marshal cbor object %s", err))
@@ -133,11 +138,11 @@ func (rs *Runtime) Put(x vmr.CBORMarshaler) cid.Cid {
var _ vmr.Runtime = (*Runtime)(nil)
func (rs *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) {
func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) {
defer func() {
if r := recover(); r != nil {
if ar, ok := r.(aerrors.ActorError); ok {
log.Errorf("VM.Call failure: %+v", ar)
log.Warnf("VM.Call failure: %+v", ar)
aerr = ar
return
}
@@ -148,8 +153,8 @@ func (rs *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.Act
ret := f()
if !rs.callerValidated {
rs.Abortf(exitcode.SysErrorIllegalActor, "Caller MUST be validated during method execution")
if !rt.callerValidated {
rt.Abortf(exitcode.SysErrorIllegalActor, "Caller MUST be validated during method execution")
}
switch ret := ret.(type) {
@@ -170,25 +175,25 @@ func (rs *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.Act
}
}
func (rs *Runtime) Message() vmr.Message {
return rs.vmsg
func (rt *Runtime) Message() vmr.Message {
return rt.vmsg
}
func (rs *Runtime) ValidateImmediateCallerAcceptAny() {
rs.abortIfAlreadyValidated()
func (rt *Runtime) ValidateImmediateCallerAcceptAny() {
rt.abortIfAlreadyValidated()
return
}
func (rs *Runtime) CurrentBalance() abi.TokenAmount {
b, err := rs.GetBalance(rs.Message().Receiver())
func (rt *Runtime) CurrentBalance() abi.TokenAmount {
b, err := rt.GetBalance(rt.Message().Receiver())
if err != nil {
rs.Abortf(exitcode.ExitCode(err.RetCode()), "get current balance: %v", err)
rt.Abortf(err.RetCode(), "get current balance: %v", err)
}
return b
}
func (rs *Runtime) GetActorCodeCID(addr address.Address) (ret cid.Cid, ok bool) {
act, err := rs.state.GetActor(addr)
func (rt *Runtime) GetActorCodeCID(addr address.Address) (ret cid.Cid, ok bool) {
act, err := rt.state.GetActor(addr)
if err != nil {
if xerrors.Is(err, types.ErrActorNotFound) {
return cid.Undef, false
@@ -208,8 +213,8 @@ func (rt *Runtime) GetRandomness(personalization crypto.DomainSeparationTag, ran
return res
}
func (rs *Runtime) Store() vmr.Store {
return rs
func (rt *Runtime) Store() vmr.Store {
return rt
}
func (rt *Runtime) NewActorAddress() address.Address {
@@ -234,12 +239,12 @@ func (rt *Runtime) NewActorAddress() address.Address {
return addr
}
func (rt *Runtime) CreateActor(codeId cid.Cid, address address.Address) {
if !builtin.IsBuiltinActor(codeId) {
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) {
if builtin.IsSingletonActor(codeID) {
rt.Abortf(exitcode.SysErrorIllegalArgument, "Can only have one instance of singleton actors.")
}
@@ -248,10 +253,10 @@ func (rt *Runtime) CreateActor(codeId cid.Cid, address address.Address) {
rt.Abortf(exitcode.SysErrorIllegalArgument, "Actor address already exists")
}
rt.ChargeGas(rt.Pricelist().OnCreateActor())
rt.chargeGas(rt.Pricelist().OnCreateActor())
err = rt.state.SetActor(address, &types.Actor{
Code: codeId,
Code: codeID,
Head: EmptyObjectCid,
Nonce: 0,
Balance: big.Zero(),
@@ -259,10 +264,11 @@ func (rt *Runtime) CreateActor(codeId cid.Cid, address address.Address) {
if err != nil {
panic(aerrors.Fatalf("creating actor entry: %v", err))
}
_ = rt.chargeGasSafe(gasOnActorExec)
}
func (rt *Runtime) DeleteActor(addr address.Address) {
rt.ChargeGas(rt.Pricelist().OnDeleteActor())
rt.chargeGas(rt.Pricelist().OnDeleteActor())
act, err := rt.state.GetActor(rt.Message().Receiver())
if err != nil {
if xerrors.Is(err, types.ErrActorNotFound) {
@@ -271,20 +277,22 @@ func (rt *Runtime) DeleteActor(addr address.Address) {
panic(aerrors.Fatalf("failed to get actor: %s", err))
}
if !act.Balance.IsZero() {
rt.vm.transfer(rt.Message().Receiver(), builtin.BurntFundsActorAddr, act.Balance)
if err := rt.vm.transfer(rt.Message().Receiver(), builtin.BurntFundsActorAddr, act.Balance); err != nil {
panic(aerrors.Fatalf("failed to transfer balance to burnt funds actor: %s", err))
}
}
if err := rt.state.DeleteActor(rt.Message().Receiver()); err != nil {
panic(aerrors.Fatalf("failed to delete actor: %s", err))
}
_ = rt.chargeGasSafe(gasOnActorExec)
}
func (rs *Runtime) Syscalls() vmr.Syscalls {
// TODO: Make sure this is wrapped in something that charges gas for each of the calls
return rs.sys
func (rt *Runtime) Syscalls() vmr.Syscalls {
return rt.sys
}
func (rs *Runtime) StartSpan(name string) vmr.TraceSpan {
func (rt *Runtime) StartSpan(name string) vmr.TraceSpan {
panic("implement me")
}
@@ -304,12 +312,12 @@ func (rt *Runtime) Context() context.Context {
return rt.ctx
}
func (rs *Runtime) Abortf(code exitcode.ExitCode, msg string, args ...interface{}) {
log.Error("Abortf: ", fmt.Sprintf(msg, args...))
func (rt *Runtime) Abortf(code exitcode.ExitCode, msg string, args ...interface{}) {
log.Warnf("Abortf: " + fmt.Sprintf(msg, args...))
panic(aerrors.NewfSkip(2, code, msg, args...))
}
func (rs *Runtime) AbortStateMsg(msg string) {
func (rt *Runtime) AbortStateMsg(msg string) {
panic(aerrors.NewfSkip(3, 101, msg))
}
@@ -327,8 +335,8 @@ func (rt *Runtime) ValidateImmediateCallerType(ts ...cid.Cid) {
rt.Abortf(exitcode.SysErrForbidden, "caller cid type %q was not one of %v", callerCid, ts)
}
func (rs *Runtime) CurrEpoch() abi.ChainEpoch {
return rs.height
func (rt *Runtime) CurrEpoch() abi.ChainEpoch {
return rt.height
}
type dumbWrapperType struct {
@@ -339,31 +347,34 @@ func (dwt *dumbWrapperType) Into(um vmr.CBORUnmarshaler) error {
return um.UnmarshalCBOR(bytes.NewReader(dwt.val))
}
func (rs *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMarshaler, value abi.TokenAmount) (vmr.SendReturn, exitcode.ExitCode) {
if !rs.allowInternal {
rs.Abortf(exitcode.SysErrorIllegalActor, "runtime.Send() is currently disallowed")
func (rt *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMarshaler, value abi.TokenAmount) (vmr.SendReturn, exitcode.ExitCode) {
if !rt.allowInternal {
rt.Abortf(exitcode.SysErrorIllegalActor, "runtime.Send() is currently disallowed")
}
var params []byte
if m != nil {
buf := new(bytes.Buffer)
if err := m.MarshalCBOR(buf); err != nil {
rs.Abortf(exitcode.SysErrInvalidParameters, "failed to marshal input parameters: %s", err)
rt.Abortf(exitcode.SysErrInvalidParameters, "failed to marshal input parameters: %s", err)
}
params = buf.Bytes()
}
ret, err := rs.internalSend(rs.Message().Receiver(), to, method, types.BigInt(value), params)
ret, err := rt.internalSend(rt.Message().Receiver(), to, method, value, params)
if err != nil {
if err.IsFatal() {
panic(err)
}
log.Warnf("vmctx send failed: to: %s, method: %d: ret: %d, err: %s", to, method, ret, err)
return nil, exitcode.ExitCode(err.RetCode())
return nil, err.RetCode()
}
_ = rt.chargeGasSafe(gasOnActorExec)
return &dumbWrapperType{ret}, 0
}
func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum, value types.BigInt, params []byte) ([]byte, aerrors.ActorError) {
start := time.Now()
ctx, span := trace.StartSpan(rt.ctx, "vmc.Send")
defer span.End()
if span.IsRecordingEvents() {
@@ -389,76 +400,62 @@ func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum,
}
defer st.ClearSnapshot()
ret, errSend, subrt := rt.vm.send(ctx, msg, rt, 0)
ret, errSend, subrt := rt.vm.send(ctx, msg, rt, nil, start)
if errSend != nil {
if errRevert := st.Revert(); errRevert != nil {
return nil, aerrors.Escalate(errRevert, "failed to revert state tree after failed subcall")
}
}
mr := types.MessageReceipt{
ExitCode: exitcode.ExitCode(aerrors.RetCode(errSend)),
Return: ret,
GasUsed: 0,
}
er := types.ExecutionResult{
Msg: msg,
MsgRct: &mr,
}
if errSend != nil {
er.Error = errSend.Error()
}
if subrt != nil {
er.Subcalls = subrt.internalExecutions
rt.numActorsCreated = subrt.numActorsCreated
}
rt.internalExecutions = append(rt.internalExecutions, &er)
rt.executionTrace.Subcalls = append(rt.executionTrace.Subcalls, subrt.executionTrace)
return ret, errSend
}
func (rs *Runtime) State() vmr.StateHandle {
return &shimStateHandle{rs: rs}
func (rt *Runtime) State() vmr.StateHandle {
return &shimStateHandle{rt: rt}
}
type shimStateHandle struct {
rs *Runtime
rt *Runtime
}
func (ssh *shimStateHandle) Create(obj vmr.CBORMarshaler) {
c := ssh.rs.Put(obj)
ssh.rs.stateCommit(EmptyObjectCid, c)
c := ssh.rt.Put(obj)
// TODO: handle error below
ssh.rt.stateCommit(EmptyObjectCid, c)
}
func (ssh *shimStateHandle) Readonly(obj vmr.CBORUnmarshaler) {
act, err := ssh.rs.state.GetActor(ssh.rs.Message().Receiver())
act, err := ssh.rt.state.GetActor(ssh.rt.Message().Receiver())
if err != nil {
ssh.rs.Abortf(exitcode.SysErrorIllegalArgument, "failed to get actor for Readonly state: %s", err)
ssh.rt.Abortf(exitcode.SysErrorIllegalArgument, "failed to get actor for Readonly state: %s", err)
}
ssh.rs.Get(act.Head, obj)
ssh.rt.Get(act.Head, obj)
}
func (ssh *shimStateHandle) Transaction(obj vmr.CBORer, f func() interface{}) interface{} {
if obj == nil {
ssh.rs.Abortf(exitcode.SysErrorIllegalActor, "Must not pass nil to Transaction()")
ssh.rt.Abortf(exitcode.SysErrorIllegalActor, "Must not pass nil to Transaction()")
}
act, err := ssh.rs.state.GetActor(ssh.rs.Message().Receiver())
act, err := ssh.rt.state.GetActor(ssh.rt.Message().Receiver())
if err != nil {
ssh.rs.Abortf(exitcode.SysErrorIllegalActor, "failed to get actor for Transaction: %s", err)
ssh.rt.Abortf(exitcode.SysErrorIllegalActor, "failed to get actor for Transaction: %s", err)
}
baseState := act.Head
ssh.rs.Get(baseState, obj)
ssh.rt.Get(baseState, obj)
ssh.rs.allowInternal = false
ssh.rt.allowInternal = false
out := f()
ssh.rs.allowInternal = true
ssh.rt.allowInternal = true
c := ssh.rs.Put(obj)
c := ssh.rt.Put(obj)
ssh.rs.stateCommit(baseState, c)
// TODO: handle error below
ssh.rt.stateCommit(baseState, c)
return out
}
@@ -495,22 +492,78 @@ func (rt *Runtime) stateCommit(oldh, newh cid.Cid) aerrors.ActorError {
return nil
}
func (rt *Runtime) ChargeGas(toUse int64) {
err := rt.chargeGasSafe(toUse)
func (rt *Runtime) finilizeGasTracing() {
if rt.lastGasCharge != nil {
rt.lastGasCharge.TimeTaken = time.Since(rt.lastGasChargeTime)
}
}
// ChargeGas is spec actors function
func (rt *Runtime) ChargeGas(name string, compute int64, virtual int64) {
err := rt.chargeGasInternal(newGasCharge(name, compute, 0).WithVirtual(virtual, 0), 1)
if err != nil {
panic(err)
}
}
func (rt *Runtime) chargeGasSafe(toUse int64) aerrors.ActorError {
func (rt *Runtime) chargeGas(gas GasCharge) {
err := rt.chargeGasInternal(gas, 1)
if err != nil {
panic(err)
}
}
func (rt *Runtime) chargeGasFunc(skip int) func(GasCharge) {
return func(gas GasCharge) {
err := rt.chargeGasInternal(gas, 1+skip)
if err != nil {
panic(err)
}
}
}
func (rt *Runtime) chargeGasInternal(gas GasCharge, skip int) aerrors.ActorError {
toUse := gas.Total()
var callers [10]uintptr
cout := gruntime.Callers(2+skip, callers[:])
now := time.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
if rt.gasUsed+toUse > rt.gasAvailable {
rt.gasUsed = rt.gasAvailable
return aerrors.Newf(exitcode.SysErrOutOfGas, "not enough gas: used=%d, available=%d", rt.gasUsed, rt.gasAvailable)
return aerrors.Newf(exitcode.SysErrOutOfGas, "not enough gas: used=%d, available=%d",
rt.gasUsed, rt.gasAvailable)
}
rt.gasUsed += toUse
return nil
}
func (rt *Runtime) chargeGasSafe(gas GasCharge) aerrors.ActorError {
return rt.chargeGasInternal(gas, 1)
}
func (rt *Runtime) Pricelist() Pricelist {
return rt.pricelist
}
+42 -20
View File
@@ -4,6 +4,8 @@ import (
"bytes"
"context"
"fmt"
goruntime "runtime"
"sync"
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid"
@@ -41,7 +43,7 @@ type syscallShim struct {
verifier ffiwrapper.Verifier
}
func (ss *syscallShim) ComputeUnsealedSectorCID(st abi.RegisteredProof, pieces []abi.PieceInfo) (cid.Cid, error) {
func (ss *syscallShim) ComputeUnsealedSectorCID(st abi.RegisteredSealProof, pieces []abi.PieceInfo) (cid.Cid, error) {
var sum abi.PaddedPieceSize
for _, p := range pieces {
sum += p.Size
@@ -113,7 +115,7 @@ func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime.Consen
// (b) time-offset mining fault
// strictly speaking no need to compare heights based on double fork mining check above,
// but at same height this would be a different fault.
if !types.CidArrsEqual(blockA.Parents, blockB.Parents) && blockA.Height != blockB.Height {
if types.CidArrsEqual(blockA.Parents, blockB.Parents) && blockA.Height != blockB.Height {
consensusFault = &runtime.ConsensusFault{
Target: blockA.Miner,
Epoch: blockB.Height,
@@ -157,7 +159,7 @@ func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime.Consen
}
if sigErr := ss.VerifyBlockSig(&blockB); sigErr != nil {
return nil, xerrors.Errorf("cannot verify first block sig: %w", sigErr)
return nil, xerrors.Errorf("cannot verify second block sig: %w", sigErr)
}
return consensusFault, nil
@@ -183,7 +185,7 @@ func (ss *syscallShim) VerifyBlockSig(blk *types.BlockHeader) error {
return err
}
if err := sigs.CheckBlockSignature(blk, ss.ctx, waddr); err != nil {
if err := sigs.CheckBlockSignature(ss.ctx, blk, waddr); err != nil {
return err
}
@@ -201,20 +203,6 @@ func (ss *syscallShim) VerifyPoSt(proof abi.WindowPoStVerifyInfo) error {
return nil
}
func cidToCommD(c cid.Cid) [32]byte {
b := c.Bytes()
var out [32]byte
copy(out[:], b[len(b)-32:])
return out
}
func cidToCommR(c cid.Cid) [32]byte {
b := c.Bytes()
var out [32]byte
copy(out[:], b[len(b)-32:])
return out
}
func (ss *syscallShim) VerifySeal(info abi.SealVerifyInfo) error {
//_, span := trace.StartSpan(ctx, "ValidatePoRep")
//defer span.End()
@@ -225,10 +213,10 @@ func (ss *syscallShim) VerifySeal(info abi.SealVerifyInfo) error {
}
ticket := []byte(info.Randomness)
proof := []byte(info.OnChain.Proof)
proof := info.Proof
seed := []byte(info.InteractiveRandomness)
log.Debugf("Verif r:%x; d:%x; m:%s; t:%x; s:%x; N:%d; p:%x", info.OnChain.SealedCID, info.UnsealedCID, miner, ticket, seed, info.SectorID.Number, proof)
log.Debugf("Verif r:%x; d:%x; m:%s; t:%x; s:%x; N:%d; p:%x", info.SealedCID, info.UnsealedCID, miner, ticket, seed, info.SectorID.Number, proof)
//func(ctx context.Context, maddr address.Address, ssize abi.SectorSize, commD, commR, ticket, proof, seed []byte, sectorID abi.SectorNumber)
ok, err := ss.verifier.VerifySeal(info)
@@ -252,3 +240,37 @@ func (ss *syscallShim) VerifySignature(sig crypto.Signature, addr address.Addres
return sigs.Verify(&sig, kaddr, input)
}
var BatchSealVerifyParallelism = goruntime.NumCPU()
func (ss *syscallShim) BatchVerifySeals(inp map[address.Address][]abi.SealVerifyInfo) (map[address.Address][]bool, error) {
out := make(map[address.Address][]bool)
sema := make(chan struct{}, BatchSealVerifyParallelism)
var wg sync.WaitGroup
for addr, seals := range inp {
results := make([]bool, len(seals))
out[addr] = results
for i, s := range seals {
wg.Add(1)
go func(ma address.Address, ix int, svi abi.SealVerifyInfo, res []bool) {
defer wg.Done()
sema <- struct{}{}
if err := ss.VerifySeal(svi); err != nil {
log.Warnw("seal verify in batch failed", "miner", ma, "index", ix, "err", err)
res[ix] = false
} else {
res[ix] = true
}
<-sema
}(addr, i, s, results)
}
}
wg.Wait()
return out, nil
}
+2
View File
@@ -41,6 +41,7 @@ func init() {
func TestChainValidationMessageSuite(t *testing.T) {
f := factory.NewFactories()
for _, testCase := range suites.MessageTestCases() {
testCase := testCase
if TestSuiteSkipper.Skip(testCase) {
continue
}
@@ -53,6 +54,7 @@ func TestChainValidationMessageSuite(t *testing.T) {
func TestChainValidationTipSetSuite(t *testing.T) {
f := factory.NewFactories()
for _, testCase := range suites.TipSetTestCases() {
testCase := testCase
if TestSuiteSkipper.Skip(testCase) {
continue
}
+111 -58
View File
@@ -35,6 +35,7 @@ import (
)
var log = logging.Logger("vm")
var gasOnActorExec = newGasCharge("OnActorExec", 0, 0)
// 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, aerrors.ActorError) {
@@ -62,17 +63,19 @@ func ResolveToKeyAddr(state types.StateTree, cst cbor.IpldStore, addr address.Ad
var _ cbor.IpldBlockstore = (*gasChargingBlocks)(nil)
type gasChargingBlocks struct {
chargeGas func(int64)
chargeGas func(GasCharge)
pricelist Pricelist
under cbor.IpldBlockstore
}
func (bs *gasChargingBlocks) Get(c cid.Cid) (block.Block, error) {
bs.chargeGas(newGasCharge("OnIpldGetStart", 0, 0))
blk, err := bs.under.Get(c)
if err != nil {
return nil, aerrors.Escalate(err, "failed to get block from blockstore")
}
bs.chargeGas(bs.pricelist.OnIpldGet(len(blk.RawData())))
bs.chargeGas(gasOnActorExec)
return blk, nil
}
@@ -83,6 +86,7 @@ func (bs *gasChargingBlocks) Put(blk block.Block) error {
if err := bs.under.Put(blk); err != nil {
return aerrors.Escalate(err, "failed to write data to disk")
}
bs.chargeGas(gasOnActorExec)
return nil
}
@@ -102,15 +106,16 @@ func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin addres
pricelist: PricelistByEpoch(vm.blockHeight),
allowInternal: true,
callerValidated: false,
executionTrace: types.ExecutionTrace{Msg: msg},
}
rt.cst = &cbor.BasicIpldStore{
Blocks: &gasChargingBlocks{rt.ChargeGas, rt.pricelist, vm.cst.Blocks},
Blocks: &gasChargingBlocks{rt.chargeGasFunc(2), rt.pricelist, vm.cst.Blocks},
Atlas: vm.cst.Atlas,
}
rt.sys = pricedSyscalls{
under: vm.Syscalls,
chargeGas: rt.ChargeGas,
chargeGas: rt.chargeGasFunc(1),
pl: rt.pricelist,
}
@@ -131,7 +136,7 @@ type VM struct {
cst *cbor.BasicIpldStore
buf *bufbstore.BufferedBS
blockHeight abi.ChainEpoch
inv *invoker
inv *Invoker
rand Rand
Syscalls runtime.Syscalls
@@ -163,63 +168,93 @@ type Rand interface {
type ApplyRet struct {
types.MessageReceipt
ActorErr aerrors.ActorError
Penalty types.BigInt
InternalExecutions []*types.ExecutionResult
Duration time.Duration
ActorErr aerrors.ActorError
Penalty types.BigInt
ExecutionTrace types.ExecutionTrace
Duration time.Duration
}
func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
gasCharge int64) ([]byte, aerrors.ActorError, *Runtime) {
gasCharge *GasCharge, start time.Time) ([]byte, aerrors.ActorError, *Runtime) {
st := vm.cstate
gasUsed := gasCharge
origin := msg.From
on := msg.Nonce
var nac uint64 = 0
var gasUsed int64
if parent != nil {
gasUsed = parent.gasUsed + gasUsed
gasUsed = parent.gasUsed
origin = parent.origin
on = parent.originNonce
nac = parent.numActorsCreated
}
rt := vm.makeRuntime(ctx, msg, origin, on, gasUsed, nac)
rt.lastGasChargeTime = start
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 aerr := rt.chargeGasSafe(rt.Pricelist().OnMethodInvocation(msg.Value, msg.Method)); aerr != nil {
return nil, aerrors.Wrap(aerr, "not enough gas for method invocation"), rt
if gasCharge != nil {
if err := rt.chargeGasSafe(*gasCharge); err != nil {
// this should never happen
return nil, aerrors.Wrap(err, "not enough gas for initial message charge, this should not happen"), rt
}
}
toActor, err := st.GetActor(msg.To)
if err != nil {
if xerrors.Is(err, init_.ErrAddressNotFound) {
a, err := TryCreateAccountActor(rt, msg.To)
if err != nil {
return nil, aerrors.Wrapf(err, "could not create account"), rt
ret, err := func() ([]byte, aerrors.ActorError) {
if aerr := rt.chargeGasSafe(rt.Pricelist().OnMethodInvocation(msg.Value, msg.Method)); aerr != nil {
return nil, aerrors.Wrap(aerr, "not enough gas for method invocation")
}
toActor, err := st.GetActor(msg.To)
if err != nil {
if xerrors.Is(err, init_.ErrAddressNotFound) {
a, err := TryCreateAccountActor(rt, msg.To)
if err != nil {
return nil, aerrors.Wrapf(err, "could not create account")
}
toActor = a
} else {
return nil, aerrors.Escalate(err, "getting actor")
}
toActor = a
} else {
return nil, aerrors.Escalate(err, "getting actor"), rt
}
}
if types.BigCmp(msg.Value, types.NewInt(0)) != 0 {
if err := vm.transfer(msg.From, msg.To, msg.Value); err != nil {
return nil, aerrors.Absorb(err, 1, "failed to transfer funds"), nil
if types.BigCmp(msg.Value, types.NewInt(0)) != 0 {
if err := vm.transfer(msg.From, msg.To, msg.Value); err != nil {
return nil, aerrors.Wrap(err, "failed to transfer funds")
}
}
if msg.Method != 0 {
var ret []byte
_ = rt.chargeGasSafe(gasOnActorExec)
ret, err := vm.Invoke(toActor, rt, msg.Method, msg.Params)
_ = rt.chargeGasSafe(newGasCharge("OnActorExecDone", 0, 0))
return ret, err
}
return nil, nil
}()
mr := types.MessageReceipt{
ExitCode: aerrors.RetCode(err),
Return: ret,
GasUsed: rt.gasUsed,
}
rt.executionTrace.MsgRct = &mr
rt.executionTrace.Duration = time.Since(start)
if err != nil {
rt.executionTrace.Error = err.Error()
}
if msg.Method != 0 {
ret, err := vm.Invoke(toActor, rt, msg.Method, msg.Params)
return ret, err, rt
}
return nil, nil, rt
return ret, err, rt
}
func checkMessage(msg *types.Message) error {
@@ -243,17 +278,18 @@ func checkMessage(msg *types.Message) error {
func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) {
start := time.Now()
ret, actorErr, rt := vm.send(ctx, msg, nil, 0)
ret, actorErr, rt := vm.send(ctx, msg, nil, nil, start)
rt.finilizeGasTracing()
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.ExitCode(aerrors.RetCode(actorErr)),
ExitCode: aerrors.RetCode(actorErr),
Return: ret,
GasUsed: 0,
},
ActorErr: actorErr,
InternalExecutions: rt.internalExecutions,
Penalty: types.NewInt(0),
Duration: time.Since(start),
ActorErr: actorErr,
ExecutionTrace: rt.executionTrace,
Penalty: types.NewInt(0),
Duration: time.Since(start),
}, actorErr
}
@@ -276,7 +312,8 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
pl := PricelistByEpoch(vm.blockHeight)
msgGasCost := pl.OnChainMessage(cmsg.ChainLength())
msgGas := pl.OnChainMessage(cmsg.ChainLength())
msgGasCost := msgGas.Total()
// this should never happen, but is currently still exercised by some tests
if msgGasCost > msg.GasLimit {
return &ApplyRet{
@@ -359,7 +396,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
}
defer st.ClearSnapshot()
ret, actorErr, rt := vm.send(ctx, msg, nil, msgGasCost)
ret, actorErr, rt := vm.send(ctx, msg, nil, &msgGas, start)
if aerrors.IsFatal(actorErr) {
return nil, xerrors.Errorf("[from=%s,to=%s,n=%d,m=%d,h=%d] fatal error: %w", msg.From, msg.To, msg.Nonce, msg.Method, vm.blockHeight, actorErr)
}
@@ -413,16 +450,18 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
return nil, xerrors.Errorf("gas handling math is wrong")
}
rt.finilizeGasTracing()
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.ExitCode(errcode),
ExitCode: errcode,
Return: ret,
GasUsed: gasUsed,
},
ActorErr: actorErr,
InternalExecutions: rt.internalExecutions,
Penalty: types.NewInt(0),
Duration: time.Since(start),
ActorErr: actorErr,
ExecutionTrace: rt.executionTrace,
Penalty: types.NewInt(0),
Duration: time.Since(start),
}, nil
}
@@ -454,7 +493,7 @@ func (vm *VM) Flush(ctx context.Context) (cid.Cid, error) {
return root, nil
}
// vm.MutateState(idAddr, func(cst cbor.IpldStore, st *ActorStateType) error {...})
// MutateState usage: MutateState(ctx, idAddr, func(cst cbor.IpldStore, st *ActorStateType) error {...})
func (vm *VM) MutateState(ctx context.Context, addr address.Address, fn interface{}) error {
act, err := vm.cstate.GetActor(addr)
if err != nil {
@@ -591,7 +630,7 @@ func (vm *VM) Invoke(act *types.Actor, rt *Runtime, method abi.MethodNum, params
return ret, nil
}
func (vm *VM) SetInvoker(i *invoker) {
func (vm *VM) SetInvoker(i *Invoker) {
vm.inv = i
}
@@ -602,36 +641,50 @@ func (vm *VM) incrementNonce(addr address.Address) error {
})
}
func (vm *VM) transfer(from, to address.Address, amt types.BigInt) error {
func (vm *VM) transfer(from, to address.Address, amt types.BigInt) aerrors.ActorError {
if from == to {
return nil
}
fromID, err := vm.cstate.LookupID(from)
if err != nil {
return aerrors.Fatalf("transfer failed when resolving sender address: %s", err)
}
toID, err := vm.cstate.LookupID(to)
if err != nil {
return aerrors.Fatalf("transfer failed when resolving receiver address: %s", err)
}
if fromID == toID {
return nil
}
if amt.LessThan(types.NewInt(0)) {
return xerrors.Errorf("attempted to transfer negative value")
return aerrors.Newf(exitcode.SysErrForbidden, "attempted to transfer negative value: %s", amt)
}
f, err := vm.cstate.GetActor(from)
f, err := vm.cstate.GetActor(fromID)
if err != nil {
return xerrors.Errorf("transfer failed when retrieving sender actor")
return aerrors.Fatalf("transfer failed when retrieving sender actor: %s", err)
}
t, err := vm.cstate.GetActor(to)
t, err := vm.cstate.GetActor(toID)
if err != nil {
return xerrors.Errorf("transfer failed when retrieving receiver actor")
return aerrors.Fatalf("transfer failed when retrieving receiver actor: %s", err)
}
if err := deductFunds(f, amt); err != nil {
return err
return aerrors.Newf(exitcode.SysErrInsufficientFunds, "transfer failed when deducting funds: %s", err)
}
depositFunds(t, amt)
if err := vm.cstate.SetActor(from, f); err != nil {
return err
if err := vm.cstate.SetActor(fromID, f); err != nil {
return aerrors.Fatalf("transfer failed when setting receiver actor: %s", err)
}
if err := vm.cstate.SetActor(to, t); err != nil {
return err
if err := vm.cstate.SetActor(toID, t); err != nil {
return aerrors.Fatalf("transfer failed when setting sender actor: %s", err)
}
return nil
+24 -6
View File
@@ -12,8 +12,8 @@ import (
"github.com/filecoin-project/go-address"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" // enable bls signatures
_ "github.com/filecoin-project/lotus/lib/sigs/secp" // enable secp signatures
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
@@ -22,10 +22,11 @@ import (
var log = logging.Logger("wallet")
const (
KNamePrefix = "wallet-"
KDefault = "default"
KTBLS = "bls"
KTSecp256k1 = "secp256k1"
KNamePrefix = "wallet-"
KTrashPrefix = "trash-"
KDefault = "default"
KTBLS = "bls"
KTSecp256k1 = "secp256k1"
)
type Wallet struct {
@@ -230,6 +231,23 @@ func (w *Wallet) HasKey(addr address.Address) (bool, error) {
return k != nil, nil
}
func (w *Wallet) DeleteKey(addr address.Address) error {
k, err := w.findKey(addr)
if err != nil {
return xerrors.Errorf("failed to delete key %s : %w", addr, err)
}
if err := w.keystore.Put(KTrashPrefix+k.Address.String(), k.KeyInfo); err != nil {
return xerrors.Errorf("failed to mark key %s as trashed: %w", addr, err)
}
if err := w.keystore.Delete(KNamePrefix + k.Address.String()); err != nil {
return xerrors.Errorf("failed to delete key %s: %w", addr, err)
}
return nil
}
type Key struct {
types.KeyInfo
+5 -3
View File
@@ -3,8 +3,10 @@ package cli
import (
"fmt"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/node/repo"
@@ -45,7 +47,7 @@ var authCreateAdminToken = &cli.Command{
perm := cctx.String("perm")
idx := 0
for i, p := range apistruct.AllPermissions {
if perm == p {
if auth.Permission(perm) == p {
idx = i + 1
}
}
@@ -93,7 +95,7 @@ var authApiInfoToken = &cli.Command{
perm := cctx.String("perm")
idx := 0
for i, p := range apistruct.AllPermissions {
if perm == p {
if auth.Permission(perm) == p {
idx = i + 1
}
}
+51 -8
View File
@@ -12,19 +12,19 @@ import (
"strings"
"time"
"github.com/docker/go-units"
"github.com/filecoin-project/go-address"
cborutil "github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/account"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/util/adt"
cid "github.com/ipfs/go-cid"
"github.com/urfave/cli/v2"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
@@ -221,6 +221,9 @@ var chainStatObjCmd = &cli.Command{
base := cid.Undef
if cctx.IsSet("base") {
base, err = cid.Decode(cctx.String("base"))
if err != nil {
return err
}
}
stats, err := api.ChainStatObj(ctx, obj, base)
@@ -229,7 +232,7 @@ var chainStatObjCmd = &cli.Command{
}
fmt.Printf("Links: %d\n", stats.Links)
fmt.Printf("Size: %s (%d)\n", units.BytesSize(float64(stats.Size)), stats.Size)
fmt.Printf("Size: %s (%d)\n", types.SizeStr(types.NewInt(stats.Size)), stats.Size)
return nil
},
}
@@ -441,7 +444,8 @@ var chainGetCmd = &cli.Command{
- /ipfs/[cid]/@Hi:123 - get varint elem 123 from hamt
- /ipfs/[cid]/@Hu:123 - get uvarint elem 123 from hamt
- /ipfs/[cid]/@Ha:t01 - get element under Addr(t01).Bytes
- /ipfs/[cid]/@A:10 - get 10th amt element
- /ipfs/[cid]/@A:10 - get 10th amt element
- .../@Ha:t01/@state - get pretty map-based actor state
List of --as-type types:
- raw
@@ -521,6 +525,12 @@ var chainGetCmd = &cli.Command{
cbu = new(power.CronEvent)
case "account-state":
cbu = new(account.State)
case "miner-state":
cbu = new(miner.State)
case "power-state":
cbu = new(power.State)
case "market-state":
cbu = new(market.State)
default:
return fmt.Errorf("unknown type: %q", t)
}
@@ -797,7 +807,12 @@ var chainExportCmd = &cli.Command{
if err != nil {
return err
}
defer fi.Close()
defer func() {
err := fi.Close()
if err != nil {
fmt.Printf("error closing output file: %+v", err)
}
}()
ts, err := LoadTipSet(ctx, cctx, api)
if err != nil {
@@ -829,6 +844,10 @@ var slashConsensusFault = &cli.Command{
Name: "miner",
Usage: "Miner address",
},
&cli.StringFlag{
Name: "extra",
Usage: "Extra block cid",
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
@@ -873,10 +892,34 @@ var slashConsensusFault = &cli.Command{
return err
}
params, err := actors.SerializeParams(&miner.ReportConsensusFaultParams{
params := miner.ReportConsensusFaultParams{
BlockHeader1: bh1,
BlockHeader2: bh2,
})
}
if cctx.String("extra") != "" {
cExtra, err := cid.Parse(cctx.String("extra"))
if err != nil {
return xerrors.Errorf("parsing cid extra: %w", err)
}
bExtra, err := api.ChainGetBlock(ctx, cExtra)
if err != nil {
return xerrors.Errorf("getting block extra: %w", err)
}
be, err := cborutil.Dump(bExtra)
if err != nil {
return err
}
params.BlockHeaderExtra = be
}
enc, err := actors.SerializeParams(&params)
if err != nil {
return err
}
if cctx.String("miner") == "" {
return xerrors.Errorf("--miner flag is required")
@@ -894,7 +937,7 @@ var slashConsensusFault = &cli.Command{
GasPrice: types.NewInt(1),
GasLimit: 10000000,
Method: builtin.MethodsMiner.ReportConsensusFault,
Params: params,
Params: enc,
}
smsg, err := api.MpoolPushMessage(ctx, msg)
+137 -40
View File
@@ -8,19 +8,48 @@ import (
"text/tabwriter"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-cidutil/cidenc"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/multiformats/go-multibase"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/lotus/api"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
)
var CidBaseFlag = cli.StringFlag{
Name: "cid-base",
Hidden: true,
Value: "base32",
Usage: "Multibase encoding used for version 1 CIDs in output.",
DefaultText: "base32",
}
// GetCidEncoder returns an encoder using the `cid-base` flag if provided, or
// the default (Base32) encoder if not.
func GetCidEncoder(cctx *cli.Context) (cidenc.Encoder, error) {
val := cctx.String("cid-base")
e := cidenc.Encoder{Base: multibase.MustNewEncoder(multibase.Base32)}
if val != "" {
var err error
e.Base, err = multibase.EncoderByName(val)
if err != nil {
return e, err
}
}
return e, nil
}
var clientCmd = &cli.Command{
Name: "client",
Usage: "Make deals, store data, retrieve data",
@@ -46,6 +75,7 @@ var clientImportCmd = &cli.Command{
Name: "car",
Usage: "import from a car file instead of a regular file",
},
&CidBaseFlag,
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
@@ -54,6 +84,11 @@ var clientImportCmd = &cli.Command{
}
defer closer()
ctx := ReqContext(cctx)
if cctx.NArg() != 1 {
return xerrors.New("expected input path as the only arg")
}
absPath, err := filepath.Abs(cctx.Args().First())
if err != nil {
return err
@@ -67,7 +102,14 @@ var clientImportCmd = &cli.Command{
if err != nil {
return err
}
fmt.Println(c.String())
encoder, err := GetCidEncoder(cctx)
if err != nil {
return err
}
fmt.Println(encoder.Encode(c))
return nil
},
}
@@ -76,6 +118,9 @@ var clientCommPCmd = &cli.Command{
Name: "commP",
Usage: "calculate the piece-cid (commP) of a CAR file",
ArgsUsage: "[inputFile minerAddress]",
Flags: []cli.Flag{
&CidBaseFlag,
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
@@ -94,12 +139,17 @@ var clientCommPCmd = &cli.Command{
}
ret, err := api.ClientCalcCommP(ctx, cctx.Args().Get(0), miner)
if err != nil {
return err
}
fmt.Println("CID: ", ret.Root)
fmt.Println("Piece size: ", ret.Size)
encoder, err := GetCidEncoder(cctx)
if err != nil {
return err
}
fmt.Println("CID: ", encoder.Encode(ret.Root))
fmt.Println("Piece size: ", types.SizeStr(types.NewInt(uint64(ret.Size))))
return nil
},
}
@@ -137,6 +187,9 @@ var clientCarGenCmd = &cli.Command{
var clientLocalCmd = &cli.Command{
Name: "local",
Usage: "List locally imported data",
Flags: []cli.Flag{
&CidBaseFlag,
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
@@ -149,8 +202,14 @@ var clientLocalCmd = &cli.Command{
if err != nil {
return err
}
encoder, err := GetCidEncoder(cctx)
if err != nil {
return err
}
for _, v := range list {
fmt.Printf("%s %s %d %s\n", v.Key, v.FilePath, v.Size, v.Status)
fmt.Printf("%s %s %s %s\n", encoder.Encode(v.Key), v.FilePath, types.SizeStr(types.NewInt(v.Size)), v.Status)
}
return nil
},
@@ -178,6 +237,7 @@ var clientDealCmd = &cli.Command{
Usage: "specify the epoch that the deal should start at",
Value: -1,
},
&CidBaseFlag,
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
@@ -263,7 +323,13 @@ var clientDealCmd = &cli.Command{
return err
}
fmt.Println(proposal)
encoder, err := GetCidEncoder(cctx)
if err != nil {
return err
}
fmt.Println(encoder.Encode(*proposal))
return nil
},
}
@@ -311,7 +377,7 @@ var clientFindCmd = &cli.Command{
fmt.Printf("ERR %s@%s: %s\n", offer.Miner, offer.MinerPeerID, offer.Err)
continue
}
fmt.Printf("RETRIEVAL %s@%s-%sfil-%db\n", offer.Miner, offer.MinerPeerID, types.FIL(offer.MinPrice), offer.Size)
fmt.Printf("RETRIEVAL %s@%s-%sfil-%s\n", offer.Miner, offer.MinerPeerID, types.FIL(offer.MinPrice), types.SizeStr(types.NewInt(offer.Size)))
}
return nil
@@ -324,13 +390,17 @@ var clientRetrieveCmd = &cli.Command{
ArgsUsage: "[dataCid outputPath]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "address",
Usage: "address to use for transactions",
Name: "from",
Usage: "address to send transactions from",
},
&cli.BoolFlag{
Name: "car",
Usage: "export to a car file instead of a regular file",
},
&cli.StringFlag{
Name: "miner",
Usage: "miner address for retrieval, if not present it'll use local discovery",
},
},
Action: func(cctx *cli.Context) error {
if cctx.NArg() != 2 {
@@ -338,7 +408,7 @@ var clientRetrieveCmd = &cli.Command{
return nil
}
api, closer, err := GetFullNodeAPI(cctx)
fapi, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
@@ -346,10 +416,10 @@ var clientRetrieveCmd = &cli.Command{
ctx := ReqContext(cctx)
var payer address.Address
if cctx.String("address") != "" {
payer, err = address.NewFromString(cctx.String("address"))
if cctx.String("from") != "" {
payer, err = address.NewFromString(cctx.String("from"))
} else {
payer, err = api.WalletDefaultAddress(ctx)
payer, err = fapi.WalletDefaultAddress(ctx)
}
if err != nil {
return err
@@ -372,23 +442,39 @@ var clientRetrieveCmd = &cli.Command{
return nil
}*/ // TODO: fix
offers, err := api.ClientFindData(ctx, file)
if err != nil {
return err
var offer api.QueryOffer
minerStrAddr := cctx.String("miner")
if minerStrAddr == "" { // Local discovery
offers, err := fapi.ClientFindData(ctx, file)
if err != nil {
return err
}
// TODO: parse offer strings from `client find`, make this smarter
if len(offers) < 1 {
fmt.Println("Failed to find file")
return nil
}
offer = offers[0]
} else { // Directed retrieval
minerAddr, err := address.NewFromString(minerStrAddr)
if err != nil {
return err
}
offer, err = fapi.ClientMinerQueryOffer(ctx, file, minerAddr)
if err != nil {
return err
}
}
if offer.Err != "" {
return fmt.Errorf("The received offer errored: %s", offer.Err)
}
// TODO: parse offer strings from `client find`, make this smarter
if len(offers) < 1 {
fmt.Println("Failed to find file")
return nil
}
ref := lapi.FileRef{
ref := &lapi.FileRef{
Path: cctx.Args().Get(1),
IsCAR: cctx.Bool("car"),
}
if err := api.ClientRetrieve(ctx, offers[0].Order(payer), ref); err != nil {
if err := fapi.ClientRetrieve(ctx, offer.Order(payer), ref); err != nil {
return xerrors.Errorf("Retrieval Failed: %w", err)
}
@@ -417,7 +503,7 @@ var clientQueryAskCmd = &cli.Command{
},
Action: func(cctx *cli.Context) error {
if cctx.NArg() != 1 {
fmt.Println("Usage: query-ask [address]")
fmt.Println("Usage: query-ask [minerAddress]")
return nil
}
@@ -446,11 +532,11 @@ var clientQueryAskCmd = &cli.Command{
return xerrors.Errorf("failed to get peerID for miner: %w", err)
}
if mi.PeerId == peer.ID("SETME") {
if peer.ID(mi.PeerId) == peer.ID("SETME") {
return fmt.Errorf("the miner hasn't initialized yet")
}
pid = mi.PeerId
pid = peer.ID(mi.PeerId)
}
ask, err := api.ClientQueryAsk(ctx, pid, maddr)
@@ -460,7 +546,7 @@ var clientQueryAskCmd = &cli.Command{
fmt.Printf("Ask: %s\n", maddr)
fmt.Printf("Price per GiB: %s\n", types.FIL(ask.Ask.Price))
fmt.Printf("Max Piece size: %d\n", ask.Ask.MaxPieceSize)
fmt.Printf("Max Piece size: %s\n", types.SizeStr(types.NewInt(uint64(ask.Ask.MaxPieceSize))))
size := cctx.Int64("size")
if size == 0 {
@@ -501,16 +587,27 @@ var clientListDeals = &cli.Command{
}
var deals []deal
for idx := range localDeals {
onChain, err := api.StateMarketStorageDeal(ctx, localDeals[idx].DealID, head.Key())
if err != nil {
return err
}
for _, v := range localDeals {
if v.DealID == 0 {
deals = append(deals, deal{
LocalDeal: v,
OnChainDealState: market.DealState{
SectorStartEpoch: -1,
LastUpdatedEpoch: -1,
SlashEpoch: -1,
},
})
} else {
onChain, err := api.StateMarketStorageDeal(ctx, v.DealID, head.Key())
if err != nil {
return err
}
deals = append(deals, deal{
LocalDeal: localDeals[idx],
OnChainDealState: onChain.State,
})
deals = append(deals, deal{
LocalDeal: v,
OnChainDealState: onChain.State,
})
}
}
w := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0)
@@ -526,7 +623,7 @@ var clientListDeals = &cli.Command{
slashed = fmt.Sprintf("Y (epoch %d)", d.OnChainDealState.SlashEpoch)
}
fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%s\t%s\t%s\t%d\t%s\t%d\t%s\n", d.LocalDeal.ProposalCid, d.LocalDeal.DealID, d.LocalDeal.Provider, storagemarket.DealStates[d.LocalDeal.State], onChain, slashed, d.LocalDeal.PieceCID, d.LocalDeal.Size, d.LocalDeal.PricePerEpoch, d.LocalDeal.Duration, d.LocalDeal.Message)
fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%d\t%s\n", d.LocalDeal.ProposalCid, d.LocalDeal.DealID, d.LocalDeal.Provider, storagemarket.DealStates[d.LocalDeal.State], onChain, slashed, d.LocalDeal.PieceCID, types.SizeStr(types.NewInt(d.LocalDeal.Size)), d.LocalDeal.PricePerEpoch, d.LocalDeal.Duration, d.LocalDeal.Message)
}
return w.Flush()
},

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