Compare commits

...
265 Commits
Author SHA1 Message Date
Whyrusleeping 1ad725a04c Merge pull request #1284 from filecoin-project/version-bump-0-2-8
bump version to 0.2.8
2020-02-20 15:45:39 -08:00
Travis Person a898b18fd6 bump version to 0.2.8 2020-02-20 21:48:17 +00:00
Łukasz Magiera 0fa362cc23 Merge pull request #1280 from filecoin-project/asr/fix
Fix #1278: debug_advance should have its API calls updated
2020-02-19 18:17:39 +01:00
Aayush Rajasekaran 61401e5e82 Fix #1278: debug_advance should have its API calls updated
- This was forgotten in commit 6097000
2020-02-18 23:14:08 -05:00
Whyrusleeping 6afeb2e72b Merge pull request #1268 from filecoin-project/feat/simple-spam-protection
basic gossip spam protection logic
2020-02-18 10:39:36 -08:00
Whyrusleeping b5d50f2b52 Merge pull request #1272 from filecoin-project/misc/add-gofmt-to-golangcilint
Add gofmt to golangci-lint
2020-02-18 09:23:55 -08:00
Whyrusleeping 7e0be91cfd Merge pull request #1263 from filecoin-project/asr/state-api
Re: #1250: API methods should receive TipSetKeys, not TipSets, as input
2020-02-18 09:22:33 -08:00
whyrusleeping 4f6ec225cf mark peer for disconnection in connmgr 2020-02-18 09:20:17 -08:00
Jakub Sztandera b2a0ad68dd Add gofmt to golangci-lint
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-02-18 13:19:04 +01:00
Aayush Rajasekaran 60970008c8 Re: #1250: API methods should receive TipSetKeys, not TipSets, as input 2020-02-17 19:53:43 -05:00
Whyrusleeping 4750f32ab6 Merge pull request #1253 from filecoin-project/feat/bad-ts-cache-reasons
mark down reason for block inclusion in bad tipset cache
2020-02-17 12:20:20 -08:00
Whyrusleeping 1c9072bf6e Merge pull request #1235 from filecoin-project/feat/tls
Prefer tls
2020-02-17 11:26:50 -08:00
Whyrusleeping 656c022ed6 Merge pull request #1260 from filecoin-project/doc/miner-wallet-bls
docs: Provide clearer instructions around bls wallets for miners
2020-02-17 11:17:32 -08:00
Jakub Sztandera 4d5af19b9d Merge pull request #1258 from filecoin-project/feat/expose-jet-permission-error
Expose JWT permission error
2020-02-17 20:16:12 +01:00
Whyrusleeping fc227561ba Merge pull request #1254 from filecoin-project/feat/no-ffi-in-types
Remove ffi from types package
2020-02-17 11:13:56 -08:00
Whyrusleeping ca0bed47c4 Merge pull request #1261 from filecoin-project/asr/faucet
Faucet: Provide more info when a user tries to create a miner with a non-BLS address
2020-02-17 11:00:11 -08:00
Whyrusleeping 4f4f18482a Merge pull request #1266 from filecoin-project/feat/cmd-log
cmd: add log command
2020-02-17 10:39:56 -08:00
whyrusleeping 1dafcf24f1 basic gossip spam protection logic 2020-02-16 21:51:18 -08:00
Travis Person d6cf76a91a cmd: add log command
Add a log command to the common api which allows for listing all
initialized golog subsystems, and setting their log level during
runtime.

Command description also adds golog environment variable documentation.
2020-02-15 06:04:55 +00:00
Jim a34537ae9f Merge pull request #1264 from filecoin-project/asr/docs
Docs: Add a Lotus-only FAQs section to the Lotus website.
2020-02-14 19:21:40 -08:00
Aayush Rajasekaran 85c7864f78 Docs: Add a Lotus-only FAQs section to the Lotus website. 2020-02-14 18:38:14 -08:00
Aayush Rajasekaran f24d947388 Faucet: Provide more info when a user tries to create a miner with a non-BLS address 2020-02-12 18:41:23 -08:00
Travis Person 78c0c9b21a docs: Provide clearer instructions around bls wallets for miners 2020-02-12 23:36:56 +00:00
Oggy Nots 6bf87e28e9 create and publish github release (#1216)
* create and publish github release

* creates a tarball of 'lotus', 'lotus-storage-miner' and
'lotus-seal-worker' for darwin and linux
* computes and saves IPFS CID and sha512sum for each architecture
* creates a github release and uploads all artifacts
* triggered by tags matching regex /^v\d+\.\d+\.\d+$/ ie. v0.1.0

* add licenses and readme
2020-02-12 16:28:37 -05:00
Jakub Sztandera 49167cc55f Expose JWT permission error
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-02-12 21:25:29 +01:00
Łukasz Magiera a2b6aa8e67 Merge pull request #1257 from filecoin-project/feat/expand-repo-log
Expand "repo" string before logging
2020-02-12 21:05:36 +01:00
Jakub Sztandera c7ffaad763 Expand "repo" string before logging
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-02-12 21:00:07 +01:00
Jakub Sztandera 14580b6144 Import go-systemd properly
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-02-12 20:44:35 +01:00
Jakub Sztandera 5c3ed4d91a Remove ffi from types package
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-02-12 18:41:35 +01:00
whyrusleeping 243b295559 expose bad block cache reasons through api/cli 2020-02-11 23:44:55 -08:00
whyrusleeping 0661a1bbfc mark down reason for block inclusion in bad tipset cache 2020-02-11 23:21:11 -08:00
Whyrusleeping 5133ff16ba Merge pull request #1247 from filecoin-project/fix/lotus-shed-keyinfo
lotus-shed: add back support for bls and secp after sig changes
2020-02-11 13:40:42 -08:00
Łukasz Magiera 201eb3bab8 Merge pull request #1251 from filecoin-project/asr/lotus-docs
Use HTTPS for links to the dashboard
2020-02-11 21:04:14 +01:00
Aayush Rajasekaran c4b790a910 Use HTTPS for links to the dashboard
- The link doesn't reliably work without HTTPS specified
2020-02-11 11:51:11 -08:00
Jim dbcf2c3cf5 Merge pull request #1248 from filecoin-project/@jimmylee/small-docs-update
documentation: adds file name length limit
2020-02-10 23:00:09 -08:00
jimmylee a9cb1d6543 documentation: adds file name length limit 2020-02-10 22:31:45 -08:00
Łukasz Magiera e326a444b1 Merge pull request #1222 from filecoin-project/feat/support-multi-storage-miner-init
Support multi storage directories in miner init
2020-02-11 02:16:55 +01:00
Travis Person bc15d5234e lotus-shed: add back support for bls and secp after sig changes 2020-02-11 01:04:50 +00:00
Łukasz Magiera 05c262eb9f Merge pull request #1246 from filecoin-project/feat/msg-wait-cmd
expose StateWaitMsg through the cli
2020-02-11 01:50:52 +01:00
whyrusleeping 1e1668e949 expose StateWaitMsg through the cli 2020-02-10 16:38:02 -08:00
Jakub Sztandera 352fb9f9ea Prefer tls
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-02-07 14:04:47 +01:00
Łukasz Magiera fc46938383 Merge pull request #1234 from filecoin-project/fix/signature-tests
add proper signature imports to tests
2020-02-07 08:15:43 +01:00
whyrusleeping 0309e2332c add proper signature imports to tests 2020-02-06 23:01:37 -08:00
Łukasz Magiera 17c3d158d2 Merge pull request #1233 from filecoin-project/fix/mark-bad
mark bad should be respected for every incoming tipset
2020-02-07 07:42:01 +01:00
whyrusleeping d4338047af mark bad should be respected for every incoming tipset 2020-02-06 22:39:24 -08:00
Łukasz Magiera 44c1e3a347 Merge pull request #1228 from steven004/statepower
better power show
2020-02-06 19:34:46 +01:00
steven004 709fd12b7f better power show 2020-02-06 14:25:30 +08:00
Jakub Sztandera 21a603ed8f Merge pull request #1226 from filecoin-project/fix/dbg-errcheck
debug: Check error in AdvanceBlockCmd
2020-02-06 07:05:57 +01:00
Łukasz Magiera 85f91a1114 debug: Check error in AdvanceBlockCmd 2020-02-06 03:09:52 +01:00
Łukasz Magiera e7a1be4dde Merge pull request #1217 from filecoin-project/feat/worker-prefetch
worker: Prefetch data in background
2020-02-05 03:09:24 +01:00
Travis Person e9470d873e Update usage 2020-02-05 00:07:44 +00:00
Travis Person cf8e90fa3e Load sectorbuilder config during storage miner init 2020-02-05 00:07:44 +00:00
Travis Person 62146b7bb3 Add pre-sealed-metadata flag to miner init
Metadata for presealed sectors now must be specified
2020-02-04 23:16:10 +00:00
Łukasz Magiera 575e962d16 Merge pull request #1220 from filecoin-project/fix/other-commands
Fix lotus-seed with sigs changes
2020-02-04 23:53:51 +01:00
Jakub Sztandera 70da3e124a Fix lotus-seed with sigs changes
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-02-04 23:49:10 +01:00
Łukasz Magiera 4bd6d7be1a storageminer: Work around broken fastPledgeCommitment 2020-02-04 21:46:31 +01:00
Łukasz Magiera 63af9f2a9e worker: Paramfetch once 2020-02-04 20:17:18 +01:00
Łukasz Magiera 1a9c775407 worker: Prefetch data in background 2020-02-04 20:09:08 +01:00
Whyrusleeping 955b86deea Merge pull request #1188 from filecoin-project/feat/sigs-standalone
Don't depend on ffi
2020-02-04 10:45:21 -08:00
Łukasz Magiera 6eb342b8ee Merge pull request #1212 from filecoin-project/fix/remote-put-commit
remote: Fix put in commit
2020-02-04 18:22:12 +01:00
Jakub Sztandera 5bc1cb2aa3 Fix CheckBlockSignature, add docks
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-02-04 15:12:10 +01:00
Jakub Sztandera cb05001e5a mod tidy
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-02-04 15:12:10 +01:00
Jakub Sztandera ad9e4db3d6 Reduce sig import locations
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-02-04 15:12:10 +01:00
Jakub Sztandera 5e6ab42cb8 Don't depend on ffi
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-02-04 15:12:04 +01:00
Łukasz Magiera 63ee6b6791 remote: Fix put in commit 2020-02-04 08:01:13 +01:00
Łukasz Magiera f837cb5513 Merge pull request #1184 from filecoin-project/feat/chain-bisect
chain: bisect cmd
2020-02-04 04:43:31 +01:00
Łukasz Magiera b7ff44485a bisect: Allow any command 2020-02-04 04:40:49 +01:00
Łukasz Magiera 9935e3acfc Merge pull request #1191 from filecoin-project/feat/new-sb-fs
Sectorbuilder FS refactor
2020-02-04 04:19:39 +01:00
Łukasz Magiera 90ecfbe0e4 Merge branch 'master' into feat/new-sb-fs 2020-02-04 04:15:25 +01:00
Łukasz Magiera 0ca349033d Merge pull request #1205 from filecoin-project/fix/readme
drop 'experimental' from readme description
2020-02-04 03:53:06 +01:00
Łukasz Magiera 5cc089be12 Merge pull request #1207 from filecoin-project/feat/api-bstore
api-backed blockstore
2020-02-04 03:52:01 +01:00
Łukasz Magiera a8d18c8ac9 api-backed blockstore 2020-02-04 03:47:59 +01:00
whyrusleeping cc0635335c drop 'experimental' from readme description 2020-02-03 17:52:46 -08:00
Łukasz Magiera 65d8769002 Merge pull request #1203 from filecoin-project/feat/split-post-scheduler-from-storage-miner
split PoSt scheduler from Miner in preparation for extraction
2020-02-04 02:13:12 +01:00
laser d8f5330c29 don't consume short-lived context 2020-02-03 15:48:11 -08:00
laser ea2f53745e split FPoStScheduler from Miner
Rationale: Nodes want to handle scheduling of PoSts. Splitting the 
FPoStScheduler from the Miner allows nodes to reuse the Miner w/out 
having to reuse the PoSt scheduler.
2020-02-03 15:48:11 -08:00
Łukasz Magiera c9bd682c33 Merge pull request #1178 from filecoin-project/feat/multisig-balance-rpc
add a method to query available multisig balance
2020-02-04 00:43:08 +01:00
Łukasz Magiera 04c8bca073 Merge pull request #1195 from filecoin-project/test/fork-height-activation
add a test to ensure there are no off-by-one errors in fork activatio…
2020-02-03 23:26:56 +01:00
Whyrusleeping 7f1335a8dd Merge pull request #1196 from filecoin-project/fix/slash-blocks
Fix slash blocks
2020-02-03 10:17:43 -08:00
Łukasz Magiera ff77198a08 Update sectorbuilder with later cache mkdir 2020-02-03 18:37:40 +01:00
Łukasz Magiera 8da64d710e sealing: Work around broken remote sector put 2020-02-03 04:48:56 +01:00
Łukasz Magiera e453a38865 sealing: fix finalize with cache only 2020-02-02 20:36:15 +01:00
Jakub Sztandera ce7be477ce Fix slash blocks
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-31 17:07:37 -08:00
whyrusleeping 01b6ddbbd3 add a test to ensure there are no off-by-one errors in fork activation logic 2020-01-31 15:52:39 -08:00
Łukasz Magiera 37929ff75f sealing: more logging in pledge sector flow 2020-01-31 20:22:31 +01:00
Łukasz Magiera b6ba0ed47c fix pledgeReader with small sectors 2020-01-31 20:07:20 +01:00
Łukasz Magiera 87f7315f5a mod tidy 2020-01-31 19:57:28 +01:00
Łukasz Magiera 1b6ad6d2a1 worker: Fix transfer urls 2020-01-31 19:56:48 +01:00
Łukasz Magiera a62572bb76 Merge remote-tracking branch 'origin/master' into feat/new-sb-fs 2020-01-31 08:36:47 +01:00
Whyrusleeping f752770a47 Merge pull request #1185 from filecoin-project/fork/snowball
WIP, fork, fix slashing power calc
2020-01-30 21:31:37 -08:00
whyrusleeping d117cb61b6 change withUpdates to match fork height logic 2020-01-30 21:20:57 -08:00
whyrusleeping c071b2dc47 move back fork point, set new version 2020-01-30 21:15:00 -08:00
whyrusleeping d70ebd2ba5 some code review 2020-01-30 21:10:37 -08:00
whyrusleeping cda7f08b76 use less than, not equals 2020-01-30 21:05:41 -08:00
whyrusleeping 19a65319ee test and fix fork, add bigint parsing to lotus shed 2020-01-30 18:14:20 -08:00
WhyrusleepingandŁukasz Magiera 7402b14df3 Update chain/actors/actor_miner2.go
Co-Authored-By: Łukasz Magiera <magik6k@users.noreply.github.com>
2020-01-30 17:51:19 -08:00
whyrusleeping 0622eb7634 put miner changes behind a fork switch 2020-01-30 17:36:33 -08:00
Łukasz Magiera 95f344540e Fix tests 2020-01-31 02:27:38 +01:00
Łukasz Magiera ee9060aa14 Update sectorbuilder 2020-01-31 02:18:48 +01:00
Jakub Sztandera c6fd45727d Add state fork logic
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-30 17:17:34 -08:00
Jakub Sztandera cd27f5a4bc Merge pull request #1186 from filecoin-project/feat/lazy-param-box
build: Lazy ParametersJson
2020-01-30 16:37:38 -08:00
whyrusleeping 8ad8fa902d extra careful power checks on slashing 2020-01-30 16:36:18 -08:00
Jakub Sztandera 7861b5e6cb Merge pull request #1189 from filecoin-project/revert/rle-fix
Revert "Fix small bug in RLE"
2020-01-30 16:15:06 -08:00
Jakub Sztandera 70aaa8fc92 Revert "Fix small bug in RLE"
This reverts commit 6ed57ede6a.

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-30 16:14:32 -08:00
Jakub Sztandera e441b48ea7 Merge pull request #1187 from filecoin-project/fix/rle-bitcap
Fix small bug in RLE
2020-01-30 15:49:38 -08:00
Jakub Sztandera 6ed57ede6a Fix small bug in RLE
Thanks @frrist

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-30 15:18:54 -08:00
Łukasz Magiera aefc463586 build: Lazy ParametersJson 2020-01-30 23:50:24 +01:00
Jakub Sztandera f2340579a5 Fix power calculations
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-30 14:01:47 -08:00
Łukasz Magiera de5577ca70 chain: bisect cmd 2020-01-30 22:32:59 +01:00
Łukasz Magiera 316b11445e storageminer: Print fault data in info 2020-01-30 19:38:03 +01:00
Łukasz Magiera b42e481600 Merge pull request #1182 from zhy2006/master
fix:a bug of the power percentage in lotus-storage-miner info
2020-01-30 08:18:49 +01:00
Yang e5a48800ab fix:a bug of the power percentage in lotus-storage-miner info 2020-01-30 15:02:50 +08:00
Łukasz Magiera db50d01db9 Merge remote-tracking branch 'origin/master' into feat/new-sb-fs 2020-01-30 07:46:47 +01:00
Łukasz Magiera cec2085790 sealing: Fix pledgeReader 2020-01-30 07:41:30 +01:00
Łukasz Magiera 75ee71e35a Merge branch 'master' into feat/new-sb-fs 2020-01-30 07:39:52 +01:00
Whyrusleeping 7f9a3ac584 Merge pull request #1175 from filecoin-project/feat/fake-mine
Intoroduce advance-block command
2020-01-29 17:36:22 -08:00
Jakub Sztandera 1e9f293994 Return errors
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-29 17:35:32 -08:00
whyrusleeping b5f9a385ae add a method to query available multisig balance 2020-01-29 17:23:16 -08:00
Whyrusleeping f1114d3852 Merge pull request #1177 from filecoin-project/fix/fastpledge-math
Fix fast pledge math
2020-01-29 17:06:20 -08:00
Łukasz Magiera d27187b1de Fix fast pledge math 2020-01-30 02:01:10 +01:00
Łukasz Magiera 4aaa758543 fpost: better fault checks 2020-01-30 01:50:58 +01:00
Łukasz Magiera 03f07042ff fpost: print message apply result 2020-01-29 23:47:28 +01:00
Jakub Sztandera bcbfc931ba Intoroduce advance-block command
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-29 14:40:19 -08:00
Łukasz Magiera e2b2026fa5 actually call finalizeSector 2020-01-29 23:37:31 +01:00
Łukasz Magiera 4b8b79dbe0 sealing: FinalizeSector step 2020-01-29 22:25:06 +01:00
Whyrusleeping 9e5cc46638 Merge pull request #1158 from filecoin-project/feat/par-pledge
sealing: Parallel CommP calc in pledge sector
2020-01-29 12:15:22 -08:00
Łukasz Magiera ba542cf67a test fastPledgeCommitment 2020-01-29 21:01:20 +01:00
Łukasz Magiera 3f58ffe572 storageminer: New storage config 2020-01-29 20:53:45 +01:00
Łukasz Magiera 25f544f3db sealing: round parts in fastPledgeCommitment 2020-01-29 20:12:27 +01:00
Jim df747c8216 Merge pull request #1171 from filecoin-project/@jimmylee/docs-update-2
documentation: updates library schema with fedora instructions
2020-01-29 01:06:54 -08:00
jimmylee 53da298c4f documentation: updates library schema with fedora instructions 2020-01-29 01:04:43 -08:00
Jim 73c7f40ce3 Merge pull request #1170 from filecoin-project/@jimmylee/docs-update
lotus client list-deals
2020-01-29 00:52:53 -08:00
jimmylee 66bfadb71a documentation: adds lotus client list-deals for checking the status of a deal 2020-01-29 00:51:05 -08:00
Łukasz Magiera 5af64c53b6 initial sectorbuilder FS refactor integration 2020-01-29 00:08:02 +01:00
Łukasz Magiera b60860456d Merge pull request #1168 from filecoin-project/bugs/invalid-state-transition
planCommitting must handle SectorCommitFailed
2020-01-28 23:32:42 +01:00
Whyrusleeping 095a309aef Merge pull request #1160 from terorie/docker-more-binaries
Dockerfile: more binaries
2020-01-28 14:11:09 -08:00
Whyrusleeping 834383b7e5 Merge pull request #1159 from jsign/fixdocker
Dockerfile: fixes
2020-01-28 14:10:27 -08:00
laser 1cdf29244c write basic test affirming state change 2020-01-28 12:39:07 -08:00
laser cb665caf9e planCommitting must handle SectorCommitFailed
The SectorCommitFailed struct can be created from within Sealing#handleCommitting, and is created if actors.SerializeParams(params) produces an error or if m.api.MpoolPushMessage(ctx.Context(), msg) produces an error.
2020-01-28 11:46:26 -08:00
Jakub Sztandera eb4b85aea5 Merge pull request #1161 from filecoin-project/feat/chainwatch-challe
Add all challenges to chainwatch
2020-01-27 20:32:41 -08:00
Whyrusleeping 9c6c5aef5d Merge pull request #1162 from filecoin-project/feat/show-where-you-run
Add log to show where is the lotus running
2020-01-27 17:16:36 -08:00
Jakub Sztandera 050d552b9d Add log to show where is the lotus running
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-27 13:39:35 -08:00
Jakub Sztandera cf86bc6e23 fix insert
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-27 13:10:13 -08:00
Jakub Sztandera af61dfd8cd Fix order
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-27 13:09:00 -08:00
Jakub Sztandera 2a2a18a163 Add candidate
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-27 13:07:32 -08:00
Jakub Sztandera 29f3d6aa28 fix typo
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-27 13:03:09 -08:00
Jakub Sztandera 4379ff60f6 Create them table
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-27 13:01:24 -08:00
Jakub Sztandera a55a37c17b Pass the error
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-27 13:00:13 -08:00
Jakub Sztandera 5532093d58 Commit only once
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-27 12:59:07 -08:00
Jakub Sztandera 752be27815 Add all challenges to chainwatch
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-27 12:16:08 -08:00
Richard Patel 80903e86fa Dockerfile: more binaries 2020-01-27 20:02:56 +01:00
jsign dc076c6441 remove Dockerfile in base
Signed-off-by: jsign <jsign.uy@gmail.com>
2020-01-27 15:14:24 -03:00
jsign c6e63db7b4 rebase and reapply
Signed-off-by: jsign <jsign.uy@gmail.com>
2020-01-27 15:08:08 -03:00
jsign dff6e87ce9 Dockerfile: fixes
Signed-off-by: jsign <jsign.uy@gmail.com>
2020-01-27 15:06:41 -03:00
Whyrusleeping c765289da9 Merge pull request #1154 from eshon/misc/docker-directory
Create a directory for Docker files, merge ldoublewood's Docker
2020-01-27 10:04:10 -08:00
Whyrusleeping 2841edfb96 Merge pull request #1157 from filecoin-project/feat/cli/stategetdeal
cli: state get-deal
2020-01-25 10:17:49 -08:00
Łukasz Magiera c9c437cb3b sealing: Parallel CommP calc in pledge sector 2020-01-25 12:15:28 +01:00
Łukasz Magiera c0e317f829 cli: state get-deal 2020-01-25 11:41:17 +01:00
eshon 63a5124f57 Moving lotus PR 745 into a tools/dockers/ directory and adding some other examples 2020-01-24 23:24:54 +01:00
ldoublewood eda726ec34 restore Makefile 2020-01-24 23:24:54 +01:00
ldoublewood bab23aa7b1 add docker support 2020-01-24 23:24:54 +01:00
Whyrusleeping 7b258eddc4 Merge pull request #975 from filecoin-project/feat/cli-slashing
chain slash-consensus command
2020-01-24 14:14:03 -08:00
Jakub Sztandera 3bf0bd6ce9 Merge pull request #1153 from filecoin-project/feat/version-bump
Bump version following blocksync bugfixes
2020-01-24 14:10:17 -08:00
whyrusleeping 0ed981be19 Bump version following blocksync bugfixes 2020-01-24 13:58:57 -08:00
Łukasz Magiera 77113844a2 chain slash-consensus command 2020-01-24 13:58:06 -08:00
Whyrusleeping 9da4296e21 Merge pull request #745 from filcloud/fix/pr-docker
add docker support
2020-01-24 13:48:30 -08:00
Łukasz Magiera 9fc5f0cd9d Merge pull request #1124 from filecoin-project/feat/sector-recovery
sealing: Implement some common error states
2020-01-24 21:25:03 +01:00
Łukasz Magiera 2f2e7be12a sealing: docstrings for sanity-checks 2020-01-24 21:15:02 +01:00
Whyrusleeping 9892bf4379 Merge pull request #1147 from filecoin-project/upd/badger
Update badger
2020-01-24 11:49:36 -08:00
Whyrusleeping 351a683812 Merge pull request #1151 from filecoin-project/lotus-health-v2
refactor lotus-health agent for robustness
2020-01-24 11:44:47 -08:00
ognots 445b7f3388 refactor lotus-health agent for robustness
add retry logic when calls to API fail.
if API reconnects fail, restart lotus-daemon as it means lotus-daemon is likely unhealthy.

wait for lotus node's chain to sync during each check cycle, to avoid restarting lotus-daemon if needing to sync.

handle SIGTERM properly.

general cleanup and refactor of code, getting ready of unnecessary channels
2020-01-24 11:46:47 -05:00
Łukasz Magiera 9e95372e5d Merge pull request #1149 from filecoin-project/fix/peermgr-ts
make expand peers thread safe
2020-01-24 17:38:35 +01:00
Łukasz Magiera b5660b58b3 Merge remote-tracking branch 'origin/master' into feat/sector-recovery 2020-01-24 01:53:58 +01:00
Jakub Sztandera b472ea371a Merge pull request #1150 from filecoin-project/feat/sync-dashboard
Sync dashboard to what we have on stats.testnet.filecoin.io
2020-01-23 16:21:11 -08:00
Travis Person 6703bd2c71 Sync dashboard to what we have on stats.testnet.filecoin.io 2020-01-24 00:13:15 +00:00
Jakub Sztandera 36388de4e1 make expand peers thread safe
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-23 15:40:17 -08:00
Jakub Sztandera 10159ba1bb Merge pull request #1145 from filecoin-project/fix/blocksync-spam
limit blocksync response sizes
2020-01-23 15:21:01 -08:00
Jakub Sztandera 792a2cad82 limit blocksync response sizes
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-23 14:24:52 -08:00
Jakub Sztandera 7f1b12d29e Merge pull request #1137 from filecoin-project/feat/chainwatch-active-deals
chainwatch: Track deal activations
2020-01-23 13:21:39 -08:00
Jakub Sztandera 23b46a05f7 Update badger
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-23 12:46:32 -08:00
Jakub Sztandera cd14a5eb40 Merge pull request #1142 from filecoin-project/feat/bs2
Add incremental timeouts to blocksync fetching
2020-01-23 12:44:08 -08:00
Jakub Sztandera 2256e62648 Improve warning
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-23 12:39:23 -08:00
Jakub Sztandera 6b42a78c3f Cleanup
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-23 12:35:57 -08:00
Łukasz Magiera 6b2b22782b sealing: PreCommitFailed can go to SealFailed 2020-01-23 18:45:57 +01:00
Łukasz Magiera de52d3cadd sealing: Handlef for PreCommitFailed 2020-01-23 18:34:04 +01:00
Łukasz Magiera 7e43c40529 storageminer: Use tabwriter in sectors list 2020-01-23 17:15:45 +01:00
Łukasz Magiera df9dfa9d0c sealing: Don't infinite-loop on fatal errors 2020-01-23 17:11:58 +01:00
Łukasz Magiera 08a2e0f82c sealing: Errors are hard 2020-01-23 17:02:55 +01:00
Łukasz Magiera 01dc9c767e sealing: Error types that can actually be checked 2020-01-23 16:57:50 +01:00
Łukasz Magiera 67b441838b sealing: Actually call handleSealFailed 2020-01-23 16:47:33 +01:00
Łukasz Magiera 94f2948020 sealing: implement handler for sealFailed 2020-01-23 16:38:10 +01:00
Łukasz Magiera f5540195de worker: Fix progress bars 2020-01-23 15:38:36 +01:00
Łukasz Magiera 558e4c7669 Fix tests after sectorbuilder update 2020-01-23 15:33:28 +01:00
Łukasz Magiera c3a5da8586 storageminer: log flag for sector status 2020-01-23 15:18:05 +01:00
Łukasz Magiera 02c8ab7839 sealing: Check ticket expiration 2020-01-23 15:05:44 +01:00
Łukasz Magiera 8414569428 Merge remote-tracking branch 'origin/master' into feat/sector-recovery 2020-01-23 14:29:44 +01:00
Łukasz Magiera bd97eb98c5 Merge pull request #1141 from filecoin-project/fix/no-cgo
Make it buld without cgo
2020-01-23 14:10:56 +01:00
Łukasz Magiera e67fbda305 mod tidy 2020-01-23 13:29:43 +01:00
Łukasz Magiera 26e6bc32ee sealing: check deal expiration 2020-01-23 13:17:45 +01:00
Łukasz Magiera 11a6bff416 miner: Handle stop signal when sleeping 2020-01-23 11:10:42 +01:00
Łukasz Magiera e67ee227a3 sealing: Nonzero exit on commit isn't fatal 2020-01-23 11:02:20 +01:00
Łukasz Magiera f8ec1d9d22 Merge remote-tracking branch 'origin/master' into feat/sector-recovery 2020-01-23 10:52:10 +01:00
Łukasz Magiera 7fb3360d6f storage: Fix handing stop call 2020-01-23 10:46:46 +01:00
Jakub Sztandera cb35625a53 Remove log
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-22 16:04:33 -08:00
Jakub Sztandera 26870501a7 mod tidy
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-22 16:04:13 -08:00
Jakub Sztandera f5d061f34f Add incremental timeouts to blocksync fetching
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-22 15:57:42 -08:00
Jakub Sztandera 362fbbf913 Add blockheader_cgo file
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-22 15:55:52 -08:00
Jakub Sztandera f8d5f610b6 Merge pull request #1140 from filecoin-project/feat/profiling-work
wire up tracing into state tree flush, add pprof flag
2020-01-22 15:47:19 -08:00
Łukasz Magiera e43174f2af sealing: Not getting seal ticket isn't fatal 2020-01-22 22:16:45 +01:00
whyrusleeping 16523c2ef9 fixup tests 2020-01-22 12:56:40 -08:00
Łukasz Magiera d3a9006272 sealing: Wire up sector event log 2020-01-22 21:29:19 +01:00
Jakub Sztandera a404d535ee Make it buld without cgo
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-22 12:03:12 -08:00
whyrusleeping dcd01df2d3 wire up tracing into state tree flush, add pprof flag 2020-01-22 11:53:06 -08:00
Łukasz Magiera ba5a5d1248 sealing: wire up checkPieces and checkSeal 2020-01-22 20:47:29 +01:00
Łukasz Magiera 052b090bbf sealing: Fix planOne for global events 2020-01-22 19:30:56 +01:00
Łukasz Magiera 4654d9c192 chainwatch: Util routines / views 2020-01-22 16:12:47 +01:00
Łukasz Magiera 1e877eae86 sealing: Add Log field to SectorInfo 2020-01-22 03:41:39 +01:00
Łukasz Magiera 3c934ea21f Merge branch 'master' into feat/sector-recovery 2020-01-22 03:27:11 +01:00
Łukasz Magiera 52718e514c chainwatch: Track deal activations 2020-01-22 03:22:12 +01:00
Łukasz Magiera 4310cc23ce Merge pull request #1135 from filecoin-project/feat/listmsgs-cids
cli: state: --cids flag for list-messages
2020-01-22 00:33:53 +01:00
Łukasz Magiera bfb1cc6379 cli: state: --cids flag for list-messages 2020-01-21 23:54:01 +01:00
Jakub Sztandera cbfc675f4f Merge pull request #1120 from dtynn/fix/current_commit_flag
fix CurrentCommit in Makefile
2020-01-21 13:42:43 -08:00
Jakub Sztandera e7b5d678a9 rearange quotes
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-01-21 13:40:30 -08:00
ognots effacec817 range over right index to prevent bounds errors
the test scenario 'healthyHeadCheckWindow5' was causing index out of bounds errors.
the second range function in checkWindow was iterating over the incorrect slice of cids.
should be comparing latest items in slices first
2020-01-21 16:07:53 -05:00
Łukasz Magiera 3a89388039 Merge pull request #1134 from filecoin-project/feat/multisig-cli
add a CLI for multisig wallets
2020-01-21 21:05:41 +01:00
WhyrusleepingandŁukasz Magiera 3366c02a36 Update cli/multisig.go
Co-Authored-By: Łukasz Magiera <magik6k@users.noreply.github.com>
2020-01-21 11:52:59 -08:00
WhyrusleepingandŁukasz Magiera a26cc96a49 Update cli/multisig.go
Co-Authored-By: Łukasz Magiera <magik6k@users.noreply.github.com>
2020-01-21 11:52:50 -08:00
whyrusleeping 6d9ac84359 add a CLI for multisig wallets 2020-01-21 11:02:51 -08:00
Łukasz Magiera 882507e915 Merge pull request #1133 from filecoin-project/fix/build
Fix master build
2020-01-21 19:58:08 +01:00
Łukasz Magiera 08e1b52281 Fix master build 2020-01-21 19:51:17 +01:00
Łukasz Magiera cf153f89df Merge pull request #1131 from filecoin-project/feat/soft-map-cbg
cbor-gen: Soft struct-map unmarshaling
2020-01-21 19:44:39 +01:00
Łukasz Magiera d2401bc339 Update cbor-gen, error on unknown fields 2020-01-21 17:28:55 +01:00
Łukasz Magiera fd0bfc8777 Merge pull request #1089 from filecoin-project/feat/state-call-cmd
implement state call command for easy method calling
2020-01-21 17:16:54 +01:00
Łukasz Magiera 7b295d7bb0 Merge pull request #1115 from filecoin-project/feat/chainwatch-json-states
chainwatch: Store json states
2020-01-21 17:15:33 +01:00
Łukasz Magiera b6563ffc29 Merge pull request #1123 from filecoin-project/fix/jsonrpc-chclose-panic
jsonrpc: Fix channel closing race
2020-01-21 17:14:55 +01:00
Jakub Sztandera 2594ff6233 Merge pull request #1121 from filecoin-project/fix/mpool-stat-errs
mpool stat: Don't exit on StateGetActor error
2020-01-21 17:13:57 +01:00
Jakub Sztandera 807d803a81 Merge pull request #1130 from filecoin-project/fix/fpost-no-candidates
fpost: More logging
2020-01-21 17:07:22 +01:00
Łukasz Magiera 2076cb106d cobr-gen: Soft struct-map unmarshaling 2020-01-21 17:05:10 +01:00
Łukasz Magiera 5b304fa20a fpost: More logging 2020-01-21 16:01:42 +01:00
Łukasz Magiera fbc0330fa8 jsonrpc: Fix channel registration deadlock 2020-01-21 14:48:17 +01:00
Łukasz Magiera f5bfaff003 Merge pull request #1128 from filecoin-project/feat/chain-export-2
Implement chain import and exporting
2020-01-21 03:35:24 +01:00
Łukasz Magiera eac17a8328 mod tidy 2020-01-21 03:35:03 +01:00
Łukasz Magiera f9c9316990 Merge pull request #1127 from filecoin-project/bug/lotus-health
fixes health agent bug
2020-01-21 03:29:51 +01:00
whyrusleeping d9f5f6e2c6 add flag to halt after chain importing 2020-01-20 17:58:58 -08:00
whyrusleeping 955b755055 wire up importing 2020-01-20 17:53:55 -08:00
ognots 0c6e4c6c40 fixes health agent bug
was passing wrong variable to updateWindow function argument.
also updates duplicate function comment
2020-01-20 20:34:13 -05:00
whyrusleeping 57812fc61d chain export should work now 2020-01-20 15:51:28 -08:00
whyrusleeping 62f05d4c14 WIP: chain export 2020-01-20 15:51:28 -08:00
Łukasz Magiera e4de5c55ac sealing: Some state renaming 2020-01-20 23:04:46 +01:00
Łukasz Magiera efaf2c720b sealing: WIP SectorInfo sanity checks 2020-01-20 23:04:27 +01:00
Łukasz Magiera d1f419c9d1 jsonrpc: Fix channel closing race 2020-01-20 19:21:16 +01:00
Łukasz Magiera c5ece2a892 Merge pull request #1119 from dtynn/fix/some_sealing_problems
small fixes
2020-01-20 17:05:14 +01:00
Łukasz Magiera 7712d97270 mpool stat: Don't exit on StateGetActor error 2020-01-20 16:18:02 +01:00
dtynn 8e90d5fb17 fix CurrentCommit in Makefile 2020-01-20 18:22:42 +08:00
dtynn b2fcca87ff small fixes 2020-01-20 16:23:56 +08:00
Łukasz Magiera a46a9bb42e chainwatch: Store deals 2020-01-20 01:49:52 +01:00
Łukasz Magiera 62d661f898 chainwatch: Store json states 2020-01-19 22:48:19 +01:00
Łukasz Magiera 4436148fa1 Merge pull request #1117 from filecoin-project/fix/dont-override-loglvl
lotuslog: Don't override log levels
2020-01-19 21:38:36 +01:00
Łukasz Magiera 3886e050b0 lotuslog: don't override log levels 2020-01-19 21:18:35 +01:00
Łukasz Magiera ff4b0c8f5d Merge pull request #1110 from filecoin-project/fix/nil-newts-fpost-panic
fpost: Don't panic with nil new tipset
2020-01-19 21:17:51 +01:00
Łukasz Magiera be2d138aac fpost: Don't panic with nil new tipset 2020-01-18 16:00:22 +01:00
whyrusleeping 9e956ff9f4 handle integers and peer IDs 2020-01-17 18:27:29 -08:00
whyrusleeping 0a45e97699 implement state call command for easy method calling 2020-01-17 18:27:29 -08:00
ldoublewood 86f078dbea restore Makefile 2019-12-05 14:47:23 +08:00
ldoublewood f739b7e377 add docker support 2019-12-05 11:31:32 +08:00
169 changed files with 6767 additions and 1928 deletions
+94 -5
View File
@@ -7,6 +7,9 @@ executors:
docker: docker:
- image: circleci/golang:1.13 - image: circleci/golang:1.13
resource_class: 2xlarge resource_class: 2xlarge
ubuntu:
docker:
- image: ubuntu:19.10
commands: commands:
install-deps: install-deps:
@@ -24,6 +27,8 @@ commands:
description: is a darwin build environment? description: is a darwin build environment?
type: boolean type: boolean
steps: steps:
- checkout
- git_fetch_all_tags
- checkout - checkout
- when: - when:
condition: << parameters.linux >> condition: << parameters.linux >>
@@ -46,7 +51,27 @@ commands:
key: 'v20-1k-lotus-params' key: 'v20-1k-lotus-params'
paths: paths:
- /var/tmp/filecoin-proof-parameters/ - /var/tmp/filecoin-proof-parameters/
install_ipfs:
steps:
- run: |
apt update
apt install -y wget
wget https://github.com/ipfs/go-ipfs/releases/download/v0.4.22/go-ipfs_v0.4.22_linux-amd64.tar.gz
wget https://github.com/ipfs/go-ipfs/releases/download/v0.4.22/go-ipfs_v0.4.22_linux-amd64.tar.gz.sha512
if [ "$(sha512sum go-ipfs_v0.4.22_linux-amd64.tar.gz)" != "$(cat go-ipfs_v0.4.22_linux-amd64.tar.gz.sha512)" ]
then
echo "ipfs failed checksum check"
exit 1
fi
tar -xf go-ipfs_v0.4.22_linux-amd64.tar.gz
mv go-ipfs/ipfs /usr/local/bin/ipfs
chmod +x /usr/local/bin/ipfs
git_fetch_all_tags:
steps:
- run:
name: fetch all tags
command: |
git fetch --all
jobs: jobs:
mod-tidy-check: mod-tidy-check:
@@ -74,6 +99,13 @@ jobs:
path: lotus path: lotus
- store_artifacts: - store_artifacts:
path: lotus-storage-miner path: lotus-storage-miner
- store_artifacts:
path: lotus-seal-worker
- run: mkdir linux && mv lotus lotus-storage-miner lotus-seal-worker linux/
- persist_to_workspace:
root: "."
paths:
- linux
test: &test test: &test
description: | description: |
@@ -153,7 +185,7 @@ jobs:
- "~/go/src/github.com" - "~/go/src/github.com"
- "~/go/src/golang.org" - "~/go/src/golang.org"
test-short: test-short:
<<: *test <<: *test
build-macos: build-macos:
@@ -196,6 +228,13 @@ jobs:
path: lotus path: lotus
- store_artifacts: - store_artifacts:
path: lotus-storage-miner path: lotus-storage-miner
- store_artifacts:
path: lotus-seal-worker
- run: mkdir darwin && mv lotus lotus-storage-miner lotus-seal-worker darwin/
- persist_to_workspace:
root: "."
paths:
- darwin
- save_cache: - save_cache:
name: save cargo cache name: save cargo cache
key: v3-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.sum" }} key: v3-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.sum" }}
@@ -246,6 +285,26 @@ jobs:
lint-all: lint-all:
<<: *lint <<: *lint
publish:
description: publish binary artifacts
executor: ubuntu
steps:
- run:
name: Install git jq curl
command: apt update && apt install -y git jq curl
- checkout
- git_fetch_all_tags
- checkout
- install_ipfs
- attach_workspace:
at: "."
- run:
name: Create bundles
command: ./scripts/build-bundle.sh
- run:
name: Publish release
command: ./scripts/publish-release.sh
workflows: workflows:
version: 2.1 version: 2.1
@@ -255,8 +314,38 @@ workflows:
args: "--new-from-rev origin/master" args: "--new-from-rev origin/master"
- test: - test:
codecov-upload: true codecov-upload: true
- mod-tidy-check
- test-short: - test-short:
go-test-flags: "--timeout 10m --short" go-test-flags: "--timeout 10m --short"
- mod-tidy-check filters:
- build-all tags:
- build-macos only:
- /^v\d+\.\d+\.\d+$/
- build-all:
requires:
- test-short
filters:
tags:
only:
- /^v\d+\.\d+\.\d+$/
- build-macos:
requires:
- test-short
filters:
branches:
ignore:
- /.*/
tags:
only:
- /^v\d+\.\d+\.\d+$/
- publish:
requires:
- build-all
- build-macos
filters:
branches:
ignore:
- /.*/
tags:
only:
- /^v\d+\.\d+\.\d+$/
+1
View File
@@ -0,0 +1 @@
.gitignore
+4
View File
@@ -2,6 +2,7 @@
/lotus-storage-miner /lotus-storage-miner
/lotus-seal-worker /lotus-seal-worker
/lotus-seed /lotus-seed
/lotus-health
/pond /pond
/townhall /townhall
/fountain /fountain
@@ -25,6 +26,9 @@ build/paramfetch.sh
/blocks.svg /blocks.svg
/chainwatch /chainwatch
/chainwatch.db /chainwatch.db
/bundle
/darwin
/linux
*-fuzz.zip *-fuzz.zip
/chain/types/work_msg/ /chain/types/work_msg/
+2 -1
View File
@@ -1,7 +1,8 @@
linters: linters:
disable-all: true disable-all: true
enable: enable:
- vet - gofmt
- govet
- goimports - goimports
- misspell - misspell
- goconst - goconst
+1 -1
View File
@@ -14,7 +14,7 @@ MODULES:=
CLEAN:= CLEAN:=
BINS:= BINS:=
GOFLAGS+=-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))' GOFLAGS+=-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))"
## FFI ## FFI
+1 -1
View File
@@ -2,7 +2,7 @@
# Project Lotus - 莲 # Project Lotus - 莲
Lotus is an experimental implementation of the Filecoin Distributed Storage Network. For more details about Filecoin, check out the [Filecoin Spec](https://github.com/filecoin-project/specs). 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 ## Development
+3
View File
@@ -29,6 +29,9 @@ type Common interface {
// Version provides information about API provider // Version provides information about API provider
Version(context.Context) (Version, error) Version(context.Context) (Version, error)
LogList(context.Context) ([]string, error)
LogSetLevel(context.Context, string, string) error
} }
// Version provides various build-time information // Version provides various build-time information
+40 -29
View File
@@ -4,11 +4,11 @@ import (
"context" "context"
"time" "time"
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/ipfs/go-filestore" "github.com/ipfs/go-filestore"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@@ -30,23 +30,26 @@ type FullNode interface {
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error) ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error) ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error)
ChainGetParentMessages(context.Context, cid.Cid) ([]Message, error) ChainGetParentMessages(context.Context, cid.Cid) ([]Message, error)
ChainGetTipSetByHeight(context.Context, uint64, *types.TipSet) (*types.TipSet, error) ChainGetTipSetByHeight(context.Context, uint64, types.TipSetKey) (*types.TipSet, error)
ChainReadObj(context.Context, cid.Cid) ([]byte, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error)
ChainSetHead(context.Context, *types.TipSet) error ChainHasObj(context.Context, cid.Cid) (bool, error)
ChainSetHead(context.Context, types.TipSetKey) error
ChainGetGenesis(context.Context) (*types.TipSet, error) ChainGetGenesis(context.Context) (*types.TipSet, error)
ChainTipSetWeight(context.Context, *types.TipSet) (types.BigInt, error) ChainTipSetWeight(context.Context, types.TipSetKey) (types.BigInt, error)
ChainGetNode(ctx context.Context, p string) (interface{}, error) ChainGetNode(ctx context.Context, p string) (interface{}, error)
ChainGetMessage(context.Context, cid.Cid) (*types.Message, error) ChainGetMessage(context.Context, cid.Cid) (*types.Message, error)
ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*store.HeadChange, error) ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*store.HeadChange, error)
ChainExport(context.Context, types.TipSetKey) (<-chan []byte, error)
// syncer // syncer
SyncState(context.Context) (*SyncState, error) SyncState(context.Context) (*SyncState, error)
SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error
SyncIncomingBlocks(ctx context.Context) (<-chan *types.BlockHeader, error) SyncIncomingBlocks(ctx context.Context) (<-chan *types.BlockHeader, error)
SyncMarkBad(ctx context.Context, bcid cid.Cid) error SyncMarkBad(ctx context.Context, bcid cid.Cid) error
SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error)
// messages // messages
MpoolPending(context.Context, *types.TipSet) ([]*types.SignedMessage, error) MpoolPending(context.Context, types.TipSetKey) ([]*types.SignedMessage, error)
MpoolPush(context.Context, *types.SignedMessage) (cid.Cid, error) MpoolPush(context.Context, *types.SignedMessage) (cid.Cid, error)
MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error) // get nonce, sign, push MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error) // get nonce, sign, push
MpoolGetNonce(context.Context, address.Address) (uint64, error) MpoolGetNonce(context.Context, address.Address) (uint64, error)
@@ -56,7 +59,7 @@ type FullNode interface {
// miner // miner
MinerCreateBlock(context.Context, address.Address, *types.TipSet, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) MinerCreateBlock(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error)
// // UX ? // // UX ?
@@ -94,32 +97,35 @@ type FullNode interface {
//ClientListAsks() []Ask //ClientListAsks() []Ask
// if tipset is nil, we'll use heaviest // if tipset is nil, we'll use heaviest
StateCall(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) StateCall(context.Context, *types.Message, types.TipSetKey) (*MethodCall, error)
StateReplay(context.Context, *types.TipSet, cid.Cid) (*ReplayResults, error) StateReplay(context.Context, types.TipSetKey, cid.Cid) (*ReplayResults, error)
StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
StateReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*ActorState, error) StateReadState(ctx context.Context, act *types.Actor, tsk types.TipSetKey) (*ActorState, error)
StateListMessages(ctx context.Context, match *types.Message, ts *types.TipSet, toht uint64) ([]cid.Cid, error) StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht uint64) ([]cid.Cid, error)
StateMinerSectors(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error) StateMinerSectors(context.Context, address.Address, types.TipSetKey) ([]*ChainSectorInfo, error)
StateMinerProvingSet(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error) StateMinerProvingSet(context.Context, address.Address, types.TipSetKey) ([]*ChainSectorInfo, error)
StateMinerPower(context.Context, address.Address, *types.TipSet) (MinerPower, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (MinerPower, error)
StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error) StateMinerWorker(context.Context, address.Address, types.TipSetKey) (address.Address, error)
StateMinerPeerID(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) StateMinerPeerID(ctx context.Context, m address.Address, tsk types.TipSetKey) (peer.ID, error)
StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, tsk types.TipSetKey) (uint64, error)
StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (uint64, error) StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (uint64, error)
StatePledgeCollateral(context.Context, *types.TipSet) (types.BigInt, error) StateMinerFaults(context.Context, address.Address, types.TipSetKey) ([]uint64, error)
StatePledgeCollateral(context.Context, types.TipSetKey) (types.BigInt, error)
StateWaitMsg(context.Context, cid.Cid) (*MsgWait, error) StateWaitMsg(context.Context, cid.Cid) (*MsgWait, error)
StateListMiners(context.Context, *types.TipSet) ([]address.Address, error) StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error)
StateListActors(context.Context, *types.TipSet) ([]address.Address, error) StateListActors(context.Context, types.TipSetKey) ([]address.Address, error)
StateMarketBalance(context.Context, address.Address, *types.TipSet) (actors.StorageParticipantBalance, error) StateMarketBalance(context.Context, address.Address, types.TipSetKey) (actors.StorageParticipantBalance, error)
StateMarketParticipants(context.Context, *types.TipSet) (map[string]actors.StorageParticipantBalance, error) StateMarketParticipants(context.Context, types.TipSetKey) (map[string]actors.StorageParticipantBalance, error)
StateMarketDeals(context.Context, *types.TipSet) (map[string]actors.OnChainDeal, error) StateMarketDeals(context.Context, types.TipSetKey) (map[string]actors.OnChainDeal, error)
StateMarketStorageDeal(context.Context, uint64, *types.TipSet) (*actors.OnChainDeal, error) StateMarketStorageDeal(context.Context, uint64, types.TipSetKey) (*actors.OnChainDeal, error)
StateLookupID(context.Context, address.Address, *types.TipSet) (address.Address, error) StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error)
StateChangedActors(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) StateChangedActors(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error)
StateGetReceipt(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateMinerSectorCount(context.Context, address.Address, *types.TipSet) (MinerSectors, error) StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error)
StateCompute(context.Context, uint64, []*types.Message, *types.TipSet) (cid.Cid, error) StateCompute(context.Context, uint64, []*types.Message, types.TipSetKey) (cid.Cid, error)
MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
MarketEnsureAvailable(context.Context, address.Address, types.BigInt) error MarketEnsureAvailable(context.Context, address.Address, types.BigInt) error
// MarketFreeBalance // MarketFreeBalance
@@ -270,6 +276,11 @@ type ReplayResults struct {
Error string Error string
} }
type MethodCall struct {
types.MessageReceipt
Error string
}
type ActiveSync struct { type ActiveSync struct {
Base *types.TipSet Base *types.TipSet
Target *types.TipSet Target *types.TipSet
+17 -4
View File
@@ -19,14 +19,14 @@ const (
Unsealed // sealing / queued Unsealed // sealing / queued
PreCommitting // on chain pre-commit PreCommitting // on chain pre-commit
PreCommitted // waiting for seed WaitSeed // waiting for seed
Committing Committing
CommitWait // waiting for message to land on chain CommitWait // waiting for message to land on chain
FinalizeSector
Proving Proving
_ // reserved _ // reserved
_ _
_ _
_
// recovery handling // recovery handling
// Reseal // Reseal
@@ -45,7 +45,7 @@ const (
PreCommitFailed PreCommitFailed
SealCommitFailed SealCommitFailed
CommitFailed CommitFailed
_ PackingFailed
_ _
_ _
_ _
@@ -61,15 +61,17 @@ var SectorStates = []string{
Packing: "Packing", Packing: "Packing",
Unsealed: "Unsealed", Unsealed: "Unsealed",
PreCommitting: "PreCommitting", PreCommitting: "PreCommitting",
PreCommitted: "PreCommitted", WaitSeed: "WaitSeed",
Committing: "Committing", Committing: "Committing",
CommitWait: "CommitWait", CommitWait: "CommitWait",
FinalizeSector: "FinalizeSector",
Proving: "Proving", Proving: "Proving",
SealFailed: "SealFailed", SealFailed: "SealFailed",
PreCommitFailed: "PreCommitFailed", PreCommitFailed: "PreCommitFailed",
SealCommitFailed: "SealCommitFailed", SealCommitFailed: "SealCommitFailed",
CommitFailed: "CommitFailed", CommitFailed: "CommitFailed",
PackingFailed: "PackingFailed",
FailedUnrecoverable: "FailedUnrecoverable", FailedUnrecoverable: "FailedUnrecoverable",
@@ -107,6 +109,15 @@ type StorageMiner interface {
WorkerDone(ctx context.Context, task uint64, res sectorbuilder.SealRes) error WorkerDone(ctx context.Context, task uint64, res sectorbuilder.SealRes) error
} }
type SectorLog struct {
Kind string
Timestamp uint64
Trace string
Message string
}
type SectorInfo struct { type SectorInfo struct {
SectorID uint64 SectorID uint64
State SectorState State SectorState
@@ -119,6 +130,8 @@ type SectorInfo struct {
Retries uint64 Retries uint64
LastErr string LastErr string
Log []SectorLog
} }
type SealedRef struct { type SealedRef struct {
+61
View File
@@ -0,0 +1,61 @@
package apibstore
import (
"context"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
blockstore "github.com/ipfs/go-ipfs-blockstore"
"golang.org/x/xerrors"
)
type ChainIO interface {
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
ChainHasObj(context.Context, cid.Cid) (bool, error)
}
type apiBStore struct {
api ChainIO
}
func (a *apiBStore) DeleteBlock(cid.Cid) error {
return xerrors.New("not supported")
}
func (a *apiBStore) Has(c cid.Cid) (bool, error) {
return a.api.ChainHasObj(context.TODO(), c)
}
func (a *apiBStore) Get(c cid.Cid) (blocks.Block, error) {
bb, err := a.api.ChainReadObj(context.TODO(), c)
if err != nil {
return nil, err
}
return blocks.NewBlockWithCid(bb, c)
}
func (a *apiBStore) GetSize(c cid.Cid) (int, error) {
bb, err := a.api.ChainReadObj(context.TODO(), c)
if err != nil {
return 0, err
}
return len(bb), nil
}
func (a *apiBStore) Put(blocks.Block) error {
return xerrors.New("not supported")
}
func (a *apiBStore) PutMany([]blocks.Block) error {
return xerrors.New("not supported")
}
func (a *apiBStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
return nil, xerrors.New("not supported")
}
func (a *apiBStore) HashOnRead(enabled bool) {
return
}
var _ blockstore.Blockstore = &apiBStore{}
+120 -83
View File
@@ -32,6 +32,9 @@ type CommonStruct struct {
ID func(context.Context) (peer.ID, error) `perm:"read"` ID func(context.Context) (peer.ID, error) `perm:"read"`
Version func(context.Context) (api.Version, 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"`
} }
} }
@@ -48,27 +51,30 @@ type FullNodeStruct struct {
ChainGetBlockMessages func(context.Context, cid.Cid) (*api.BlockMessages, error) `perm:"read"` ChainGetBlockMessages func(context.Context, cid.Cid) (*api.BlockMessages, error) `perm:"read"`
ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"` ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"`
ChainGetTipSetByHeight func(context.Context, uint64, *types.TipSet) (*types.TipSet, error) `perm:"read"` ChainGetTipSetByHeight func(context.Context, uint64, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"` ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"` ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"`
ChainSetHead func(context.Context, types.TipSetKey) error `perm:"admin"`
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"` ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainTipSetWeight func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"` ChainTipSetWeight func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"`
ChainGetNode func(ctx context.Context, p string) (interface{}, error) `perm:"read"` ChainGetNode func(ctx context.Context, p string) (interface{}, error) `perm:"read"`
ChainGetMessage func(context.Context, cid.Cid) (*types.Message, error) `perm:"read"` ChainGetMessage func(context.Context, cid.Cid) (*types.Message, error) `perm:"read"`
ChainGetPath func(context.Context, types.TipSetKey, types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"` ChainGetPath func(context.Context, types.TipSetKey, types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"`
ChainExport func(context.Context, types.TipSetKey) (<-chan []byte, error) `perm:"read"`
SyncState func(context.Context) (*api.SyncState, error) `perm:"read"` SyncState func(context.Context) (*api.SyncState, error) `perm:"read"`
SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"` SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"`
SyncIncomingBlocks func(ctx context.Context) (<-chan *types.BlockHeader, error) `perm:"read"` SyncIncomingBlocks func(ctx context.Context) (<-chan *types.BlockHeader, error) `perm:"read"`
SyncMarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"` SyncMarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"`
SyncCheckBad func(ctx context.Context, bcid cid.Cid) (string, error) `perm:"read"`
MpoolPending func(context.Context, *types.TipSet) ([]*types.SignedMessage, error) `perm:"read"` MpoolPending func(context.Context, types.TipSetKey) ([]*types.SignedMessage, error) `perm:"read"`
MpoolPush func(context.Context, *types.SignedMessage) (cid.Cid, error) `perm:"write"` MpoolPush func(context.Context, *types.SignedMessage) (cid.Cid, error) `perm:"write"`
MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"` MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"` MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"` MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"`
MinerCreateBlock func(context.Context, address.Address, *types.TipSet, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) `perm:"write"` MinerCreateBlock func(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) `perm:"write"`
WalletNew func(context.Context, string) (address.Address, error) `perm:"write"` WalletNew func(context.Context, string) (address.Address, error) `perm:"write"`
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"` WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
@@ -91,31 +97,34 @@ type FullNodeStruct struct {
ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, path string) error `perm:"admin"` ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, path string) error `perm:"admin"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) `perm:"read"` ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) `perm:"read"` StateMinerSectors func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) `perm:"read"` StateMinerProvingSet func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, *types.TipSet) (api.MinerPower, error) `perm:"read"` StateMinerPower func(context.Context, address.Address, types.TipSetKey) (api.MinerPower, error) `perm:"read"`
StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"` StateMinerWorker func(context.Context, address.Address, types.TipSetKey) (address.Address, error) `perm:"read"`
StateMinerPeerID func(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) `perm:"read"` StateMinerPeerID func(ctx context.Context, m address.Address, tsk types.TipSetKey) (peer.ID, error) `perm:"read"`
StateMinerElectionPeriodStart func(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) `perm:"read"` StateMinerElectionPeriodStart func(ctx context.Context, actor address.Address, tsk types.TipSetKey) (uint64, error) `perm:"read"`
StateMinerSectorSize func(context.Context, address.Address, *types.TipSet) (uint64, error) `perm:"read"` StateMinerSectorSize func(context.Context, address.Address, types.TipSetKey) (uint64, error) `perm:"read"`
StateCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"` StateMinerFaults func(context.Context, address.Address, types.TipSetKey) ([]uint64, error) `perm:"read"`
StateReplay func(context.Context, *types.TipSet, cid.Cid) (*api.ReplayResults, error) `perm:"read"` StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.MethodCall, error) `perm:"read"`
StateGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"` StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.ReplayResults, error) `perm:"read"`
StateReadState func(context.Context, *types.Actor, *types.TipSet) (*api.ActorState, error) `perm:"read"` StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"`
StatePledgeCollateral func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"` StateReadState func(context.Context, *types.Actor, 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.MsgWait, error) `perm:"read"` StateWaitMsg func(context.Context, cid.Cid) (*api.MsgWait, error) `perm:"read"`
StateListMiners func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"` StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
StateListActors func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"` StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
StateMarketBalance func(context.Context, address.Address, *types.TipSet) (actors.StorageParticipantBalance, error) `perm:"read"` StateMarketBalance func(context.Context, address.Address, types.TipSetKey) (actors.StorageParticipantBalance, error) `perm:"read"`
StateMarketParticipants func(context.Context, *types.TipSet) (map[string]actors.StorageParticipantBalance, error) `perm:"read"` StateMarketParticipants func(context.Context, types.TipSetKey) (map[string]actors.StorageParticipantBalance, error) `perm:"read"`
StateMarketDeals func(context.Context, *types.TipSet) (map[string]actors.OnChainDeal, error) `perm:"read"` StateMarketDeals func(context.Context, types.TipSetKey) (map[string]actors.OnChainDeal, error) `perm:"read"`
StateMarketStorageDeal func(context.Context, uint64, *types.TipSet) (*actors.OnChainDeal, error) `perm:"read"` StateMarketStorageDeal func(context.Context, uint64, types.TipSetKey) (*actors.OnChainDeal, error) `perm:"read"`
StateLookupID func(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) `perm:"read"` StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) `perm:"read"`
StateChangedActors func(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) `perm:"read"` StateChangedActors func(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) `perm:"read"`
StateGetReceipt func(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"` StateGetReceipt func(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"`
StateMinerSectorCount func(context.Context, address.Address, *types.TipSet) (api.MinerSectors, error) `perm:"read"` StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"`
StateListMessages func(ctx context.Context, match *types.Message, ts *types.TipSet, toht uint64) ([]cid.Cid, error) `perm:"read"` StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht uint64) ([]cid.Cid, error) `perm:"read"`
StateCompute func(context.Context, uint64, []*types.Message, *types.TipSet) (cid.Cid, error) `perm:"read"` StateCompute func(context.Context, uint64, []*types.Message, types.TipSetKey) (cid.Cid, error) `perm:"read"`
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
MarketEnsureAvailable func(context.Context, address.Address, types.BigInt) error `perm:"sign"` MarketEnsureAvailable func(context.Context, address.Address, types.BigInt) error `perm:"sign"`
@@ -135,8 +144,8 @@ type FullNodeStruct struct {
} }
} }
func (c *FullNodeStruct) StateMinerSectorCount(ctx context.Context, addr address.Address, ts *types.TipSet) (api.MinerSectors, error) { func (c *FullNodeStruct) StateMinerSectorCount(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MinerSectors, error) {
return c.Internal.StateMinerSectorCount(ctx, addr, ts) return c.Internal.StateMinerSectorCount(ctx, addr, tsk)
} }
type StorageMinerStruct struct { type StorageMinerStruct struct {
@@ -198,6 +207,14 @@ func (c *CommonStruct) Version(ctx context.Context) (api.Version, error) {
return c.Internal.Version(ctx) return c.Internal.Version(ctx)
} }
func (c *CommonStruct) LogList(ctx context.Context) ([]string, error) {
return c.Internal.LogList(ctx)
}
func (c *CommonStruct) LogSetLevel(ctx context.Context, group, level string) error {
return c.Internal.LogSetLevel(ctx, group, level)
}
func (c *FullNodeStruct) ClientListImports(ctx context.Context) ([]api.Import, error) { func (c *FullNodeStruct) ClientListImports(ctx context.Context) ([]api.Import, error) {
return c.Internal.ClientListImports(ctx) return c.Internal.ClientListImports(ctx)
} }
@@ -233,8 +250,8 @@ func (c *FullNodeStruct) ClientQueryAsk(ctx context.Context, p peer.ID, miner ad
return c.Internal.ClientQueryAsk(ctx, p, miner) return c.Internal.ClientQueryAsk(ctx, p, miner)
} }
func (c *FullNodeStruct) MpoolPending(ctx context.Context, ts *types.TipSet) ([]*types.SignedMessage, error) { func (c *FullNodeStruct) MpoolPending(ctx context.Context, tsk types.TipSetKey) ([]*types.SignedMessage, error) {
return c.Internal.MpoolPending(ctx, ts) return c.Internal.MpoolPending(ctx, tsk)
} }
func (c *FullNodeStruct) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) { func (c *FullNodeStruct) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) {
@@ -249,7 +266,7 @@ func (c *FullNodeStruct) MpoolSub(ctx context.Context) (<-chan api.MpoolUpdate,
return c.Internal.MpoolSub(ctx) return c.Internal.MpoolSub(ctx)
} }
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) { func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base types.TipSetKey, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) {
return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts) return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts)
} }
@@ -261,8 +278,8 @@ func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, pts types.TipSe
return c.Internal.ChainGetRandomness(ctx, pts, round) return c.Internal.ChainGetRandomness(ctx, pts, round)
} }
func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h uint64, ts *types.TipSet) (*types.TipSet, error) { func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h uint64, tsk types.TipSetKey) (*types.TipSet, error) {
return c.Internal.ChainGetTipSetByHeight(ctx, h, ts) return c.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
} }
func (c *FullNodeStruct) WalletNew(ctx context.Context, typ string) (address.Address, error) { func (c *FullNodeStruct) WalletNew(ctx context.Context, typ string) (address.Address, error) {
@@ -337,16 +354,20 @@ func (c *FullNodeStruct) ChainReadObj(ctx context.Context, obj cid.Cid) ([]byte,
return c.Internal.ChainReadObj(ctx, obj) return c.Internal.ChainReadObj(ctx, obj)
} }
func (c *FullNodeStruct) ChainSetHead(ctx context.Context, ts *types.TipSet) error { func (c *FullNodeStruct) ChainHasObj(ctx context.Context, o cid.Cid) (bool, error) {
return c.Internal.ChainSetHead(ctx, ts) return c.Internal.ChainHasObj(ctx, o)
}
func (c *FullNodeStruct) ChainSetHead(ctx context.Context, tsk types.TipSetKey) error {
return c.Internal.ChainSetHead(ctx, tsk)
} }
func (c *FullNodeStruct) ChainGetGenesis(ctx context.Context) (*types.TipSet, error) { func (c *FullNodeStruct) ChainGetGenesis(ctx context.Context) (*types.TipSet, error) {
return c.Internal.ChainGetGenesis(ctx) return c.Internal.ChainGetGenesis(ctx)
} }
func (c *FullNodeStruct) ChainTipSetWeight(ctx context.Context, ts *types.TipSet) (types.BigInt, error) { func (c *FullNodeStruct) ChainTipSetWeight(ctx context.Context, tsk types.TipSetKey) (types.BigInt, error) {
return c.Internal.ChainTipSetWeight(ctx, ts) return c.Internal.ChainTipSetWeight(ctx, tsk)
} }
func (c *FullNodeStruct) ChainGetNode(ctx context.Context, p string) (interface{}, error) { func (c *FullNodeStruct) ChainGetNode(ctx context.Context, p string) (interface{}, error) {
@@ -361,6 +382,10 @@ func (c *FullNodeStruct) ChainGetPath(ctx context.Context, from types.TipSetKey,
return c.Internal.ChainGetPath(ctx, from, to) return c.Internal.ChainGetPath(ctx, from, to)
} }
func (c *FullNodeStruct) ChainExport(ctx context.Context, tsk types.TipSetKey) (<-chan []byte, error) {
return c.Internal.ChainExport(ctx, tsk)
}
func (c *FullNodeStruct) SyncState(ctx context.Context) (*api.SyncState, error) { func (c *FullNodeStruct) SyncState(ctx context.Context) (*api.SyncState, error) {
return c.Internal.SyncState(ctx) return c.Internal.SyncState(ctx)
} }
@@ -377,99 +402,111 @@ func (c *FullNodeStruct) SyncMarkBad(ctx context.Context, bcid cid.Cid) error {
return c.Internal.SyncMarkBad(ctx, bcid) return c.Internal.SyncMarkBad(ctx, bcid)
} }
func (c *FullNodeStruct) StateMinerSectors(ctx context.Context, addr address.Address, ts *types.TipSet) ([]*api.ChainSectorInfo, error) { func (c *FullNodeStruct) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) {
return c.Internal.StateMinerSectors(ctx, addr, ts) return c.Internal.SyncCheckBad(ctx, bcid)
} }
func (c *FullNodeStruct) StateMinerProvingSet(ctx context.Context, addr address.Address, ts *types.TipSet) ([]*api.ChainSectorInfo, error) { func (c *FullNodeStruct) StateMinerSectors(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.ChainSectorInfo, error) {
return c.Internal.StateMinerProvingSet(ctx, addr, ts) return c.Internal.StateMinerSectors(ctx, addr, tsk)
} }
func (c *FullNodeStruct) StateMinerPower(ctx context.Context, a address.Address, ts *types.TipSet) (api.MinerPower, error) { func (c *FullNodeStruct) StateMinerProvingSet(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.ChainSectorInfo, error) {
return c.Internal.StateMinerPower(ctx, a, ts) return c.Internal.StateMinerProvingSet(ctx, addr, tsk)
} }
func (c *FullNodeStruct) StateMinerWorker(ctx context.Context, m address.Address, ts *types.TipSet) (address.Address, error) { func (c *FullNodeStruct) StateMinerPower(ctx context.Context, a address.Address, tsk types.TipSetKey) (api.MinerPower, error) {
return c.Internal.StateMinerWorker(ctx, m, ts) return c.Internal.StateMinerPower(ctx, a, tsk)
} }
func (c *FullNodeStruct) StateMinerPeerID(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) { func (c *FullNodeStruct) StateMinerWorker(ctx context.Context, m address.Address, tsk types.TipSetKey) (address.Address, error) {
return c.Internal.StateMinerPeerID(ctx, m, ts) return c.Internal.StateMinerWorker(ctx, m, tsk)
} }
func (c *FullNodeStruct) StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) { func (c *FullNodeStruct) StateMinerPeerID(ctx context.Context, m address.Address, tsk types.TipSetKey) (peer.ID, error) {
return c.Internal.StateMinerElectionPeriodStart(ctx, actor, ts) return c.Internal.StateMinerPeerID(ctx, m, tsk)
} }
func (c *FullNodeStruct) StateMinerSectorSize(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) { func (c *FullNodeStruct) StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, tsk types.TipSetKey) (uint64, error) {
return c.Internal.StateMinerSectorSize(ctx, actor, ts) return c.Internal.StateMinerElectionPeriodStart(ctx, actor, tsk)
} }
func (c *FullNodeStruct) StateCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) { func (c *FullNodeStruct) StateMinerSectorSize(ctx context.Context, actor address.Address, tsk types.TipSetKey) (uint64, error) {
return c.Internal.StateCall(ctx, msg, ts) return c.Internal.StateMinerSectorSize(ctx, actor, tsk)
} }
func (c *FullNodeStruct) StateReplay(ctx context.Context, ts *types.TipSet, mc cid.Cid) (*api.ReplayResults, error) { func (c *FullNodeStruct) StateMinerFaults(ctx context.Context, actor address.Address, tsk types.TipSetKey) ([]uint64, error) {
return c.Internal.StateReplay(ctx, ts, mc) return c.Internal.StateMinerFaults(ctx, actor, tsk)
} }
func (c *FullNodeStruct) StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) { func (c *FullNodeStruct) StateCall(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (*api.MethodCall, error) {
return c.Internal.StateGetActor(ctx, actor, ts) return c.Internal.StateCall(ctx, msg, tsk)
} }
func (c *FullNodeStruct) StateReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*api.ActorState, error) { func (c *FullNodeStruct) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.ReplayResults, error) {
return c.Internal.StateReadState(ctx, act, ts) return c.Internal.StateReplay(ctx, tsk, mc)
} }
func (c *FullNodeStruct) StatePledgeCollateral(ctx context.Context, ts *types.TipSet) (types.BigInt, error) { func (c *FullNodeStruct) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
return c.Internal.StatePledgeCollateral(ctx, ts) 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) 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.MsgWait, error) { func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid) (*api.MsgWait, error) {
return c.Internal.StateWaitMsg(ctx, msgc) return c.Internal.StateWaitMsg(ctx, msgc)
} }
func (c *FullNodeStruct) StateListMiners(ctx context.Context, ts *types.TipSet) ([]address.Address, error) { func (c *FullNodeStruct) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
return c.Internal.StateListMiners(ctx, ts) return c.Internal.StateListMiners(ctx, tsk)
} }
func (c *FullNodeStruct) StateListActors(ctx context.Context, ts *types.TipSet) ([]address.Address, error) { func (c *FullNodeStruct) StateListActors(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
return c.Internal.StateListActors(ctx, ts) return c.Internal.StateListActors(ctx, tsk)
} }
func (c *FullNodeStruct) StateMarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (actors.StorageParticipantBalance, error) { func (c *FullNodeStruct) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (actors.StorageParticipantBalance, error) {
return c.Internal.StateMarketBalance(ctx, addr, ts) return c.Internal.StateMarketBalance(ctx, addr, tsk)
} }
func (c *FullNodeStruct) StateMarketParticipants(ctx context.Context, ts *types.TipSet) (map[string]actors.StorageParticipantBalance, error) { func (c *FullNodeStruct) StateMarketParticipants(ctx context.Context, tsk types.TipSetKey) (map[string]actors.StorageParticipantBalance, error) {
return c.Internal.StateMarketParticipants(ctx, ts) return c.Internal.StateMarketParticipants(ctx, tsk)
} }
func (c *FullNodeStruct) StateMarketDeals(ctx context.Context, ts *types.TipSet) (map[string]actors.OnChainDeal, error) { func (c *FullNodeStruct) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (map[string]actors.OnChainDeal, error) {
return c.Internal.StateMarketDeals(ctx, ts) return c.Internal.StateMarketDeals(ctx, tsk)
} }
func (c *FullNodeStruct) StateMarketStorageDeal(ctx context.Context, dealid uint64, ts *types.TipSet) (*actors.OnChainDeal, error) { func (c *FullNodeStruct) StateMarketStorageDeal(ctx context.Context, dealid uint64, tsk types.TipSetKey) (*actors.OnChainDeal, error) {
return c.Internal.StateMarketStorageDeal(ctx, dealid, ts) return c.Internal.StateMarketStorageDeal(ctx, dealid, tsk)
} }
func (c *FullNodeStruct) StateLookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) { func (c *FullNodeStruct) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
return c.Internal.StateLookupID(ctx, addr, ts) return c.Internal.StateLookupID(ctx, addr, tsk)
} }
func (c *FullNodeStruct) StateChangedActors(ctx context.Context, olnstate cid.Cid, newstate cid.Cid) (map[string]types.Actor, error) { func (c *FullNodeStruct) StateChangedActors(ctx context.Context, olnstate cid.Cid, newstate cid.Cid) (map[string]types.Actor, error) {
return c.Internal.StateChangedActors(ctx, olnstate, newstate) return c.Internal.StateChangedActors(ctx, olnstate, newstate)
} }
func (c *FullNodeStruct) StateGetReceipt(ctx context.Context, msg cid.Cid, ts *types.TipSet) (*types.MessageReceipt, error) { func (c *FullNodeStruct) StateGetReceipt(ctx context.Context, msg cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) {
return c.Internal.StateGetReceipt(ctx, msg, ts) return c.Internal.StateGetReceipt(ctx, msg, tsk)
} }
func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *types.Message, ts *types.TipSet, toht uint64) ([]cid.Cid, error) { func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht uint64) ([]cid.Cid, error) {
return c.Internal.StateListMessages(ctx, match, ts, toht) return c.Internal.StateListMessages(ctx, match, tsk, toht)
} }
func (c *FullNodeStruct) StateCompute(ctx context.Context, height uint64, msgs []*types.Message, ts *types.TipSet) (cid.Cid, error) { func (c *FullNodeStruct) StateCompute(ctx context.Context, height uint64, msgs []*types.Message, tsk types.TipSetKey) (cid.Cid, error) {
return c.Internal.StateCompute(ctx, height, msgs, ts) return c.Internal.StateCompute(ctx, height, msgs, tsk)
}
func (c *FullNodeStruct) MsigGetAvailableBalance(ctx context.Context, a address.Address, tsk types.TipSetKey) (types.BigInt, error) {
return c.Internal.MsigGetAvailableBalance(ctx, a, tsk)
} }
func (c *FullNodeStruct) MarketEnsureAvailable(ctx context.Context, addr address.Address, amt types.BigInt) error { func (c *FullNodeStruct) MarketEnsureAvailable(ctx context.Context, addr address.Address, amt types.BigInt) error {
+155 -186
View File
@@ -98,114 +98,95 @@ func (t *PaymentInfo) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("cbor input should be of type map") return fmt.Errorf("cbor input should be of type map")
} }
if extra != 3 { if extra > cbg.MaxLength {
return fmt.Errorf("cbor input had wrong number of fields") return fmt.Errorf("PaymentInfo: map struct too large (%d)", extra)
} }
var name string var name string
n := extra
// t.Channel (address.Address) (struct) for i := uint64(0); i < n; i++ {
{ {
sval, err := cbg.ReadString(br) sval, err := cbg.ReadString(br)
if err != nil { if err != nil {
return err
}
name = string(sval)
}
if name != "Channel" {
return fmt.Errorf("expected struct map entry %s to be Channel", name)
}
{
if err := t.Channel.UnmarshalCBOR(br); err != nil {
return err
}
}
// t.ChannelMessage (cid.Cid) (struct)
{
sval, err := cbg.ReadString(br)
if err != nil {
return err
}
name = string(sval)
}
if name != "ChannelMessage" {
return fmt.Errorf("expected struct map entry %s to be ChannelMessage", name)
}
{
pb, err := br.PeekByte()
if err != nil {
return err
}
if pb == cbg.CborNull[0] {
var nbuf [1]byte
if _, err := br.Read(nbuf[:]); err != nil {
return err return err
} }
} else {
c, err := cbg.ReadCid(br) name = string(sval)
}
switch name {
// t.Channel (address.Address) (struct)
case "Channel":
{
if err := t.Channel.UnmarshalCBOR(br); err != nil {
return err
}
}
// t.ChannelMessage (cid.Cid) (struct)
case "ChannelMessage":
{
pb, err := br.PeekByte()
if err != nil {
return err
}
if pb == cbg.CborNull[0] {
var nbuf [1]byte
if _, err := br.Read(nbuf[:]); err != nil {
return err
}
} else {
c, err := cbg.ReadCid(br)
if err != nil {
return xerrors.Errorf("failed to read cid field t.ChannelMessage: %w", err)
}
t.ChannelMessage = &c
}
}
// t.Vouchers ([]*types.SignedVoucher) (slice)
case "Vouchers":
maj, extra, err = cbg.CborReadHeader(br)
if err != nil { if err != nil {
return xerrors.Errorf("failed to read cid field t.ChannelMessage: %w", err) return err
} }
t.ChannelMessage = &c if extra > cbg.MaxLength {
return fmt.Errorf("t.Vouchers: array too large (%d)", extra)
}
if maj != cbg.MajArray {
return fmt.Errorf("expected cbor array")
}
if extra > 0 {
t.Vouchers = make([]*types.SignedVoucher, extra)
}
for i := 0; i < int(extra); i++ {
var v types.SignedVoucher
if err := v.UnmarshalCBOR(br); err != nil {
return err
}
t.Vouchers[i] = &v
}
default:
return fmt.Errorf("unknown struct field %d: '%s'", i, name)
} }
}
// t.Vouchers ([]*types.SignedVoucher) (slice)
{
sval, err := cbg.ReadString(br)
if err != nil {
return err
}
name = string(sval)
}
if name != "Vouchers" {
return fmt.Errorf("expected struct map entry %s to be Vouchers", name)
}
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > cbg.MaxLength {
return fmt.Errorf("t.Vouchers: array too large (%d)", extra)
}
if maj != cbg.MajArray {
return fmt.Errorf("expected cbor array")
}
if extra > 0 {
t.Vouchers = make([]*types.SignedVoucher, extra)
}
for i := 0; i < int(extra); i++ {
var v types.SignedVoucher
if err := v.UnmarshalCBOR(br); err != nil {
return err
}
t.Vouchers[i] = &v
} }
return nil return nil
} }
func (t *SealedRef) MarshalCBOR(w io.Writer) error { func (t *SealedRef) MarshalCBOR(w io.Writer) error {
if t == nil { if t == nil {
_, err := w.Write(cbg.CborNull) _, err := w.Write(cbg.CborNull)
@@ -276,84 +257,66 @@ func (t *SealedRef) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("cbor input should be of type map") return fmt.Errorf("cbor input should be of type map")
} }
if extra != 3 { if extra > cbg.MaxLength {
return fmt.Errorf("cbor input had wrong number of fields") return fmt.Errorf("SealedRef: map struct too large (%d)", extra)
} }
var name string var name string
n := extra
// t.SectorID (uint64) (uint64) for i := uint64(0); i < n; i++ {
{ {
sval, err := cbg.ReadString(br) sval, err := cbg.ReadString(br)
if err != nil { if err != nil {
return err return err
}
name = string(sval)
} }
name = string(sval) switch name {
} // t.SectorID (uint64) (uint64)
case "SectorID":
if name != "SectorID" { maj, extra, err = cbg.CborReadHeader(br)
return fmt.Errorf("expected struct map entry %s to be SectorID", name) if err != nil {
} return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.SectorID = uint64(extra)
// t.Offset (uint64) (uint64)
case "Offset":
maj, extra, err = cbg.CborReadHeader(br) maj, extra, err = cbg.CborReadHeader(br)
if err != nil { if err != nil {
return err return err
} }
if maj != cbg.MajUnsignedInt { if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field") return fmt.Errorf("wrong type for uint64 field")
} }
t.SectorID = uint64(extra) t.Offset = uint64(extra)
// t.Offset (uint64) (uint64) // t.Size (uint64) (uint64)
case "Size":
{ maj, extra, err = cbg.CborReadHeader(br)
sval, err := cbg.ReadString(br) if err != nil {
if err != nil { return err
return err }
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Size = uint64(extra)
default:
return fmt.Errorf("unknown struct field %d: '%s'", i, name)
} }
name = string(sval)
} }
if name != "Offset" {
return fmt.Errorf("expected struct map entry %s to be Offset", name)
}
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Offset = uint64(extra)
// t.Size (uint64) (uint64)
{
sval, err := cbg.ReadString(br)
if err != nil {
return err
}
name = string(sval)
}
if name != "Size" {
return fmt.Errorf("expected struct map entry %s to be Size", name)
}
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Size = uint64(extra)
return nil return nil
} }
func (t *SealedRefs) MarshalCBOR(w io.Writer) error { func (t *SealedRefs) MarshalCBOR(w io.Writer) error {
if t == nil { if t == nil {
_, err := w.Write(cbg.CborNull) _, err := w.Write(cbg.CborNull)
@@ -401,50 +364,56 @@ func (t *SealedRefs) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("cbor input should be of type map") return fmt.Errorf("cbor input should be of type map")
} }
if extra != 1 { if extra > cbg.MaxLength {
return fmt.Errorf("cbor input had wrong number of fields") return fmt.Errorf("SealedRefs: map struct too large (%d)", extra)
} }
var name string var name string
n := extra
// t.Refs ([]api.SealedRef) (slice) for i := uint64(0); i < n; i++ {
{ {
sval, err := cbg.ReadString(br) sval, err := cbg.ReadString(br)
if err != nil { if err != nil {
return err return err
}
name = string(sval)
} }
name = string(sval) switch name {
} // t.Refs ([]api.SealedRef) (slice)
case "Refs":
if name != "Refs" { maj, extra, err = cbg.CborReadHeader(br)
return fmt.Errorf("expected struct map entry %s to be Refs", name) if err != nil {
} return err
}
maj, extra, err = cbg.CborReadHeader(br) if extra > cbg.MaxLength {
if err != nil { return fmt.Errorf("t.Refs: array too large (%d)", extra)
return err }
}
if extra > cbg.MaxLength { if maj != cbg.MajArray {
return fmt.Errorf("t.Refs: array too large (%d)", extra) return fmt.Errorf("expected cbor array")
} }
if extra > 0 {
t.Refs = make([]SealedRef, extra)
}
for i := 0; i < int(extra); i++ {
if maj != cbg.MajArray { var v SealedRef
return fmt.Errorf("expected cbor array") if err := v.UnmarshalCBOR(br); err != nil {
} return err
if extra > 0 { }
t.Refs = make([]SealedRef, extra)
}
for i := 0; i < int(extra); i++ {
var v SealedRef t.Refs[i] = v
if err := v.UnmarshalCBOR(br); err != nil { }
return err
default:
return fmt.Errorf("unknown struct field %d: '%s'", i, name)
} }
t.Refs[i] = v
} }
return nil return nil
-1
View File
@@ -65,7 +65,6 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
defer close(done) defer close(done)
for mine { for mine {
time.Sleep(blocktime) time.Sleep(blocktime)
fmt.Println("mining a block now")
if err := sn[0].MineOne(ctx); err != nil { if err := sn[0].MineOne(ctx); err != nil {
t.Error(err) t.Error(err)
} }
+2
View File
@@ -5,3 +5,5 @@ const ForkBlizzardHeight = 6288
const ForkFrigidHeight = 7950 const ForkFrigidHeight = 7950
const ForkBootyBayHeight = 11000 const ForkBootyBayHeight = 11000
const ForkMissingSnowballs = 34000
+3 -1
View File
@@ -2,4 +2,6 @@ package build
import rice "github.com/GeertJohan/go.rice" import rice "github.com/GeertJohan/go.rice"
var ParametersJson = rice.MustFindBox("proof-params").MustBytes("parameters.json") func ParametersJson() []byte {
return rice.MustFindBox("proof-params").MustBytes("parameters.json")
}
+4
View File
@@ -2,6 +2,10 @@
package build package build
func init() {
InsecurePoStValidation = true
}
var SectorSizes = []uint64{1024} var SectorSizes = []uint64{1024}
// Seconds // Seconds
+2
View File
@@ -21,6 +21,8 @@ func SupportedSectorSize(ssize uint64) bool {
return false return false
} }
const SectorChallengeRatioDiv = 25
// ///// // /////
// Payments // Payments
+1 -1
View File
@@ -5,7 +5,7 @@ import "fmt"
var CurrentCommit string var CurrentCommit string
// BuildVersion is the local build version, set by build system // BuildVersion is the local build version, set by build system
const BuildVersion = "0.2.5" const BuildVersion = "0.2.8"
var UserVersion = BuildVersion + CurrentCommit var UserVersion = BuildVersion + CurrentCommit
+3 -6
View File
@@ -27,6 +27,8 @@ const (
GasCreateActor = 100 GasCreateActor = 100
) )
var BuiltInActors map[cid.Cid]bool
func init() { func init() {
n, err := cbor.WrapObject(map[string]string{}, mh.SHA2_256, -1) n, err := cbor.WrapObject(map[string]string{}, mh.SHA2_256, -1)
@@ -160,12 +162,7 @@ func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams)
} }
func IsBuiltinActor(code cid.Cid) bool { func IsBuiltinActor(code cid.Cid) bool {
switch code { return BuiltInActors[code]
case StorageMarketCodeCid, StoragePowerCodeCid, StorageMinerCodeCid, StorageMiner2CodeCid, AccountCodeCid, InitCodeCid, MultisigCodeCid, PaymentChannelCodeCid:
return true
default:
return false
}
} }
func IsSingletonActor(code cid.Cid) bool { func IsSingletonActor(code cid.Cid) bool {
+5 -7
View File
@@ -6,8 +6,6 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-sectorbuilder" "github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
@@ -483,7 +481,7 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM
} }
activeFaults := uint64(0) activeFaults := uint64(0)
var sectorInfos []ffi.PublicSectorInfo var sectorInfos []types.PublicSectorInfo
if err := pss.ForEach(func(id uint64, v *cbg.Deferred) error { if err := pss.ForEach(func(id uint64, v *cbg.Deferred) error {
if faults[id] { if faults[id] {
activeFaults++ activeFaults++
@@ -494,7 +492,7 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM
if err := cbor.DecodeInto(v.Raw, &comms); err != nil { if err := cbor.DecodeInto(v.Raw, &comms); err != nil {
return xerrors.New("could not decode comms") return xerrors.New("could not decode comms")
} }
si := ffi.PublicSectorInfo{ si := types.PublicSectorInfo{
SectorID: id, SectorID: id,
} }
commR := comms[0] commR := comms[0]
@@ -512,11 +510,11 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM
proverID := vmctx.Message().To // TODO: normalize to ID address proverID := vmctx.Message().To // TODO: normalize to ID address
var candidates []sectorbuilder.EPostCandidate var candidates []types.Candidate
for _, t := range params.Candidates { for _, t := range params.Candidates {
var partial [32]byte var partial [32]byte
copy(partial[:], t.Partial) copy(partial[:], t.Partial)
candidates = append(candidates, sectorbuilder.EPostCandidate{ candidates = append(candidates, types.Candidate{
PartialTicket: partial, PartialTicket: partial,
SectorID: t.SectorID, SectorID: t.SectorID,
SectorChallengeIndex: t.ChallengeIndex, SectorChallengeIndex: t.ChallengeIndex,
@@ -524,7 +522,7 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM
} }
if ok, lerr := vmctx.Sys().VerifyFallbackPost(vmctx.Context(), mi.SectorSize, if ok, lerr := vmctx.Sys().VerifyFallbackPost(vmctx.Context(), mi.SectorSize,
sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), seed[:], params.Proof, candidates, proverID, activeFaults); !ok || lerr != nil { sectorInfos, seed[:], params.Proof, candidates, proverID, activeFaults); !ok || lerr != nil {
if lerr != nil { if lerr != nil {
// TODO: study PoST errors // TODO: study PoST errors
return nil, aerrors.Absorb(lerr, 4, "PoST error") return nil, aerrors.Absorb(lerr, 4, "PoST error")
+46 -8
View File
@@ -5,7 +5,6 @@ import (
"context" "context"
"fmt" "fmt"
ffi "github.com/filecoin-project/filecoin-ffi"
amt2 "github.com/filecoin-project/go-amt-ipld/v2" amt2 "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/go-sectorbuilder" "github.com/filecoin-project/go-sectorbuilder"
@@ -33,7 +32,10 @@ func (sma StorageMinerActor2) Exports() []interface{} {
//8: sma.DePledge, //8: sma.DePledge,
9: sma.GetOwner, 9: sma.GetOwner,
10: sma.GetWorkerAddr, 10: sma.GetWorkerAddr,
11: sma.GetPower, // TODO: Remove 11: withUpdates(
update{0, sma.GetPower},
update{build.ForkMissingSnowballs, sma.GetPower2},
), // FORK
12: sma.GetPeerID, 12: sma.GetPeerID,
13: sma.GetSectorSize, 13: sma.GetSectorSize,
14: sma.UpdatePeerID, 14: sma.UpdatePeerID,
@@ -328,7 +330,7 @@ func (sma StorageMinerActor2) SubmitFallbackPoSt(act *types.Actor, vmctx types.V
} }
activeFaults := uint64(0) activeFaults := uint64(0)
var sectorInfos []ffi.PublicSectorInfo var sectorInfos []types.PublicSectorInfo
if err := pss.ForEach(func(id uint64, v *cbg.Deferred) error { if err := pss.ForEach(func(id uint64, v *cbg.Deferred) error {
if faults[id] { if faults[id] {
activeFaults++ activeFaults++
@@ -339,7 +341,7 @@ func (sma StorageMinerActor2) SubmitFallbackPoSt(act *types.Actor, vmctx types.V
if err := cbor.DecodeInto(v.Raw, &comms); err != nil { if err := cbor.DecodeInto(v.Raw, &comms); err != nil {
return xerrors.New("could not decode comms") return xerrors.New("could not decode comms")
} }
si := ffi.PublicSectorInfo{ si := types.PublicSectorInfo{
SectorID: id, SectorID: id,
} }
commR := comms[0] commR := comms[0]
@@ -357,11 +359,11 @@ func (sma StorageMinerActor2) SubmitFallbackPoSt(act *types.Actor, vmctx types.V
proverID := vmctx.Message().To // TODO: normalize to ID address proverID := vmctx.Message().To // TODO: normalize to ID address
var candidates []sectorbuilder.EPostCandidate var candidates []types.Candidate
for _, t := range params.Candidates { for _, t := range params.Candidates {
var partial [32]byte var partial [32]byte
copy(partial[:], t.Partial) copy(partial[:], t.Partial)
candidates = append(candidates, sectorbuilder.EPostCandidate{ candidates = append(candidates, types.Candidate{
PartialTicket: partial, PartialTicket: partial,
SectorID: t.SectorID, SectorID: t.SectorID,
SectorChallengeIndex: t.ChallengeIndex, SectorChallengeIndex: t.ChallengeIndex,
@@ -369,7 +371,7 @@ func (sma StorageMinerActor2) SubmitFallbackPoSt(act *types.Actor, vmctx types.V
} }
if ok, lerr := vmctx.Sys().VerifyFallbackPost(vmctx.Context(), mi.SectorSize, if ok, lerr := vmctx.Sys().VerifyFallbackPost(vmctx.Context(), mi.SectorSize,
sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), seed[:], params.Proof, candidates, proverID, activeFaults); !ok || lerr != nil { sectorInfos, seed[:], params.Proof, candidates, proverID, activeFaults); !ok || lerr != nil {
if lerr != nil { if lerr != nil {
// TODO: study PoST errors // TODO: study PoST errors
return nil, aerrors.Absorb(lerr, 4, "PoST error") return nil, aerrors.Absorb(lerr, 4, "PoST error")
@@ -401,6 +403,20 @@ func (sma StorageMinerActor2) GetPower(act *types.Actor, vmctx types.VMContext,
if err != nil { if err != nil {
return nil, err return nil, err
} }
return self.Power.Bytes(), nil
}
func (sma StorageMinerActor2) GetPower2(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
_, self, err := loadState(vmctx)
if err != nil {
return nil, err
}
if self.SlashedAt != 0 {
return types.NewInt(0).Bytes(), nil
}
return self.Power.Bytes(), nil return self.Power.Bytes(), nil
} }
@@ -615,6 +631,11 @@ func (sma StorageMinerActor2) CheckMiner(act *types.Actor, vmctx types.VMContext
// Slash for being late // Slash for being late
self.SlashedAt = vmctx.BlockHeight() self.SlashedAt = vmctx.BlockHeight()
oldPower := self.Power
if vmctx.BlockHeight() > build.ForkMissingSnowballs {
self.Power = types.NewInt(0)
}
nstate, err := vmctx.Storage().Put(self) nstate, err := vmctx.Storage().Put(self)
if err != nil { if err != nil {
@@ -625,7 +646,7 @@ func (sma StorageMinerActor2) CheckMiner(act *types.Actor, vmctx types.VMContext
} }
var out bytes.Buffer var out bytes.Buffer
if err := self.Power.MarshalCBOR(&out); err != nil { if err := oldPower.MarshalCBOR(&out); err != nil {
return nil, aerrors.HandleExternalError(err, "marshaling return value") return nil, aerrors.HandleExternalError(err, "marshaling return value")
} }
return out.Bytes(), nil return out.Bytes(), nil
@@ -710,6 +731,23 @@ func (sma StorageMinerActor2) SlashConsensusFault(act *types.Actor, vmctx types.
return nil, aerrors.Wrap(err, "failed to burn funds") return nil, aerrors.Wrap(err, "failed to burn funds")
} }
if vmctx.BlockHeight() > build.ForkMissingSnowballs {
oldstate, self, err := loadState(vmctx)
if err != nil {
return nil, aerrors.Wrap(err, "failed to load state for slashing")
}
self.Power = types.NewInt(0)
ncid, err := vmctx.Storage().Put(self)
if err != nil {
return nil, err
}
if err := vmctx.Storage().Commit(oldstate, ncid); err != nil {
return nil, err
}
}
// TODO: this still allows the miner to commit sectors and submit posts, // TODO: this still allows the miner to commit sectors and submit posts,
// their users could potentially be unaffected, but the miner will never be // their users could potentially be unaffected, but the miner will never be
// able to mine a block again // able to mine a block again
+3 -2
View File
@@ -13,11 +13,12 @@ import (
"github.com/ipfs/go-hamt-ipld" "github.com/ipfs/go-hamt-ipld"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-cbor-util" cborutil "github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/go-sectorbuilder" "github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
) )
type StorageMarketActor struct{} type StorageMarketActor struct{}
@@ -131,7 +132,7 @@ func (sdp *StorageDealProposal) Verify(worker address.Address) error {
return err return err
} }
if err := sdp.ProposerSignature.Verify(sdp.Client, buf.Bytes()); err != nil { if err := sigs.Verify(sdp.ProposerSignature, sdp.Client, buf.Bytes()); err != nil {
return err return err
} }
} }
+47 -11
View File
@@ -17,6 +17,7 @@ import (
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
) )
type StoragePowerActor struct{} type StoragePowerActor struct{}
@@ -170,11 +171,11 @@ func (spa StoragePowerActor) ArbitrateConsensusFault(act *types.Actor, vmctx typ
return nil, aerrors.Absorb(oerr, 3, "response from 'GetWorkerAddr' was not a valid address") return nil, aerrors.Absorb(oerr, 3, "response from 'GetWorkerAddr' was not a valid address")
} }
if err := params.Block1.CheckBlockSignature(vmctx.Context(), worker); err != nil { if err := sigs.CheckBlockSignature(params.Block1, vmctx.Context(), worker); err != nil {
return nil, aerrors.Absorb(err, 4, "block1 did not have valid signature") return nil, aerrors.Absorb(err, 4, "block1 did not have valid signature")
} }
if err := params.Block2.CheckBlockSignature(vmctx.Context(), worker); err != nil { if err := sigs.CheckBlockSignature(params.Block2, vmctx.Context(), worker); err != nil {
return nil, aerrors.Absorb(err, 5, "block2 did not have valid signature") return nil, aerrors.Absorb(err, 5, "block2 did not have valid signature")
} }
@@ -474,7 +475,8 @@ func powerLookup(ctx context.Context, vmctx types.VMContext, self *StoragePowerS
} }
if !has { if !has {
return types.EmptyInt, aerrors.New(1, "miner not registered with storage power actor") // A miner could be registered with storage power actor, but removed for some reasons, e.g. consensus fault
return types.EmptyInt, aerrors.New(1, "miner not registered with storage power actor, or removed already")
} }
// TODO: Use local amt // TODO: Use local amt
@@ -648,6 +650,8 @@ func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, he
return aerrors.HandleExternalError(err, "failed to load proving bucket") return aerrors.HandleExternalError(err, "failed to load proving bucket")
} }
forRemoval := make([]address.Address, 0)
err = bhamt.ForEach(vmctx.Context(), func(k string, val interface{}) error { err = bhamt.ForEach(vmctx.Context(), func(k string, val interface{}) error {
_, span := trace.StartSpan(vmctx.Context(), "StoragePowerActor.CheckProofSubmissions.loop") _, span := trace.StartSpan(vmctx.Context(), "StoragePowerActor.CheckProofSubmissions.loop")
defer span.End() defer span.End()
@@ -657,6 +661,18 @@ func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, he
return aerrors.Escalate(err, "parsing miner address") return aerrors.Escalate(err, "parsing miner address")
} }
if vmctx.BlockHeight() > build.ForkMissingSnowballs {
has, aerr := MinerSetHas(vmctx, self.Miners, maddr)
if aerr != nil {
return aerr
}
if !has {
forRemoval = append(forRemoval, maddr)
}
}
span.AddAttributes(trace.StringAttribute("miner", maddr.String())) span.AddAttributes(trace.StringAttribute("miner", maddr.String()))
params, err := SerializeParams(&CheckMinerParams{NetworkPower: self.TotalStorage}) params, err := SerializeParams(&CheckMinerParams{NetworkPower: self.TotalStorage})
@@ -690,6 +706,24 @@ func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, he
return aerrors.HandleExternalError(err, "iterating miners in proving bucket") return aerrors.HandleExternalError(err, "iterating miners in proving bucket")
} }
if vmctx.BlockHeight() > build.ForkMissingSnowballs && len(forRemoval) > 0 {
nBucket, err := MinerSetRemove(vmctx.Context(), vmctx, bucket, forRemoval...)
if err != nil {
return aerrors.Wrap(err, "could not remove miners from set")
}
eerr := buckets.Set(bucketID, nBucket)
if err != nil {
return aerrors.HandleExternalError(eerr, "could not set the bucket")
}
ncid, eerr := buckets.Flush()
if err != nil {
return aerrors.HandleExternalError(eerr, "could not flush buckets")
}
self.ProvingBuckets = ncid
}
return nil return nil
} }
@@ -764,19 +798,21 @@ func MinerSetAdd(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr
return c, nil return c, nil
} }
func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (cid.Cid, aerrors.ActorError) { func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddrs ...address.Address) (cid.Cid, aerrors.ActorError) {
nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid) nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid)
if err != nil { if err != nil {
return cid.Undef, aerrors.HandleExternalError(err, "failed to load miner set") return cid.Undef, aerrors.HandleExternalError(err, "failed to load miner set")
} }
mkey := string(maddr.Bytes()) for _, maddr := range maddrs {
switch nd.Delete(ctx, mkey) { mkey := string(maddr.Bytes())
default: switch nd.Delete(ctx, mkey) {
return cid.Undef, aerrors.HandleExternalError(err, "failed to delete miner from set") default:
case hamt.ErrNotFound: return cid.Undef, aerrors.HandleExternalError(err, "failed to delete miner from set")
return cid.Undef, aerrors.New(1, "miner not found in set on delete") case hamt.ErrNotFound:
case nil: return cid.Undef, aerrors.New(1, "miner not found in set on delete")
case nil:
}
} }
if err := nd.Flush(ctx); err != nil { if err := nd.Flush(ctx); err != nil {
+2
View File
@@ -13,6 +13,8 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld" hamt "github.com/ipfs/go-hamt-ipld"
+11
View File
@@ -51,4 +51,15 @@ func init() {
MultisigCodeCid = mustSum("fil/1/multisig") MultisigCodeCid = mustSum("fil/1/multisig")
InitCodeCid = mustSum("fil/1/init") InitCodeCid = mustSum("fil/1/init")
PaymentChannelCodeCid = mustSum("fil/1/paych") PaymentChannelCodeCid = mustSum("fil/1/paych")
BuiltInActors = map[cid.Cid]bool{
StorageMarketCodeCid: true,
StoragePowerCodeCid: true,
StorageMinerCodeCid: true,
StorageMiner2CodeCid: true,
AccountCodeCid: true,
InitCodeCid: true,
MultisigCodeCid: true,
PaymentChannelCodeCid: true,
}
} }
+1 -1
View File
@@ -45,7 +45,7 @@ func setupVMTestEnv(t *testing.T) (*vm.VM, []address.Address, bstore.Blockstore)
t.Fatal(err) t.Fatal(err)
} }
stateroot, err := st.Flush() stateroot, err := st.Flush(context.TODO())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
+1 -1
View File
@@ -26,7 +26,7 @@ func withUpdates(updates ...update) interface{} {
vmctx := args[1].Interface().(types.VMContext) vmctx := args[1].Interface().(types.VMContext)
for _, u := range updates { for _, u := range updates {
if vmctx.BlockHeight() >= u.start { if vmctx.BlockHeight() > u.start {
return reflect.ValueOf(u.method).Call(args) return reflect.ValueOf(u.method).Call(args)
} }
} }
+3 -2
View File
@@ -3,10 +3,11 @@ package actors_test
import ( import (
"bytes" "bytes"
"context" "context"
"github.com/filecoin-project/go-sectorbuilder"
"math/rand" "math/rand"
"testing" "testing"
"github.com/filecoin-project/go-sectorbuilder"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore" dstore "github.com/ipfs/go-datastore"
hamt "github.com/ipfs/go-hamt-ipld" hamt "github.com/ipfs/go-hamt-ipld"
@@ -185,7 +186,7 @@ func NewHarness(t *testing.T, options ...HarnessOpt) *Harness {
t.Fatal(err) t.Fatal(err)
} }
stateroot, err := st.Flush() stateroot, err := st.Flush(context.TODO())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
+9 -4
View File
@@ -21,10 +21,15 @@ func NewBadBlockCache() *BadBlockCache {
} }
} }
func (bts *BadBlockCache) Add(c cid.Cid) { func (bts *BadBlockCache) Add(c cid.Cid, reason string) {
bts.badBlocks.Add(c, nil) bts.badBlocks.Add(c, reason)
} }
func (bts *BadBlockCache) Has(c cid.Cid) bool { func (bts *BadBlockCache) Has(c cid.Cid) (string, bool) {
return bts.badBlocks.Contains(c) rval, ok := bts.badBlocks.Get(c)
if !ok {
return "", false
}
return rval.(string), true
} }
+36 -17
View File
@@ -3,17 +3,17 @@ package blocksync
import ( import (
"bufio" "bufio"
"context" "context"
"time"
"github.com/libp2p/go-libp2p-core/protocol" "github.com/libp2p/go-libp2p-core/protocol"
"go.opencensus.io/trace" "go.opencensus.io/trace"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-cbor-util" cborutil "github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
inet "github.com/libp2p/go-libp2p-core/network" inet "github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
@@ -25,11 +25,7 @@ type NewStreamFunc func(context.Context, peer.ID, ...protocol.ID) (inet.Stream,
const BlockSyncProtocolID = "/fil/sync/blk/0.0.1" const BlockSyncProtocolID = "/fil/sync/blk/0.0.1"
func init() { const BlockSyncMaxRequestLength = 800
cbor.RegisterCborType(BlockSyncRequest{})
cbor.RegisterCborType(BlockSyncResponse{})
cbor.RegisterCborType(BSTipSet{})
}
type BlockSyncService struct { type BlockSyncService struct {
cs *store.ChainStore cs *store.ChainStore
@@ -55,8 +51,17 @@ func ParseBSOptions(optfield uint64) *BSOptions {
} }
const ( const (
BSOptBlocks = 1 << 0 BSOptBlocks = 1 << iota
BSOptMessages = 1 << 1 BSOptMessages
)
const (
StatusOK = uint64(0)
StatusPartial = uint64(101)
StatusNotFound = uint64(201)
StatusGoAway = uint64(202)
StatusInternalError = uint64(203)
StatusBadRequest = uint64(204)
) )
type BlockSyncResponse struct { type BlockSyncResponse struct {
@@ -93,28 +98,30 @@ func (bss *BlockSyncService) HandleStream(s inet.Stream) {
log.Warnf("failed to read block sync request: %s", err) log.Warnf("failed to read block sync request: %s", err)
return return
} }
log.Infof("block sync request for: %s %d", req.Start, req.RequestLength) log.Infow("block sync request", "start", req.Start, "len", req.RequestLength)
resp, err := bss.processRequest(ctx, &req) resp, err := bss.processRequest(ctx, s.Conn().RemotePeer(), &req)
if err != nil { if err != nil {
log.Warn("failed to process block sync request: ", err) log.Warn("failed to process block sync request: ", err)
return return
} }
writeDeadline := 60 * time.Second
s.SetDeadline(time.Now().Add(writeDeadline))
if err := cborutil.WriteCborRPC(s, resp); err != nil { if err := cborutil.WriteCborRPC(s, resp); err != nil {
log.Warn("failed to write back response for handle stream: ", err) log.Warnw("failed to write back response for handle stream", "err", err, "peer", s.Conn().RemotePeer())
return return
} }
} }
func (bss *BlockSyncService) processRequest(ctx context.Context, req *BlockSyncRequest) (*BlockSyncResponse, error) { func (bss *BlockSyncService) processRequest(ctx context.Context, p peer.ID, req *BlockSyncRequest) (*BlockSyncResponse, error) {
_, span := trace.StartSpan(ctx, "blocksync.ProcessRequest") _, span := trace.StartSpan(ctx, "blocksync.ProcessRequest")
defer span.End() defer span.End()
opts := ParseBSOptions(req.Options) opts := ParseBSOptions(req.Options)
if len(req.Start) == 0 { if len(req.Start) == 0 {
return &BlockSyncResponse{ return &BlockSyncResponse{
Status: 204, Status: StatusBadRequest,
Message: "no cids given in blocksync request", Message: "no cids given in blocksync request",
}, nil }, nil
} }
@@ -122,20 +129,32 @@ func (bss *BlockSyncService) processRequest(ctx context.Context, req *BlockSyncR
span.AddAttributes( span.AddAttributes(
trace.BoolAttribute("blocks", opts.IncludeBlocks), trace.BoolAttribute("blocks", opts.IncludeBlocks),
trace.BoolAttribute("messages", opts.IncludeMessages), trace.BoolAttribute("messages", opts.IncludeMessages),
trace.Int64Attribute("reqlen", int64(req.RequestLength)),
) )
chain, err := bss.collectChainSegment(types.NewTipSetKey(req.Start...), req.RequestLength, opts) reqlen := req.RequestLength
if reqlen > BlockSyncMaxRequestLength {
log.Warnw("limiting blocksync request length", "orig", req.RequestLength, "peer", p)
reqlen = BlockSyncMaxRequestLength
}
chain, err := bss.collectChainSegment(types.NewTipSetKey(req.Start...), reqlen, opts)
if err != nil { if err != nil {
log.Warn("encountered error while responding to block sync request: ", err) log.Warn("encountered error while responding to block sync request: ", err)
return &BlockSyncResponse{ return &BlockSyncResponse{
Status: 203, Status: StatusInternalError,
Message: err.Error(), Message: err.Error(),
}, nil }, nil
} }
status := StatusOK
if reqlen < req.RequestLength {
status = StatusPartial
}
return &BlockSyncResponse{ return &BlockSyncResponse{
Chain: chain, Chain: chain,
Status: 0, Status: status,
}, nil }, nil
} }
+18 -10
View File
@@ -18,9 +18,10 @@ import (
"go.opencensus.io/trace" "go.opencensus.io/trace"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-cbor-util" cborutil "github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
incrt "github.com/filecoin-project/lotus/lib/increadtimeout"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/peermgr" "github.com/filecoin-project/lotus/peermgr"
) )
@@ -44,15 +45,15 @@ func NewBlockSyncClient(bserv dtypes.ChainBlockService, h host.Host, pmgr peermg
func (bs *BlockSync) processStatus(req *BlockSyncRequest, res *BlockSyncResponse) error { func (bs *BlockSync) processStatus(req *BlockSyncRequest, res *BlockSyncResponse) error {
switch res.Status { switch res.Status {
case 101: // Partial Response case StatusPartial: // Partial Response
return xerrors.Errorf("not handling partial blocksync responses yet") return xerrors.Errorf("not handling partial blocksync responses yet")
case 201: // req.Start not found case StatusNotFound: // req.Start not found
return xerrors.Errorf("not found") return xerrors.Errorf("not found")
case 202: // Go Away case StatusGoAway: // Go Away
return xerrors.Errorf("not handling 'go away' blocksync responses yet") return xerrors.Errorf("not handling 'go away' blocksync responses yet")
case 203: // Internal Error case StatusInternalError: // Internal Error
return xerrors.Errorf("block sync peer errored: %s", res.Message) return xerrors.Errorf("block sync peer errored: %s", res.Message)
case 204: case StatusBadRequest:
return xerrors.Errorf("block sync request invalid: %s", res.Message) return xerrors.Errorf("block sync request invalid: %s", res.Message)
default: default:
return xerrors.Errorf("unrecognized response code: %d", res.Status) return xerrors.Errorf("unrecognized response code: %d", res.Status)
@@ -194,11 +195,16 @@ func (bs *BlockSync) GetChainMessages(ctx context.Context, h *types.TipSet, coun
continue continue
} }
if res.Status == 0 { if res.Status == StatusOK {
bs.syncPeers.logGlobalSuccess(time.Since(start)) bs.syncPeers.logGlobalSuccess(time.Since(start))
return res.Chain, nil return res.Chain, nil
} }
if res.Status == StatusPartial {
log.Warn("dont yet handle partial responses")
continue
}
err = bs.processStatus(req, res) err = bs.processStatus(req, res)
if err != nil { if err != nil {
log.Warnf("BlockSync peer %s response was an error: %s", p.String(), err) log.Warnf("BlockSync peer %s response was an error: %s", p.String(), err)
@@ -241,16 +247,18 @@ func (bs *BlockSync) sendRequestToPeer(ctx context.Context, p peer.ID, req *Bloc
bs.RemovePeer(p) bs.RemovePeer(p)
return nil, xerrors.Errorf("failed to open stream to peer: %w", err) return nil, xerrors.Errorf("failed to open stream to peer: %w", err)
} }
s.SetDeadline(time.Now().Add(10 * time.Second)) s.SetWriteDeadline(time.Now().Add(5 * time.Second))
defer s.SetDeadline(time.Time{})
if err := cborutil.WriteCborRPC(s, req); err != nil { if err := cborutil.WriteCborRPC(s, req); err != nil {
s.SetWriteDeadline(time.Time{})
bs.syncPeers.logFailure(p, time.Since(start)) bs.syncPeers.logFailure(p, time.Since(start))
return nil, err return nil, err
} }
s.SetWriteDeadline(time.Time{})
var res BlockSyncResponse var res BlockSyncResponse
if err := cborutil.ReadCborRPC(bufio.NewReader(s), &res); err != nil { r := incrt.New(s, 50<<10, 5*time.Second)
if err := cborutil.ReadCborRPC(bufio.NewReader(r), &res); err != nil {
bs.syncPeers.logFailure(p, time.Since(start)) bs.syncPeers.logFailure(p, time.Since(start))
return nil, err return nil, err
} }
+3 -3
View File
@@ -33,10 +33,10 @@ type heightHandler struct {
type eventApi interface { type eventApi interface {
ChainNotify(context.Context) (<-chan []*store.HeadChange, error) ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
ChainGetTipSetByHeight(context.Context, uint64, *types.TipSet) (*types.TipSet, error) ChainGetTipSetByHeight(context.Context, uint64, types.TipSetKey) (*types.TipSet, error)
StateGetReceipt(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) // optional / for CalledMsg StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // optional / for CalledMsg
} }
type Events struct { type Events struct {
+1 -1
View File
@@ -192,7 +192,7 @@ func (e *calledEvents) applyWithConfidence(ts *types.TipSet) {
continue continue
} }
rec, err := e.cs.StateGetReceipt(e.ctx, event.msg.Cid(), ts) rec, err := e.cs.StateGetReceipt(e.ctx, event.msg.Cid(), ts.Key())
if err != nil { if err != nil {
log.Error(err) log.Error(err)
return return
+3 -3
View File
@@ -40,15 +40,15 @@ type fakeCS struct {
sub func(rev, app []*types.TipSet) sub func(rev, app []*types.TipSet)
} }
func (fcs *fakeCS) StateGetReceipt(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) { func (fcs *fakeCS) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) {
return nil, nil return nil, nil
} }
func (fcs *fakeCS) StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) { func (fcs *fakeCS) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
panic("Not Implemented") panic("Not Implemented")
} }
func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, uint64, *types.TipSet) (*types.TipSet, error) { func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, uint64, types.TipSetKey) (*types.TipSet, error) {
panic("Not Implemented") panic("Not Implemented")
} }
+3 -3
View File
@@ -8,7 +8,7 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
type tsByHFunc func(context.Context, uint64, *types.TipSet) (*types.TipSet, error) type tsByHFunc func(context.Context, uint64, types.TipSetKey) (*types.TipSet, error)
// tipSetCache implements a simple ring-buffer cache to keep track of recent // tipSetCache implements a simple ring-buffer cache to keep track of recent
// tipsets // tipsets
@@ -93,7 +93,7 @@ func (tsc *tipSetCache) getNonNull(height uint64) (*types.TipSet, error) {
func (tsc *tipSetCache) get(height uint64) (*types.TipSet, error) { func (tsc *tipSetCache) get(height uint64) (*types.TipSet, error) {
if tsc.len == 0 { if tsc.len == 0 {
log.Warnf("tipSetCache.get: cache is empty, requesting from storage (h=%d)", height) log.Warnf("tipSetCache.get: cache is empty, requesting from storage (h=%d)", height)
return tsc.storage(context.TODO(), height, nil) return tsc.storage(context.TODO(), height, types.EmptyTSK)
} }
headH := tsc.cache[tsc.start].Height() headH := tsc.cache[tsc.start].Height()
@@ -113,7 +113,7 @@ func (tsc *tipSetCache) get(height uint64) (*types.TipSet, error) {
if height < tail.Height() { if height < tail.Height() {
log.Warnf("tipSetCache.get: requested tipset not in cache, requesting from storage (h=%d; tail=%d)", height, tail.Height()) log.Warnf("tipSetCache.get: requested tipset not in cache, requesting from storage (h=%d; tail=%d)", height, tail.Height())
return tsc.storage(context.TODO(), height, tail) return tsc.storage(context.TODO(), height, tail.Key())
} }
return tsc.cache[normalModulo(tsc.start-int(headH-height), clen)], nil return tsc.cache[normalModulo(tsc.start-int(headH-height), clen)], nil
+2 -2
View File
@@ -11,7 +11,7 @@ import (
) )
func TestTsCache(t *testing.T) { func TestTsCache(t *testing.T) {
tsc := newTSCache(50, func(context.Context, uint64, *types.TipSet) (*types.TipSet, error) { tsc := newTSCache(50, func(context.Context, uint64, types.TipSetKey) (*types.TipSet, error) {
t.Fatal("storage call") t.Fatal("storage call")
return &types.TipSet{}, nil return &types.TipSet{}, nil
}) })
@@ -54,7 +54,7 @@ func TestTsCache(t *testing.T) {
} }
func TestTsCacheNulls(t *testing.T) { func TestTsCacheNulls(t *testing.T) {
tsc := newTSCache(50, func(context.Context, uint64, *types.TipSet) (*types.TipSet, error) { tsc := newTSCache(50, func(context.Context, uint64, types.TipSetKey) (*types.TipSet, error) {
t.Fatal("storage call") t.Fatal("storage call")
return &types.TipSet{}, nil return &types.TipSet{}, nil
}) })
+2 -2
View File
@@ -13,7 +13,7 @@ func (e *calledEvents) CheckMsg(ctx context.Context, smsg store.ChainMsg, hnd Ca
msg := smsg.VMMessage() msg := smsg.VMMessage()
return func(ts *types.TipSet) (done bool, more bool, err error) { return func(ts *types.TipSet) (done bool, more bool, err error) {
fa, err := e.cs.StateGetActor(ctx, msg.From, ts) fa, err := e.cs.StateGetActor(ctx, msg.From, ts.Key())
if err != nil { if err != nil {
return false, true, err return false, true, err
} }
@@ -23,7 +23,7 @@ func (e *calledEvents) CheckMsg(ctx context.Context, smsg store.ChainMsg, hnd Ca
return false, true, nil return false, true, nil
} }
rec, err := e.cs.StateGetReceipt(ctx, smsg.VMMessage().Cid(), ts) rec, err := e.cs.StateGetReceipt(ctx, smsg.VMMessage().Cid(), ts.Key())
if err != nil { if err != nil {
return false, true, xerrors.Errorf("getting receipt in CheckMsg: %w", err) return false, true, xerrors.Errorf("getting receipt in CheckMsg: %w", err)
} }
+64 -29
View File
@@ -6,36 +6,36 @@ import (
"crypto/sha256" "crypto/sha256"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"github.com/filecoin-project/lotus/chain/vm"
"io/ioutil" "io/ioutil"
"sync/atomic" "sync/atomic"
ffi "github.com/filecoin-project/filecoin-ffi" block "github.com/ipfs/go-block-format"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/ipfs/go-blockservice" "github.com/ipfs/go-blockservice"
"github.com/ipfs/go-car" "github.com/ipfs/go-car"
"github.com/ipfs/go-cid"
blockstore "github.com/ipfs/go-ipfs-blockstore"
offline "github.com/ipfs/go-ipfs-exchange-offline" offline "github.com/ipfs/go-ipfs-exchange-offline"
logging "github.com/ipfs/go-log/v2"
"github.com/ipfs/go-merkledag" "github.com/ipfs/go-merkledag"
peer "github.com/libp2p/go-libp2p-core/peer" peer "github.com/libp2p/go-libp2p-core/peer"
"go.opencensus.io/trace"
"golang.org/x/xerrors"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed" "github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
"github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/node/repo"
block "github.com/ipfs/go-block-format" "go.opencensus.io/trace"
"github.com/ipfs/go-cid" "golang.org/x/xerrors"
blockstore "github.com/ipfs/go-ipfs-blockstore"
logging "github.com/ipfs/go-log/v2"
) )
var log = logging.Logger("gen") var log = logging.Logger("gen")
@@ -56,6 +56,8 @@ type ChainGen struct {
Timestamper func(*types.TipSet, uint64) uint64 Timestamper func(*types.TipSet, uint64) uint64
GetMessages func(*ChainGen) ([]*types.SignedMessage, error)
w *wallet.Wallet w *wallet.Wallet
eppProvs map[address.Address]ElectionPoStProver eppProvs map[address.Address]ElectionPoStProver
@@ -210,10 +212,11 @@ func NewGenerator() (*ChainGen, error) {
genesis: genb.Genesis, genesis: genb.Genesis,
w: w, w: w,
Miners: minercfg.MinerAddrs, GetMessages: getRandomMessages,
eppProvs: mgen, Miners: minercfg.MinerAddrs,
banker: banker, eppProvs: mgen,
receivers: receievers, banker: banker,
receivers: receievers,
CurTipset: gents, CurTipset: gents,
@@ -224,6 +227,14 @@ func NewGenerator() (*ChainGen, error) {
return gen, nil return gen, nil
} }
func (cg *ChainGen) SetStateManager(sm *stmgr.StateManager) {
cg.sm = sm
}
func (cg *ChainGen) ChainStore() *store.ChainStore {
return cg.cs
}
func (cg *ChainGen) Genesis() *types.BlockHeader { func (cg *ChainGen) Genesis() *types.BlockHeader {
return cg.genesis return cg.genesis
} }
@@ -295,7 +306,7 @@ func (cg *ChainGen) NextTipSet() (*MinedTipSet, error) {
func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Address) (*MinedTipSet, error) { func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Address) (*MinedTipSet, error) {
var blks []*types.FullBlock var blks []*types.FullBlock
msgs, err := cg.getRandomMessages() msgs, err := cg.GetMessages(cg)
if err != nil { if err != nil {
return nil, xerrors.Errorf("get random messages: %w", err) return nil, xerrors.Errorf("get random messages: %w", err)
} }
@@ -359,7 +370,15 @@ func (cg *ChainGen) ResyncBankerNonce(ts *types.TipSet) error {
return nil return nil
} }
func (cg *ChainGen) getRandomMessages() ([]*types.SignedMessage, error) { func (cg *ChainGen) Banker() address.Address {
return cg.banker
}
func (cg *ChainGen) Wallet() *wallet.Wallet {
return cg.w
}
func getRandomMessages(cg *ChainGen) ([]*types.SignedMessage, error) {
msgs := make([]*types.SignedMessage, cg.msgsPerBlock) msgs := make([]*types.SignedMessage, cg.msgsPerBlock)
for m := range msgs { for m := range msgs {
msg := types.Message{ msg := types.Message{
@@ -400,13 +419,13 @@ func (cg *ChainGen) YieldRepo() (repo.Repo, error) {
type MiningCheckAPI interface { type MiningCheckAPI interface {
ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error) ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error)
StateMinerPower(context.Context, address.Address, *types.TipSet) (api.MinerPower, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (api.MinerPower, error)
StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error) StateMinerWorker(context.Context, address.Address, types.TipSetKey) (address.Address, error)
StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (uint64, error) StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (uint64, error)
StateMinerProvingSet(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) StateMinerProvingSet(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error)
WalletSign(context.Context, address.Address, []byte) (*types.Signature, error) WalletSign(context.Context, address.Address, []byte) (*types.Signature, error)
} }
@@ -420,7 +439,11 @@ func (mca mca) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, lb i
return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), int64(lb)) return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), int64(lb))
} }
func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, ts *types.TipSet) (api.MinerPower, error) { func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (api.MinerPower, error) {
ts, err := mca.sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return api.MinerPower{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
mpow, tpow, err := stmgr.GetPower(ctx, mca.sm, ts, maddr) mpow, tpow, err := stmgr.GetPower(ctx, mca.sm, ts, maddr)
if err != nil { if err != nil {
return api.MinerPower{}, err return api.MinerPower{}, err
@@ -432,15 +455,27 @@ func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, ts *t
}, err }, err
} }
func (mca mca) StateMinerWorker(ctx context.Context, maddr address.Address, ts *types.TipSet) (address.Address, error) { func (mca mca) StateMinerWorker(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (address.Address, error) {
ts, err := mca.sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return address.Undef, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetMinerWorkerRaw(ctx, mca.sm, ts.ParentState(), maddr) return stmgr.GetMinerWorkerRaw(ctx, mca.sm, ts.ParentState(), maddr)
} }
func (mca mca) StateMinerSectorSize(ctx context.Context, maddr address.Address, ts *types.TipSet) (uint64, error) { func (mca mca) StateMinerSectorSize(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (uint64, error) {
ts, err := mca.sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return 0, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetMinerSectorSize(ctx, mca.sm, ts, maddr) return stmgr.GetMinerSectorSize(ctx, mca.sm, ts, maddr)
} }
func (mca mca) StateMinerProvingSet(ctx context.Context, maddr address.Address, ts *types.TipSet) ([]*api.ChainSectorInfo, error) { func (mca mca) StateMinerProvingSet(ctx context.Context, maddr address.Address, tsk types.TipSetKey) ([]*api.ChainSectorInfo, error) {
ts, err := mca.sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetMinerProvingSet(ctx, mca.sm, ts, maddr) return stmgr.GetMinerProvingSet(ctx, mca.sm, ts, maddr)
} }
@@ -484,7 +519,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
return nil, xerrors.Errorf("chain get randomness: %w", err) return nil, xerrors.Errorf("chain get randomness: %w", err)
} }
mworker, err := a.StateMinerWorker(ctx, miner, ts) mworker, err := a.StateMinerWorker(ctx, miner, ts.Key())
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to get miner worker: %w", err) return nil, xerrors.Errorf("failed to get miner worker: %w", err)
} }
@@ -494,7 +529,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
return nil, xerrors.Errorf("failed to compute VRF: %w", err) return nil, xerrors.Errorf("failed to compute VRF: %w", err)
} }
pset, err := a.StateMinerProvingSet(ctx, miner, ts) pset, err := a.StateMinerProvingSet(ctx, miner, ts.Key())
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to load proving set for miner: %w", err) return nil, xerrors.Errorf("failed to load proving set for miner: %w", err)
} }
@@ -519,12 +554,12 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
return nil, xerrors.Errorf("failed to generate electionPoSt candidates: %w", err) return nil, xerrors.Errorf("failed to generate electionPoSt candidates: %w", err)
} }
pow, err := a.StateMinerPower(ctx, miner, ts) pow, err := a.StateMinerPower(ctx, miner, ts.Key())
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to check power: %w", err) return nil, xerrors.Errorf("failed to check power: %w", err)
} }
ssize, err := a.StateMinerSectorSize(ctx, miner, ts) ssize, err := a.StateMinerSectorSize(ctx, miner, ts.Key())
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to look up miners sector size: %w", err) return nil, xerrors.Errorf("failed to look up miners sector size: %w", err)
} }
@@ -611,7 +646,7 @@ func VerifyVRF(ctx context.Context, worker, miner address.Address, p uint64, inp
Data: vrfproof, Data: vrfproof,
} }
if err := sig.Verify(worker, vrfBase); err != nil { if err := sigs.Verify(sig, worker, vrfBase); err != nil {
return xerrors.Errorf("vrf was invalid: %w", err) return xerrors.Errorf("vrf was invalid: %w", err)
} }
+2
View File
@@ -4,6 +4,8 @@ import (
"testing" "testing"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
) )
func init() { func init() {
+3 -3
View File
@@ -254,7 +254,7 @@ func SetupStorageMarketActor(bs bstore.Blockstore, sroot cid.Cid, deals []actors
return cid.Undef, xerrors.Errorf("set storage market actor: %w", err) return cid.Undef, xerrors.Errorf("set storage market actor: %w", err)
} }
return state.Flush() return state.Flush(context.TODO())
} }
type GenMinerCfg struct { type GenMinerCfg struct {
@@ -563,7 +563,7 @@ func MakeGenesisBlock(bs bstore.Blockstore, sys *types.VMSyscalls, balances map[
return nil, xerrors.Errorf("make initial state tree failed: %w", err) return nil, xerrors.Errorf("make initial state tree failed: %w", err)
} }
stateroot, err := state.Flush() stateroot, err := state.Flush(ctx)
if err != nil { if err != nil {
return nil, xerrors.Errorf("flush state tree failed: %w", err) return nil, xerrors.Errorf("flush state tree failed: %w", err)
} }
@@ -673,5 +673,5 @@ func AdjustInitActorStartID(ctx context.Context, bs blockstore.Blockstore, state
return cid.Undef, err return cid.Undef, err
} }
return tree.Flush() return tree.Flush(ctx)
} }
+2 -1
View File
@@ -25,6 +25,7 @@ import (
"github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
) )
@@ -303,7 +304,7 @@ func (mp *MessagePool) addTs(m *types.SignedMessage, curTs *types.TipSet) error
return ErrMessageValueTooHigh return ErrMessageValueTooHigh
} }
if err := m.Signature.Verify(m.Message.From, m.Message.Cid().Bytes()); err != nil { if err := sigs.Verify(&m.Signature, m.Message.From, m.Message.Cid().Bytes()); err != nil {
log.Warnf("mpooladd signature verification failed: %s", err) log.Warnf("mpooladd signature verification failed: %s", err)
return err return err
} }
+2
View File
@@ -9,6 +9,8 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/mock" "github.com/filecoin-project/lotus/chain/types/mock"
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
) )
+1 -1
View File
@@ -95,7 +95,7 @@ func sendHeadNotifs(ctx context.Context, ps *pubsub.PubSub, topic string, chain
case notif := <-notifs: case notif := <-notifs:
n := notif[len(notif)-1] n := notif[len(notif)-1]
w, err := chain.ChainTipSetWeight(ctx, n.Val) w, err := chain.ChainTipSetWeight(ctx, n.Val.Key())
if err != nil { if err != nil {
return err return err
} }
+13 -6
View File
@@ -7,6 +7,7 @@ import (
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld" hamt "github.com/ipfs/go-hamt-ipld"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"go.opencensus.io/trace"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
@@ -116,23 +117,29 @@ func (st *StateTree) GetActor(addr address.Address) (*types.Actor, error) {
return &act, nil return &act, nil
} }
func (st *StateTree) Flush() (cid.Cid, error) { func (st *StateTree) Flush(ctx context.Context) (cid.Cid, error) {
ctx, span := trace.StartSpan(ctx, "stateTree.Flush")
defer span.End()
for addr, act := range st.actorcache { for addr, act := range st.actorcache {
if err := st.root.Set(context.TODO(), string(addr.Bytes()), act); err != nil { if err := st.root.Set(ctx, string(addr.Bytes()), act); err != nil {
return cid.Undef, err return cid.Undef, err
} }
} }
st.actorcache = make(map[address.Address]*types.Actor) st.actorcache = make(map[address.Address]*types.Actor)
if err := st.root.Flush(context.TODO()); err != nil { if err := st.root.Flush(ctx); err != nil {
return cid.Undef, err return cid.Undef, err
} }
return st.Store.Put(context.TODO(), st.root) return st.Store.Put(ctx, st.root)
} }
func (st *StateTree) Snapshot() error { func (st *StateTree) Snapshot(ctx context.Context) error {
ss, err := st.Flush() ctx, span := trace.StartSpan(ctx, "stateTree.SnapShot")
defer span.End()
ss, err := st.Flush(ctx)
if err != nil { if err != nil {
return err return err
} }
+3 -2
View File
@@ -1,6 +1,7 @@
package state package state
import ( import (
"context"
"testing" "testing"
address "github.com/filecoin-project/go-address" address "github.com/filecoin-project/go-address"
@@ -60,7 +61,7 @@ func BenchmarkStateTreeSetFlush(b *testing.B) {
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
if _, err := st.Flush(); err != nil { if _, err := st.Flush(context.TODO()); err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
@@ -88,7 +89,7 @@ func BenchmarkStateTree10kGetActor(b *testing.B) {
} }
} }
if _, err := st.Flush(); err != nil { if _, err := st.Flush(context.TODO()); err != nil {
b.Fatal(err) b.Fatal(err)
} }
+9 -3
View File
@@ -8,13 +8,14 @@ import (
"go.opencensus.io/trace" "go.opencensus.io/trace"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
) )
func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate cid.Cid, r vm.Rand, bheight uint64) (*types.MessageReceipt, error) { func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate cid.Cid, r vm.Rand, bheight uint64) (*api.MethodCall, error) {
ctx, span := trace.StartSpan(ctx, "statemanager.CallRaw") ctx, span := trace.StartSpan(ctx, "statemanager.CallRaw")
defer span.End() defer span.End()
@@ -54,14 +55,19 @@ func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate
return nil, xerrors.Errorf("apply message failed: %w", err) return nil, xerrors.Errorf("apply message failed: %w", err)
} }
var errs string
if ret.ActorErr != nil { if ret.ActorErr != nil {
errs = ret.ActorErr.Error()
log.Warnf("chain call failed: %s", ret.ActorErr) log.Warnf("chain call failed: %s", ret.ActorErr)
} }
return &ret.MessageReceipt, nil return &api.MethodCall{
MessageReceipt: ret.MessageReceipt,
Error: errs,
}, nil
} }
func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) { func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.MethodCall, error) {
if ts == nil { if ts == nil {
ts = sm.cs.GetHeaviestTipSet() ts = sm.cs.GetHeaviestTipSet()
} }
+93 -18
View File
@@ -7,6 +7,7 @@ import (
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld" hamt "github.com/ipfs/go-hamt-ipld"
blockstore "github.com/ipfs/go-ipfs-blockstore" blockstore "github.com/ipfs/go-ipfs-blockstore"
@@ -14,33 +15,107 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
) )
var ForksAtHeight = map[uint64]func(context.Context, *StateManager, cid.Cid) (cid.Cid, error){
build.ForkBlizzardHeight: func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
log.Warnw("Executing blizzard fork logic")
nstate, err := fixBlizzardAMTBug(ctx, sm, pstate)
if err != nil {
return cid.Undef, xerrors.Errorf("blizzard bug fix failed: %w", err)
}
return nstate, nil
},
build.ForkFrigidHeight: func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
log.Warnw("Executing frigid fork logic")
nstate, err := fixBlizzardAMTBug(ctx, sm, pstate)
if err != nil {
return cid.Undef, xerrors.Errorf("frigid bug fix failed: %w", err)
}
return nstate, nil
},
build.ForkBootyBayHeight: func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
log.Warnw("Executing booty bay fork logic")
nstate, err := fixBlizzardAMTBug(ctx, sm, pstate)
if err != nil {
return cid.Undef, xerrors.Errorf("booty bay bug fix failed: %w", err)
}
return nstate, nil
},
build.ForkMissingSnowballs: func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
log.Warnw("Adding more snow to the world")
nstate, err := fixTooFewSnowballs(ctx, sm, pstate)
if err != nil {
return cid.Undef, xerrors.Errorf("missing snowballs bug fix failed: %w", err)
}
return nstate, nil
},
}
func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, height, parentH uint64) (_ cid.Cid, err error) { func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, height, parentH uint64) (_ cid.Cid, err error) {
for i := parentH; i < height; i++ { for i := parentH; i < height; i++ {
switch i { f, ok := ForksAtHeight[i]
case build.ForkBlizzardHeight: if ok {
log.Warnw("Executing blizzard fork logic", "height", i) nstate, err := f(ctx, sm, pstate)
pstate, err = fixBlizzardAMTBug(ctx, sm, pstate)
if err != nil { if err != nil {
return cid.Undef, xerrors.Errorf("blizzard bug fix failed: %w", err) return cid.Undef, err
}
case build.ForkFrigidHeight:
log.Warnw("Executing frigid fork logic", "height", i)
pstate, err = fixBlizzardAMTBug(ctx, sm, pstate)
if err != nil {
return cid.Undef, xerrors.Errorf("frigid bug fix failed: %w", err)
}
case build.ForkBootyBayHeight:
log.Warnw("Executing booty bay fork logic", "height", i)
pstate, err = fixBlizzardAMTBug(ctx, sm, pstate)
if err != nil {
return cid.Undef, xerrors.Errorf("booty bay bug fix failed: %w", err)
} }
pstate = nstate
} }
} }
return pstate, nil return pstate, nil
} }
func fixTooFewSnowballs(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
cst := hamt.CSTFromBstore(sm.cs.Blockstore())
st, err := state.LoadStateTree(cst, pstate)
if err != nil {
return cid.Undef, err
}
spa, err := st.GetActor(actors.StoragePowerAddress)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to get storage power actor: %w", err)
}
var spast actors.StoragePowerState
if err := cst.Get(ctx, spa.Head, &spast); err != nil {
return cid.Undef, err
}
miners, err := actors.MinerSetList(ctx, cst, spast.Miners)
if err != nil {
return cid.Undef, err
}
sum := types.NewInt(0)
for _, m := range miners {
mact, err := st.GetActor(m)
if err != nil {
return cid.Undef, xerrors.Errorf("getting miner actor to fix: %w", err)
}
var mstate actors.StorageMinerActorState
if err := cst.Get(ctx, mact.Head, &mstate); err != nil {
return cid.Undef, xerrors.Errorf("failed to load miner actor state: %w", err)
}
if mstate.SlashedAt != 0 {
continue
}
sum = types.BigAdd(sum, mstate.Power)
}
spast.TotalStorage = sum
nspahead, err := cst.Put(ctx, &spast)
if err != nil {
return cid.Undef, err
}
spa.Head = nspahead
return st.Flush(ctx)
}
/* /*
1) Iterate through each miner in the chain: 1) Iterate through each miner in the chain:
1.1) Fixup their sector set and proving set 1.1) Fixup their sector set and proving set
@@ -91,7 +166,7 @@ func fixBlizzardAMTBug(ctx context.Context, sm *StateManager, pstate cid.Cid) (c
} }
} }
return st.Flush() return st.Flush(ctx)
} }
func fixMiner(ctx context.Context, cst *hamt.CborIpldStore, bs blockstore.Blockstore, mscid cid.Cid) (cid.Cid, error) { func fixMiner(ctx context.Context, cst *hamt.CborIpldStore, bs blockstore.Blockstore, mscid cid.Cid) (cid.Cid, error) {
+233
View File
@@ -0,0 +1,233 @@
package stmgr_test
import (
"context"
"fmt"
"io"
"testing"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr"
. "github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
blockstore "github.com/ipfs/go-ipfs-blockstore"
logging "github.com/ipfs/go-log"
mh "github.com/multiformats/go-multihash"
cbg "github.com/whyrusleeping/cbor-gen"
)
func init() {
build.SectorSizes = []uint64{1024}
build.MinimumMinerPower = 1024
}
const testForkHeight = 40
type testActor struct {
}
type testActorState struct {
HasUpgraded uint64
}
func (tas *testActorState) MarshalCBOR(w io.Writer) error {
return cbg.CborWriteHeader(w, cbg.MajUnsignedInt, tas.HasUpgraded)
}
func (tas *testActorState) UnmarshalCBOR(r io.Reader) error {
t, v, err := cbg.CborReadHeader(r)
if err != nil {
return err
}
if t != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type in test actor state")
}
tas.HasUpgraded = v
return nil
}
func (ta *testActor) Exports() []interface{} {
return []interface{}{
1: ta.Constructor,
2: ta.TestMethod,
}
}
func (ta *testActor) Constructor(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
c, err := vmctx.Storage().Put(&testActorState{11})
if err != nil {
return nil, err
}
fmt.Println("NEW ACTOR ADDRESS IS: ", vmctx.Message().To.String())
return nil, vmctx.Storage().Commit(actors.EmptyCBOR, c)
}
func (ta *testActor) TestMethod(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
var st testActorState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &st); err != nil {
return nil, err
}
if vmctx.BlockHeight() > testForkHeight {
if st.HasUpgraded != 55 {
return nil, aerrors.Fatal("fork updating applied in wrong order")
}
} else {
if st.HasUpgraded != 11 {
return nil, aerrors.Fatal("fork updating happened too early")
}
}
return nil, nil
}
func TestForkHeightTriggers(t *testing.T) {
logging.SetAllLoggers(logging.LevelInfo)
ctx := context.TODO()
cg, err := gen.NewGenerator()
if err != nil {
t.Fatal(err)
}
sm := NewStateManager(cg.ChainStore())
inv := vm.NewInvoker()
pref := cid.NewPrefixV1(cid.Raw, mh.IDENTITY)
actcid, err := pref.Sum([]byte("testactor"))
if err != nil {
t.Fatal(err)
}
actors.BuiltInActors[actcid] = true
// predicting the address here... may break if other assumptions change
taddr, err := address.NewIDAddress(1000)
if err != nil {
t.Fatal(err)
}
stmgr.ForksAtHeight[testForkHeight] = func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
cst := hamt.CSTFromBstore(sm.ChainStore().Blockstore())
st, err := state.LoadStateTree(cst, pstate)
if err != nil {
return cid.Undef, err
}
act, err := st.GetActor(taddr)
if err != nil {
return cid.Undef, err
}
var tas testActorState
if err := cst.Get(ctx, act.Head, &tas); err != nil {
return cid.Undef, err
}
tas.HasUpgraded = 55
ns, err := cst.Put(ctx, &tas)
if err != nil {
return cid.Undef, err
}
act.Head = ns
if err := st.SetActor(taddr, act); err != nil {
return cid.Undef, err
}
return st.Flush(ctx)
}
inv.Register(actcid, &testActor{}, &testActorState{})
sm.SetVMConstructor(func(c cid.Cid, h uint64, r vm.Rand, a address.Address, b blockstore.Blockstore, s *types.VMSyscalls) (*vm.VM, error) {
nvm, err := vm.NewVM(c, h, r, a, b, s)
if err != nil {
return nil, err
}
nvm.SetInvoker(inv)
return nvm, nil
})
cg.SetStateManager(sm)
var msgs []*types.SignedMessage
enc, err := actors.SerializeParams(&actors.ExecParams{Code: actcid})
if err != nil {
t.Fatal(err)
}
m := &types.Message{
From: cg.Banker(),
To: actors.InitAddress,
Method: actors.IAMethods.Exec,
Params: enc,
GasLimit: types.NewInt(10000),
GasPrice: types.NewInt(0),
}
sig, err := cg.Wallet().Sign(ctx, cg.Banker(), m.Cid().Bytes())
if err != nil {
t.Fatal(err)
}
msgs = append(msgs, &types.SignedMessage{
Signature: *sig,
Message: *m,
})
nonce := uint64(1)
cg.GetMessages = func(cg *gen.ChainGen) ([]*types.SignedMessage, error) {
if len(msgs) > 0 {
fmt.Println("added construct method")
m := msgs
msgs = nil
return m, nil
}
m := &types.Message{
From: cg.Banker(),
To: taddr,
Method: 2,
Params: nil,
Nonce: nonce,
GasLimit: types.NewInt(10000),
GasPrice: types.NewInt(0),
}
nonce++
sig, err := cg.Wallet().Sign(ctx, cg.Banker(), m.Cid().Bytes())
if err != nil {
return nil, err
}
return []*types.SignedMessage{
&types.SignedMessage{
Signature: *sig,
Message: *m,
},
}, nil
}
for i := 0; i < 50; i++ {
_, err = cg.NextTipSet()
if err != nil {
t.Fatal(err)
}
}
}
+37 -1
View File
@@ -18,6 +18,7 @@ import (
bls "github.com/filecoin-project/filecoin-ffi" bls "github.com/filecoin-project/filecoin-ffi"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld" hamt "github.com/ipfs/go-hamt-ipld"
blockstore "github.com/ipfs/go-ipfs-blockstore"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"go.opencensus.io/trace" "go.opencensus.io/trace"
) )
@@ -30,10 +31,12 @@ type StateManager struct {
stCache map[string][]cid.Cid stCache map[string][]cid.Cid
compWait map[string]chan struct{} compWait map[string]chan struct{}
stlk sync.Mutex stlk sync.Mutex
newVM func(cid.Cid, uint64, vm.Rand, address.Address, blockstore.Blockstore, *types.VMSyscalls) (*vm.VM, error)
} }
func NewStateManager(cs *store.ChainStore) *StateManager { func NewStateManager(cs *store.ChainStore) *StateManager {
return &StateManager{ return &StateManager{
newVM: vm.NewVM,
cs: cs, cs: cs,
stCache: make(map[string][]cid.Cid), stCache: make(map[string][]cid.Cid),
compWait: make(map[string]chan struct{}), compWait: make(map[string]chan struct{}),
@@ -139,7 +142,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
r := store.NewChainRand(sm.cs, cids, blks[0].Height) r := store.NewChainRand(sm.cs, cids, blks[0].Height)
vmi, err := vm.NewVM(pstate, blks[0].Height, r, address.Undef, sm.cs.Blockstore(), sm.cs.VMSys()) vmi, err := sm.newVM(pstate, blks[0].Height, r, address.Undef, sm.cs.Blockstore(), sm.cs.VMSys())
if err != nil { if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err) return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
} }
@@ -607,3 +610,36 @@ func (sm *StateManager) MarketBalance(ctx context.Context, addr address.Address,
return b[0], nil return b[0], nil
} }
func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) error {
tschain := []*types.TipSet{ts}
for ts.Height() != 0 {
next, err := sm.cs.LoadTipSet(ts.Parents())
if err != nil {
return err
}
tschain = append(tschain, next)
ts = next
}
lastState := tschain[len(tschain)-1].ParentState()
for i := len(tschain) - 1; i >= 0; i-- {
cur := tschain[i]
log.Infof("computing state (height: %d, ts=%s)", cur.Height(), cur.Cids())
if cur.ParentState() != lastState {
return xerrors.Errorf("tipset chain had state mismatch at height %d", cur.Height())
}
st, _, err := sm.TipSetState(ctx, cur)
if err != nil {
return err
}
lastState = st
}
return nil
}
func (sm *StateManager) SetVMConstructor(nvm func(cid.Cid, uint64, vm.Rand, address.Address, blockstore.Blockstore, *types.VMSyscalls) (*vm.VM, error)) {
sm.newVM = nvm
}
+17
View File
@@ -2,6 +2,8 @@ package stmgr
import ( import (
"context" "context"
amt2 "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
ffi "github.com/filecoin-project/filecoin-ffi" ffi "github.com/filecoin-project/filecoin-ffi"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder" sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
@@ -253,6 +255,21 @@ func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, ma
return mas.SlashedAt, nil return mas.SlashedAt, nil
} }
func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]uint64, error) {
var mas actors.StorageMinerActorState
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return nil, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
}
ss, lerr := amt2.LoadAMT(amt.WrapBlockstore(sm.cs.Blockstore()), mas.Sectors)
if lerr != nil {
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
}
return mas.FaultSet.All(2 * ss.Count)
}
func GetStorageDeal(ctx context.Context, sm *StateManager, dealId uint64, ts *types.TipSet) (*actors.OnChainDeal, error) { func GetStorageDeal(ctx context.Context, sm *StateManager, dealId uint64, ts *types.TipSet) (*actors.OnChainDeal, error) {
var state actors.StorageMarketState var state actors.StorageMarketState
if _, err := sm.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil { if _, err := sm.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil {
+93
View File
@@ -1,10 +1,12 @@
package store package store
import ( import (
"bytes"
"context" "context"
"crypto/sha256" "crypto/sha256"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"io"
"sync" "sync"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
@@ -19,11 +21,16 @@ import (
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
block "github.com/ipfs/go-block-format" block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-blockservice"
car "github.com/ipfs/go-car"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore" dstore "github.com/ipfs/go-datastore"
hamt "github.com/ipfs/go-hamt-ipld" hamt "github.com/ipfs/go-hamt-ipld"
blockstore "github.com/ipfs/go-ipfs-blockstore"
bstore "github.com/ipfs/go-ipfs-blockstore" bstore "github.com/ipfs/go-ipfs-blockstore"
format "github.com/ipfs/go-ipld-format"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
dag "github.com/ipfs/go-merkledag"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
pubsub "github.com/whyrusleeping/pubsub" pubsub "github.com/whyrusleeping/pubsub"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@@ -917,6 +924,84 @@ func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h uint64, ts *types
} }
} }
func recurseLinks(bs blockstore.Blockstore, root cid.Cid, in []cid.Cid) ([]cid.Cid, error) {
data, err := bs.Get(root)
if err != nil {
return nil, err
}
top, err := cbg.ScanForLinks(bytes.NewReader(data.RawData()))
if err != nil {
return nil, err
}
in = append(in, top...)
for _, c := range top {
var err error
in, err = recurseLinks(bs, c, in)
if err != nil {
return nil, err
}
}
return in, nil
}
func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, w io.Writer) error {
if ts == nil {
ts = cs.GetHeaviestTipSet()
}
bsrv := blockservice.New(cs.bs, nil)
dserv := dag.NewDAGService(bsrv)
return car.WriteCarWithWalker(ctx, dserv, ts.Cids(), w, func(nd format.Node) ([]*format.Link, error) {
var b types.BlockHeader
if err := b.UnmarshalCBOR(bytes.NewBuffer(nd.RawData())); err != nil {
return nil, err
}
var out []*format.Link
for _, p := range b.Parents {
out = append(out, &format.Link{Cid: p})
}
cids, err := recurseLinks(cs.bs, b.Messages, nil)
if err != nil {
return nil, err
}
for _, c := range cids {
out = append(out, &format.Link{Cid: c})
}
if b.Height == 0 {
cids, err := recurseLinks(cs.bs, b.ParentStateRoot, nil)
if err != nil {
return nil, err
}
for _, c := range cids {
out = append(out, &format.Link{Cid: c})
}
}
return out, nil
})
}
func (cs *ChainStore) Import(r io.Reader) (*types.TipSet, error) {
header, err := car.LoadCar(cs.Blockstore(), r)
if err != nil {
return nil, xerrors.Errorf("loadcar failed: %w", err)
}
root, err := cs.LoadTipSet(types.NewTipSetKey(header.Roots...))
if err != nil {
return nil, xerrors.Errorf("failed to load root tipset from chainfile: %w", err)
}
return root, nil
}
type chainRand struct { type chainRand struct {
cs *ChainStore cs *ChainStore
blks []cid.Cid blks []cid.Cid
@@ -934,3 +1019,11 @@ func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight uint64) vm.Rand {
func (cr *chainRand) GetRandomness(ctx context.Context, round int64) ([]byte, error) { func (cr *chainRand) GetRandomness(ctx context.Context, round int64) ([]byte, error) {
return cr.cs.GetRandomness(ctx, cr.blks, round) return cr.cs.GetRandomness(ctx, cr.blks, round)
} }
func (cs *ChainStore) GetTipSetFromKey(tsk types.TipSetKey) (*types.TipSet, error) {
if tsk.IsEmpty() {
return cs.GetHeaviestTipSet(), nil
} else {
return cs.LoadTipSet(tsk)
}
}
+92 -12
View File
@@ -4,8 +4,11 @@ import (
"context" "context"
"time" "time"
lru "github.com/hashicorp/golang-lru"
"github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
connmgr "github.com/libp2p/go-libp2p-core/connmgr" connmgr "github.com/libp2p/go-libp2p-core/connmgr"
peer "github.com/libp2p/go-libp2p-peer"
pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
@@ -28,15 +31,9 @@ func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *cha
continue continue
} }
blk, err := types.DecodeBlockMsg(msg.GetData()) blk, ok := msg.ValidatorData.(*types.BlockMsg)
if err != nil { if !ok {
log.Error("got invalid block over pubsub: ", err) log.Warnf("pubsub block validator passed on wrong type: %#v", msg.ValidatorData)
continue
}
if len(blk.BlsMessages)+len(blk.SecpkMessages) > build.BlockMessageLimit {
log.Warnf("received block with too many messages over pubsub")
continue
} }
go func() { go func() {
@@ -73,6 +70,89 @@ func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *cha
} }
} }
type BlockValidator struct {
peers *lru.TwoQueueCache
killThresh int
recvBlocks *blockReceiptCache
blacklist func(peer.ID)
}
func NewBlockValidator(blacklist func(peer.ID)) *BlockValidator {
p, _ := lru.New2Q(4096)
return &BlockValidator{
peers: p,
killThresh: 5,
blacklist: blacklist,
recvBlocks: newBlockReceiptCache(),
}
}
func (bv *BlockValidator) flagPeer(p peer.ID) {
v, ok := bv.peers.Get(p)
if !ok {
bv.peers.Add(p, int(1))
return
}
val := v.(int)
if val >= bv.killThresh {
bv.blacklist(p)
}
bv.peers.Add(p, v.(int)+1)
}
func (bv *BlockValidator) Validate(ctx context.Context, pid peer.ID, msg *pubsub.Message) bool {
blk, err := types.DecodeBlockMsg(msg.GetData())
if err != nil {
log.Error("got invalid block over pubsub: ", err)
bv.flagPeer(pid)
return false
}
if len(blk.BlsMessages)+len(blk.SecpkMessages) > build.BlockMessageLimit {
log.Warnf("received block with too many messages over pubsub")
bv.flagPeer(pid)
return false
}
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 false
}
msg.ValidatorData = blk
return true
}
type blockReceiptCache struct {
blocks *lru.TwoQueueCache
}
func newBlockReceiptCache() *blockReceiptCache {
c, _ := lru.New2Q(8192)
return &blockReceiptCache{
blocks: c,
}
}
func (brc *blockReceiptCache) add(bcid cid.Cid) int {
val, ok := brc.blocks.Get(bcid)
if !ok {
brc.blocks.Add(bcid, int(1))
return 0
}
brc.blocks.Add(bcid, val.(int)+1)
return val.(int)
}
func HandleIncomingMessages(ctx context.Context, mpool *messagepool.MessagePool, msub *pubsub.Subscription) { func HandleIncomingMessages(ctx context.Context, mpool *messagepool.MessagePool, msub *pubsub.Subscription) {
for { for {
msg, err := msub.Next(ctx) msg, err := msub.Next(ctx)
@@ -85,9 +165,9 @@ func HandleIncomingMessages(ctx context.Context, mpool *messagepool.MessagePool,
continue continue
} }
m, err := types.DecodeSignedMessage(msg.GetData()) m, ok := msg.ValidatorData.(*types.SignedMessage)
if err != nil { if !ok {
log.Errorf("got incorrectly formatted Message: %s", err) log.Errorf("message validator func passed on wrong type: %#v", msg.ValidatorData)
continue continue
} }
+23 -14
View File
@@ -37,6 +37,7 @@ import (
"github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
) )
var log = logging.Logger("chain") var log = logging.Logger("chain")
@@ -117,6 +118,10 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) bool {
} }
for _, b := range fts.Blocks { 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)
return false
}
if err := syncer.ValidateMsgMeta(b); err != nil { if err := syncer.ValidateMsgMeta(b); err != nil {
log.Warnf("invalid block received: %s", err) log.Warnf("invalid block received: %s", err)
return false return false
@@ -445,7 +450,7 @@ func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet)
for _, b := range fts.Blocks { for _, b := range fts.Blocks {
if err := syncer.ValidateBlock(ctx, b); err != nil { if err := syncer.ValidateBlock(ctx, b); err != nil {
if isPermanent(err) { if isPermanent(err) {
syncer.bad.Add(b.Cid()) syncer.bad.Add(b.Cid(), err.Error())
} }
return xerrors.Errorf("validating block %s: %w", b.Cid(), err) return xerrors.Errorf("validating block %s: %w", b.Cid(), err)
} }
@@ -604,7 +609,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
} }
blockSigCheck := async.Err(func() error { blockSigCheck := async.Err(func() error {
if err := h.CheckBlockSignature(ctx, waddr); err != nil { if err := sigs.CheckBlockSignature(h, ctx, waddr); err != nil {
return xerrors.Errorf("check block signature failed: %w", err) return xerrors.Errorf("check block signature failed: %w", err)
} }
return nil return nil
@@ -787,7 +792,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
return xerrors.Errorf("failed to resolve key addr: %w", err) return xerrors.Errorf("failed to resolve key addr: %w", err)
} }
if err := m.Signature.Verify(kaddr, m.Message.Cid().Bytes()); err != nil { if err := sigs.Verify(&m.Signature, kaddr, m.Message.Cid().Bytes()); err != nil {
return xerrors.Errorf("secpk message %s has invalid signature: %w", m.Cid(), err) return xerrors.Errorf("secpk message %s has invalid signature: %w", m.Cid(), err)
} }
@@ -871,11 +876,11 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to
) )
for _, pcid := range from.Parents().Cids() { for _, pcid := range from.Parents().Cids() {
if syncer.bad.Has(pcid) { if reason, ok := syncer.bad.Has(pcid); ok {
for _, b := range from.Cids() { for _, b := range from.Cids() {
syncer.bad.Add(b) syncer.bad.Add(b, fmt.Sprintf("linked to %s", pcid))
} }
return nil, xerrors.Errorf("chain linked to block marked previously as bad (%s, %s)", from.Cids(), pcid) return nil, xerrors.Errorf("chain linked to block marked previously as bad (%s, %s) (reason: %s)", from.Cids(), pcid, reason)
} }
} }
@@ -893,12 +898,12 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to
loop: loop:
for blockSet[len(blockSet)-1].Height() > untilHeight { for blockSet[len(blockSet)-1].Height() > untilHeight {
for _, bc := range at.Cids() { for _, bc := range at.Cids() {
if syncer.bad.Has(bc) { if reason, ok := syncer.bad.Has(bc); ok {
for _, b := range acceptedBlocks { for _, b := range acceptedBlocks {
syncer.bad.Add(b) syncer.bad.Add(b, fmt.Sprintf("chain contained %s", bc))
} }
return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s)", from.Cids(), bc) return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s) (reason: %s)", from.Cids(), bc, reason)
} }
} }
@@ -941,12 +946,12 @@ loop:
break loop break loop
} }
for _, bc := range b.Cids() { for _, bc := range b.Cids() {
if syncer.bad.Has(bc) { if reason, ok := syncer.bad.Has(bc); ok {
for _, b := range acceptedBlocks { for _, b := range acceptedBlocks {
syncer.bad.Add(b) syncer.bad.Add(b, fmt.Sprintf("chain contained %s", bc))
} }
return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s)", from.Cids(), bc) return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s) (reason: %s)", from.Cids(), bc, reason)
} }
} }
blockSet = append(blockSet, b) blockSet = append(blockSet, b)
@@ -973,7 +978,7 @@ loop:
// TODO: we're marking this block bad in the same way that we mark invalid blocks bad. Maybe distinguish? // 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") log.Warn("adding forked chain to our bad tipset cache")
for _, b := range from.Blocks() { for _, b := range from.Blocks() {
syncer.bad.Add(b.Cid()) syncer.bad.Add(b.Cid(), "fork past finality")
} }
} }
return nil, xerrors.Errorf("failed to sync fork: %w", err) return nil, xerrors.Errorf("failed to sync fork: %w", err)
@@ -1190,5 +1195,9 @@ func (syncer *Syncer) State() []SyncerState {
} }
func (syncer *Syncer) MarkBad(blk cid.Cid) { func (syncer *Syncer) MarkBad(blk cid.Cid) {
syncer.bad.Add(blk) syncer.bad.Add(blk, "manually marked bad")
}
func (syncer *Syncer) CheckBadBlockCache(blk cid.Cid) (string, bool) {
return syncer.bad.Has(blk)
} }
+1 -1
View File
@@ -73,7 +73,7 @@ func prepSyncTest(t testing.TB, h int) *syncTestUtil {
g, err := gen.NewGenerator() g, err := gen.NewGenerator()
if err != nil { if err != nil {
t.Fatal(err) t.Fatalf("%+v", err)
} }
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
+18 -34
View File
@@ -2,16 +2,12 @@ package types
import ( import (
"bytes" "bytes"
"context"
"math/big" "math/big"
"github.com/filecoin-project/go-sectorbuilder"
block "github.com/ipfs/go-block-format" block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/minio/sha256-simd" "github.com/minio/sha256-simd"
"github.com/multiformats/go-multihash" "github.com/multiformats/go-multihash"
"go.opencensus.io/trace"
xerrors "golang.org/x/xerrors" xerrors "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
@@ -36,31 +32,31 @@ type EPostProof struct {
} }
type BlockHeader struct { type BlockHeader struct {
Miner address.Address Miner address.Address // 0
Ticket *Ticket Ticket *Ticket // 1
EPostProof EPostProof EPostProof EPostProof // 2
Parents []cid.Cid Parents []cid.Cid // 3
ParentWeight BigInt ParentWeight BigInt // 4
Height uint64 Height uint64 // 5
ParentStateRoot cid.Cid ParentStateRoot cid.Cid // 6
ParentMessageReceipts cid.Cid ParentMessageReceipts cid.Cid // 7
Messages cid.Cid Messages cid.Cid // 8
BLSAggregate Signature BLSAggregate Signature // 9
Timestamp uint64 Timestamp uint64 // 10
BlockSig *Signature BlockSig *Signature // 11
ForkSignaling uint64 ForkSignaling uint64 // 12
} }
func (b *BlockHeader) ToStorageBlock() (block.Block, error) { func (b *BlockHeader) ToStorageBlock() (block.Block, error) {
@@ -116,22 +112,6 @@ func (blk *BlockHeader) SigningBytes() ([]byte, error) {
return blkcopy.Serialize() return blkcopy.Serialize()
} }
func (blk *BlockHeader) CheckBlockSignature(ctx context.Context, worker address.Address) error {
_, span := trace.StartSpan(ctx, "checkBlockSignature")
defer span.End()
if blk.BlockSig == nil {
return xerrors.New("block signature not present")
}
sigb, err := blk.SigningBytes()
if err != nil {
return xerrors.Errorf("failed to get block signing bytes: %w", err)
}
return blk.BlockSig.Verify(worker, sigb)
}
type MsgMeta struct { type MsgMeta struct {
BlsMessages cid.Cid BlsMessages cid.Cid
SecpkMessages cid.Cid SecpkMessages cid.Cid
@@ -223,7 +203,11 @@ func IsTicketWinner(partialTicket []byte, ssizeI uint64, snum uint64, totpow Big
} }
func ElectionPostChallengeCount(sectors uint64, faults uint64) uint64 { func ElectionPostChallengeCount(sectors uint64, faults uint64) uint64 {
return sectorbuilder.ElectionPostChallengeCount(sectors, faults) if sectors-faults == 0 {
return 0
}
// ceil(sectors / SectorChallengeRatioDiv)
return (sectors-faults-1)/build.SectorChallengeRatioDiv + 1
} }
func (t *Ticket) Equals(ot *Ticket) bool { func (t *Ticket) Equals(ot *Ticket) bool {
-60
View File
@@ -1,60 +0,0 @@
//+build cgo
package types
import (
"fmt"
bls "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-crypto"
"github.com/minio/blake2b-simd"
"golang.org/x/xerrors"
)
func (s *Signature) Verify(addr address.Address, msg []byte) error {
if s == nil {
return xerrors.Errorf("signature is nil")
}
if addr.Protocol() == address.ID {
return fmt.Errorf("must resolve ID addresses before using them to verify a signature")
}
b2sum := blake2b.Sum256(msg)
switch s.Type {
case KTSecp256k1:
pubk, err := crypto.EcRecover(b2sum[:], s.Data)
if err != nil {
return err
}
maybeaddr, err := address.NewSecp256k1Address(pubk)
if err != nil {
return err
}
if addr != maybeaddr {
return fmt.Errorf("signature did not match")
}
return nil
case KTBLS:
digests := []bls.Digest{bls.Hash(bls.Message(msg))}
var pubk bls.PublicKey
copy(pubk[:], addr.Payload())
pubkeys := []bls.PublicKey{pubk}
var sig bls.Signature
copy(sig[:], s.Data)
if !bls.Verify(&sig, digests, pubkeys) {
return fmt.Errorf("bls signature failed to verify")
}
return nil
default:
return fmt.Errorf("cannot verify signature of unsupported type: %s", s.Type)
}
}
+3
View File
@@ -129,6 +129,9 @@ func (ts *TipSet) Cids() []cid.Cid {
} }
func (ts *TipSet) Key() TipSetKey { func (ts *TipSet) Key() TipSetKey {
if ts == nil {
return EmptyTSK
}
return NewTipSetKey(ts.cids...) return NewTipSetKey(ts.cids...)
} }
+6
View File
@@ -9,6 +9,8 @@ import (
"github.com/multiformats/go-multihash" "github.com/multiformats/go-multihash"
) )
var EmptyTSK = TipSetKey{}
// The length of a block header CID in bytes. // The length of a block header CID in bytes.
var blockHeaderCIDLen int var blockHeaderCIDLen int
@@ -90,6 +92,10 @@ func (k *TipSetKey) UnmarshalJSON(b []byte) error {
return nil return nil
} }
func (k TipSetKey) IsEmpty() bool {
return len(k.value) == 0
}
func encodeKey(cids []cid.Cid) []byte { func encodeKey(cids []cid.Cid) []byte {
buffer := new(bytes.Buffer) buffer := new(bytes.Buffer)
for _, c := range cids { for _, c := range cids {
+17 -3
View File
@@ -2,11 +2,11 @@ package types
import ( import (
"context" "context"
"github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-amt-ipld" "github.com/filecoin-project/go-amt-ipld"
"github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/actors/aerrors"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld" hamt "github.com/ipfs/go-hamt-ipld"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
@@ -46,14 +46,28 @@ type VMContext interface {
Context() context.Context Context() context.Context
} }
const CommitmentBytesLen = 32
type PublicSectorInfo struct {
SectorID uint64
CommR [CommitmentBytesLen]byte
}
type Candidate struct {
SectorID uint64
PartialTicket [32]byte
Ticket [32]byte
SectorChallengeIndex uint64
}
type VMSyscalls struct { type VMSyscalls struct {
ValidatePoRep func(context.Context, address.Address, uint64, []byte, []byte, []byte, []byte, []byte, uint64) (bool, aerrors.ActorError) ValidatePoRep func(context.Context, address.Address, uint64, []byte, []byte, []byte, []byte, []byte, uint64) (bool, aerrors.ActorError)
VerifyFallbackPost func(ctx context.Context, VerifyFallbackPost func(ctx context.Context,
sectorSize uint64, sectorSize uint64,
sectorInfo sectorbuilder.SortedPublicSectorInfo, sectorInfo []PublicSectorInfo,
challengeSeed []byte, challengeSeed []byte,
proof []byte, proof []byte,
candidates []sectorbuilder.EPostCandidate, candidates []Candidate,
proverID address.Address, proverID address.Address,
faults uint64) (bool, error) faults uint64) (bool, error)
} }
+1
View File
@@ -16,6 +16,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
) )
func TestMessageFactory(t *testing.T) { func TestMessageFactory(t *testing.T) {
+2 -2
View File
@@ -59,7 +59,7 @@ func NewState() *StateWrapper {
if err != nil { if err != nil {
panic(err) // Never returns error, the error return should be removed. panic(err) // Never returns error, the error return should be removed.
} }
root, err := treeImpl.Flush() root, err := treeImpl.Flush(context.TODO())
if err != nil { if err != nil {
panic(err) panic(err)
} }
@@ -208,7 +208,7 @@ func (s *StateWrapper) Signer() *keyStore {
// Flushes a state tree to storage and sets this state's root to that tree's root CID. // Flushes a state tree to storage and sets this state's root to that tree's root CID.
func (s *StateWrapper) flush(tree *state.StateTree) (err error) { func (s *StateWrapper) flush(tree *state.StateTree) (err error) {
s.stateRoot, err = tree.Flush() s.stateRoot, err = tree.Flush(context.TODO())
return return
} }
+15 -11
View File
@@ -23,21 +23,21 @@ type invoker struct {
type invokeFunc func(act *types.Actor, vmctx types.VMContext, params []byte) ([]byte, aerrors.ActorError) type invokeFunc func(act *types.Actor, vmctx types.VMContext, params []byte) ([]byte, aerrors.ActorError)
type nativeCode []invokeFunc type nativeCode []invokeFunc
func newInvoker() *invoker { func NewInvoker() *invoker {
inv := &invoker{ inv := &invoker{
builtInCode: make(map[cid.Cid]nativeCode), builtInCode: make(map[cid.Cid]nativeCode),
builtInState: make(map[cid.Cid]reflect.Type), builtInState: make(map[cid.Cid]reflect.Type),
} }
// add builtInCode using: register(cid, singleton) // add builtInCode using: register(cid, singleton)
inv.register(actors.InitCodeCid, actors.InitActor{}, actors.InitActorState{}) inv.Register(actors.InitCodeCid, actors.InitActor{}, actors.InitActorState{})
inv.register(actors.CronCodeCid, actors.CronActor{}, actors.CronActorState{}) inv.Register(actors.CronCodeCid, actors.CronActor{}, actors.CronActorState{})
inv.register(actors.StoragePowerCodeCid, actors.StoragePowerActor{}, actors.StoragePowerState{}) inv.Register(actors.StoragePowerCodeCid, actors.StoragePowerActor{}, actors.StoragePowerState{})
inv.register(actors.StorageMarketCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{}) inv.Register(actors.StorageMarketCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{})
inv.register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{}) inv.Register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{})
inv.register(actors.StorageMiner2CodeCid, actors.StorageMinerActor2{}, actors.StorageMinerActorState{}) inv.Register(actors.StorageMiner2CodeCid, actors.StorageMinerActor2{}, actors.StorageMinerActorState{})
inv.register(actors.MultisigCodeCid, actors.MultiSigActor{}, actors.MultiSigActorState{}) inv.Register(actors.MultisigCodeCid, actors.MultiSigActor{}, actors.MultiSigActorState{})
inv.register(actors.PaymentChannelCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{}) inv.Register(actors.PaymentChannelCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{})
return inv return inv
} }
@@ -60,7 +60,7 @@ func (inv *invoker) Invoke(act *types.Actor, vmctx types.VMContext, method uint6
} }
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) code, err := inv.transform(instance)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -161,7 +161,11 @@ func DecodeParams(b []byte, out interface{}) error {
} }
func DumpActorState(code cid.Cid, b []byte) (interface{}, error) { func DumpActorState(code cid.Cid, b []byte) (interface{}, error) {
i := newInvoker() // TODO: register builtins in init block if code == actors.AccountCodeCid { // Account code special case
return nil, nil
}
i := NewInvoker() // TODO: register builtins in init block
typ, ok := i.builtInState[code] typ, ok := i.builtInState[code]
if !ok { if !ok {
+41 -1
View File
@@ -2,6 +2,8 @@ package vm
import ( import (
"context" "context"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-sectorbuilder" "github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
@@ -24,6 +26,44 @@ func Syscalls(verifier sectorbuilder.Verifier) *types.VMSyscalls {
return ok, nil return ok, nil
}, },
VerifyFallbackPost: verifier.VerifyFallbackPost, VerifyFallbackPost: func(ctx context.Context,
sectorSize uint64,
sectorInfo []types.PublicSectorInfo,
challengeSeed []byte,
proof []byte,
candidates []types.Candidate,
proverID address.Address,
faults uint64) (bool, error) {
sI := make([]ffi.PublicSectorInfo, len(sectorInfo))
for i, v := range sectorInfo {
sI[i] = ffi.PublicSectorInfo{
SectorID: v.SectorID,
CommR: v.CommR,
}
}
cand := make([]sectorbuilder.EPostCandidate, len(candidates))
for i, v := range candidates {
cand[i] = sectorbuilder.EPostCandidate{
SectorID: v.SectorID,
PartialTicket: v.PartialTicket,
Ticket: v.Ticket,
SectorChallengeIndex: v.SectorChallengeIndex,
}
}
return verifier.VerifyFallbackPost(
ctx,
sectorSize,
sectorbuilder.NewSortedPublicSectorInfo(sI),
challengeSeed,
proof,
cand,
proverID,
faults,
)
},
} }
} }
+9 -4
View File
@@ -22,6 +22,7 @@ import (
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/bufbstore" "github.com/filecoin-project/lotus/lib/bufbstore"
"github.com/filecoin-project/lotus/lib/sigs"
) )
var log = logging.Logger("vm") var log = logging.Logger("vm")
@@ -196,7 +197,7 @@ func (vmctx *VMContext) VerifySignature(sig *types.Signature, act address.Addres
act = kaddr act = kaddr
} }
if err := sig.Verify(act, data); err != nil { if err := sigs.Verify(sig, act, data); err != nil {
return aerrors.New(2, "signature verification failed") return aerrors.New(2, "signature verification failed")
} }
@@ -327,7 +328,7 @@ func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cbs block
buf: buf, buf: buf,
blockHeight: height, blockHeight: height,
blockMiner: maddr, blockMiner: maddr,
inv: newInvoker(), inv: NewInvoker(),
rand: r, // TODO: Probably should be a syscall rand: r, // TODO: Probably should be a syscall
Syscalls: syscalls, Syscalls: syscalls,
}, nil }, nil
@@ -430,7 +431,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, msg *types.Message) (*ApplyRet,
} }
st := vm.cstate st := vm.cstate
if err := st.Snapshot(); err != nil { if err := st.Snapshot(ctx); err != nil {
return nil, xerrors.Errorf("snapshot failed: %w", err) return nil, xerrors.Errorf("snapshot failed: %w", err)
} }
@@ -534,7 +535,7 @@ func (vm *VM) Flush(ctx context.Context) (cid.Cid, error) {
from := vm.buf from := vm.buf
to := vm.buf.Read() to := vm.buf.Read()
root, err := vm.cstate.Flush() root, err := vm.cstate.Flush(ctx)
if err != nil { if err != nil {
return cid.Undef, xerrors.Errorf("flushing vm: %w", err) return cid.Undef, xerrors.Errorf("flushing vm: %w", err)
} }
@@ -671,6 +672,10 @@ func Transfer(from, to *types.Actor, amt types.BigInt) error {
return nil return nil
} }
func (vm *VM) SetInvoker(i *invoker) {
vm.inv = i
}
func deductFunds(act *types.Actor, amt types.BigInt) error { func deductFunds(act *types.Actor, amt types.BigInt) error {
if act.Balance.LessThan(amt) { if act.Balance.LessThan(amt) {
return fmt.Errorf("not enough funds") return fmt.Errorf("not enough funds")
+2
View File
@@ -7,6 +7,8 @@ import (
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
) )
const HalvingPeriodEpochs = 6 * 365 * 24 * 60 * 2 const HalvingPeriodEpochs = 6 * 365 * 24 * 60 * 2
+16 -63
View File
@@ -2,20 +2,16 @@ package wallet
import ( import (
"context" "context"
"fmt"
"sort" "sort"
"strings" "strings"
"sync" "sync"
bls "github.com/filecoin-project/filecoin-ffi"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"github.com/minio/blake2b-simd"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-crypto"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
) )
var log = logging.Logger("wallet") var log = logging.Logger("wallet")
@@ -61,31 +57,7 @@ func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*t
return nil, xerrors.Errorf("signing using key '%s': %w", addr.String(), types.ErrKeyInfoNotFound) return nil, xerrors.Errorf("signing using key '%s': %w", addr.String(), types.ErrKeyInfoNotFound)
} }
switch ki.Type { return sigs.Sign(ki.Type, ki.PrivateKey, msg)
case types.KTSecp256k1:
b2sum := blake2b.Sum256(msg)
sig, err := crypto.Sign(ki.PrivateKey, b2sum[:])
if err != nil {
return nil, err
}
return &types.Signature{
Type: types.KTSecp256k1,
Data: sig,
}, nil
case types.KTBLS:
var pk bls.PrivateKey
copy(pk[:], ki.PrivateKey)
sig := bls.PrivateKeySign(pk, msg)
return &types.Signature{
Type: types.KTBLS,
Data: sig[:],
}, nil
default:
return nil, fmt.Errorf("cannot sign with unsupported key type: %q", ki.Type)
}
} }
func (w *Wallet) findKey(addr address.Address) (*Key, error) { func (w *Wallet) findKey(addr address.Address) (*Key, error) {
@@ -204,29 +176,15 @@ func (w *Wallet) SetDefault(a address.Address) error {
} }
func GenerateKey(typ string) (*Key, error) { func GenerateKey(typ string) (*Key, error) {
switch typ { pk, err := sigs.Generate(typ)
case types.KTSecp256k1: if err != nil {
priv, err := crypto.GenerateKey() return nil, err
if err != nil {
return nil, err
}
ki := types.KeyInfo{
Type: typ,
PrivateKey: priv,
}
return NewKey(ki)
case types.KTBLS:
priv := bls.PrivateKeyGenerate()
ki := types.KeyInfo{
Type: typ,
PrivateKey: priv[:],
}
return NewKey(ki)
default:
return nil, xerrors.Errorf("invalid key type: %s", typ)
} }
ki := types.KeyInfo{
Type: typ,
PrivateKey: pk,
}
return NewKey(ki)
} }
func (w *Wallet) GenerateKey(typ string) (address.Address, error) { func (w *Wallet) GenerateKey(typ string) (address.Address, error) {
@@ -277,28 +235,23 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
KeyInfo: keyinfo, KeyInfo: keyinfo,
} }
var err error
k.PublicKey, err = sigs.ToPublic(k.Type, k.PrivateKey)
if err != nil {
return nil, err
}
switch k.Type { switch k.Type {
case types.KTSecp256k1: case types.KTSecp256k1:
k.PublicKey = crypto.PublicKey(k.PrivateKey)
var err error
k.Address, err = address.NewSecp256k1Address(k.PublicKey) k.Address, err = address.NewSecp256k1Address(k.PublicKey)
if err != nil { if err != nil {
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err) return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
} }
case types.KTBLS: case types.KTBLS:
var pk bls.PrivateKey
copy(pk[:], k.PrivateKey)
pub := bls.PrivateKeyPublicKey(pk)
k.PublicKey = pub[:]
var err error
k.Address, err = address.NewBLSAddress(k.PublicKey) k.Address, err = address.NewBLSAddress(k.PublicKey)
if err != nil { if err != nil {
return nil, xerrors.Errorf("converting BLS to address: %w", err) return nil, xerrors.Errorf("converting BLS to address: %w", err)
} }
default: default:
return nil, xerrors.Errorf("unknown key type") return nil, xerrors.Errorf("unknown key type")
} }
+237 -3
View File
@@ -1,9 +1,13 @@
package cli package cli
import ( import (
"bytes"
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"os"
"os/exec"
"strconv"
"strings" "strings"
"time" "time"
@@ -12,6 +16,7 @@ import (
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
types "github.com/filecoin-project/lotus/chain/types" types "github.com/filecoin-project/lotus/chain/types"
) )
@@ -26,6 +31,9 @@ var chainCmd = &cli.Command{
chainSetHeadCmd, chainSetHeadCmd,
chainListCmd, chainListCmd,
chainGetCmd, chainGetCmd,
chainBisectCmd,
chainExportCmd,
slashConsensusFault,
}, },
} }
@@ -172,6 +180,10 @@ var chainGetMsgCmd = &cli.Command{
Name: "getmessage", Name: "getmessage",
Usage: "Get and print a message by its cid", Usage: "Get and print a message by its cid",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if !cctx.Args().Present() {
return fmt.Errorf("must pass a cid of a message to get")
}
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@@ -238,7 +250,7 @@ var chainSetHeadCmd = &cli.Command{
ts, err = api.ChainGetGenesis(ctx) ts, err = api.ChainGetGenesis(ctx)
} }
if ts == nil && cctx.IsSet("epoch") { if ts == nil && cctx.IsSet("epoch") {
ts, err = api.ChainGetTipSetByHeight(ctx, cctx.Uint64("epoch"), nil) ts, err = api.ChainGetTipSetByHeight(ctx, cctx.Uint64("epoch"), types.EmptyTSK)
} }
if ts == nil { if ts == nil {
ts, err = parseTipSet(api, ctx, cctx.Args().Slice()) ts, err = parseTipSet(api, ctx, cctx.Args().Slice())
@@ -251,7 +263,7 @@ var chainSetHeadCmd = &cli.Command{
return fmt.Errorf("must pass cids for tipset to set as head") return fmt.Errorf("must pass cids for tipset to set as head")
} }
if err := api.ChainSetHead(ctx, ts); err != nil { if err := api.ChainSetHead(ctx, ts.Key()); err != nil {
return err return err
} }
@@ -301,7 +313,7 @@ var chainListCmd = &cli.Command{
var head *types.TipSet var head *types.TipSet
if cctx.IsSet("height") { if cctx.IsSet("height") {
head, err = api.ChainGetTipSetByHeight(ctx, cctx.Uint64("height"), nil) head, err = api.ChainGetTipSetByHeight(ctx, cctx.Uint64("height"), types.EmptyTSK)
} else { } else {
head, err = api.ChainHead(ctx) head, err = api.ChainHead(ctx)
} }
@@ -380,8 +392,230 @@ func printTipSet(format string, ts *types.TipSet) {
blks += fmt.Sprintf("%s: %s,", b.Cid(), b.Miner) blks += fmt.Sprintf("%s: %s,", b.Cid(), b.Miner)
} }
blks += " ]" blks += " ]"
sCids := make([]string, 0, len(blks))
for _, c := range ts.Cids() {
sCids = append(sCids, c.String())
}
format = strings.ReplaceAll(format, "<tipset>", strings.Join(sCids, ","))
format = strings.ReplaceAll(format, "<blocks>", blks) format = strings.ReplaceAll(format, "<blocks>", blks)
format = strings.ReplaceAll(format, "<weight>", fmt.Sprint(ts.Blocks()[0].ParentWeight)) format = strings.ReplaceAll(format, "<weight>", fmt.Sprint(ts.Blocks()[0].ParentWeight))
fmt.Println(format) fmt.Println(format)
} }
var chainBisectCmd = &cli.Command{
Name: "bisect",
Usage: "bisect chain for an event",
Description: `Bisect the chain state tree:
lotus chain bisect [min height] [max height] '1/2/3/state/path' 'shell command' 'args'
Returns the first tipset in which condition is true
v
[start] FFFFFFFTTT [end]
Example: find height at which deal ID 100 000 appeared
- lotus chain bisect 1 32000 '@Ha:t03/1' jq -e '.[2] > 100000'
For special path elements see 'chain get' help
`,
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
if cctx.Args().Len() < 4 {
return xerrors.New("need at least 4 args")
}
start, err := strconv.ParseUint(cctx.Args().Get(0), 10, 64)
if err != nil {
return err
}
end, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
if err != nil {
return err
}
subPath := cctx.Args().Get(2)
highest, err := api.ChainGetTipSetByHeight(ctx, end, types.EmptyTSK)
if err != nil {
return err
}
prev := highest.Height()
for {
mid := (start + end) / 2
if end-start == 1 {
mid = end
start = end
}
midTs, err := api.ChainGetTipSetByHeight(ctx, mid, highest.Key())
if err != nil {
return err
}
path := "/ipld/" + midTs.ParentState().String() + "/" + subPath
fmt.Printf("* Testing %d (%d - %d) (%s): ", mid, start, end, path)
nd, err := api.ChainGetNode(ctx, path)
if err != nil {
return err
}
b, err := json.MarshalIndent(nd, "", "\t")
if err != nil {
return err
}
cmd := exec.CommandContext(ctx, cctx.Args().Get(3), cctx.Args().Slice()[4:]...)
cmd.Stdin = bytes.NewReader(b)
var out bytes.Buffer
cmd.Stdout = &out
switch cmd.Run().(type) {
case nil:
// it's lower
end = mid
highest = midTs
fmt.Println("true")
case *exec.ExitError:
start = mid
fmt.Println("false")
default:
return err
}
if start == end {
if strings.TrimSpace(out.String()) == "true" {
fmt.Println(midTs.Height())
} else {
fmt.Println(prev)
}
return nil
}
prev = mid
}
},
}
var chainExportCmd = &cli.Command{
Name: "export",
Usage: "export chain to a car file",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "tipset",
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
if !cctx.Args().Present() {
return fmt.Errorf("must specify filename to export chain to")
}
fi, err := os.Create(cctx.Args().First())
if err != nil {
return err
}
defer fi.Close()
ts, err := loadTipSet(ctx, cctx, api)
if err != nil {
return err
}
stream, err := api.ChainExport(ctx, ts.Key())
if err != nil {
return err
}
for b := range stream {
_, err := fi.Write(b)
if err != nil {
return err
}
}
return nil
},
}
var slashConsensusFault = &cli.Command{
Name: "slash-consensus",
Usage: "Report consensus fault",
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
c1, err := cid.Parse(cctx.Args().Get(0))
if err != nil {
return xerrors.Errorf("parsing cid 1: %w", err)
}
b1, err := api.ChainGetBlock(ctx, c1)
if err != nil {
return xerrors.Errorf("getting block 1: %w", err)
}
c2, err := cid.Parse(cctx.Args().Get(1))
if err != nil {
return xerrors.Errorf("parsing cid 2: %w", err)
}
b2, err := api.ChainGetBlock(ctx, c2)
if err != nil {
return xerrors.Errorf("getting block 2: %w", err)
}
def, err := api.WalletDefaultAddress(ctx)
if err != nil {
return err
}
params, err := actors.SerializeParams(&actors.ArbitrateConsensusFaultParams{
Block1: b1,
Block2: b2,
})
msg := &types.Message{
To: actors.StoragePowerAddress,
From: def,
Value: types.NewInt(0),
GasPrice: types.NewInt(1),
GasLimit: types.NewInt(10000000),
Method: actors.SPAMethods.ArbitrateConsensusFault,
Params: params,
}
smsg, err := api.MpoolPushMessage(ctx, msg)
if err != nil {
return err
}
fmt.Println(smsg.Cid())
return nil
},
}
+1 -1
View File
@@ -295,7 +295,7 @@ var clientQueryAskCmd = &cli.Command{
To: maddr, To: maddr,
From: maddr, From: maddr,
Method: actors.MAMethods.GetPeerID, Method: actors.MAMethods.GetPeerID,
}, nil) }, types.EmptyTSK)
if err != nil { if err != nil {
return xerrors.Errorf("failed to get peerID for miner: %w", err) return xerrors.Errorf("failed to get peerID for miner: %w", err)
} }
+2
View File
@@ -202,6 +202,7 @@ var Commands = []*cli.Command{
clientCmd, clientCmd,
fetchParamCmd, fetchParamCmd,
mpoolCmd, mpoolCmd,
multisigCmd,
netCmd, netCmd,
paychCmd, paychCmd,
sendCmd, sendCmd,
@@ -209,4 +210,5 @@ var Commands = []*cli.Command{
syncCmd, syncCmd,
versionCmd, versionCmd,
walletCmd, walletCmd,
logCmd,
} }
+101
View File
@@ -0,0 +1,101 @@
package cli
import (
"fmt"
"golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
)
var logCmd = &cli.Command{
Name: "log",
Usage: "Manage logging",
Subcommands: []*cli.Command{
logList,
logSetLevel,
},
}
var logList = &cli.Command{
Name: "list",
Usage: "List log systems",
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
systems, err := api.LogList(ctx)
if err != nil {
return err
}
for _, system := range systems {
fmt.Println(system)
}
return nil
},
}
var logSetLevel = &cli.Command{
Name: "set-level",
Usage: "Set log level",
ArgsUsage: "<level>",
Description: `Set the log level for logging systems:
The system flag can be specified multiple times.
eg) log set-level --system chain --system blocksync debug
Available Levels:
debug
info
warn
error
Environment Variables:
GOLOG_LOG_LEVEL - Default log level for all log systems
GOLOG_LOG_FMT - Change output log format (json, nocolor)
GOLOG_FILE - Write logs to file in addition to stderr
`,
Flags: []cli.Flag{
&cli.StringSliceFlag{
Name: "system",
Usage: "limit to log system",
Value: &cli.StringSlice{},
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
if !cctx.Args().Present() {
return fmt.Errorf("level is required")
}
systems := cctx.StringSlice("system")
if len(systems) == 0 {
var err error
systems, err = api.LogList(ctx)
if err != nil {
return err
}
}
for _, system := range systems {
if err := api.LogSetLevel(ctx, system, cctx.Args().First()); err != nil {
return xerrors.Errorf("setting log level on %s: %w", system, err)
}
}
return nil
},
}
+5 -4
View File
@@ -33,7 +33,7 @@ var mpoolPending = &cli.Command{
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msgs, err := api.MpoolPending(ctx, nil) msgs, err := api.MpoolPending(ctx, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
@@ -103,7 +103,7 @@ var mpoolStat = &cli.Command{
return xerrors.Errorf("getting chain head: %w", err) return xerrors.Errorf("getting chain head: %w", err)
} }
msgs, err := api.MpoolPending(ctx, nil) msgs, err := api.MpoolPending(ctx, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
@@ -122,9 +122,10 @@ var mpoolStat = &cli.Command{
bkt.msgs[v.Message.Nonce] = v bkt.msgs[v.Message.Nonce] = v
} }
for a, bkt := range buckets { for a, bkt := range buckets {
act, err := api.StateGetActor(ctx, a, ts) act, err := api.StateGetActor(ctx, a, ts.Key())
if err != nil { if err != nil {
return err fmt.Printf("%s, err: %s\n", a, err)
continue
} }
cur := act.Nonce cur := act.Nonce
+400
View File
@@ -0,0 +1,400 @@
package cli
import (
"bytes"
"encoding/hex"
"fmt"
"os"
"strconv"
"text/tabwriter"
"github.com/filecoin-project/go-address"
actors "github.com/filecoin-project/lotus/chain/actors"
types "github.com/filecoin-project/lotus/chain/types"
cbg "github.com/whyrusleeping/cbor-gen"
"gopkg.in/urfave/cli.v2"
)
var multisigCmd = &cli.Command{
Name: "msig",
Usage: "Interact with a multisig wallet",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "source",
Usage: "specify the account to send propose from",
},
},
Subcommands: []*cli.Command{
msigCreateCmd,
msigInspectCmd,
msigProposeCmd,
msigApproveCmd,
},
}
var msigCreateCmd = &cli.Command{
Name: "create",
Usage: "Create a new multisig wallet",
Flags: []cli.Flag{
&cli.Uint64Flag{
Name: "required",
},
&cli.StringFlag{
Name: "value",
Usage: "initial funds to give to multisig",
Value: "0",
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
var addrs []address.Address
for _, a := range cctx.Args().Slice() {
addr, err := address.NewFromString(a)
if err != nil {
return err
}
addrs = append(addrs, addr)
}
// get the address we're going to use to create the multisig (can be one of the above, as long as they have funds)
sendAddr, err := api.WalletDefaultAddress(ctx)
if err != nil {
return err
}
val := cctx.String("value")
filval, err := types.ParseFIL(val)
if err != nil {
return err
}
required := cctx.Uint64("required")
if required == 0 {
required = uint64(len(addrs))
}
// Set up constructor parameters for multisig
msigParams := &actors.MultiSigConstructorParams{
Signers: addrs,
Required: required,
}
enc, err := actors.SerializeParams(msigParams)
if err != nil {
return err
}
// new actors are created by invoking 'exec' on the init actor with the constructor params
execParams := &actors.ExecParams{
Code: actors.MultisigCodeCid,
Params: enc,
}
enc, err = actors.SerializeParams(execParams)
if err != nil {
return err
}
// now we create the message to send this with
msg := types.Message{
To: actors.InitAddress,
From: sendAddr,
Method: actors.IAMethods.Exec,
Params: enc,
GasPrice: types.NewInt(1),
GasLimit: types.NewInt(1000000),
Value: types.BigInt(filval),
}
// send the message out to the network
smsg, err := api.MpoolPushMessage(ctx, &msg)
if err != nil {
return err
}
// wait for it to get mined into a block
wait, err := api.StateWaitMsg(ctx, smsg.Cid())
if err != nil {
return err
}
// check it executed successfully
if wait.Receipt.ExitCode != 0 {
fmt.Println("actor creation failed!")
return err
}
// get address of newly created miner
msigaddr, err := address.NewFromBytes(wait.Receipt.Return)
if err != nil {
return err
}
fmt.Println("Created new multisig: ", msigaddr.String())
// TODO: maybe register this somewhere
return nil
},
}
var msigInspectCmd = &cli.Command{
Name: "inspect",
Usage: "Inspect a multisig wallet",
Flags: []cli.Flag{},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
if !cctx.Args().Present() {
return fmt.Errorf("must specify address of multisig to inspect")
}
maddr, err := address.NewFromString(cctx.Args().First())
if err != nil {
return err
}
act, err := api.StateGetActor(ctx, maddr, types.EmptyTSK)
if err != nil {
return err
}
obj, err := api.ChainReadObj(ctx, act.Head)
if err != nil {
return err
}
var mstate actors.MultiSigActorState
if err := mstate.UnmarshalCBOR(bytes.NewReader(obj)); err != nil {
return err
}
fmt.Printf("Balance: %sfil\n", types.FIL(act.Balance))
fmt.Printf("Threshold: %d / %d\n", mstate.Required, len(mstate.Signers))
fmt.Println("Signers:")
for _, s := range mstate.Signers {
fmt.Printf("\t%s\n", s)
}
fmt.Println("Transactions: ", len(mstate.Transactions))
if len(mstate.Transactions) > 0 {
w := tabwriter.NewWriter(os.Stdout, 8, 4, 0, ' ', 0)
fmt.Fprintf(w, "ID\tState\tTo\tValue\tMethod\tParams\n")
for _, tx := range mstate.Transactions {
fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%d\t%x\n", tx.TxID, state(tx), tx.To, types.FIL(tx.Value), tx.Method, tx.Params)
}
w.Flush()
}
return nil
},
}
func state(tx actors.MTransaction) string {
if tx.Complete {
return "done"
}
if tx.Canceled {
return "canceled"
}
return "pending"
}
var msigProposeCmd = &cli.Command{
Name: "propose",
Usage: "Propose a multisig transaction",
Flags: []cli.Flag{},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
if cctx.Args().Len() < 3 {
return fmt.Errorf("must pass multisig address, destination, and value")
}
if cctx.Args().Len() > 3 && cctx.Args().Len() != 5 {
return fmt.Errorf("usage: msig propose <msig addr> <desination> <value> [ <method> <params> ]")
}
msig, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return err
}
dest, err := address.NewFromString(cctx.Args().Get(1))
if err != nil {
return err
}
value, err := types.ParseFIL(cctx.Args().Get(2))
if err != nil {
return err
}
var method uint64
var params []byte
if cctx.Args().Len() == 5 {
m, err := strconv.ParseUint(cctx.Args().Get(3), 10, 64)
if err != nil {
return err
}
method = m
p, err := hex.DecodeString(cctx.Args().Get(4))
if err != nil {
return err
}
params = p
}
enc, err := actors.SerializeParams(&actors.MultiSigProposeParams{
To: dest,
Value: types.BigInt(value),
Method: method,
Params: params,
})
if err != nil {
return err
}
var from address.Address
if cctx.IsSet("source") {
f, err := address.NewFromString(cctx.String("source"))
if err != nil {
return err
}
from = f
} else {
defaddr, err := api.WalletDefaultAddress(ctx)
if err != nil {
return err
}
from = defaddr
}
msg := &types.Message{
To: msig,
From: from,
Value: types.NewInt(0),
Method: actors.MultiSigMethods.Propose,
Params: enc,
GasLimit: types.NewInt(100000),
GasPrice: types.NewInt(1),
}
smsg, err := api.MpoolPushMessage(ctx, msg)
if err != nil {
return err
}
fmt.Println("send proposal in message: ", smsg.Cid())
wait, err := api.StateWaitMsg(ctx, smsg.Cid())
if err != nil {
return err
}
if wait.Receipt.ExitCode != 0 {
return fmt.Errorf("proposal returned exit %d", wait.Receipt.ExitCode)
}
_, v, err := cbg.CborReadHeader(bytes.NewReader(wait.Receipt.Return))
if err != nil {
return err
}
fmt.Printf("Transaction ID: %d\n", v)
return nil
},
}
var msigApproveCmd = &cli.Command{
Name: "approve",
Usage: "Approve a multisig transaction",
Flags: []cli.Flag{},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
if cctx.Args().Len() < 2 {
return fmt.Errorf("must pass multisig address and transaction ID")
}
msig, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return err
}
txid, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
if err != nil {
return err
}
enc, err := actors.SerializeParams(&actors.MultiSigTxID{
TxID: txid,
})
if err != nil {
return err
}
var from address.Address
if cctx.IsSet("source") {
f, err := address.NewFromString(cctx.String("source"))
if err != nil {
return err
}
from = f
} else {
defaddr, err := api.WalletDefaultAddress(ctx)
if err != nil {
return err
}
from = defaddr
}
msg := &types.Message{
To: msig,
From: from,
Value: types.NewInt(0),
Method: actors.MultiSigMethods.Approve,
Params: enc,
GasLimit: types.NewInt(100000),
GasPrice: types.NewInt(1),
}
smsg, err := api.MpoolPushMessage(ctx, msg)
if err != nil {
return err
}
fmt.Println("sent approval in message: ", smsg.Cid())
wait, err := api.StateWaitMsg(ctx, smsg.Cid())
if err != nil {
return err
}
if wait.Receipt.ExitCode != 0 {
return fmt.Errorf("approve returned exit %d", wait.Receipt.ExitCode)
}
return nil
},
}
+1 -1
View File
@@ -24,7 +24,7 @@ var fetchParamCmd = &cli.Command{
return err return err
} }
sectorSize := uint64(sectorSizeInt) sectorSize := uint64(sectorSizeInt)
err = paramfetch.GetParams(build.ParametersJson, sectorSize) err = paramfetch.GetParams(build.ParametersJson(), sectorSize)
if err != nil { if err != nil {
return xerrors.Errorf("fetching proof parameters: %w", err) return xerrors.Errorf("fetching proof parameters: %w", err)
} }
+1 -1
View File
@@ -15,7 +15,7 @@ var sendCmd = &cli.Command{
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: "source", Name: "source",
Usage: "optinally specifiy the account to send funds from", Usage: "optionally specify the account to send funds from",
}, },
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
+326 -18
View File
@@ -1,18 +1,24 @@
package cli package cli
import ( import (
"bytes"
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"reflect"
"strconv"
"strings" "strings"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
actors "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/miner"
"github.com/libp2p/go-libp2p-core/peer"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
) )
@@ -39,6 +45,9 @@ var stateCmd = &cli.Command{
stateReadStateCmd, stateReadStateCmd,
stateListMessagesCmd, stateListMessagesCmd,
stateComputeStateCmd, stateComputeStateCmd,
stateCallCmd,
stateGetDealSetCmd,
stateWaitMsgCmd,
}, },
} }
@@ -106,17 +115,20 @@ var statePowerCmd = &cli.Command{
return err return err
} }
power, err := api.StateMinerPower(ctx, maddr, ts) power, err := api.StateMinerPower(ctx, maddr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
res := power.TotalPower tp := power.TotalPower
if cctx.Args().Present() { if cctx.Args().Present() {
res = power.MinerPower mp := power.MinerPower
percI := types.BigDiv(types.BigMul(mp, types.NewInt(1000000)), tp)
fmt.Printf("%s(%s) / %s(%s) ~= %0.4f%%\n", mp.String(), mp.SizeStr(), tp.String(), tp.SizeStr(), float64(percI.Int64())/10000)
} else {
fmt.Printf("%s(%s)\n", tp.String(), tp.SizeStr())
} }
fmt.Println(res.String())
return nil return nil
}, },
} }
@@ -147,7 +159,7 @@ var stateSectorsCmd = &cli.Command{
return err return err
} }
sectors, err := api.StateMinerSectors(ctx, maddr, ts) sectors, err := api.StateMinerSectors(ctx, maddr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@@ -186,7 +198,7 @@ var stateProvingSetCmd = &cli.Command{
return err return err
} }
sectors, err := api.StateMinerProvingSet(ctx, maddr, ts) sectors, err := api.StateMinerProvingSet(ctx, maddr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@@ -248,7 +260,7 @@ var stateReplaySetCmd = &cli.Command{
return err return err
} }
res, err := api.StateReplay(ctx, ts, mcid) res, err := api.StateReplay(ctx, ts.Key(), mcid)
if err != nil { if err != nil {
return xerrors.Errorf("replay call failed: %w", err) return xerrors.Errorf("replay call failed: %w", err)
} }
@@ -282,7 +294,7 @@ var statePledgeCollateralCmd = &cli.Command{
return err return err
} }
coll, err := api.StatePledgeCollateral(ctx, ts) coll, err := api.StatePledgeCollateral(ctx, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@@ -292,6 +304,47 @@ var statePledgeCollateralCmd = &cli.Command{
}, },
} }
var stateGetDealSetCmd = &cli.Command{
Name: "get-deal",
Usage: "View on-chain deal info",
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
if !cctx.Args().Present() {
return fmt.Errorf("must specify miner to list sectors for")
}
dealid, err := strconv.ParseUint(cctx.Args().First(), 10, 64)
if err != nil {
return xerrors.Errorf("parsing deal ID: %w", err)
}
ts, err := loadTipSet(ctx, cctx, api)
if err != nil {
return err
}
deal, err := api.StateMarketStorageDeal(ctx, dealid, ts.Key())
if err != nil {
return err
}
data, err := json.MarshalIndent(deal, "", " ")
if err != nil {
return err
}
fmt.Println(string(data))
return nil
},
}
var stateListMinersCmd = &cli.Command{ var stateListMinersCmd = &cli.Command{
Name: "list-miners", Name: "list-miners",
Usage: "list all miners in the network", Usage: "list all miners in the network",
@@ -309,7 +362,7 @@ var stateListMinersCmd = &cli.Command{
return err return err
} }
miners, err := api.StateListMiners(ctx, ts) miners, err := api.StateListMiners(ctx, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@@ -339,7 +392,7 @@ var stateListActorsCmd = &cli.Command{
return err return err
} }
actors, err := api.StateListActors(ctx, ts) actors, err := api.StateListActors(ctx, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@@ -378,7 +431,7 @@ var stateGetActorCmd = &cli.Command{
return err return err
} }
a, err := api.StateGetActor(ctx, addr, ts) a, err := api.StateGetActor(ctx, addr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@@ -419,7 +472,7 @@ var stateLookupIDCmd = &cli.Command{
return err return err
} }
a, err := api.StateLookupID(ctx, addr, ts) a, err := api.StateLookupID(ctx, addr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@@ -456,7 +509,7 @@ var stateSectorSizeCmd = &cli.Command{
return err return err
} }
ssize, err := api.StateMinerSectorSize(ctx, addr, ts) ssize, err := api.StateMinerSectorSize(ctx, addr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@@ -492,12 +545,12 @@ var stateReadStateCmd = &cli.Command{
return err return err
} }
act, err := api.StateGetActor(ctx, addr, ts) act, err := api.StateGetActor(ctx, addr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
as, err := api.StateReadState(ctx, act, ts) as, err := api.StateReadState(ctx, act, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@@ -528,6 +581,10 @@ var stateListMessagesCmd = &cli.Command{
Name: "toheight", Name: "toheight",
Usage: "don't look before given block height", Usage: "don't look before given block height",
}, },
&cli.BoolFlag{
Name: "cids",
Usage: "print message CIDs instead of messages",
},
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
@@ -562,12 +619,17 @@ var stateListMessagesCmd = &cli.Command{
return err return err
} }
msgs, err := api.StateListMessages(ctx, &types.Message{To: toa, From: froma}, ts, toh) msgs, err := api.StateListMessages(ctx, &types.Message{To: toa, From: froma}, ts.Key(), toh)
if err != nil { if err != nil {
return err return err
} }
for _, c := range msgs { for _, c := range msgs {
if cctx.Bool("cids") {
fmt.Println(c.String())
continue
}
m, err := api.ChainGetMessage(ctx, c) m, err := api.ChainGetMessage(ctx, c)
if err != nil { if err != nil {
return err return err
@@ -624,7 +686,7 @@ var stateComputeStateCmd = &cli.Command{
var msgs []*types.Message var msgs []*types.Message
if cctx.Bool("apply-mpool-messages") { if cctx.Bool("apply-mpool-messages") {
pmsgs, err := api.MpoolPending(ctx, ts) pmsgs, err := api.MpoolPending(ctx, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@@ -639,7 +701,7 @@ var stateComputeStateCmd = &cli.Command{
} }
} }
nstate, err := api.StateCompute(ctx, h, msgs, ts) nstate, err := api.StateCompute(ctx, h, msgs, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@@ -648,3 +710,249 @@ var stateComputeStateCmd = &cli.Command{
return nil return nil
}, },
} }
var stateWaitMsgCmd = &cli.Command{
Name: "wait-msg",
Usage: "Wait for a message to appear on chain",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "timeout",
Value: "10m",
},
},
Action: func(cctx *cli.Context) error {
if !cctx.Args().Present() {
return fmt.Errorf("must specify message cid to wait for")
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
msg, err := cid.Decode(cctx.Args().First())
if err != nil {
return err
}
mw, err := api.StateWaitMsg(ctx, msg)
if err != nil {
return err
}
fmt.Printf("message was executed in tipset: %s", mw.TipSet.Cids())
fmt.Printf("Exit Code: %d", mw.Receipt.ExitCode)
fmt.Printf("Gas Used: %s", mw.Receipt.GasUsed)
fmt.Printf("Return: %x", mw.Receipt.Return)
return nil
},
}
var stateCallCmd = &cli.Command{
Name: "call",
Usage: "Invoke a method on an actor locally",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
Usage: "",
Value: actors.NetworkAddress.String(),
},
&cli.StringFlag{
Name: "value",
Usage: "specify value field for invocation",
Value: "0",
},
&cli.StringFlag{
Name: "ret",
Usage: "specify how to parse output (auto, raw, addr, big)",
Value: "auto",
},
},
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() < 2 {
return fmt.Errorf("must specify at least actor and method to invoke")
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
toa, err := address.NewFromString(cctx.Args().First())
if err != nil {
return fmt.Errorf("given 'to' address %q was invalid: %w", cctx.Args().First(), err)
}
froma, err := address.NewFromString(cctx.String("from"))
if err != nil {
return fmt.Errorf("given 'from' address %q was invalid: %w", cctx.String("from"), err)
}
ts, err := loadTipSet(ctx, cctx, api)
if err != nil {
return err
}
method, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
if err != nil {
return fmt.Errorf("must pass method as a number")
}
value, err := types.ParseFIL(cctx.String("value"))
if err != nil {
return fmt.Errorf("failed to parse 'value': %s", err)
}
act, err := api.StateGetActor(ctx, toa, ts.Key())
if err != nil {
return fmt.Errorf("failed to lookup target actor: %s", err)
}
params, err := parseParamsForMethod(act.Code, method, cctx.Args().Slice()[2:])
if err != nil {
return fmt.Errorf("failed to parse params: %s", err)
}
ret, err := api.StateCall(ctx, &types.Message{
From: froma,
To: toa,
Value: types.BigInt(value),
GasLimit: types.NewInt(10000000000),
GasPrice: types.NewInt(0),
Method: method,
Params: params,
}, ts.Key())
if err != nil {
return fmt.Errorf("state call failed: %s", err)
}
if ret.ExitCode != 0 {
return fmt.Errorf("invocation failed (exit: %d): %s", ret.ExitCode, ret.Error)
}
s, err := formatOutput(cctx.String("ret"), ret.Return)
if err != nil {
return fmt.Errorf("failed to format output: %s", err)
}
fmt.Printf("return: %s\n", s)
return nil
},
}
func formatOutput(t string, val []byte) (string, error) {
switch t {
case "raw", "hex":
return fmt.Sprintf("%x", val), nil
case "address", "addr", "a":
a, err := address.NewFromBytes(val)
if err != nil {
return "", err
}
return a.String(), nil
case "big", "int", "bigint":
bi := types.BigFromBytes(val)
return bi.String(), nil
case "fil":
bi := types.FIL(types.BigFromBytes(val))
return bi.String(), nil
case "pid", "peerid", "peer":
pid, err := peer.IDFromBytes(val)
if err != nil {
return "", err
}
return pid.Pretty(), nil
case "auto":
if len(val) == 0 {
return "", nil
}
a, err := address.NewFromBytes(val)
if err == nil {
return "address: " + a.String(), nil
}
pid, err := peer.IDFromBytes(val)
if err == nil {
return "peerID: " + pid.Pretty(), nil
}
bi := types.BigFromBytes(val)
return "bigint: " + bi.String(), nil
default:
return "", fmt.Errorf("unrecognized output type: %q", t)
}
}
func parseParamsForMethod(act cid.Cid, method uint64, args []string) ([]byte, error) {
if len(args) == 0 {
return nil, nil
}
var f interface{}
switch act {
case actors.StorageMarketCodeCid:
f = actors.StorageMarketActor{}.Exports()[method]
case actors.StorageMinerCodeCid:
f = actors.StorageMinerActor{}.Exports()[method]
case actors.StoragePowerCodeCid:
f = actors.StoragePowerActor{}.Exports()[method]
case actors.MultisigCodeCid:
f = actors.MultiSigActor{}.Exports()[method]
case actors.PaymentChannelCodeCid:
f = actors.PaymentChannelActor{}.Exports()[method]
default:
return nil, fmt.Errorf("the lazy devs didnt add support for that actor to this call yet")
}
rf := reflect.TypeOf(f)
if rf.NumIn() != 3 {
return nil, fmt.Errorf("expected referenced method to have three arguments")
}
paramObj := rf.In(2).Elem()
if paramObj.NumField() != len(args) {
return nil, fmt.Errorf("not enough arguments given to call that method (expecting %d)", paramObj.NumField())
}
p := reflect.New(paramObj)
for i := 0; i < len(args); i++ {
switch paramObj.Field(i).Type {
case reflect.TypeOf(address.Address{}):
a, err := address.NewFromString(args[i])
if err != nil {
return nil, fmt.Errorf("failed to parse address: %s", err)
}
p.Elem().Field(i).Set(reflect.ValueOf(a))
case reflect.TypeOf(uint64(0)):
val, err := strconv.ParseUint(args[i], 10, 64)
if err != nil {
return nil, err
}
p.Elem().Field(i).Set(reflect.ValueOf(val))
case reflect.TypeOf(peer.ID("")):
pid, err := peer.IDB58Decode(args[i])
if err != nil {
return nil, fmt.Errorf("failed to parse peer ID: %s", err)
}
p.Elem().Field(i).Set(reflect.ValueOf(pid))
default:
return nil, fmt.Errorf("unsupported type for call (TODO): %s", paramObj.Field(i).Type)
}
}
m := p.Interface().(cbg.CBORMarshaler)
buf := new(bytes.Buffer)
if err := m.MarshalCBOR(buf); err != nil {
return nil, fmt.Errorf("failed to marshal param object: %s", err)
}
return buf.Bytes(), nil
}
+36
View File
@@ -20,6 +20,7 @@ var syncCmd = &cli.Command{
syncStatusCmd, syncStatusCmd,
syncWaitCmd, syncWaitCmd,
syncMarkBadCmd, syncMarkBadCmd,
syncCheckBadCmd,
}, },
} }
@@ -115,6 +116,41 @@ var syncMarkBadCmd = &cli.Command{
}, },
} }
var syncCheckBadCmd = &cli.Command{
Name: "check-bad",
Usage: "check if the given block was marked bad, and for what reason",
Action: func(cctx *cli.Context) error {
napi, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
if !cctx.Args().Present() {
return fmt.Errorf("must specify block cid to check")
}
bcid, err := cid.Decode(cctx.Args().First())
if err != nil {
return fmt.Errorf("failed to decode input as a cid: %s", err)
}
reason, err := napi.SyncCheckBad(ctx, bcid)
if err != nil {
return err
}
if reason == "" {
fmt.Println("block was not marked as bad")
return nil
}
fmt.Println(reason)
return nil
},
}
func SyncWait(ctx context.Context, napi api.FullNode) error { func SyncWait(ctx context.Context, napi api.FullNode) error {
for { for {
state, err := napi.SyncState(ctx) state, err := napi.SyncState(ctx)
+4 -4
View File
@@ -146,7 +146,7 @@ func main() {
Miner: maddr, Miner: maddr,
SectorSize: sectorSize, SectorSize: sectorSize,
WorkerThreads: 2, WorkerThreads: 2,
Dir: sbdir, Paths: sectorbuilder.SimplePath(sbdir),
} }
if robench == "" { if robench == "" {
@@ -155,7 +155,7 @@ func main() {
} }
} }
if err := paramfetch.GetParams(build.ParametersJson, sectorSize); err != nil { if err := paramfetch.GetParams(build.ParametersJson(), sectorSize); err != nil {
return xerrors.Errorf("getting params: %w", err) return xerrors.Errorf("getting params: %w", err)
} }
sb, err := sectorbuilder.New(cfg, mds) sb, err := sectorbuilder.New(cfg, mds)
@@ -174,7 +174,7 @@ func main() {
r := rand.New(rand.NewSource(100 + int64(i))) r := rand.New(rand.NewSource(100 + int64(i)))
pi, err := sb.AddPiece(dataSize, i, r, nil) pi, err := sb.AddPiece(context.TODO(), dataSize, i, r, nil)
if err != nil { if err != nil {
return err return err
} }
@@ -225,7 +225,7 @@ func main() {
if !c.Bool("skip-unseal") { if !c.Bool("skip-unseal") {
log.Info("Unsealing sector") log.Info("Unsealing sector")
rc, err := sb.ReadPieceFromSealedSector(1, 0, dataSize, ticket.TicketBytes[:], commD[:]) rc, err := sb.ReadPieceFromSealedSector(context.TODO(), 1, 0, dataSize, ticket.TicketBytes[:], commD[:])
if err != nil { if err != nil {
return err return err
} }
+333 -24
View File
@@ -2,16 +2,18 @@ package main
import ( import (
"database/sql" "database/sql"
"encoding/hex"
"fmt" "fmt"
"github.com/filecoin-project/lotus/api"
"golang.org/x/xerrors"
"sync" "sync"
"time" "time"
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
_ "github.com/lib/pq" _ "github.com/lib/pq"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
@@ -75,13 +77,22 @@ create table if not exists blocks
eprof bytea, eprof bytea,
prand bytea, prand bytea,
ep0partial bytea, ep0partial bytea,
ep0sector bigint not null, ep0sector numeric not null,
ep0challangei bigint not null ep0challangei numeric not null
); );
create unique index if not exists block_cid_uindex create unique index if not exists block_cid_uindex
on blocks (cid); on blocks (cid);
create materialized view if not exists state_heights
as select distinct height, parentstateroot from blocks;
create unique index if not exists state_heights_uindex
on state_heights (height);
create index if not exists state_heights_height_index
on state_heights (parentstateroot);
create table if not exists id_address_map create table if not exists id_address_map
( (
id text not null, id text not null,
@@ -117,6 +128,38 @@ create index if not exists id_address_map_address_index
create index if not exists id_address_map_id_index create index if not exists id_address_map_id_index
on id_address_map (id); on id_address_map (id);
create or replace function actor_tips(epoch bigint)
returns table (id text,
code text,
head text,
nonce int,
balance text,
stateroot text,
height bigint,
parentstateroot text) as
$body$
select distinct on (id) * from actors
inner join state_heights sh on sh.parentstateroot = stateroot
where height < $1
order by id, height desc;
$body$ language sql;
create table if not exists actor_states
(
head text not null,
code text not null,
state json not null
);
create unique index if not exists actor_states_head_code_uindex
on actor_states (head, code);
create index if not exists actor_states_head_index
on actor_states (head);
create index if not exists actor_states_code_head_index
on actor_states (head, code);
create table if not exists messages create table if not exists messages
( (
cid text not null cid text not null
@@ -124,11 +167,11 @@ create table if not exists messages
primary key, primary key,
"from" text not null, "from" text not null,
"to" text not null, "to" text not null,
nonce int not null, nonce bigint not null,
value text not null, value text not null,
gasprice int not null, gasprice bigint not null,
gaslimit int not null, gaslimit bigint not null,
method int, method bigint,
params bytea params bytea
); );
@@ -184,7 +227,7 @@ create table if not exists miner_heads
worker text not null, worker text not null,
peerid text not null, peerid text not null,
sectorsize bigint not null, sectorsize bigint not null,
power bigint not null, power decimal not null,
active bool, active bool,
ppe bigint not null, ppe bigint not null,
slashed_at bigint not null, slashed_at bigint not null,
@@ -192,6 +235,104 @@ create table if not exists miner_heads
primary key (head, addr) primary key (head, addr)
); );
create or replace function miner_tips(epoch bigint)
returns table (head text,
addr text,
stateroot text,
sectorset text,
setsize decimal,
provingset text,
provingsize decimal,
owner text,
worker text,
peerid text,
sectorsize bigint,
power decimal,
active bool,
ppe bigint,
slashed_at bigint,
height bigint,
parentstateroot text) as
$body$
select distinct on (addr) * from miner_heads
inner join state_heights sh on sh.parentstateroot = stateroot
where height < $1
order by addr, height desc;
$body$ language sql;
create table if not exists deals
(
id int not null,
pieceRef text not null,
pieceSize bigint not null,
client text not null,
provider text not null,
expiration decimal not null,
duration decimal not null,
epochPrice decimal not null,
collateral decimal not null,
constraint deals_pk
primary key (id)
);
create index if not exists deals_client_index
on deals (client);
create unique index if not exists deals_id_uindex
on deals (id);
create index if not exists deals_pieceRef_index
on deals (pieceRef);
create index if not exists deals_provider_index
on deals (provider);
create table if not exists deal_activations
(
deal bigint not null
constraint deal_activations_deals_id_fk
references deals,
activation_epoch bigint not null,
constraint deal_activations_pk
primary key (deal)
);
create index if not exists deal_activations_activation_epoch_index
on deal_activations (activation_epoch);
create unique index if not exists deal_activations_deal_uindex
on deal_activations (deal);
create table if not exists blocks_challenges
(
block text not null
constraint blocks_challenges_pk_2
primary key
constraint blocks_challenges_blocks_cid_fk
references blocks,
index bigint not null,
sector_id bigint not null,
partial bytea not null,
candidate bigint not null,
constraint blocks_challenges_pk
unique (block, index)
);
create index if not exists blocks_challenges_block_index
on blocks_challenges (block);
create index if not exists blocks_challenges_block_candidate_index
on blocks_challenges (block,candidate);
create index if not exists blocks_challenges_block_index_index
on blocks_challenges (block, index);
create index if not exists blocks_challenges_candidate_index
on blocks_challenges (candidate);
create index if not exists blocks_challenges_index_index
on blocks_challenges (index);
`) `)
if err != nil { if err != nil {
return err return err
@@ -226,17 +367,15 @@ func (st *storage) hasList() map[cid.Cid]struct{} {
return out return out
} }
func (st *storage) storeActors(actors map[address.Address]map[types.Actor]cid.Cid) error { func (st *storage) storeActors(actors map[address.Address]map[types.Actor]actorInfo) error {
// Basic
tx, err := st.db.Begin() tx, err := st.db.Begin()
if err != nil { if err != nil {
return err return err
} }
if _, err := tx.Exec(` if _, err := tx.Exec(`
create temp table a (like actors excluding constraints) on commit drop;
create temp table a (like actors excluding constraints) on commit drop; `); err != nil {
`); err != nil {
return xerrors.Errorf("prep temp: %w", err) return xerrors.Errorf("prep temp: %w", err)
} }
@@ -247,7 +386,7 @@ create temp table a (like actors excluding constraints) on commit drop;
for addr, acts := range actors { for addr, acts := range actors {
for act, st := range acts { for act, st := range acts {
if _, err := stmt.Exec(addr.String(), act.Code.String(), act.Head.String(), act.Nonce, act.Balance.String(), st.String()); err != nil { if _, err := stmt.Exec(addr.String(), act.Code.String(), act.Head.String(), act.Nonce, act.Balance.String(), st.stateroot.String()); err != nil {
return err return err
} }
} }
@@ -261,7 +400,47 @@ create temp table a (like actors excluding constraints) on commit drop;
return xerrors.Errorf("actor put: %w", err) return xerrors.Errorf("actor put: %w", err)
} }
return tx.Commit() if err := tx.Commit(); err != nil {
return err
}
// States
tx, err = st.db.Begin()
if err != nil {
return err
}
if _, err := tx.Exec(`
create temp table a (like actor_states excluding constraints) on commit drop;
`); err != nil {
return xerrors.Errorf("prep temp: %w", err)
}
stmt, err = tx.Prepare(`copy a (head, code, state) from stdin `)
if err != nil {
return err
}
for _, acts := range actors {
for act, st := range acts {
if _, err := stmt.Exec(act.Head.String(), act.Code.String(), st.state); err != nil {
return err
}
}
}
if err := stmt.Close(); err != nil {
return err
}
if _, err := tx.Exec(`insert into actor_states select * from a on conflict do nothing `); err != nil {
return xerrors.Errorf("actor put: %w", err)
}
if err := tx.Commit(); err != nil {
return err
}
return nil
} }
func (st *storage) storeMiners(miners map[minerKey]*minerInfo) error { func (st *storage) storeMiners(miners map[minerKey]*minerInfo) error {
@@ -329,6 +508,7 @@ func (st *storage) storeHeaders(bhs map[cid.Cid]*types.BlockHeader, sync bool) e
create temp table tbp (like block_parents excluding constraints) on commit drop; create temp table tbp (like block_parents excluding constraints) on commit drop;
create temp table bs (like blocks_synced excluding constraints) on commit drop; create temp table bs (like blocks_synced excluding constraints) on commit drop;
create temp table b (like blocks excluding constraints) on commit drop; create temp table b (like blocks excluding constraints) on commit drop;
create temp table c (like blocks_challenges excluding constraints) on commit drop;
`); err != nil { `); err != nil {
@@ -379,7 +559,7 @@ create temp table b (like blocks excluding constraints) on commit drop;
} }
} }
stmt2, err := tx.Prepare(`copy b (cid, parentWeight, parentStateRoot, height, miner, "timestamp", vrfproof, tickets, eprof, prand, ep0partial, ep0sector, ep0challangei) from stdin `) stmt2, err := tx.Prepare(`copy b (cid, parentWeight, parentStateRoot, height, miner, "timestamp", vrfproof, tickets, eprof, prand, ep0partial, ep0sector, ep0challangei) from stdin`)
if err != nil { if err != nil {
return err return err
} }
@@ -416,10 +596,36 @@ create temp table b (like blocks excluding constraints) on commit drop;
return xerrors.Errorf("blk put: %w", err) return xerrors.Errorf("blk put: %w", err)
} }
stmt3, err := tx.Prepare(`copy c (block, index, sector_id, partial, candidate) from stdin`)
if err != nil {
return xerrors.Errorf("s3 create: %w", err)
}
for _, bh := range bhs {
for index, c := range bh.EPostProof.Candidates {
if _, err := stmt3.Exec(
bh.Cid().String(),
index,
c.SectorID,
c.Partial,
c.ChallengeIndex); err != nil {
log.Error(err)
}
}
}
if err := stmt3.Close(); err != nil {
return xerrors.Errorf("s2 close: %w", err)
}
if _, err := tx.Exec(`insert into blocks_challenges select * from c on conflict do nothing `); err != nil {
return xerrors.Errorf("blk put: %w", err)
}
err = tx.Commit() err = tx.Commit()
if err != nil { if err != nil {
return xerrors.Errorf("commit: %w", err) return xerrors.Errorf("commit: %w", err)
} }
return nil return nil
} }
@@ -602,11 +808,8 @@ func (st *storage) storeMpoolInclusions(msgs []api.MpoolUpdate) error {
} }
if _, err := tx.Exec(` if _, err := tx.Exec(`
create temp table mi (like mpool_messages excluding constraints) on commit drop;
create temp table mi (like mpool_messages excluding constraints) on commit drop; `); err != nil {
`); err != nil {
return xerrors.Errorf("prep temp: %w", err) return xerrors.Errorf("prep temp: %w", err)
} }
@@ -639,6 +842,112 @@ create temp table mi (like mpool_messages excluding constraints) on commit drop;
return tx.Commit() return tx.Commit()
} }
func (st *storage) storeDeals(deals map[string]actors.OnChainDeal) error {
tx, err := st.db.Begin()
if err != nil {
return err
}
if _, err := tx.Exec(`
create temp table d (like deals excluding constraints) on commit drop;
`); err != nil {
return xerrors.Errorf("prep temp: %w", err)
}
stmt, err := tx.Prepare(`copy d (id, pieceref, piecesize, client, "provider", expiration, duration, epochprice, collateral) from stdin `)
if err != nil {
return err
}
var bloat uint64
for id, deal := range deals {
if len(deal.PieceRef) > 40 {
bloat += uint64(len(deal.PieceRef))
continue
}
if _, err := stmt.Exec(
id,
hex.EncodeToString(deal.PieceRef),
deal.PieceSize,
deal.Client.String(),
deal.Provider.String(),
fmt.Sprint(deal.ProposalExpiration),
fmt.Sprint(deal.Duration),
deal.StoragePricePerEpoch.String(),
deal.StorageCollateral.String(),
); err != nil {
return err
}
}
if bloat > 0 {
log.Warnf("deal PieceRefs had %d bytes of garbage", bloat)
}
if err := stmt.Close(); err != nil {
return err
}
if _, err := tx.Exec(`insert into deals select * from d on conflict do nothing `); err != nil {
return xerrors.Errorf("actor put: %w", err)
}
if err := tx.Commit(); err != nil {
return err
}
// Activations
tx, err = st.db.Begin()
if err != nil {
return err
}
if _, err := tx.Exec(`
create temp table d (like deal_activations excluding constraints) on commit drop;
`); err != nil {
return xerrors.Errorf("prep temp: %w", err)
}
stmt, err = tx.Prepare(`copy d (deal, activation_epoch) from stdin `)
if err != nil {
return err
}
for id, deal := range deals {
if deal.ActivationEpoch == 0 {
continue
}
if _, err := stmt.Exec(
id,
deal.ActivationEpoch,
); err != nil {
return err
}
}
if err := stmt.Close(); err != nil {
return err
}
if _, err := tx.Exec(`insert into deal_activations select * from d on conflict do nothing `); err != nil {
return xerrors.Errorf("actor put: %w", err)
}
if err := tx.Commit(); err != nil {
return err
}
return nil
}
func (st *storage) refreshViews() error {
if _, err := st.db.Exec(`refresh materialized view state_heights`); err != nil {
return err
}
return nil
}
func (st *storage) close() error { func (st *storage) close() error {
return st.db.Close() return st.db.Close()
} }
+66 -11
View File
@@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"container/list" "container/list"
"context" "context"
"encoding/json"
"math" "math"
"sync" "sync"
@@ -40,7 +41,6 @@ func runSyncer(ctx context.Context, api api.FullNode, st *storage) {
go subMpool(ctx, api, st) go subMpool(ctx, api, st)
go subBlocks(ctx, api, st) go subBlocks(ctx, api, st)
} }
} }
} }
}() }()
@@ -60,9 +60,14 @@ type minerInfo struct {
psize uint64 psize uint64
} }
type actorInfo struct {
stateroot cid.Cid
state string
}
func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipSet) { func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipSet) {
addresses := map[address.Address]address.Address{} addresses := map[address.Address]address.Address{}
actors := map[address.Address]map[types.Actor]cid.Cid{} actors := map[address.Address]map[types.Actor]actorInfo{}
var alk sync.Mutex var alk sync.Mutex
log.Infof("Getting synced block list") log.Infof("Getting synced block list")
@@ -138,24 +143,38 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
if len(bh.Parents) == 0 { // genesis case if len(bh.Parents) == 0 { // genesis case
ts, err := types.NewTipSet([]*types.BlockHeader{bh}) ts, err := types.NewTipSet([]*types.BlockHeader{bh})
aadrs, err := api.StateListActors(ctx, ts) aadrs, err := api.StateListActors(ctx, ts.Key())
if err != nil { if err != nil {
log.Error(err) log.Error(err)
return return
} }
par(50, aadrs, func(addr address.Address) { par(50, aadrs, func(addr address.Address) {
act, err := api.StateGetActor(ctx, addr, ts) act, err := api.StateGetActor(ctx, addr, ts.Key())
if err != nil { if err != nil {
log.Error(err) log.Error(err)
return return
} }
ast, err := api.StateReadState(ctx, act, ts.Key())
if err != nil {
log.Error(err)
return
}
state, err := json.Marshal(ast.State)
if err != nil {
log.Error(err)
return
}
alk.Lock() alk.Lock()
_, ok := actors[addr] _, ok := actors[addr]
if !ok { if !ok {
actors[addr] = map[types.Actor]cid.Cid{} actors[addr] = map[types.Actor]actorInfo{}
}
actors[addr][*act] = actorInfo{
stateroot: bh.ParentStateRoot,
state: string(state),
} }
actors[addr][*act] = bh.ParentStateRoot
addresses[addr] = address.Undef addresses[addr] = address.Undef
alk.Unlock() alk.Unlock()
}) })
@@ -181,13 +200,26 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
log.Error(err) log.Error(err)
return return
} }
ast, err := api.StateReadState(ctx, &act, ts.Key())
if err != nil {
log.Error(err)
return
}
state, err := json.Marshal(ast.State)
if err != nil {
log.Error(err)
return
}
alk.Lock() alk.Lock()
_, ok := actors[addr] _, ok := actors[addr]
if !ok { if !ok {
actors[addr] = map[types.Actor]cid.Cid{} actors[addr] = map[types.Actor]actorInfo{}
}
actors[addr][act] = actorInfo{
stateroot: bh.ParentStateRoot,
state: string(state),
} }
actors[addr][act] = bh.ParentStateRoot
addresses[addr] = address.Undef addresses[addr] = address.Undef
alk.Unlock() alk.Unlock()
} }
@@ -205,7 +237,7 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
} }
par(50, kmaparr(addresses), func(addr address.Address) { par(50, kmaparr(addresses), func(addr address.Address) {
raddr, err := api.StateLookupID(ctx, addr, nil) raddr, err := api.StateLookupID(ctx, addr, types.EmptyTSK)
if err != nil { if err != nil {
log.Warn(err) log.Warn(err)
return return
@@ -228,7 +260,7 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
miners[minerKey{ miners[minerKey{
addr: addr, addr: addr,
act: actor, act: actor,
stateroot: c, stateroot: c.stateroot,
}] = &minerInfo{} }] = &minerInfo{}
} }
} }
@@ -236,7 +268,7 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
par(50, kvmaparr(miners), func(it func() (minerKey, *minerInfo)) { par(50, kvmaparr(miners), func(it func() (minerKey, *minerInfo)) {
k, info := it() k, info := it()
sszs, err := api.StateMinerSectorCount(ctx, k.addr, nil) sszs, err := api.StateMinerSectorCount(ctx, k.addr, types.EmptyTSK)
if err != nil { if err != nil {
log.Error(err) log.Error(err)
return return
@@ -322,6 +354,29 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
log.Infof("Sync stage done") log.Infof("Sync stage done")
} }
log.Infof("Get deals")
// TODO: incremental, gather expired
deals, err := api.StateMarketDeals(ctx, ts.Key())
if err != nil {
log.Error(err)
return
}
log.Infof("Store deals")
if err := st.storeDeals(deals); err != nil {
log.Error(err)
return
}
log.Infof("Refresh views")
if err := st.refreshViews(); err != nil {
log.Error(err)
return
}
log.Infof("Sync done") log.Infof("Sync done")
} }
+3 -2
View File
@@ -207,7 +207,8 @@ func (h *handler) mkminer(w http.ResponseWriter, r *http.Request) {
if owner.Protocol() != address.BLS { if owner.Protocol() != address.BLS {
w.WriteHeader(400) w.WriteHeader(400)
w.Write([]byte("Miner address must use BLS")) w.Write([]byte("Miner address must use BLS. A BLS address starts with the prefix 't3'."))
w.Write([]byte("Please create a BLS address by running \"lotus wallet new bls\" while connected to a Lotus node."))
return return
} }
@@ -238,7 +239,7 @@ func (h *handler) mkminer(w http.ResponseWriter, r *http.Request) {
return return
} }
collateral, err := h.api.StatePledgeCollateral(r.Context(), nil) collateral, err := h.api.StatePledgeCollateral(r.Context(), types.EmptyTSK)
if err != nil { if err != nil {
w.WriteHeader(400) w.WriteHeader(400)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
+120 -69
View File
@@ -2,12 +2,17 @@ package main
import ( import (
"context" "context"
"errors"
"os" "os"
"os/signal"
"syscall"
"time" "time"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli" lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/lib/jsonrpc"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
@@ -41,7 +46,7 @@ func main() {
} }
if err := app.Run(os.Args); err != nil { if err := app.Run(os.Args); err != nil {
log.Warn(err) log.Fatal(err)
return return
} }
} }
@@ -64,61 +69,72 @@ var watchHeadCmd = &cli.Command{
Value: "lotus-daemon.service", Value: "lotus-daemon.service",
Usage: "systemd unit name to restart on health check failure", Usage: "systemd unit name to restart on health check failure",
}, },
&cli.IntFlag{
Name: "api-timeout",
Value: build.BlockDelay,
Usage: "timeout between API retries",
},
&cli.IntFlag{
Name: "api-retries",
Value: 8,
Usage: "number of API retry attemps",
},
}, },
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
var headCheckWindow CidWindow
threshold := c.Int("threshold") threshold := c.Int("threshold")
interval := time.Duration(c.Int("interval")) * time.Second interval := time.Duration(c.Int("interval")) * time.Second
name := c.String("systemd-unit") name := c.String("systemd-unit")
apiRetries := c.Int("api-retries")
apiTimeout := time.Duration(c.Int("api-timeout")) * time.Second
var headCheckWindow CidWindow nCh := make(chan interface{}, 1)
sCh := make(chan os.Signal, 1)
signal.Notify(sCh, os.Interrupt, syscall.SIGTERM)
api, closer, err := lcli.GetFullNodeAPI(c) api, closer, err := getFullNodeAPI(c, apiRetries, apiTimeout)
if err != nil { if err != nil {
return err return err
} }
defer closer() defer closer()
ctx := lcli.ReqContext(c) ctx := lcli.ReqContext(c)
if err := WaitForSyncComplete(ctx, api); err != nil {
log.Fatal(err)
}
ch := make(chan CidWindow, 1)
aCh := make(chan interface{}, 1)
go func() { go func() {
for { for {
headCheckWindow, err = updateWindow(ctx, api, headCheckWindow, threshold, ch) log.Info("Waiting for sync to complete")
if err != nil { if err := waitForSyncComplete(ctx, api, apiRetries, apiTimeout); err != nil {
log.Fatal(err) nCh <- err
return
} }
headCheckWindow, err = updateWindow(ctx, api, headCheckWindow, threshold, apiRetries, apiTimeout)
if err != nil {
log.Warn("Failed to connect to API. Restarting systemd service")
nCh <- nil
return
}
ok := checkWindow(headCheckWindow, threshold)
if !ok {
log.Warn("Chain head has not updated. Restarting systemd service")
nCh <- nil
break
}
log.Info("Chain head is healthy")
time.Sleep(interval) time.Sleep(interval)
} }
return
}() }()
go func() { restart, err := notifyHandler(name, nCh, sCh)
result, err := alertHandler(name, aCh) if err != nil {
if err != nil { return err
log.Fatal(err)
}
if result != "done" {
log.Fatal("systemd unit failed to restart:", result)
}
log.Info("restarting health agent")
// Exit health agent and let supervisor restart health agent
// Restarting lotus systemd unit kills api connection
os.Exit(130)
}()
for {
ok := checkWindow(ch, int(interval))
if !ok {
log.Warn("chain head has not updated. Restarting systemd service")
aCh <- nil
break
}
log.Info("chain head is healthy")
} }
if restart != "done" {
return errors.New("Systemd unit failed to restart:" + restart)
}
log.Info("Restarting health agent")
// Exit health agent and let supervisor restart health agent
// Restarting lotus systemd unit kills api connection
os.Exit(130)
return nil return nil
}, },
} }
@@ -128,52 +144,67 @@ var watchHeadCmd = &cli.Command{
* compares slices of Cids when len is greater or equal to `t` - threshold * compares slices of Cids when len is greater or equal to `t` - threshold
* if all slices are equal, head has not updated and returns false * if all slices are equal, head has not updated and returns false
*/ */
func checkWindow(ch chan CidWindow, t int) bool { func checkWindow(window CidWindow, t int) bool {
select { var dup int
case window := <-ch: windowLen := len(window)
var dup int if windowLen >= t {
windowLen := len(window) cidWindow:
if windowLen >= t { for i := range window {
cidWindow: next := windowLen - 1 - i
for i, cids := range window { // if array length is different, head is changing
next := windowLen - 1 - i if next >= 1 && len(window[next]) != len(window[next-1]) {
// if array length is different, head is changing break cidWindow
if next >= 1 && len(window[next]) != len(window[next-1]) { }
// if cids are different, head is changing
for j := range window[next] {
if next >= 1 && window[next][j] != window[next-1][j] {
break cidWindow break cidWindow
} }
// if cids are different, head is changing
for j := range cids {
if next >= 1 && window[next][j] != window[next-1][j] {
break cidWindow
}
}
if i < (t - 1) {
dup++
}
} }
if i < (t - 1) {
if dup == (t - 1) { dup++
return false
} }
} }
return true
if dup == (t - 1) {
return false
}
} }
return true
} }
/* /*
* reads channel of slices of slices of Cids * returns a slice of slices of Cids
* compares Cids when len of window is greater or equal to `t` - threshold * len of slice <= `t` - threshold
* if all slices are the equal, head has not updated and returns false
*/ */
func updateWindow(ctx context.Context, a api.FullNode, w CidWindow, t int, ch chan CidWindow) (CidWindow, error) { func updateWindow(ctx context.Context, a api.FullNode, w CidWindow, t int, r int, to time.Duration) (CidWindow, error) {
head, err := a.ChainHead(ctx) head, err := getHead(ctx, a, r, to)
if err != nil { if err != nil {
return nil, err return nil, err
} }
window := appendCIDsToWindow(w, head.Cids(), t) window := appendCIDsToWindow(w, head.Cids(), t)
ch <- window return window, err
return window, nil }
/*
* get chain head from API
* retries if API no available
* returns tipset
*/
func getHead(ctx context.Context, a api.FullNode, r int, t time.Duration) (*types.TipSet, error) {
for i := 0; i < r; i++ {
head, err := a.ChainHead(ctx)
if err != nil && i == (r-1) {
return nil, err
}
if err != nil {
log.Warnf("Call to API failed. Retrying in %.0fs", t.Seconds())
time.Sleep(t)
continue
}
return head, err
}
return nil, nil
} }
/* /*
@@ -192,13 +223,13 @@ func appendCIDsToWindow(w CidWindow, c []cid.Cid, t int) CidWindow {
/* /*
* wait for node to sync * wait for node to sync
*/ */
func WaitForSyncComplete(ctx context.Context, napi api.FullNode) error { func waitForSyncComplete(ctx context.Context, a api.FullNode, r int, t time.Duration) error {
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
return ctx.Err() return ctx.Err()
case <-time.After(3 * time.Second): case <-time.After(3 * time.Second):
head, err := napi.ChainHead(ctx) head, err := getHead(ctx, a, r, t)
if err != nil { if err != nil {
return err return err
} }
@@ -209,3 +240,23 @@ func WaitForSyncComplete(ctx context.Context, napi api.FullNode) error {
} }
} }
} }
/*
* A thin wrapper around lotus cli GetFullNodeAPI
* Adds retry logic
*/
func getFullNodeAPI(ctx *cli.Context, r int, t time.Duration) (api.FullNode, jsonrpc.ClientCloser, error) {
for i := 0; i < r; i++ {
api, closer, err := lcli.GetFullNodeAPI(ctx)
if err != nil && i == (r-1) {
return nil, nil, err
}
if err != nil {
log.Warnf("API connection failed. Retrying in %.0fs", t.Seconds())
time.Sleep(t)
continue
}
return api, closer, err
}
return nil, nil, nil
}
+100 -18
View File
@@ -28,12 +28,8 @@ func TestAppendCIDsToWindow(t *testing.T) {
func TestCheckWindow(t *testing.T) { func TestCheckWindow(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
ch := make(chan CidWindow, 1)
och := make(chan bool, 1)
threshold := 3 threshold := 3
go func() {
och <- checkWindow(ch, threshold)
}()
var healthyHeadCheckWindow CidWindow var healthyHeadCheckWindow CidWindow
healthyHeadCheckWindow = appendCIDsToWindow(healthyHeadCheckWindow, []cid.Cid{ healthyHeadCheckWindow = appendCIDsToWindow(healthyHeadCheckWindow, []cid.Cid{
makeCID("abcd"), makeCID("abcd"),
@@ -46,14 +42,79 @@ func TestCheckWindow(t *testing.T) {
makeCID("bbcd"), makeCID("bbcd"),
makeCID("bbfe"), makeCID("bbfe"),
}, threshold) }, threshold)
ch <- healthyHeadCheckWindow ok := checkWindow(healthyHeadCheckWindow, threshold)
select { assert.True(ok)
case ok := <-och:
assert.True(ok) var healthyHeadCheckWindow1 CidWindow
} healthyHeadCheckWindow1 = appendCIDsToWindow(healthyHeadCheckWindow1, []cid.Cid{
go func() { makeCID("bbcd"),
och <- checkWindow(ch, threshold) makeCID("bbfe"),
}() }, threshold)
healthyHeadCheckWindow1 = appendCIDsToWindow(healthyHeadCheckWindow1, []cid.Cid{
makeCID("bbcd"),
makeCID("bbfe"),
makeCID("abcd"),
}, threshold)
healthyHeadCheckWindow1 = appendCIDsToWindow(healthyHeadCheckWindow1, []cid.Cid{
makeCID("abcd"),
}, threshold)
ok = checkWindow(healthyHeadCheckWindow1, threshold)
assert.True(ok)
var healthyHeadCheckWindow2 CidWindow
healthyHeadCheckWindow2 = appendCIDsToWindow(healthyHeadCheckWindow2, []cid.Cid{
makeCID("bbcd"),
makeCID("bbfe"),
}, threshold)
healthyHeadCheckWindow2 = appendCIDsToWindow(healthyHeadCheckWindow2, []cid.Cid{
makeCID("abcd"),
}, threshold)
ok = checkWindow(healthyHeadCheckWindow2, threshold)
assert.True(ok)
var healthyHeadCheckWindow3 CidWindow
healthyHeadCheckWindow3 = appendCIDsToWindow(healthyHeadCheckWindow3, []cid.Cid{
makeCID("abcd"),
}, threshold)
healthyHeadCheckWindow3 = appendCIDsToWindow(healthyHeadCheckWindow3, []cid.Cid{
makeCID("bbcd"),
makeCID("bbfe"),
}, threshold)
ok = checkWindow(healthyHeadCheckWindow3, threshold)
assert.True(ok)
var healthyHeadCheckWindow4 CidWindow
healthyHeadCheckWindow4 = appendCIDsToWindow(healthyHeadCheckWindow4, []cid.Cid{
makeCID("bbcd"),
makeCID("bbfe"),
}, threshold)
ok = checkWindow(healthyHeadCheckWindow4, threshold)
assert.True(ok)
var healthyHeadCheckWindow5 CidWindow
healthyHeadCheckWindow5 = appendCIDsToWindow(healthyHeadCheckWindow5, []cid.Cid{
makeCID("bbcd"),
makeCID("bbfe"),
makeCID("bbff"),
}, 5)
healthyHeadCheckWindow5 = appendCIDsToWindow(healthyHeadCheckWindow5, []cid.Cid{
makeCID("bbcd"),
makeCID("bbfe"),
}, 5)
healthyHeadCheckWindow5 = appendCIDsToWindow(healthyHeadCheckWindow5, []cid.Cid{
makeCID("abcd"),
}, 5)
healthyHeadCheckWindow5 = appendCIDsToWindow(healthyHeadCheckWindow5, []cid.Cid{
makeCID("cbcd"),
makeCID("cbfe"),
}, 5)
healthyHeadCheckWindow5 = appendCIDsToWindow(healthyHeadCheckWindow5, []cid.Cid{
makeCID("cbcd"),
makeCID("cbfe"),
}, 5)
ok = checkWindow(healthyHeadCheckWindow5, threshold)
assert.True(ok)
var unhealthyHeadCheckWindow CidWindow var unhealthyHeadCheckWindow CidWindow
unhealthyHeadCheckWindow = appendCIDsToWindow(unhealthyHeadCheckWindow, []cid.Cid{ unhealthyHeadCheckWindow = appendCIDsToWindow(unhealthyHeadCheckWindow, []cid.Cid{
makeCID("abcd"), makeCID("abcd"),
@@ -67,12 +128,33 @@ func TestCheckWindow(t *testing.T) {
makeCID("abcd"), makeCID("abcd"),
makeCID("fbcd"), makeCID("fbcd"),
}, threshold) }, threshold)
ch <- unhealthyHeadCheckWindow ok = checkWindow(unhealthyHeadCheckWindow, threshold)
select { assert.False(ok)
case ok := <-och:
assert.False(ok)
}
var unhealthyHeadCheckWindow1 CidWindow
unhealthyHeadCheckWindow1 = appendCIDsToWindow(unhealthyHeadCheckWindow1, []cid.Cid{
makeCID("abcd"),
makeCID("fbcd"),
}, threshold)
unhealthyHeadCheckWindow1 = appendCIDsToWindow(unhealthyHeadCheckWindow1, []cid.Cid{
makeCID("abcd"),
makeCID("fbcd"),
}, threshold)
ok = checkWindow(unhealthyHeadCheckWindow1, threshold)
assert.True(ok)
var unhealthyHeadCheckWindow2 CidWindow
unhealthyHeadCheckWindow2 = appendCIDsToWindow(unhealthyHeadCheckWindow2, []cid.Cid{
makeCID("abcd"),
}, threshold)
unhealthyHeadCheckWindow2 = appendCIDsToWindow(unhealthyHeadCheckWindow2, []cid.Cid{
makeCID("abcd"),
}, threshold)
unhealthyHeadCheckWindow2 = appendCIDsToWindow(unhealthyHeadCheckWindow2, []cid.Cid{
makeCID("abcd"),
}, threshold)
ok = checkWindow(unhealthyHeadCheckWindow2, threshold)
assert.False(ok)
} }
func makeCID(s string) cid.Cid { func makeCID(s string) cid.Cid {
@@ -1,11 +1,14 @@
package main package main
import ( import (
"github.com/coreos/go-systemd/dbus" "os"
"github.com/coreos/go-systemd/v22/dbus"
) )
func alertHandler(n string, ch chan interface{}) (string, error) { func notifyHandler(n string, ch chan interface{}, sCh chan os.Signal) (string, error) {
select { select {
// alerts to restart systemd unit
case <-ch: case <-ch:
statusCh := make(chan string, 1) statusCh := make(chan string, 1)
c, err := dbus.New() c, err := dbus.New()
@@ -20,5 +23,9 @@ func alertHandler(n string, ch chan interface{}) (string, error) {
case result := <-statusCh: case result := <-statusCh:
return result, nil return result, nil
} }
// SIGTERM
case <-sCh:
os.Exit(1)
return "", nil
} }
} }
+60 -2
View File
@@ -2,23 +2,32 @@ package main
import ( import (
"os" "os"
"sync"
paramfetch "github.com/filecoin-project/go-paramfetch"
"github.com/filecoin-project/go-sectorbuilder"
"github.com/mitchellh/go-homedir" "github.com/mitchellh/go-homedir"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
manet "github.com/multiformats/go-multiaddr-net"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
lcli "github.com/filecoin-project/lotus/cli" lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/lib/lotuslog" "github.com/filecoin-project/lotus/lib/lotuslog"
"github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/node/repo"
manet "github.com/multiformats/go-multiaddr-net"
) )
var log = logging.Logger("main") var log = logging.Logger("main")
const (
workers = 1 // TODO: Configurability
transfers = 1
)
func main() { func main() {
lotuslog.SetupLogLevels() lotuslog.SetupLogLevels()
@@ -67,6 +76,11 @@ func main() {
} }
} }
type limits struct {
workLimit chan struct{}
transferLimit chan struct{}
}
var runCmd = &cli.Command{ var runCmd = &cli.Command{
Name: "run", Name: "run",
Usage: "Start lotus worker", Usage: "Start lotus worker",
@@ -106,6 +120,50 @@ var runCmd = &cli.Command{
log.Warn("Shutting down..") log.Warn("Shutting down..")
}() }()
return acceptJobs(ctx, nodeApi, "http://"+storageAddr, ainfo.AuthHeader(), r, cctx.Bool("no-precommit"), cctx.Bool("no-commit")) limiter := &limits{
workLimit: make(chan struct{}, workers),
transferLimit: make(chan struct{}, transfers),
}
act, err := nodeApi.ActorAddress(ctx)
if err != nil {
return err
}
ssize, err := nodeApi.ActorSectorSize(ctx, act)
if err != nil {
return err
}
if err := paramfetch.GetParams(build.ParametersJson(), ssize); err != nil {
return xerrors.Errorf("get params: %w", err)
}
sb, err := sectorbuilder.NewStandalone(&sectorbuilder.Config{
SectorSize: ssize,
Miner: act,
WorkerThreads: workers,
Paths: sectorbuilder.SimplePath(r),
})
if err != nil {
return err
}
nQueues := workers + transfers
var wg sync.WaitGroup
wg.Add(nQueues)
for i := 0; i < nQueues; i++ {
go func() {
defer wg.Done()
if err := acceptJobs(ctx, nodeApi, sb, limiter, "http://"+storageAddr, ainfo.AuthHeader(), r, cctx.Bool("no-precommit"), cctx.Bool("no-commit")); err != nil {
log.Warnf("%+v", err)
return
}
}()
}
wg.Wait()
return nil
}, },
} }
+12 -28
View File
@@ -4,12 +4,10 @@ import (
"context" "context"
"net/http" "net/http"
paramfetch "github.com/filecoin-project/go-paramfetch"
"github.com/filecoin-project/go-sectorbuilder" "github.com/filecoin-project/go-sectorbuilder"
"golang.org/x/xerrors" "golang.org/x/xerrors"
lapi "github.com/filecoin-project/lotus/api" lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
) )
type worker struct { type worker struct {
@@ -18,39 +16,19 @@ type worker struct {
repo string repo string
auth http.Header auth http.Header
sb *sectorbuilder.SectorBuilder limiter *limits
sb *sectorbuilder.SectorBuilder
} }
func acceptJobs(ctx context.Context, api lapi.StorageMiner, endpoint string, auth http.Header, repo string, noprecommit, nocommit bool) error { func acceptJobs(ctx context.Context, api lapi.StorageMiner, sb *sectorbuilder.SectorBuilder, limiter *limits, endpoint string, auth http.Header, repo string, noprecommit, nocommit bool) error {
act, err := api.ActorAddress(ctx)
if err != nil {
return err
}
ssize, err := api.ActorSectorSize(ctx, act)
if err != nil {
return err
}
sb, err := sectorbuilder.NewStandalone(&sectorbuilder.Config{
SectorSize: ssize,
Miner: act,
WorkerThreads: 1,
Dir: repo,
})
if err != nil {
return err
}
if err := paramfetch.GetParams(build.ParametersJson, ssize); err != nil {
return xerrors.Errorf("get params: %w", err)
}
w := &worker{ w := &worker{
api: api, api: api,
minerEndpoint: endpoint, minerEndpoint: endpoint,
auth: auth, auth: auth,
repo: repo, repo: repo,
sb: sb,
limiter: limiter,
sb: sb,
} }
tasks, err := api.WorkerQueue(ctx, sectorbuilder.WorkerCfg{ tasks, err := api.WorkerQueue(ctx, sectorbuilder.WorkerCfg{
@@ -103,7 +81,10 @@ func (w *worker) processTask(ctx context.Context, task sectorbuilder.WorkerTask)
switch task.Type { switch task.Type {
case sectorbuilder.WorkerPreCommit: case sectorbuilder.WorkerPreCommit:
w.limiter.workLimit <- struct{}{}
rspco, err := w.sb.SealPreCommit(ctx, task.SectorID, task.SealTicket, task.Pieces) rspco, err := w.sb.SealPreCommit(ctx, task.SectorID, task.SealTicket, task.Pieces)
<-w.limiter.workLimit
if err != nil { if err != nil {
return errRes(xerrors.Errorf("precomitting: %w", err)) return errRes(xerrors.Errorf("precomitting: %w", err))
} }
@@ -121,7 +102,10 @@ func (w *worker) processTask(ctx context.Context, task sectorbuilder.WorkerTask)
return errRes(xerrors.Errorf("cleaning up staged sector: %w", err)) return errRes(xerrors.Errorf("cleaning up staged sector: %w", err))
} }
case sectorbuilder.WorkerCommit: case sectorbuilder.WorkerCommit:
w.limiter.workLimit <- struct{}{}
proof, err := w.sb.SealCommit(ctx, task.SectorID, task.SealTicket, task.SealSeed, task.Pieces, task.Rspco) proof, err := w.sb.SealCommit(ctx, task.SectorID, task.SealTicket, task.SealSeed, task.Pieces, task.Rspco)
<-w.limiter.workLimit
if err != nil { if err != nil {
return errRes(xerrors.Errorf("comitting: %w", err)) return errRes(xerrors.Errorf("comitting: %w", err))
} }
+31 -8
View File
@@ -1,12 +1,14 @@
package main package main
import ( import (
"fmt"
"io" "io"
"mime" "mime"
"net/http" "net/http"
"os" "os"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder" sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/go-sectorbuilder/fs"
files "github.com/ipfs/go-ipfs-files" files "github.com/ipfs/go-ipfs-files"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/cheggaaa/pb.v1" "gopkg.in/cheggaaa/pb.v1"
@@ -15,10 +17,18 @@ import (
"github.com/filecoin-project/lotus/lib/tarutil" "github.com/filecoin-project/lotus/lib/tarutil"
) )
func (w *worker) sizeForType(typ string) int64 {
size := int64(w.sb.SectorSize())
if typ == "cache" {
size *= 10
}
return size
}
func (w *worker) fetch(typ string, sectorID uint64) error { func (w *worker) fetch(typ string, sectorID uint64) error {
outname := filepath.Join(w.repo, typ, w.sb.SectorName(sectorID)) outname := filepath.Join(w.repo, typ, w.sb.SectorName(sectorID))
url := w.minerEndpoint + "/remote/" + typ + "/" + w.sb.SectorName(sectorID) url := w.minerEndpoint + "/remote/" + typ + "/" + fmt.Sprint(sectorID)
log.Infof("Fetch %s %s", typ, url) log.Infof("Fetch %s %s", typ, url)
req, err := http.NewRequest("GET", url, nil) req, err := http.NewRequest("GET", url, nil)
@@ -37,7 +47,7 @@ func (w *worker) fetch(typ string, sectorID uint64) error {
return xerrors.Errorf("non-200 code: %d", resp.StatusCode) return xerrors.Errorf("non-200 code: %d", resp.StatusCode)
} }
bar := pb.New64(resp.ContentLength) bar := pb.New64(w.sizeForType(typ))
bar.ShowPercent = true bar.ShowPercent = true
bar.ShowSpeed = true bar.ShowSpeed = true
bar.Units = pb.U_BYTES bar.Units = pb.U_BYTES
@@ -68,27 +78,35 @@ func (w *worker) fetch(typ string, sectorID uint64) error {
} }
func (w *worker) push(typ string, sectorID uint64) error { func (w *worker) push(typ string, sectorID uint64) error {
filename := filepath.Join(w.repo, typ, w.sb.SectorName(sectorID)) w.limiter.transferLimit <- struct{}{}
defer func() {
<-w.limiter.transferLimit
}()
url := w.minerEndpoint + "/remote/" + typ + "/" + w.sb.SectorName(sectorID) filename, err := w.sb.SectorPath(fs.DataType(typ), sectorID)
if err != nil {
return err
}
url := w.minerEndpoint + "/remote/" + typ + "/" + fmt.Sprint(sectorID)
log.Infof("Push %s %s", typ, url) log.Infof("Push %s %s", typ, url)
stat, err := os.Stat(filename) stat, err := os.Stat(string(filename))
if err != nil { if err != nil {
return err return err
} }
var r io.Reader var r io.Reader
if stat.IsDir() { if stat.IsDir() {
r, err = tarutil.TarDirectory(filename) r, err = tarutil.TarDirectory(string(filename))
} else { } else {
r, err = os.OpenFile(filename, os.O_RDONLY, 0644) r, err = os.OpenFile(string(filename), os.O_RDONLY, 0644)
} }
if err != nil { if err != nil {
return xerrors.Errorf("opening push reader: %w", err) return xerrors.Errorf("opening push reader: %w", err)
} }
bar := pb.New64(0) bar := pb.New64(w.sizeForType(typ))
bar.ShowPercent = true bar.ShowPercent = true
bar.ShowSpeed = true bar.ShowSpeed = true
bar.ShowCounters = true bar.ShowCounters = true
@@ -134,6 +152,11 @@ func (w *worker) remove(typ string, sectorID uint64) error {
} }
func (w *worker) fetchSector(sectorID uint64, typ sectorbuilder.WorkerTaskType) error { func (w *worker) fetchSector(sectorID uint64, typ sectorbuilder.WorkerTaskType) error {
w.limiter.transferLimit <- struct{}{}
defer func() {
<-w.limiter.transferLimit
}()
var err error var err error
switch typ { switch typ {
case sectorbuilder.WorkerPreCommit: case sectorbuilder.WorkerPreCommit:
+5 -2
View File
@@ -8,6 +8,9 @@ import (
"encoding/json" "encoding/json"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder" sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/namespace" "github.com/ipfs/go-datastore/namespace"
badger "github.com/ipfs/go-ds-badger2" badger "github.com/ipfs/go-ds-badger2"
@@ -196,7 +199,7 @@ var aggregateSectorDirsCmd = &cli.Command{
agsb, err := sectorbuilder.New(&sectorbuilder.Config{ agsb, err := sectorbuilder.New(&sectorbuilder.Config{
Miner: maddr, Miner: maddr,
SectorSize: ssize, SectorSize: ssize,
Dir: destdir, Paths: sectorbuilder.SimplePath(destdir),
WorkerThreads: 2, WorkerThreads: 2,
}, namespace.Wrap(agmds, datastore.NewKey("/sectorbuilder"))) }, namespace.Wrap(agmds, datastore.NewKey("/sectorbuilder")))
if err != nil { if err != nil {
@@ -257,7 +260,7 @@ var aggregateSectorDirsCmd = &cli.Command{
sb, err := sectorbuilder.New(&sectorbuilder.Config{ sb, err := sectorbuilder.New(&sectorbuilder.Config{
Miner: maddr, Miner: maddr,
SectorSize: genm.SectorSize, SectorSize: genm.SectorSize,
Dir: dir, Paths: sectorbuilder.SimplePath(dir),
WorkerThreads: 2, WorkerThreads: 2,
}, namespace.Wrap(mds, datastore.NewKey("/sectorbuilder"))) }, namespace.Wrap(mds, datastore.NewKey("/sectorbuilder")))
if err != nil { if err != nil {
+3 -3
View File
@@ -32,7 +32,7 @@ func PreSeal(maddr address.Address, ssize uint64, offset uint64, sectors int, sb
Miner: maddr, Miner: maddr,
SectorSize: ssize, SectorSize: ssize,
FallbackLastID: offset, FallbackLastID: offset,
Dir: sbroot, Paths: sectorbuilder.SimplePath(sbroot),
WorkerThreads: 2, WorkerThreads: 2,
} }
@@ -59,7 +59,7 @@ func PreSeal(maddr address.Address, ssize uint64, offset uint64, sectors int, sb
return nil, err return nil, err
} }
pi, err := sb.AddPiece(size, sid, rand.Reader, nil) pi, err := sb.AddPiece(context.TODO(), size, sid, rand.Reader, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -76,7 +76,7 @@ func PreSeal(maddr address.Address, ssize uint64, offset uint64, sectors int, sb
return nil, xerrors.Errorf("commit: %w", err) return nil, xerrors.Errorf("commit: %w", err)
} }
if err := sb.TrimCache(sid); err != nil { if err := sb.TrimCache(context.TODO(), sid); err != nil {
return nil, xerrors.Errorf("trim cache: %w", err) return nil, xerrors.Errorf("trim cache: %w", err)
} }
+47
View File
@@ -0,0 +1,47 @@
package main
import (
"encoding/base64"
"encoding/hex"
"fmt"
"github.com/filecoin-project/lotus/chain/types"
"gopkg.in/urfave/cli.v2"
)
var bigIntParseCmd = &cli.Command{
Name: "bigint",
Description: "parse encoded big ints",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "enc",
Value: "base64",
Usage: "specify input encoding to parse",
},
},
Action: func(cctx *cli.Context) error {
val := cctx.Args().Get(0)
var dec []byte
switch cctx.String("enc") {
case "base64":
d, err := base64.StdEncoding.DecodeString(val)
if err != nil {
return fmt.Errorf("decoding base64 value: %w", err)
}
dec = d
case "hex":
d, err := hex.DecodeString(val)
if err != nil {
return fmt.Errorf("decoding hex value: %w", err)
}
dec = d
default:
return fmt.Errorf("unrecognized encoding: %s", cctx.String("enc"))
}
iv := types.BigFromBytes(dec)
fmt.Println(iv.String())
return nil
},
}
+3
View File
@@ -11,6 +11,9 @@ import (
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
) )
+1
View File
@@ -20,6 +20,7 @@ func main() {
keyinfoCmd, keyinfoCmd,
peerkeyCmd, peerkeyCmd,
noncefix, noncefix,
bigIntParseCmd,
} }
app := &cli.App{ app := &cli.App{
+19 -7
View File
@@ -38,27 +38,39 @@ var infoCmd = &cli.Command{
fmt.Printf("Miner: %s\n", maddr) fmt.Printf("Miner: %s\n", maddr)
// Sector size // Sector size
sizeByte, err := api.StateMinerSectorSize(ctx, maddr, nil) sizeByte, err := api.StateMinerSectorSize(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
fmt.Printf("Sector Size: %s\n", types.NewInt(sizeByte).SizeStr()) fmt.Printf("Sector Size: %s\n", types.NewInt(sizeByte).SizeStr())
pow, err := api.StateMinerPower(ctx, maddr, nil) pow, err := api.StateMinerPower(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
percI := types.BigDiv(types.BigMul(pow.MinerPower, types.NewInt(1000)), pow.TotalPower) percI := types.BigDiv(types.BigMul(pow.MinerPower, types.NewInt(1000000)), pow.TotalPower)
fmt.Printf("Power: %s / %s (%0.4f%%)\n", pow.MinerPower.SizeStr(), pow.TotalPower.SizeStr(), float64(percI.Int64())/100000*10000) fmt.Printf("Power: %s / %s (%0.4f%%)\n", pow.MinerPower.SizeStr(), pow.TotalPower.SizeStr(), float64(percI.Int64())/10000)
secCounts, err := api.StateMinerSectorCount(ctx, maddr, nil) secCounts, err := api.StateMinerSectorCount(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
faults, err := api.StateMinerFaults(ctx, maddr, types.EmptyTSK)
if err != nil {
return err
}
fmt.Printf("\tCommitted: %s\n", types.BigMul(types.NewInt(secCounts.Sset), types.NewInt(sizeByte)).SizeStr()) fmt.Printf("\tCommitted: %s\n", types.BigMul(types.NewInt(secCounts.Sset), types.NewInt(sizeByte)).SizeStr())
fmt.Printf("\tProving: %s\n", types.BigMul(types.NewInt(secCounts.Pset), types.NewInt(sizeByte)).SizeStr()) if len(faults) == 0 {
fmt.Printf("\tProving: %s\n", types.BigMul(types.NewInt(secCounts.Pset), types.NewInt(sizeByte)).SizeStr())
} else {
fmt.Printf("\tProving: %s (%s Faulty, %.2f%%)\n",
types.BigMul(types.NewInt(secCounts.Pset-uint64(len(faults))), types.NewInt(sizeByte)).SizeStr(),
types.BigMul(types.NewInt(uint64(len(faults))), types.NewInt(sizeByte)).SizeStr(),
float64(10000*uint64(len(faults))/secCounts.Pset)/100.)
}
// TODO: indicate whether the post worker is in use // TODO: indicate whether the post worker is in use
wstat, err := nodeApi.WorkerStats(ctx) wstat, err := nodeApi.WorkerStats(ctx)
@@ -76,7 +88,7 @@ var infoCmd = &cli.Command{
fmt.Printf("\tCommit: %d\n", wstat.CommitWait) fmt.Printf("\tCommit: %d\n", wstat.CommitWait)
fmt.Printf("\tUnseal: %d\n", wstat.UnsealWait) fmt.Printf("\tUnseal: %d\n", wstat.UnsealWait)
eps, err := api.StateMinerElectionPeriodStart(ctx, maddr, nil) eps, err := api.StateMinerElectionPeriodStart(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
+41 -21
View File
@@ -34,6 +34,7 @@ import (
"github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/markets/utils" "github.com/filecoin-project/lotus/markets/utils"
"github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/lotus/node/config"
"github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/modules"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/node/repo"
@@ -77,6 +78,10 @@ var initCmd = &cli.Command{
Name: "pre-sealed-sectors", Name: "pre-sealed-sectors",
Usage: "specify set of presealed sectors for starting as a genesis miner", Usage: "specify set of presealed sectors for starting as a genesis miner",
}, },
&cli.StringFlag{
Name: "pre-sealed-metadata",
Usage: "specify the metadata file for the presealed sectors",
},
&cli.BoolFlag{ &cli.BoolFlag{
Name: "nosync", Name: "nosync",
Usage: "don't check full-node sync status", Usage: "don't check full-node sync status",
@@ -97,7 +102,7 @@ var initCmd = &cli.Command{
} }
log.Info("Checking proof parameters") log.Info("Checking proof parameters")
if err := paramfetch.GetParams(build.ParametersJson, ssize); err != nil { if err := paramfetch.GetParams(build.ParametersJson(), ssize); err != nil {
return xerrors.Errorf("fetching proof parameters: %w", err) return xerrors.Errorf("fetching proof parameters: %w", err)
} }
@@ -177,7 +182,7 @@ var initCmd = &cli.Command{
oldsb, err := sectorbuilder.New(&sectorbuilder.Config{ oldsb, err := sectorbuilder.New(&sectorbuilder.Config{
SectorSize: ssize, SectorSize: ssize,
WorkerThreads: 2, WorkerThreads: 2,
Dir: pssb, Paths: sectorbuilder.SimplePath(pssb),
}, namespace.Wrap(oldmds, datastore.NewKey("/sectorbuilder"))) }, namespace.Wrap(oldmds, datastore.NewKey("/sectorbuilder")))
if err != nil { if err != nil {
return xerrors.Errorf("failed to open up preseal sectorbuilder: %w", err) return xerrors.Errorf("failed to open up preseal sectorbuilder: %w", err)
@@ -186,7 +191,7 @@ var initCmd = &cli.Command{
nsb, err := sectorbuilder.New(&sectorbuilder.Config{ nsb, err := sectorbuilder.New(&sectorbuilder.Config{
SectorSize: ssize, SectorSize: ssize,
WorkerThreads: 2, WorkerThreads: 2,
Dir: lr.Path(), Paths: sectorbuilder.SimplePath(lr.Path()),
}, namespace.Wrap(mds, datastore.NewKey("/sectorbuilder"))) }, namespace.Wrap(mds, datastore.NewKey("/sectorbuilder")))
if err != nil { if err != nil {
return xerrors.Errorf("failed to open up sectorbuilder: %w", err) return xerrors.Errorf("failed to open up sectorbuilder: %w", err)
@@ -220,13 +225,13 @@ var initCmd = &cli.Command{
}, },
} }
func migratePreSealMeta(ctx context.Context, api lapi.FullNode, presealDir string, maddr address.Address, mds dtypes.MetadataDS) error { func migratePreSealMeta(ctx context.Context, api lapi.FullNode, metadata string, maddr address.Address, mds dtypes.MetadataDS) error {
presealDir, err := homedir.Expand(presealDir) metadata, err := homedir.Expand(metadata)
if err != nil { if err != nil {
return xerrors.Errorf("expanding preseal dir: %w", err) return xerrors.Errorf("expanding preseal dir: %w", err)
} }
b, err := ioutil.ReadFile(filepath.Join(presealDir, "pre-seal-"+maddr.String()+".json")) b, err := ioutil.ReadFile(metadata)
if err != nil { if err != nil {
return xerrors.Errorf("reading preseal metadata: %w", err) return xerrors.Errorf("reading preseal metadata: %w", err)
} }
@@ -319,7 +324,7 @@ func findMarketDealID(ctx context.Context, api lapi.FullNode, deal actors.Storag
// TODO: find a better way // TODO: find a better way
// (this is only used by genesis miners) // (this is only used by genesis miners)
deals, err := api.StateMarketDeals(ctx, nil) deals, err := api.StateMarketDeals(ctx, types.EmptyTSK)
if err != nil { if err != nil {
return 0, xerrors.Errorf("getting market deals: %w", err) return 0, xerrors.Errorf("getting market deals: %w", err)
} }
@@ -369,7 +374,22 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode,
return err return err
} }
sbcfg, err := modules.SectorBuilderConfig(lr.Path(), 2, false, false)(mds, api) c, err := lr.Config()
if err != nil {
return err
}
cfg, ok := c.(*config.StorageMiner)
if !ok {
return xerrors.Errorf("invalid config from repo, got: %T", c)
}
scfg := sectorbuilder.SimplePath(lr.Path())
if len(cfg.SectorBuilder.Storage) > 0 {
scfg = cfg.SectorBuilder.Storage
}
sbcfg, err := modules.SectorBuilderConfig(scfg, 2, false, false)(mds, api)
if err != nil { if err != nil {
return xerrors.Errorf("getting genesis miner sector builder config: %w", err) return xerrors.Errorf("getting genesis miner sector builder config: %w", err)
} }
@@ -396,20 +416,20 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode,
} }
} }
if pssb := cctx.String("pre-sealed-sectors"); pssb != "" { return nil
pssb, err := homedir.Expand(pssb) }
if err != nil {
return err
}
log.Infof("Importing pre-sealed sector metadata for %s", a) if pssb := cctx.String("pre-sealed-metadata"); pssb != "" {
pssb, err := homedir.Expand(pssb)
if err := migratePreSealMeta(ctx, api, pssb, a, mds); err != nil { if err != nil {
return xerrors.Errorf("migrating presealed sector metadata: %w", err) return err
}
} }
return nil log.Infof("Importing pre-sealed sector metadata for %s", a)
if err := migratePreSealMeta(ctx, api, pssb, a, mds); err != nil {
return xerrors.Errorf("migrating presealed sector metadata: %w", err)
}
} }
if err := configureStorageMiner(ctx, api, a, peerid); err != nil { if err := configureStorageMiner(ctx, api, a, peerid); err != nil {
@@ -466,7 +486,7 @@ func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address.
To: addr, To: addr,
From: addr, From: addr,
Method: actors.MAMethods.GetWorkerAddr, Method: actors.MAMethods.GetWorkerAddr,
}, nil) }, types.EmptyTSK)
if err != nil { if err != nil {
return xerrors.Errorf("failed to get worker address: %w", err) return xerrors.Errorf("failed to get worker address: %w", err)
} }
@@ -539,7 +559,7 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID,
return address.Undef, err return address.Undef, err
} }
collateral, err := api.StatePledgeCollateral(ctx, nil) collateral, err := api.StatePledgeCollateral(ctx, types.EmptyTSK)
if err != nil { if err != nil {
return address.Undef, err return address.Undef, err
} }
+29 -5
View File
@@ -2,8 +2,12 @@ package main
import ( import (
"fmt" "fmt"
"github.com/filecoin-project/lotus/chain/types"
"os"
"sort" "sort"
"strconv" "strconv"
"text/tabwriter"
"time"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
@@ -41,6 +45,12 @@ var sectorsCmd = &cli.Command{
var sectorsStatusCmd = &cli.Command{ var sectorsStatusCmd = &cli.Command{
Name: "status", Name: "status",
Usage: "Get the seal status of a sector by its ID", Usage: "Get the seal status of a sector by its ID",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "log",
Usage: "display event log",
},
},
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil { if err != nil {
@@ -77,6 +87,17 @@ var sectorsStatusCmd = &cli.Command{
if status.LastErr != "" { if status.LastErr != "" {
fmt.Printf("Last Error:\t\t%s\n", status.LastErr) fmt.Printf("Last Error:\t\t%s\n", status.LastErr)
} }
if cctx.Bool("log") {
fmt.Printf("--------\nEvent Log:\n")
for i, l := range status.Log {
fmt.Printf("%d.\t%s:\t[%s]\t%s\n", i, time.Unix(int64(l.Timestamp), 0), l.Kind, l.Message)
if l.Trace != "" {
fmt.Printf("\t%s\n", l.Trace)
}
}
}
return nil return nil
}, },
} }
@@ -109,7 +130,7 @@ var sectorsListCmd = &cli.Command{
return err return err
} }
pset, err := fullApi.StateMinerProvingSet(ctx, maddr, nil) pset, err := fullApi.StateMinerProvingSet(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
@@ -118,7 +139,7 @@ var sectorsListCmd = &cli.Command{
provingIDs[info.SectorID] = struct{}{} provingIDs[info.SectorID] = struct{}{}
} }
sset, err := fullApi.StateMinerSectors(ctx, maddr, nil) sset, err := fullApi.StateMinerSectors(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
@@ -131,17 +152,19 @@ var sectorsListCmd = &cli.Command{
return list[i] < list[j] return list[i] < list[j]
}) })
w := tabwriter.NewWriter(os.Stdout, 8, 4, 1, ' ', 0)
for _, s := range list { for _, s := range list {
st, err := nodeApi.SectorsStatus(ctx, s) st, err := nodeApi.SectorsStatus(ctx, s)
if err != nil { if err != nil {
fmt.Printf("%d:\tError: %s\n", s, err) fmt.Fprintf(w, "%d:\tError: %s\n", s, err)
continue continue
} }
_, inSSet := commitedIDs[s] _, inSSet := commitedIDs[s]
_, inPSet := provingIDs[s] _, inPSet := provingIDs[s]
fmt.Printf("%d: %s\tsSet: %s\tpSet: %s\ttktH: %d\tseedH: %d\tdeals: %v\n", fmt.Fprintf(w, "%d: %s\tsSet: %s\tpSet: %s\ttktH: %d\tseedH: %d\tdeals: %v\n",
s, s,
api.SectorStates[st.State], api.SectorStates[st.State],
yesno(inSSet), yesno(inSSet),
@@ -151,7 +174,8 @@ var sectorsListCmd = &cli.Command{
st.Deals, st.Deals,
) )
} }
return nil
return w.Flush()
}, },
} }
+99 -1
View File
@@ -5,14 +5,22 @@ package main
import ( import (
"context" "context"
"io/ioutil" "io/ioutil"
"os"
"runtime/pprof"
paramfetch "github.com/filecoin-project/go-paramfetch" paramfetch "github.com/filecoin-project/go-paramfetch"
"github.com/filecoin-project/go-sectorbuilder"
blockstore "github.com/ipfs/go-ipfs-blockstore"
"github.com/mitchellh/go-homedir"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/node" "github.com/filecoin-project/lotus/node"
"github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/modules"
"github.com/filecoin-project/lotus/node/modules/testing" "github.com/filecoin-project/lotus/node/modules/testing"
@@ -56,9 +64,42 @@ var DaemonCmd = &cli.Command{
Name: "bootstrap", Name: "bootstrap",
Value: true, Value: true,
}, },
&cli.StringFlag{
Name: "import-chain",
Usage: "on first run, load chain from given file",
},
&cli.BoolFlag{
Name: "halt-after-import",
Usage: "halt the process after importing chain from file",
},
&cli.StringFlag{
Name: "pprof",
Usage: "specify name of file for writing cpu profile to",
},
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if prof := cctx.String("pprof"); prof != "" {
profile, err := os.Create(prof)
if err != nil {
return err
}
if err := pprof.StartCPUProfile(profile); err != nil {
return err
}
defer pprof.StopCPUProfile()
}
ctx := context.Background() ctx := context.Background()
{
dir, err := homedir.Expand(cctx.String("repo"))
if err != nil {
log.Warnw("could not expand repo location", "error", err)
} else {
log.Infof("lotus repo: %s", dir)
}
}
r, err := repo.NewFS(cctx.String("repo")) r, err := repo.NewFS(cctx.String("repo"))
if err != nil { if err != nil {
return xerrors.Errorf("opening fs repo: %w", err) return xerrors.Errorf("opening fs repo: %w", err)
@@ -68,7 +109,7 @@ var DaemonCmd = &cli.Command{
return xerrors.Errorf("repo init error: %w", err) return xerrors.Errorf("repo init error: %w", err)
} }
if err := paramfetch.GetParams(build.ParametersJson, 0); err != nil { if err := paramfetch.GetParams(build.ParametersJson(), 0); err != nil {
return xerrors.Errorf("fetching proof parameters: %w", err) return xerrors.Errorf("fetching proof parameters: %w", err)
} }
@@ -81,6 +122,16 @@ var DaemonCmd = &cli.Command{
} }
} }
chainfile := cctx.String("import-chain")
if chainfile != "" {
if err := ImportChain(r, chainfile); err != nil {
return err
}
if cctx.Bool("halt-after-import") {
return nil
}
}
genesis := node.Options() genesis := node.Options()
if len(genBytes) > 0 { if len(genBytes) > 0 {
genesis = node.Override(new(modules.Genesis), modules.LoadGenesis(genBytes)) genesis = node.Override(new(modules.Genesis), modules.LoadGenesis(genBytes))
@@ -129,3 +180,50 @@ var DaemonCmd = &cli.Command{
return serveRPC(api, stop, endpoint) return serveRPC(api, stop, endpoint)
}, },
} }
func ImportChain(r repo.Repo, fname string) error {
fi, err := os.Open(fname)
if err != nil {
return err
}
lr, err := r.Lock(repo.FullNode)
if err != nil {
return err
}
defer lr.Close()
ds, err := lr.Datastore("/blocks")
if err != nil {
return err
}
mds, err := lr.Datastore("/metadata")
if err != nil {
return err
}
bs := blockstore.NewBlockstore(ds)
cst := store.NewChainStore(bs, mds, vm.Syscalls(sectorbuilder.ProofVerifier))
log.Info("importing chain from file...")
ts, err := cst.Import(fi)
if err != nil {
return xerrors.Errorf("importing chain failed: %w", err)
}
stm := stmgr.NewStateManager(cst)
log.Infof("validating imported chain...")
if err := stm.ValidateChain(context.TODO(), ts); err != nil {
return xerrors.Errorf("chain validation failed: %w", err)
}
log.Info("accepting %s as new head", ts.Cids())
if err := cst.SetHead(ts); err != nil {
return err
}
return nil
}
+115
View File
@@ -0,0 +1,115 @@
// +build debug
package main
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/miner"
"golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
)
func init() {
AdvanceBlockCmd = &cli.Command{
Name: "advance-block",
Action: func(cctx *cli.Context) error {
api, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := lcli.ReqContext(cctx)
head, err := api.ChainHead(ctx)
if err != nil {
return err
}
pending, err := api.MpoolPending(ctx, head.Key())
if err != nil {
return err
}
msgs, err := miner.SelectMessages(ctx, api.StateGetActor, head, pending)
if err != nil {
return err
}
if len(msgs) > build.BlockMessageLimit {
log.Error("SelectMessages returned too many messages: ", len(msgs))
msgs = msgs[:build.BlockMessageLimit]
}
addr, _ := address.NewIDAddress(101)
var ticket *types.Ticket
{
vrfBase := head.MinTicket().VRFProof
ret, err := api.StateCall(ctx, &types.Message{
From: addr,
To: addr,
Method: actors.MAMethods.GetWorkerAddr,
}, head.Key())
if err != nil {
return xerrors.Errorf("failed to get miner worker addr: %w", err)
}
if ret.ExitCode != 0 {
return xerrors.Errorf("failed to get miner worker addr (exit code %d)", ret.ExitCode)
}
w, err := address.NewFromBytes(ret.Return)
if err != nil {
return xerrors.Errorf("GetWorkerAddr returned malformed address: %w", err)
}
t, err := gen.ComputeVRF(ctx, api.WalletSign, w, addr, gen.DSepTicket, vrfBase)
if err != nil {
return xerrors.Errorf("compute vrf failed: %w", err)
}
ticket = &types.Ticket{
VRFProof: t,
}
}
epostp := &types.EPostProof{
Proof: []byte("valid proof"),
Candidates: []types.EPostTicket{
{
ChallengeIndex: 0,
SectorID: 1,
},
},
}
{
r, err := api.ChainGetRandomness(ctx, head.Key(), int64(head.Height()+1)-build.EcRandomnessLookback)
if err != nil {
return xerrors.Errorf("chain get randomness: %w", err)
}
mworker, err := api.StateMinerWorker(ctx, addr, head.Key())
if err != nil {
return xerrors.Errorf("failed to get miner worker: %w", err)
}
vrfout, err := gen.ComputeVRF(ctx, api.WalletSign, mworker, addr, gen.DSepElectionPost, r)
if err != nil {
return xerrors.Errorf("failed to compute VRF: %w", err)
}
epostp.PostRand = vrfout
}
uts := head.MinTimestamp() + uint64(build.BlockDelay)
nheight := head.Height() + 1
blk, err := api.MinerCreateBlock(ctx, addr, head.Key(), ticket, epostp, msgs, nheight, uts)
if err != nil {
return xerrors.Errorf("creating block: %w", err)
}
return api.SyncSubmitBlock(ctx, blk)
},
}
}
+6
View File
@@ -14,12 +14,18 @@ import (
"github.com/filecoin-project/lotus/tracing" "github.com/filecoin-project/lotus/tracing"
) )
var AdvanceBlockCmd *cli.Command
func main() { func main() {
lotuslog.SetupLogLevels() lotuslog.SetupLogLevels()
local := []*cli.Command{ local := []*cli.Command{
DaemonCmd, DaemonCmd,
} }
if AdvanceBlockCmd != nil {
local = append(local, AdvanceBlockCmd)
}
jaeger := tracing.SetupJaegerTracing("lotus") jaeger := tracing.SetupJaegerTracing("lotus")
defer func() { defer func() {
if jaeger != nil { if jaeger != nil {
+13
View File
@@ -32,6 +32,12 @@
"github": "en/install-lotus-ubuntu.md", "github": "en/install-lotus-ubuntu.md",
"value": null "value": null
}, },
{
"title": "Fedora Installation",
"slug": "en+install-lotus-fedora",
"github": "en/install-lotus-fedora.md",
"value": null
},
{ {
"title": "MacOS Installation", "title": "MacOS Installation",
"slug": "en+install-lotus-macos", "slug": "en+install-lotus-macos",
@@ -154,6 +160,13 @@
} }
] ]
}, },
{
"title": "FAQs",
"slug": "en+faqs",
"github": "en/faqs.md",
"value": null,
"posts": []
},
{ {
"title": "Glossary", "title": "Glossary",
"slug": "en+glossary", "slug": "en+glossary",
+134
View File
@@ -0,0 +1,134 @@
# Frequently Asked Questions
Here are some FAQs concerning the Lotus implementation and participation in
Testnet.
For questions concerning the broader Filecoin project, please
go [here](https://filecoin.io/faqs/).
## Introduction to Lotus
### What is Lotus?
Lotus is an implementation of the **Filecoin Distributed Storage Network**, written in Go.
It is designed to be modular and interoperable with any other implementation of the Filecoin Protocol.
More information about Lotus can be found [here](https://lotu.sh/).
### What are the components of Lotus?
Lotus is composed of two separate pieces that can talk to each other:
The Lotus Node can sync the blockchain, validating all blocks, transfers, and deals
along the way. It can also facilitate the creation of new storage deals. If you are not
interested in providing your own storage to the network, and do not want to produce blocks
yourself, then the Lotus Node is all you need!
The Lotus Storage Miner does everything you need for the registration of storage, and the
production of new blocks. The Lotus Storage Miner communicates with the network
by talking to a Lotus Node over the JSON-RPC API.
## Setting up a Lotus Node
### How do I set up a Lotus Node?
Follow the instructions found [here](https://docs.lotu.sh/en+getting-started).
### Where can I get the latest version of Lotus?
Download the binary tagged as the `Latest Release` from the
[Lotus Github repo](https://github.com/filecoin-project/lotus/releases).
### What operating systems can Lotus run on?
Lotus can build and run on most Linux and MacOS systems with at least
8GB of RAM. Windows is not yet supported.
### How can I update to the latest version of Lotus?
To update Lotus, follow the instructions [here](https://lotu.sh/en+updating-lotus).
### How do I prepare a fresh installation of Lotus?
Stop the Lotus daemon, and delete all related files, including sealed and chain data by
running `rm ~/.lotus ~/.lotusstorage`.
Then, install Lotus afresh by following the instructions
found [here](https://docs.lotu.sh/en+getting-started).
## Interacting with a Lotus Node
### How can I communicate with a Lotus Node?
Lotus Nodes have a command-line interface, as well as a JSON-RPC API.
### What are the commands I can send using the command-line interface?
The command-line interface is self-documenting, try running `lotus --help` from the `lotus` home
directory for more.
### How can I send a request over the JSON-RPC API?
Information on how to send a `cURL` request to the JSON-RPC API can be found
[here](https://lotu.sh/en+api). A JavaScript client is under development.
### What are the requests I can send over the JSON-RPC API?
Please have a look at the
[source code](https://github.com/filecoin-project/lotus/blob/master/api/api_common.go)
for a list of methods supported by the JSON-RPC API.
## The Test Network
### What is Testnet?
Testnet is a live network of Lotus Nodes run by the
community for testing purposes.
It has 2 PiB of storage (and growing!) dedicated to it.
### Is FIL on the Testnet worth anything?
Nothing at all! Real-world incentives may be provided in a future phase of Testnet, but this is
yet to be confirmed.
### Will there be future phases of Testnet?
Yes, there will be at least one more phase of Testnet. We plan on introducing interoperable
[go-filecoin nodes](https://github.com/filecoin-project/go-filecoin#filecoin-go-filecoin)
in a future phase.
### How can I see the status of Testnet?
The [dashboard](https://stats.testnet.filecoin.io/) displays the status of the network as
well as a ton
of other metrics you might find interesting.
## Mining with a Lotus Node on Testnet
### How do I get started mining with Lotus?
Follow the instructions found [here](https://lotu.sh/en+mining).
### What are the minimum hardware requirements?
An example test configuration, and minimum hardware requirements can be found
[here](https://lotu.sh/en+hardware-mining).
Note that these might NOT be the minimum requirements for mining on Mainnet.
### What are some GPUs that have been tested?
A list of benchmarked GPUs can be found [here](https://lotu.sh/en+hardware-mining#benchmarked-gpus-7393).
## Advanced questions
### Is there a Docker image for lotus?
Community-contributed Docker and Docker Compose examples are available
[here](https://github.com/filecoin-project/lotus/tree/master/tools/dockers/docker-examples).
### How can I run two miners on the same machine?
You can do so by changing the storage path variable for the second miner, e.g.,
`LOTUS_STORAGE_PATH=~/.lotusstorage2`. You will also need to make sure that no ports collide.
### How do I setup my own local devnet?
Follow the instructions found [here](https://lotu.sh/en+setup-local-dev-net).
+4 -2
View File
@@ -36,7 +36,7 @@ In order to connect to the network, you need to be connected to at least 1 peer.
## Chain sync ## Chain sync
While the daemon is running, the next requirement is to sync the chain. Run the command below to start the chain sync progress. To see current chain height, visit the [network stats page](http://stats.testnet.filecoin.io/). While the daemon is running, the next requirement is to sync the chain. Run the command below to start the chain sync progress. To see current chain height, visit the [network stats page](https://stats.testnet.filecoin.io/).
```sh ```sh
lotus sync wait lotus sync wait
@@ -50,9 +50,11 @@ lotus sync wait
Initialize a new wallet: Initialize a new wallet:
```sh ```sh
lotus wallet new lotus wallet new
``` ```
Sometimes your operating system may limit file name length to under 150 characters. You need to use a file system that supports long filenames.
Here is an example of the response: Here is an example of the response:
```sh ```sh

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