Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8943de27e4 | ||
|
|
fc728d9e11 | ||
|
|
f6131ce3b5 | ||
|
|
cd95b40d61 | ||
|
|
e94e26f529 | ||
|
|
6958b6fc2b | ||
|
|
34df787be6 | ||
|
|
2767cdba9c | ||
|
|
735f6fec1a | ||
|
|
6fbaba1323 | ||
|
|
5a5a6f9cd2 | ||
|
|
8efc8051d1 | ||
|
|
bcfe7a76e8 | ||
|
|
7d17ee5960 | ||
|
|
dc6bd2b015 | ||
|
|
724dfc6a4d | ||
|
|
47b82bdaea | ||
|
|
0fc1239445 | ||
|
|
18834de7d0 | ||
|
|
6607019788 | ||
|
|
1f339f623e | ||
|
|
95d294db63 | ||
|
|
a94a48f70b | ||
|
|
e1deed3b1a | ||
|
|
9369c54f54 | ||
|
|
67c732a100 | ||
|
|
3f7b15b598 | ||
|
|
f7884c4f45 | ||
|
|
a60ccbf106 | ||
|
|
97e4921a4a | ||
|
|
8182ffcf9f | ||
|
|
9ba7f372cd | ||
|
|
b7fe165b8f | ||
|
|
d2e9d21031 | ||
|
|
32a855b984 | ||
|
|
9a993d25d0 | ||
|
|
b1c06ece85 | ||
|
|
32ce12acfc | ||
|
|
726d9b86ea | ||
|
|
852ac4c178 | ||
|
|
d9100981ad | ||
|
|
e508055dc1 | ||
|
|
ba171954b4 | ||
|
|
1d8a9c75d4 | ||
|
|
c2d4dcae19 | ||
|
|
116ed01197 | ||
|
|
7b8d1cc54c | ||
|
|
7a55e8e892 | ||
|
|
3ab8ec57f1 | ||
|
|
0e17b6c066 | ||
|
|
44e092c07c | ||
|
|
c8a187e779 | ||
|
|
76d009e409 | ||
|
|
080aa3356a | ||
|
|
3b2e8c439a | ||
|
|
70589e4406 | ||
|
|
261238e157 | ||
|
|
11d738eee0 | ||
|
|
3943c3ae6f | ||
|
|
463f55ba13 | ||
|
|
e493d9e2e3 | ||
|
|
19f52b4541 | ||
|
|
9606dce425 | ||
|
|
98ff1c4d20 | ||
|
|
e5d73f2923 | ||
|
|
03806f7063 | ||
|
|
63c8b8edd1 | ||
|
|
a0795165af | ||
|
|
c23cff45f6 | ||
|
|
02cef1353e | ||
|
|
008120747e | ||
|
|
9964f80bb7 | ||
|
|
afe54ab5f3 | ||
|
|
6cd6732225 | ||
|
|
429b9a1bc5 | ||
|
|
d063a32def | ||
|
|
1ebd908fe3 | ||
|
|
e1a08b1c89 | ||
|
|
dd998037cf | ||
|
|
9dbeb3028d | ||
|
|
8e168cb657 | ||
|
|
5616dfb1bc | ||
|
|
ddef708178 | ||
|
|
67bdc266af | ||
|
|
f352c18290 | ||
|
|
d1e15e61d0 | ||
|
|
9fcc27edd5 | ||
|
|
e47cbae885 | ||
|
|
1a6c9b9c0e | ||
|
|
f1b4d2b1b3 | ||
|
|
1bd7f5b7ec | ||
|
|
8319323329 | ||
|
|
20544b6b7b | ||
|
|
1242e4a292 | ||
|
|
42a233c083 | ||
|
|
047f7e5015 | ||
|
|
d1e1f8bdce | ||
|
|
3a3edbbb16 | ||
|
|
8957213c56 | ||
|
|
f9433811c7 | ||
|
|
df2a852e6c | ||
|
|
c6b28b4d8b | ||
|
|
c92d73384b | ||
|
|
5abba9ca9f | ||
|
|
35291983a1 | ||
|
|
a19dbb8c91 | ||
|
|
6a3bb184b7 | ||
|
|
1acb6b4328 | ||
|
|
6e5ccc87cf | ||
|
|
4853762763 | ||
|
|
8533ae0032 | ||
|
|
90ff1d3ccf | ||
|
|
b4302df892 | ||
|
|
1723793c35 | ||
|
|
be774f55ce | ||
|
|
e158b1d1e4 | ||
|
|
28e94bf9db | ||
|
|
6184e8a943 | ||
|
|
c776811ea9 | ||
|
|
c8042540d5 | ||
|
|
bfcfb199a0 | ||
|
|
8b01725129 | ||
|
|
cb39dd8ed0 | ||
|
|
734a03cf82 | ||
|
|
aed6e8d0be | ||
|
|
ec0f7795d3 | ||
|
|
c95940acac | ||
|
|
3215eba0eb | ||
|
|
4e98f0abdc | ||
|
|
0ba88ac53a | ||
|
|
2c10dc6c57 | ||
|
|
778483166f | ||
|
|
a40aa9f90b | ||
|
|
c4a7de9d37 | ||
|
|
9e76aba3d1 | ||
|
|
1993efe201 | ||
|
|
e74f70346e | ||
|
|
530011fd09 | ||
|
|
1cdb414bf8 | ||
|
|
a572787013 | ||
|
|
3f92940a19 | ||
|
|
177aa3cffd | ||
|
|
6e44755b55 | ||
|
|
7e6c3a330a | ||
|
|
89db4235ce | ||
|
|
001fc7dd53 | ||
|
|
46ae2556c7 | ||
|
|
9b69b10fea | ||
|
|
a460ab84fa | ||
|
|
bac783774d | ||
|
|
4221461ede | ||
|
|
a324b3fce0 | ||
|
|
bd2176c398 | ||
|
|
441bcdc4af | ||
|
|
26ae8bb3a7 | ||
|
|
f8ac98bf46 | ||
|
|
5e6aceeb0e | ||
|
|
cbb147de23 | ||
|
|
f60692c7ef | ||
|
|
97c2cdb8d6 | ||
|
|
43f7fd5e10 | ||
|
|
a4e2fce9ca | ||
|
|
bff3af81d5 | ||
|
|
1d2f84322d | ||
|
|
368d72ebfe | ||
|
|
8d9f3719ce | ||
|
|
af0d9b650d | ||
|
|
2a1094fc17 | ||
|
|
cadbd00ac4 | ||
|
|
f70ec02a6c | ||
|
|
16973bc2e8 | ||
|
|
38e01cba83 | ||
|
|
9af82f2d68 | ||
|
|
b87142ec8e | ||
|
|
fc10281d96 | ||
|
|
28e720fef2 | ||
|
|
d7fbd8b67d | ||
|
|
809289f5ef | ||
|
|
c2fa54ca9c | ||
|
|
edcb28737c | ||
|
|
a8a9818043 | ||
|
|
95e8b59367 | ||
|
|
1b1879342c | ||
|
|
b3432b512e | ||
|
|
7c84e22c3e | ||
|
|
2f8a2fc907 | ||
|
|
4192e40a9a | ||
|
|
d7690aa719 | ||
|
|
89d7a72a4b | ||
|
|
98c99b4fea | ||
|
|
cd66afb05c | ||
|
|
c3faadf749 | ||
|
|
83c8e981b4 | ||
|
|
dbcb662f9c | ||
|
|
53a9dd5da4 | ||
|
|
0e7e665e6d | ||
|
|
8e0314b3a3 | ||
|
|
7759f13a13 | ||
|
|
fa7a5789aa | ||
|
|
7694f895c2 | ||
|
|
92190c7e0b | ||
|
|
f57d4b4126 | ||
|
|
7e933f7045 | ||
|
|
574b5c03dc | ||
|
|
b3816bc2dc | ||
|
|
9a07c2fd38 | ||
|
|
44ed3dc46b | ||
|
|
6064d2f2f1 | ||
|
|
ac2194b0eb | ||
|
|
fe56995244 | ||
|
|
714d7a146e | ||
|
|
c7e4217693 | ||
|
|
7863a269ad | ||
|
|
e70cefaa28 | ||
|
|
a80bc34d59 | ||
|
|
89ac8b09b5 | ||
|
|
2437a4182d | ||
|
|
ee7b6f2470 | ||
|
|
926858aeec | ||
|
|
38f7cbc6c7 | ||
|
|
b4a129068a | ||
|
|
ccf24b9952 | ||
|
|
3508a5b664 | ||
|
|
f79d34be5c | ||
|
|
605953565b | ||
|
|
34e3dc2b37 | ||
|
|
595b51ecdd | ||
|
|
6df17bceb1 | ||
|
|
ef03314c6d | ||
|
|
4fc78bf720 | ||
|
|
1d6db306ec | ||
|
|
b681078b06 | ||
|
|
aab42dd96f | ||
|
|
888b2040de | ||
|
|
aae9bf3f46 | ||
|
|
4d9b852875 | ||
|
|
3e10f2e250 | ||
|
|
67dc7523d5 | ||
|
|
caaff9b7af | ||
|
|
fe602ab3bb | ||
|
|
20a7193b06 | ||
|
|
65befc281e | ||
|
|
b4a3eb55e1 | ||
|
|
027c1b5ab8 | ||
|
|
b0b016b58c | ||
|
|
0444435589 | ||
|
|
0a04302fb2 | ||
|
|
8612d1e824 | ||
|
|
1ce7c250d7 | ||
|
|
2c5f4386ba | ||
|
|
92c12f9bde | ||
|
|
3b25934649 | ||
|
|
aef741ae19 | ||
|
|
16c60914eb | ||
|
|
d1d8845ab2 | ||
|
|
612befc962 | ||
|
|
cf94aed32e | ||
|
|
a5bcf8b5b2 | ||
|
|
ab71bc0e78 | ||
|
|
26da526379 |
+11
-47
@@ -285,21 +285,6 @@ jobs:
|
||||
root: "."
|
||||
paths:
|
||||
- linux-butterflynet
|
||||
build-ntwk-nerpa:
|
||||
description: |
|
||||
Compile lotus binaries for the nerpa network
|
||||
parameters:
|
||||
<<: *test-params
|
||||
executor: << parameters.executor >>
|
||||
steps:
|
||||
- install-deps
|
||||
- prepare
|
||||
- run: make nerpanet
|
||||
- run: mkdir linux-nerpanet && mv lotus lotus-miner lotus-worker linux-nerpanet
|
||||
- persist_to_workspace:
|
||||
root: "."
|
||||
paths:
|
||||
- linux-nerpanet
|
||||
build-lotus-soup:
|
||||
description: |
|
||||
Compile `lotus-soup` Testground test plan
|
||||
@@ -333,7 +318,7 @@ jobs:
|
||||
command: pushd testplans/lotus-soup && mkdir -p $HOME/testground && cp env-ci.toml $HOME/testground/.env.toml && echo 'endpoint="https://ci.testground.ipfs.team"' >> $HOME/testground/.env.toml && echo 'user="circleci"' >> $HOME/testground/.env.toml
|
||||
- run:
|
||||
name: "prepare testground home dir and link test plans"
|
||||
command: mkdir -p $HOME/testground/plans && ln -s $(pwd)/testplans/lotus-soup $HOME/testground/plans/lotus-soup && ln -s $(pwd)/testplans/graphsync $HOME/testground/plans/graphsync
|
||||
command: mkdir -p $HOME/testground/plans && ln -s $(pwd)/testplans/lotus-soup $HOME/testground/plans/lotus-soup
|
||||
- run:
|
||||
name: "go get lotus@master"
|
||||
command: cd testplans/lotus-soup && go get github.com/filecoin-project/lotus@master
|
||||
@@ -343,10 +328,6 @@ jobs:
|
||||
- run:
|
||||
name: "trigger payment channel stress testplan on taas"
|
||||
command: ~/testground-cli run composition -f $HOME/testground/plans/lotus-soup/_compositions/paych-stress-k8s.toml --metadata-commit=$CIRCLE_SHA1 --metadata-repo=filecoin-project/lotus --metadata-branch=$CIRCLE_BRANCH
|
||||
- run:
|
||||
name: "trigger graphsync testplan on taas"
|
||||
command: ~/testground-cli run composition -f $HOME/testground/plans/graphsync/_compositions/stress-k8s.toml --metadata-commit=$CIRCLE_SHA1 --metadata-repo=filecoin-project/lotus --metadata-branch=$CIRCLE_BRANCH
|
||||
|
||||
|
||||
build-macos:
|
||||
description: build darwin lotus binary
|
||||
@@ -724,18 +705,6 @@ jobs:
|
||||
- packer/build:
|
||||
template: tools/packer/lotus.pkr.hcl
|
||||
args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG"
|
||||
publish-packer-nerpanet:
|
||||
description: build and push AWS IAM and DigitalOcean droplet.
|
||||
executor:
|
||||
name: packer/default
|
||||
packer-version: 1.6.6
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: "."
|
||||
- packer/build:
|
||||
template: tools/packer/lotus.pkr.hcl
|
||||
args: "-var ci_workspace_bins=./linux-nerpanet -var lotus_network=nerpanet -var git_tag=$CIRCLE_TAG"
|
||||
publish-dockerhub:
|
||||
description: publish to dockerhub
|
||||
machine:
|
||||
@@ -836,6 +805,11 @@ workflows:
|
||||
suite: itest-deals_padding
|
||||
target: "./itests/deals_padding_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-deals_partial_retrieval
|
||||
suite: itest-deals_partial_retrieval
|
||||
target: "./itests/deals_partial_retrieval_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-deals_power
|
||||
suite: itest-deals_power
|
||||
@@ -851,6 +825,11 @@ workflows:
|
||||
suite: itest-deals_publish
|
||||
target: "./itests/deals_publish_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-deals_retry_deal_no_funds
|
||||
suite: itest-deals_retry_deal_no_funds
|
||||
target: "./itests/deals_retry_deal_no_funds_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-deals
|
||||
suite: itest-deals
|
||||
@@ -983,11 +962,6 @@ workflows:
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
- build-ntwk-nerpa:
|
||||
filters:
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
- build-lotus-soup
|
||||
- build-macos:
|
||||
filters:
|
||||
@@ -1052,16 +1026,6 @@ workflows:
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
- publish-packer-nerpanet:
|
||||
requires:
|
||||
- build-ntwk-nerpa
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- /.*/
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
- publish-snapcraft:
|
||||
name: publish-snapcraft-stable
|
||||
channel: stable
|
||||
|
||||
+1
-47
@@ -285,21 +285,6 @@ jobs:
|
||||
root: "."
|
||||
paths:
|
||||
- linux-butterflynet
|
||||
build-ntwk-nerpa:
|
||||
description: |
|
||||
Compile lotus binaries for the nerpa network
|
||||
parameters:
|
||||
<<: *test-params
|
||||
executor: << parameters.executor >>
|
||||
steps:
|
||||
- install-deps
|
||||
- prepare
|
||||
- run: make nerpanet
|
||||
- run: mkdir linux-nerpanet && mv lotus lotus-miner lotus-worker linux-nerpanet
|
||||
- persist_to_workspace:
|
||||
root: "."
|
||||
paths:
|
||||
- linux-nerpanet
|
||||
build-lotus-soup:
|
||||
description: |
|
||||
Compile `lotus-soup` Testground test plan
|
||||
@@ -333,7 +318,7 @@ jobs:
|
||||
command: pushd testplans/lotus-soup && mkdir -p $HOME/testground && cp env-ci.toml $HOME/testground/.env.toml && echo 'endpoint="https://ci.testground.ipfs.team"' >> $HOME/testground/.env.toml && echo 'user="circleci"' >> $HOME/testground/.env.toml
|
||||
- run:
|
||||
name: "prepare testground home dir and link test plans"
|
||||
command: mkdir -p $HOME/testground/plans && ln -s $(pwd)/testplans/lotus-soup $HOME/testground/plans/lotus-soup && ln -s $(pwd)/testplans/graphsync $HOME/testground/plans/graphsync
|
||||
command: mkdir -p $HOME/testground/plans && ln -s $(pwd)/testplans/lotus-soup $HOME/testground/plans/lotus-soup
|
||||
- run:
|
||||
name: "go get lotus@master"
|
||||
command: cd testplans/lotus-soup && go get github.com/filecoin-project/lotus@master
|
||||
@@ -343,10 +328,6 @@ jobs:
|
||||
- run:
|
||||
name: "trigger payment channel stress testplan on taas"
|
||||
command: ~/testground-cli run composition -f $HOME/testground/plans/lotus-soup/_compositions/paych-stress-k8s.toml --metadata-commit=$CIRCLE_SHA1 --metadata-repo=filecoin-project/lotus --metadata-branch=$CIRCLE_BRANCH
|
||||
- run:
|
||||
name: "trigger graphsync testplan on taas"
|
||||
command: ~/testground-cli run composition -f $HOME/testground/plans/graphsync/_compositions/stress-k8s.toml --metadata-commit=$CIRCLE_SHA1 --metadata-repo=filecoin-project/lotus --metadata-branch=$CIRCLE_BRANCH
|
||||
|
||||
|
||||
build-macos:
|
||||
description: build darwin lotus binary
|
||||
@@ -724,18 +705,6 @@ jobs:
|
||||
- packer/build:
|
||||
template: tools/packer/lotus.pkr.hcl
|
||||
args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG"
|
||||
publish-packer-nerpanet:
|
||||
description: build and push AWS IAM and DigitalOcean droplet.
|
||||
executor:
|
||||
name: packer/default
|
||||
packer-version: 1.6.6
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: "."
|
||||
- packer/build:
|
||||
template: tools/packer/lotus.pkr.hcl
|
||||
args: "-var ci_workspace_bins=./linux-nerpanet -var lotus_network=nerpanet -var git_tag=$CIRCLE_TAG"
|
||||
publish-dockerhub:
|
||||
description: publish to dockerhub
|
||||
machine:
|
||||
@@ -838,11 +807,6 @@ workflows:
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
- build-ntwk-nerpa:
|
||||
filters:
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
- build-lotus-soup
|
||||
- build-macos:
|
||||
filters:
|
||||
@@ -907,16 +871,6 @@ workflows:
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
- publish-packer-nerpanet:
|
||||
requires:
|
||||
- build-ntwk-nerpa
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- /.*/
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
- publish-snapcraft:
|
||||
name: publish-snapcraft-stable
|
||||
channel: stable
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
name: sync-master-main
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: update remote branch main
|
||||
run: |
|
||||
# overrides the remote branch (origin:github) `main`
|
||||
git push origin --force master:main
|
||||
+176
@@ -1,5 +1,181 @@
|
||||
# Lotus changelog
|
||||
|
||||
# v1.13.1 / 2021-11-26
|
||||
|
||||
This is an optional Lotus v1.13.1 release.
|
||||
|
||||
## New Features
|
||||
- Shed: Add a util to find miner based on peerid ([filecoin-project/lotus#7544](https://github.com/filecoin-project/lotus/pull/7544))
|
||||
- Collect and expose graphsync metrics ([filecoin-project/lotus#7542](https://github.com/filecoin-project/lotus/pull/7542))
|
||||
- Shed: Add a util to find the most recent null tipset ([filecoin-project/lotus#7456](https://github.com/filecoin-project/lotus/pull/7456))
|
||||
|
||||
## Improvements
|
||||
- Show prepared tasks in sealing jobs ([filecoin-project/lotus#7527](https://github.com/filecoin-project/lotus/pull/7527))
|
||||
- To make Deep happy ([filecoin-project/lotus#7546](https://github.com/filecoin-project/lotus/pull/7546))
|
||||
- Expose per-state sector counts on the prometheus endpoint ([filecoin-project/lotus#7541](https://github.com/filecoin-project/lotus/pull/7541))
|
||||
- Add storage-id flag to proving check ([filecoin-project/lotus#7479](https://github.com/filecoin-project/lotus/pull/7479))
|
||||
- FilecoinEC: Improve a log message ([filecoin-project/lotus#7499](https://github.com/filecoin-project/lotus/pull/7499))
|
||||
- itests: retry deal when control addr is out of funds ([filecoin-project/lotus#7454](https://github.com/filecoin-project/lotus/pull/7454))
|
||||
- Normlize selector use within lotus ([filecoin-project/lotus#7467](https://github.com/filecoin-project/lotus/pull/7467))
|
||||
- sealing: Improve scheduling of ready work ([filecoin-project/lotus#7335](https://github.com/filecoin-project/lotus/pull/7335))
|
||||
- Remove dead example code + dep ([filecoin-project/lotus#7466](https://github.com/filecoin-project/lotus/pull/7466))
|
||||
|
||||
## Bug Fixes
|
||||
- fix the withdrawn amount unit ([filecoin-project/lotus#7563](https://github.com/filecoin-project/lotus/pull/7563))
|
||||
- rename vm#make{=>Account}Actor(). ([filecoin-project/lotus#7562](https://github.com/filecoin-project/lotus/pull/7562))
|
||||
- Fix used sector space accounting after AddPieceFailed ([filecoin-project/lotus#7530](https://github.com/filecoin-project/lotus/pull/7530))
|
||||
- Don't remove sector data when moving data into a shared path ([filecoin-project/lotus#7494](https://github.com/filecoin-project/lotus/pull/7494))
|
||||
- fix: support node instantiation in external packages ([filecoin-project/lotus#7511](https://github.com/filecoin-project/lotus/pull/7511))
|
||||
- Stop adding Jennifer's $HOME to lotus docs ([filecoin-project/lotus#7477](https://github.com/filecoin-project/lotus/pull/7477))
|
||||
- Bugfix: Use correct startup network versions ([filecoin-project/lotus#7486](https://github.com/filecoin-project/lotus/pull/7486))
|
||||
- Dep upgrade pass ([filecoin-project/lotus#7478](https://github.com/filecoin-project/lotus/pull/7478))
|
||||
- Remove obsolete GS testplan - it now lives in go-graphsync ([filecoin-project/lotus#7469](https://github.com/filecoin-project/lotus/pull/7469))
|
||||
- sealing: Recover sectors after failed AddPiece ([filecoin-project/lotus#7444](https://github.com/filecoin-project/lotus/pull/7444))
|
||||
|
||||
## Dependency Updates
|
||||
- Update go-graphsync v0.10.1 ([filecoin-project/lotus#7457](https://github.com/filecoin-project/lotus/pull/7457))
|
||||
- update to proof v10.1.0 ([filecoin-project/lotus#7564](https://github.com/filecoin-project/lotus/pull/7564))
|
||||
- github.com/filecoin-project/specs-actors/v6 (v6.0.0 -> v6.0.1):
|
||||
- github.com/filecoin-project/go-jsonrpc (v0.1.4-0.20210217175800-45ea43ac2bec -> v0.1.5):
|
||||
- github.com/filecoin-project/go-fil-markets (v1.13.1 -> v1.13.3):
|
||||
- github.com/filecoin-project/go-data-transfer (v1.11.1 -> v1.11.4):
|
||||
- github.com/filecoin-project/go-crypto (v0.0.0-20191218222705-effae4ea9f03 -> v0.0.1):
|
||||
- github.com/filecoin-project/go-commp-utils (v0.1.1-0.20210427191551-70bf140d31c7 -> v0.1.2):
|
||||
- github.com/filecoin-project/go-cbor-util (v0.0.0-20191219014500-08c40a1e63a2 -> v0.0.1):
|
||||
- github.com/filecoin-project/go-address (v0.0.5 -> v0.0.6):
|
||||
- unpin the yamux dependency ([filecoin-project/lotus#7532](https://github.com/filecoin-project/lotus/pull/7532)
|
||||
- peerstore@v0.2.9 was withdrawn, let's not depend on it directly ([filecoin-project/lotus#7481](https://github.com/filecoin-project/lotus/pull/7481))
|
||||
- chore(deps): use tagged github.com/ipld/go-ipld-selector-text-lite ([filecoin-project/lotus#7464](https://github.com/filecoin-project/lotus/pull/7464))
|
||||
- Stop indirectly depending on deprecated github.com/prometheus/common ([filecoin-project/lotus#7473](https://github.com/filecoin-project/lotus/pull/7473))
|
||||
|
||||
## Others
|
||||
- fix the changelog ([filecoin-project/lotus#7594](https://github.com/filecoin-project/lotus/pull/7594))
|
||||
- v1.13.1-rc2 prep ([filecoin-project/lotus#7593](https://github.com/filecoin-project/lotus/pull/7593))
|
||||
- lotus v1.13.1-rc1 ([filecoin-project/lotus#7569](https://github.com/filecoin-project/lotus/pull/7569))
|
||||
- misc: back-port v1.13.0 back to master ([filecoin-project/lotus#7537](https://github.com/filecoin-project/lotus/pull/7537))
|
||||
- Inline codegen ([filecoin-project/lotus#7495](https://github.com/filecoin-project/lotus/pull/7495))
|
||||
- releases -> master ([filecoin-project/lotus#7507](https://github.com/filecoin-project/lotus/pull/7507))
|
||||
- Make chocolate back to master ([filecoin-project/lotus#7493](https://github.com/filecoin-project/lotus/pull/7493))
|
||||
- restore filters for the build-macos job ([filecoin-project/lotus#7455](https://github.com/filecoin-project/lotus/pull/7455))
|
||||
- bump master to v1.13.1-dev ([filecoin-project/lotus#7451](https://github.com/filecoin-project/lotus/pull/7451))
|
||||
|
||||
Contributors
|
||||
|
||||
| Contributor | Commits | Lines ± | Files Changed |
|
||||
|-------------|---------|---------|---------------|
|
||||
| @magik6k | 27 | +1285/-531 | 76 |
|
||||
| @ribasushi | 7 | +265/-1635 | 21 |
|
||||
| @raulk | 2 | +2/-737 | 13 |
|
||||
| @nonsens | 4 | +391/-21 | 19 |
|
||||
| @arajasek | 6 | +216/-23 | 14 |
|
||||
| @jennijuju| 8 | +102/-37 | 29 |
|
||||
| Steven Allen | 2 | +77/-29 | 6 |
|
||||
| @jennijuju | 4 | +19/-18 | 11 |
|
||||
| @dirkmc | 2 | +9/-9 | 4 |
|
||||
| @@coryschwartz | 1 | +16/-2 | 2 |
|
||||
| @frrist | 1 | +12/-0 | 2 |
|
||||
| @Kubuxu | 5 | +5/-5 | 5 |
|
||||
| @hunjixin | 2 | +6/-3 | 2 |
|
||||
| @vyzo | 1 | +3/-3 | 2 |
|
||||
| @@rvagg | 1 | +3/-3 | 2 |
|
||||
| @hannahhoward | 1 | +3/-2 | 2 |
|
||||
| Marten Seemann | 1 | +3/-0 | 1 |
|
||||
| @ZenGround0 | 1 | +1/-1 | 1 |
|
||||
|
||||
|
||||
# v1.13.0 / 2021-10-18
|
||||
|
||||
Lotus v1.13.0 is a *highly recommended* feature release for all lotus users(i.e: storage providers, data brokers, application developers and so on) that supports the upcoming
|
||||
[Network v14 Chocolate upgrade](https://github.com/filecoin-project/lotus/discussions/7431).
|
||||
This feature release includes the latest functionalities and improvements, like data transfer rate-limiting for both storage and retrieval deals, proof v10 with CUDA support, etc. You can find more details in the Changelog below.
|
||||
|
||||
## Highlights
|
||||
- Enable separate storage and retrieval transfer limits ([filecoin-project/lotus#7405](https://github.com/filecoin-project/lotus/pull/7405))
|
||||
- `SimultaneousTransfer` is now replaced by `SimultaneousTransfersForStorage` and `SimultaneousTransfersForRetrieval`, where users may set the amount of ongoing data transfer for storage and retrieval deals in parallel separately. The default value for both is set to 20.
|
||||
- If you are using the lotus client, these two configuration variables are under the `Client` section in `./lotus/config.toml`.
|
||||
- If you are a service provider, these two configuration variables should be set under the `Dealmaking` section in `/.lotusminer/config.toml`.
|
||||
- Update proofs to v10.0.0 ([filecoin-project/lotus#7420](https://github.com/filecoin-project/lotus/pull/7420))
|
||||
- This version supports CUDA. To enable CUDA instead of openCL, build lotus with `FFI_USE_CUDA=1 FFI_BUILD_FROM_SOURCE=1 ...`.
|
||||
- You can find additional Nvidia driver installation instructions written by MinerX fellows [here](https://github.com/filecoin-project/lotus/discussions/7443#discussioncomment-1425274) and perf improvements result on PC2/C2/WindowPoSt computation on different profiles [here](https://github.com/filecoin-project/lotus/discussions/7443), most people observe a 30-50% decrease in computation time.
|
||||
|
||||
## New Features
|
||||
- Feat/datamodel selector retrieval ([filecoin-project/lotus#6393](https://github.com/filecoin-project/lotus/pull/66393393))
|
||||
- This introduces a new RetrievalOrder-struct field and a CLI option that takes a string representation as understood by [https://pkg.go.dev/github.com/ipld/go-ipld-selector-text-lite#SelectorSpecFromPath](https://pkg.go.dev/github.com/ipld/go-ipld-selector-text-lite#SelectorSpecFromPath). This allows for partial retrieval of any sub-DAG of a deal provided the user knows the exact low-level shape of the deal contents.
|
||||
- For example, to retrieve the first entry of a UnixFS directory by executing, run `lotus client retrieve --miner f0XXXXX --datamodel-path-selector 'Links/0/Hash' bafyROOTCID ~/output`
|
||||
- Expose storage stats on the metrics endpoint ([filecoin-project/lotus#7418](https://github.com/filecoin-project/lotus/pull/7418))
|
||||
- feat: Catch panic to generate report and reraise ([filecoin-project/lotus#7341](https://github.com/filecoin-project/lotus/pull/7341))
|
||||
- Set `LOTUS_PANIC_REPORT_PATH` and `LOTUS_PANIC_JOURNAL_LOOKBACK` to get reports generated when a panic occurs on your daemon miner or workers.
|
||||
- Add envconfig docs to the config ([filecoin-project/lotus#7412](https://github.com/filecoin-project/lotus/pull/7412))
|
||||
- You can now find supported env vars in [default-lotus-miner-config.toml](https://github.com/filecoin-project/lotus/blob/master/documentation/en/default-lotus-miner-config.toml).
|
||||
- lotus shed: fr32 utils ([filecoin-project/lotus#7355](https://github.com/filecoin-project/lotus/pull/7355))
|
||||
- Miner CLI: Allow trying to change owners of any miner actor ([filecoin-project/lotus#7328](https://github.com/filecoin-project/lotus/pull/7328))
|
||||
- Add --unproven flag to the sectors list command ([filecoin-project/lotus#7308](https://github.com/filecoin-project/lotus/pull/7308))
|
||||
|
||||
## Improvements
|
||||
- check for deal start epoch on SectorAddPieceToAny ([filecoin-project/lotus#7407](https://github.com/filecoin-project/lotus/pull/7407))
|
||||
- Verify Voucher locks in VoucherValidUnlocked ([filecoin-project/lotus#5609](https://github.com/filecoin-project/lotus/pull/5609))
|
||||
- Add more info to miner allinfo command ([filecoin-project/lotus#7384](https://github.com/filecoin-project/lotus/pull/7384))
|
||||
- add `lotus-miner storage-deals list --format=json` with transfers ([filecoin-project/lotus#7312](https://github.com/filecoin-project/lotus/pull/7312))
|
||||
- Fix formatting ([filecoin-project/lotus#7383](https://github.com/filecoin-project/lotus/pull/7383))
|
||||
- GetCurrentDealInfo err: handle correctly err case ([filecoin-project/lotus#7346](https://github.com/filecoin-project/lotus/pull/7346))
|
||||
- fix: Enforce verification key integrity check regardless of TRUST_PARAMS=1 ([filecoin-project/lotus#7327](https://github.com/filecoin-project/lotus/pull/7327))
|
||||
- Show more deal states in miner info ([filecoin-project/lotus#7311](https://github.com/filecoin-project/lotus/pull/7311))
|
||||
- Prep retrieval for selectors: no functional changes ([filecoin-project/lotus#7306](https://github.com/filecoin-project/lotus/pull/7306))
|
||||
- Seed: improve helptext ([filecoin-project/lotus#7304](https://github.com/filecoin-project/lotus/pull/7304))
|
||||
- Mempool: reduce size of sigValCache ([filecoin-project/lotus#7305](https://github.com/filecoin-project/lotus/pull/7305))
|
||||
- Stop indirectly depending on deprecated github.com/prometheus/common ([filecoin-project/lotus#7474](https://github.com/filecoin-project/lotus/pull/7474))
|
||||
|
||||
## Bug Fixes
|
||||
- StateSearchMsg: Correct usage of the allowReplaced flag ([filecoin-project/lotus#7450](https://github.com/filecoin-project/lotus/pull/7450))
|
||||
- fix staging area path buildup ([filecoin-project/lotus#7363](https://github.com/filecoin-project/lotus/pull/7363))
|
||||
- storagemgr: Cleanup workerLk around worker resources ([filecoin-project/lotus#7334](https://github.com/filecoin-project/lotus/pull/7334))
|
||||
- fix: check padSector Cid ([filecoin-project/lotus#7310](https://github.com/filecoin-project/lotus/pull/7310))
|
||||
- sealing: Recover sectors after failed AddPiece ([filecoin-project/lotus#7492](https://github.com/filecoin-project/lotus/pull/7492))
|
||||
- fix: support node instantiation in external packages ([filecoin-project/lotus#7511](https://github.com/filecoin-project/lotus/pull/7511))
|
||||
- Chore/backport cleanup withdrawn dependency ([filecoin-project/lotus#7482](https://github.com/filecoin-project/lotus/pull/7482))
|
||||
|
||||
## Dependency Updates
|
||||
- github.com/filecoin-project/go-data-transfer (v1.10.1 -> v1.11.1):
|
||||
- github.com/filecoin-project/go-fil-markets (v1.12.0 -> v1.13.1):
|
||||
- github.com/filecoin-project/go-paramfetch (v0.0.2-0.20210614165157-25a6c7769498 -> v0.0.2):
|
||||
- update go-libp2p to v0.15.0 ([filecoin-project/lotus#7362](https://github.com/filecoin-project/lotus/pull/7362))
|
||||
- update to go-graphsync v0.10.1 ([filecoin-project/lotus#7359](https://github.com/filecoin-project/lotus/pull/7359))
|
||||
|
||||
## Others
|
||||
- Chocolate to master ([filecoin-project/lotus#7440](https://github.com/filecoin-project/lotus/pull/7440))
|
||||
- releases -> master ([filecoin-project/lotus#7403](https://github.com/filecoin-project/lotus/pull/7403))
|
||||
- remove nerpanet related code ([filecoin-project/lotus#7373](https://github.com/filecoin-project/lotus/pull/7373))
|
||||
- sync branch main with master on updates ([filecoin-project/lotus#7366](https://github.com/filecoin-project/lotus/pull/7366))
|
||||
- remove job to install jq ([filecoin-project/lotus#7309](https://github.com/filecoin-project/lotus/pull/7309))
|
||||
- restore filters for the build-macos job ([filecoin-project/lotus#7455](https://github.com/filecoin-project/lotus/pull/7455))
|
||||
- v1.13.0-rc2 ([filecoin-project/lotus#7458](https://github.com/filecoin-project/lotus/pull/7458))
|
||||
- v1.13.0-rc1 ([filecoin-project/lotus#7452](https://github.com/filecoin-project/lotus/pull/7452))
|
||||
|
||||
## Contributors
|
||||
|
||||
| Contributor | Commits | Lines ± | Files Changed |
|
||||
|-------------|---------|---------|---------------|
|
||||
| @dirkmc | 8 | +845/-375 | 55 |
|
||||
| @magik6k | 10 | +1056/-60 | 26 |
|
||||
| @aarshkshah1992 | 6 | +813/-259 | 16 |
|
||||
| @arajasek | 10 | +552/-251 | 43 |
|
||||
| @ribasushi | 6 | +505/-78 | 22 |
|
||||
| @jennijuju | 7 | +212/-323 | 34 |
|
||||
| @nonsense | 10 | +335/-139 | 19 |
|
||||
| @dirkmc | 8 | +149/-55 | 16 |
|
||||
| @hannahhoward | 4 | +56/-32 | 17 |
|
||||
| @rvagg | 4 | +61/-13 | 9 |
|
||||
| @jennijuju | 2 | +0/-57 | 2 |
|
||||
| @hannahhoward | 1 | +33/-18 | 7 |
|
||||
| @Kubuxu | 8 | +27/-16 | 9 |
|
||||
| @coryschwartz | 1 | +16/-2 | 2 |
|
||||
| @travisperson | 1 | +14/-0 | 1 |
|
||||
| @frrist | 1 | +12/-0 | 2 |
|
||||
| @ognots | 1 | +0/-10 | 2 |
|
||||
| @lanzafame | 1 | +3/-3 | 1 |
|
||||
| @jennijuju | 1 | +2/-2 | 1 |
|
||||
| @swift-mx | 1 | +1/-1 | 1 |
|
||||
|
||||
# v1.12.0 / 2021-10-12
|
||||
|
||||
This is a mandatory release of Lotus that introduces [Filecoin Network v14](https://github.com/filecoin-project/community/discussions/74#discussioncomment-1398542), codenamed the Chocolate upgrade. The Filecoin mainnet will upgrade at epoch 1231620, on 2021-10-26T13:30:00Z.
|
||||
|
||||
@@ -76,9 +76,6 @@ debug: build-devnets
|
||||
calibnet: GOFLAGS+=-tags=calibnet
|
||||
calibnet: build-devnets
|
||||
|
||||
nerpanet: GOFLAGS+=-tags=nerpanet
|
||||
nerpanet: build-devnets
|
||||
|
||||
butterflynet: GOFLAGS+=-tags=butterflynet
|
||||
butterflynet: build-devnets
|
||||
|
||||
@@ -294,6 +291,7 @@ method-gen: api-gen
|
||||
(cd ./lotuspond/front/src/chain && $(GOCC) run ./methodgen.go)
|
||||
|
||||
actors-gen:
|
||||
$(GOCC) run ./gen/inline-gen . gen/inlinegen-data.json
|
||||
$(GOCC) run ./chain/actors/agen
|
||||
$(GOCC) fmt ./...
|
||||
|
||||
@@ -344,7 +342,7 @@ docsgen-openrpc-worker: docsgen-openrpc-bin
|
||||
.PHONY: docsgen docsgen-md-bin docsgen-openrpc-bin
|
||||
|
||||
gen: actors-gen type-gen method-gen cfgdoc-gen docsgen api-gen circleci
|
||||
@echo ">>> IF YOU'VE MODIFIED THE CLI, REMEMBER TO ALSO MAKE docsgen-cli"
|
||||
@echo ">>> IF YOU'VE MODIFIED THE CLI OR CONFIG, REMEMBER TO ALSO MAKE docsgen-cli"
|
||||
.PHONY: gen
|
||||
|
||||
snap: lotus lotus-miner lotus-worker
|
||||
@@ -354,6 +352,8 @@ snap: lotus lotus-miner lotus-worker
|
||||
# separate from gen because it needs binaries
|
||||
docsgen-cli: lotus lotus-miner lotus-worker
|
||||
python ./scripts/generate-lotus-cli.py
|
||||
./lotus config default > documentation/en/default-lotus-config.toml
|
||||
./lotus-miner config default > documentation/en/default-lotus-miner-config.toml
|
||||
.PHONY: docsgen-cli
|
||||
|
||||
print-%:
|
||||
|
||||
@@ -123,7 +123,6 @@ Note: The default branch `master` is the dev branch where the latest new feature
|
||||
|
||||
# Or to join a testnet or devnet:
|
||||
make clean calibnet # Calibration with min 32GiB sectors
|
||||
make clean nerpanet # Nerpa with min 512MiB sectors
|
||||
|
||||
sudo make install
|
||||
```
|
||||
|
||||
+6
-4
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
textselector "github.com/ipld/go-ipld-selector-text-lite"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
@@ -290,7 +291,7 @@ type FullNode interface {
|
||||
|
||||
// // UX ?
|
||||
|
||||
// MethodGroup: Wallet
|
||||
// MethodGroup: WalletF
|
||||
|
||||
// WalletNew creates a new address in the wallet with the given sigType.
|
||||
// Available key types: bls, secp256k1, secp256k1-ledger
|
||||
@@ -930,9 +931,10 @@ type MarketDeal struct {
|
||||
|
||||
type RetrievalOrder struct {
|
||||
// TODO: make this less unixfs specific
|
||||
Root cid.Cid
|
||||
Piece *cid.Cid
|
||||
Size uint64
|
||||
Root cid.Cid
|
||||
Piece *cid.Cid
|
||||
DatamodelPathSelector *textselector.Expression
|
||||
Size uint64
|
||||
|
||||
FromLocalCAR string // if specified, get data from a local CARv2 file.
|
||||
// TODO: support offset
|
||||
|
||||
@@ -166,6 +166,7 @@ type StorageMiner interface {
|
||||
MarketCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error //perm:write
|
||||
MarketPendingDeals(ctx context.Context) (PendingDealInfo, error) //perm:write
|
||||
MarketPublishPendingDeals(ctx context.Context) error //perm:admin
|
||||
MarketRetryPublishDeal(ctx context.Context, propcid cid.Cid) error //perm:admin
|
||||
|
||||
// DagstoreListShards returns information about all shards known to the
|
||||
// DAG store. Only available on nodes running the markets subsystem.
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/filecoin-project/go-bitfield"
|
||||
"github.com/google/uuid"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-filestore"
|
||||
"github.com/libp2p/go-libp2p-core/metrics"
|
||||
"github.com/libp2p/go-libp2p-core/network"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
@@ -24,9 +23,10 @@ import (
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
filestore2 "github.com/filecoin-project/go-fil-markets/filestore"
|
||||
filestore "github.com/filecoin-project/go-fil-markets/filestore"
|
||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||
"github.com/filecoin-project/go-jsonrpc/auth"
|
||||
textselector "github.com/ipld/go-ipld-selector-text-lite"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
@@ -90,6 +90,7 @@ func init() {
|
||||
addExample(&pid)
|
||||
|
||||
storeIDExample := imports.ID(50)
|
||||
textSelExample := textselector.Expression("Links/21/Hash/Links/42/Hash")
|
||||
|
||||
addExample(bitfield.NewFromSet([]uint64{5}))
|
||||
addExample(abi.RegisteredSealProof_StackedDrg32GiBV1_1)
|
||||
@@ -108,7 +109,6 @@ func init() {
|
||||
addExample(abi.UnpaddedPieceSize(1024))
|
||||
addExample(abi.UnpaddedPieceSize(1024).Padded())
|
||||
addExample(abi.DealID(5432))
|
||||
addExample(filestore.StatusFileChanged)
|
||||
addExample(abi.SectorNumber(9))
|
||||
addExample(abi.SectorSize(32 * 1024 * 1024 * 1024))
|
||||
addExample(api.MpoolChange(0))
|
||||
@@ -124,6 +124,7 @@ func init() {
|
||||
addExample(&storeIDExample)
|
||||
addExample(retrievalmarket.ClientEventDealAccepted)
|
||||
addExample(retrievalmarket.DealStatusNew)
|
||||
addExample(&textSelExample)
|
||||
addExample(network.ReachabilityPublic)
|
||||
addExample(build.NewestNetworkVersion)
|
||||
addExample(map[string]int{"name": 42})
|
||||
@@ -175,7 +176,7 @@ func init() {
|
||||
ExampleValues[reflect.TypeOf(struct{ A multiaddr.Multiaddr }{}).Field(0).Type] = maddr
|
||||
|
||||
// miner specific
|
||||
addExample(filestore2.Path(".lotusminer/fstmp123"))
|
||||
addExample(filestore.Path(".lotusminer/fstmp123"))
|
||||
si := uint64(12)
|
||||
addExample(&si)
|
||||
addExample(retrievalmarket.DealID(5))
|
||||
|
||||
@@ -683,6 +683,8 @@ type StorageMinerStruct struct {
|
||||
|
||||
MarketRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"`
|
||||
|
||||
MarketRetryPublishDeal func(p0 context.Context, p1 cid.Cid) error `perm:"admin"`
|
||||
|
||||
MarketSetAsk func(p0 context.Context, p1 types.BigInt, p2 types.BigInt, p3 abi.ChainEpoch, p4 abi.PaddedPieceSize, p5 abi.PaddedPieceSize) error `perm:"admin"`
|
||||
|
||||
MarketSetRetrievalAsk func(p0 context.Context, p1 *retrievalmarket.Ask) error `perm:"admin"`
|
||||
@@ -4020,6 +4022,17 @@ func (s *StorageMinerStub) MarketRestartDataTransfer(p0 context.Context, p1 data
|
||||
return ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *StorageMinerStruct) MarketRetryPublishDeal(p0 context.Context, p1 cid.Cid) error {
|
||||
if s.Internal.MarketRetryPublishDeal == nil {
|
||||
return ErrNotSupported
|
||||
}
|
||||
return s.Internal.MarketRetryPublishDeal(p0, p1)
|
||||
}
|
||||
|
||||
func (s *StorageMinerStub) MarketRetryPublishDeal(p0 context.Context, p1 cid.Cid) error {
|
||||
return ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *StorageMinerStruct) MarketSetAsk(p0 context.Context, p1 types.BigInt, p2 types.BigInt, p3 abi.ChainEpoch, p4 abi.PaddedPieceSize, p5 abi.PaddedPieceSize) error {
|
||||
if s.Internal.MarketSetAsk == nil {
|
||||
return ErrNotSupported
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
/dns4/bootstrap-2.nerpa.interplanetary.dev/tcp/1347/p2p/12D3KooWQcL6ReWmR6ASWx4iT7EiAmxKDQpvgq1MKNTQZp5NPnWW
|
||||
/dns4/bootstrap-0.nerpa.interplanetary.dev/tcp/1347/p2p/12D3KooWGyJCwCm7EfupM15CFPXM4c7zRVHwwwjcuy9umaGeztMX
|
||||
/dns4/bootstrap-3.nerpa.interplanetary.dev/tcp/1347/p2p/12D3KooWNK9RmfksKXSCQj7ZwAM7L6roqbN4kwJteihq7yPvSgPs
|
||||
/dns4/bootstrap-1.nerpa.interplanetary.dev/tcp/1347/p2p/12D3KooWCWSaH6iUyXYspYxELjDfzToBsyVGVz3QvC7ysXv7wESo
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,183 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime/debug"
|
||||
"runtime/pprof"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/icza/backscanner"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
panicLog = logging.Logger("panic-reporter")
|
||||
defaultJournalTail = 500
|
||||
)
|
||||
|
||||
// PanicReportingPath is the name of the subdir created within the repoPath
|
||||
// path provided to GeneratePanicReport
|
||||
var PanicReportingPath = "panic-reports"
|
||||
|
||||
// PanicReportJournalTail is the number of lines captured from the end of
|
||||
// the lotus journal to be included in the panic report.
|
||||
var PanicReportJournalTail = defaultJournalTail
|
||||
|
||||
// GeneratePanicReport produces a timestamped dump of the application state
|
||||
// for inspection and debugging purposes. Call this function from any place
|
||||
// where a panic or severe error needs to be examined. `persistPath` is the
|
||||
// path where the reports should be saved. `repoPath` is the path where the
|
||||
// journal should be read from. `label` is an optional string to include
|
||||
// next to the report timestamp.
|
||||
func GeneratePanicReport(persistPath, repoPath, label string) {
|
||||
// make sure we always dump the latest logs on the way out
|
||||
// especially since we're probably panicking
|
||||
defer panicLog.Sync() //nolint:errcheck
|
||||
|
||||
if persistPath == "" && repoPath == "" {
|
||||
panicLog.Warn("missing persist and repo paths, aborting panic report creation")
|
||||
return
|
||||
}
|
||||
|
||||
reportPath := filepath.Join(repoPath, PanicReportingPath, generateReportName(label))
|
||||
if persistPath != "" {
|
||||
reportPath = filepath.Join(persistPath, generateReportName(label))
|
||||
}
|
||||
panicLog.Warnf("generating panic report at %s", reportPath)
|
||||
|
||||
tl := os.Getenv("LOTUS_PANIC_JOURNAL_LOOKBACK")
|
||||
if tl != "" && PanicReportJournalTail == defaultJournalTail {
|
||||
i, err := strconv.Atoi(tl)
|
||||
if err == nil {
|
||||
PanicReportJournalTail = i
|
||||
}
|
||||
}
|
||||
|
||||
err := os.MkdirAll(reportPath, 0755)
|
||||
if err != nil {
|
||||
panicLog.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
writeAppVersion(filepath.Join(reportPath, "version"))
|
||||
writeStackTrace(filepath.Join(reportPath, "stacktrace.dump"))
|
||||
writeProfile("goroutines", filepath.Join(reportPath, "goroutines.pprof.gz"))
|
||||
writeProfile("heap", filepath.Join(reportPath, "heap.pprof.gz"))
|
||||
writeJournalTail(PanicReportJournalTail, repoPath, filepath.Join(reportPath, "journal.ndjson"))
|
||||
}
|
||||
|
||||
func writeAppVersion(file string) {
|
||||
f, err := os.Create(file)
|
||||
if err != nil {
|
||||
panicLog.Error(err.Error())
|
||||
}
|
||||
defer f.Close() //nolint:errcheck
|
||||
|
||||
versionString := []byte(BuildVersion + BuildTypeString() + CurrentCommit + "\n")
|
||||
if _, err := f.Write(versionString); err != nil {
|
||||
panicLog.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func writeStackTrace(file string) {
|
||||
f, err := os.Create(file)
|
||||
if err != nil {
|
||||
panicLog.Error(err.Error())
|
||||
}
|
||||
defer f.Close() //nolint:errcheck
|
||||
|
||||
if _, err := f.Write(debug.Stack()); err != nil {
|
||||
panicLog.Error(err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func writeProfile(profileType string, file string) {
|
||||
p := pprof.Lookup(profileType)
|
||||
if p == nil {
|
||||
panicLog.Warnf("%s profile not available", profileType)
|
||||
return
|
||||
}
|
||||
f, err := os.Create(file)
|
||||
if err != nil {
|
||||
panicLog.Error(err.Error())
|
||||
return
|
||||
}
|
||||
defer f.Close() //nolint:errcheck
|
||||
|
||||
if err := p.WriteTo(f, 0); err != nil {
|
||||
panicLog.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func writeJournalTail(tailLen int, repoPath, file string) {
|
||||
if repoPath == "" {
|
||||
panicLog.Warn("repo path is empty, aborting copy of journal log")
|
||||
return
|
||||
}
|
||||
|
||||
f, err := os.Create(file)
|
||||
if err != nil {
|
||||
panicLog.Error(err.Error())
|
||||
return
|
||||
}
|
||||
defer f.Close() //nolint:errcheck
|
||||
|
||||
jPath, err := getLatestJournalFilePath(repoPath)
|
||||
if err != nil {
|
||||
panicLog.Warnf("failed getting latest journal: %s", err.Error())
|
||||
return
|
||||
}
|
||||
j, err := os.OpenFile(jPath, os.O_RDONLY, 0400)
|
||||
if err != nil {
|
||||
panicLog.Error(err.Error())
|
||||
return
|
||||
}
|
||||
js, err := j.Stat()
|
||||
if err != nil {
|
||||
panicLog.Error(err.Error())
|
||||
return
|
||||
}
|
||||
jScan := backscanner.New(j, int(js.Size()))
|
||||
linesWritten := 0
|
||||
for {
|
||||
if linesWritten > tailLen {
|
||||
break
|
||||
}
|
||||
line, _, err := jScan.LineBytes()
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
panicLog.Error(err.Error())
|
||||
}
|
||||
break
|
||||
}
|
||||
if _, err := f.Write(line); err != nil {
|
||||
panicLog.Error(err.Error())
|
||||
break
|
||||
}
|
||||
if _, err := f.Write([]byte("\n")); err != nil {
|
||||
panicLog.Error(err.Error())
|
||||
break
|
||||
}
|
||||
linesWritten++
|
||||
}
|
||||
}
|
||||
|
||||
func getLatestJournalFilePath(repoPath string) (string, error) {
|
||||
journalPath := filepath.Join(repoPath, "journal")
|
||||
entries, err := os.ReadDir(journalPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(journalPath, entries[len(entries)-1].Name()), nil
|
||||
}
|
||||
|
||||
func generateReportName(label string) string {
|
||||
label = strings.ReplaceAll(label, " ", "")
|
||||
return fmt.Sprintf("report_%s_%s", label, time.Now().Format("2006-01-02T150405"))
|
||||
}
|
||||
@@ -28,8 +28,16 @@ const UnixfsLinksPerLevel = 1024
|
||||
const AllowableClockDriftSecs = uint64(1)
|
||||
|
||||
// TODO: This is still terrible...What's the impact of updating this before mainnet actually upgrades
|
||||
/* inline-gen template
|
||||
|
||||
const NewestNetworkVersion = network.Version{{.latestNetworkVersion}}
|
||||
|
||||
/* inline-gen start */
|
||||
|
||||
const NewestNetworkVersion = network.Version14
|
||||
|
||||
/* inline-gen end */
|
||||
|
||||
// Epochs
|
||||
const ForkLengthThreshold = Finality
|
||||
|
||||
|
||||
+3
-6
@@ -12,11 +12,10 @@ const (
|
||||
BuildDebug = 0x3
|
||||
BuildCalibnet = 0x4
|
||||
BuildInteropnet = 0x5
|
||||
BuildNerpanet = 0x6
|
||||
BuildButterflynet = 0x7
|
||||
)
|
||||
|
||||
func buildType() string {
|
||||
func BuildTypeString() string {
|
||||
switch BuildType {
|
||||
case BuildDefault:
|
||||
return ""
|
||||
@@ -30,8 +29,6 @@ func buildType() string {
|
||||
return "+calibnet"
|
||||
case BuildInteropnet:
|
||||
return "+interopnet"
|
||||
case BuildNerpanet:
|
||||
return "+nerpanet"
|
||||
case BuildButterflynet:
|
||||
return "+butterflynet"
|
||||
default:
|
||||
@@ -40,12 +37,12 @@ func buildType() string {
|
||||
}
|
||||
|
||||
// BuildVersion is the local build version
|
||||
const BuildVersion = "1.12.0"
|
||||
const BuildVersion = "1.13.1"
|
||||
|
||||
func UserVersion() string {
|
||||
if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" {
|
||||
return BuildVersion
|
||||
}
|
||||
|
||||
return BuildVersion + buildType() + CurrentCommit
|
||||
return BuildVersion + BuildTypeString() + CurrentCommit
|
||||
}
|
||||
|
||||
+15
-1
@@ -8,9 +8,21 @@ import (
|
||||
|
||||
type Version int
|
||||
|
||||
/* inline-gen template
|
||||
|
||||
var LatestVersion = {{.latestActorsVersion}}
|
||||
|
||||
var Versions = []int{ {{range .actorVersions}} {{.}}, {{end}} }
|
||||
|
||||
const ({{range .actorVersions}}
|
||||
Version{{.}} Version = {{.}}{{end}}
|
||||
)
|
||||
|
||||
/* inline-gen start */
|
||||
|
||||
var LatestVersion = 6
|
||||
|
||||
var Versions = []int{0, 2, 3, 4, 5, LatestVersion}
|
||||
var Versions = []int{0, 2, 3, 4, 5, 6}
|
||||
|
||||
const (
|
||||
Version0 Version = 0
|
||||
@@ -21,6 +33,8 @@ const (
|
||||
Version6 Version = 6
|
||||
)
|
||||
|
||||
/* inline-gen end */
|
||||
|
||||
// Converts a network version into an actors adt version.
|
||||
func VersionForNetwork(version network.Version) (Version, error) {
|
||||
switch version {
|
||||
|
||||
@@ -16,6 +16,12 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
blockadt "github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
|
||||
/* inline-gen template
|
||||
{{range .actorVersions}}
|
||||
exported{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin/exported"{{end}}
|
||||
|
||||
/* inline-gen start */
|
||||
|
||||
exported0 "github.com/filecoin-project/specs-actors/actors/builtin/exported"
|
||||
exported2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/exported"
|
||||
exported3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/exported"
|
||||
@@ -23,6 +29,8 @@ import (
|
||||
exported5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/exported"
|
||||
exported6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/exported"
|
||||
|
||||
/* inline-gen end */
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
@@ -39,6 +47,11 @@ func NewActorRegistry() *vm.ActorRegistry {
|
||||
inv := vm.NewActorRegistry()
|
||||
|
||||
// TODO: define all these properties on the actors themselves, in specs-actors.
|
||||
/* inline-gen template
|
||||
{{range .actorVersions}}
|
||||
inv.Register(vm.ActorsVersionPredicate(actors.Version{{.}}), exported{{.}}.BuiltinActors()...){{end}}
|
||||
|
||||
/* inline-gen start */
|
||||
|
||||
inv.Register(vm.ActorsVersionPredicate(actors.Version0), exported0.BuiltinActors()...)
|
||||
inv.Register(vm.ActorsVersionPredicate(actors.Version2), exported2.BuiltinActors()...)
|
||||
@@ -47,6 +60,8 @@ func NewActorRegistry() *vm.ActorRegistry {
|
||||
inv.Register(vm.ActorsVersionPredicate(actors.Version5), exported5.BuiltinActors()...)
|
||||
inv.Register(vm.ActorsVersionPredicate(actors.Version6), exported6.BuiltinActors()...)
|
||||
|
||||
/* inline-gen end */
|
||||
|
||||
return inv
|
||||
}
|
||||
|
||||
|
||||
@@ -823,7 +823,7 @@ func (filec *FilecoinEC) checkPowerAndGetWorkerKey(ctx context.Context, bh *type
|
||||
|
||||
key, err := stmgr.GetMinerWorkerRaw(ctx, filec.sm, lbst, bh.Miner)
|
||||
if err != nil {
|
||||
log.Warnf("failed to resolve worker key for miner %s: %s", bh.Miner, err)
|
||||
log.Warnf("failed to resolve worker key for miner %s and block height %d: %s", bh.Miner, bh.Height, err)
|
||||
return address.Undef, ErrSoftFailure
|
||||
}
|
||||
|
||||
|
||||
@@ -297,6 +297,10 @@ func NewGeneratorWithUpgradeSchedule(us stmgr.UpgradeSchedule) (*ChainGen, error
|
||||
return NewGeneratorWithSectorsAndUpgradeSchedule(1, us)
|
||||
}
|
||||
|
||||
func (cg *ChainGen) Blockstore() blockstore.Blockstore {
|
||||
return cg.bs
|
||||
}
|
||||
|
||||
func (cg *ChainGen) StateManager() *stmgr.StateManager {
|
||||
return cg.sm
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
ffi "github.com/filecoin-project/filecoin-ffi"
|
||||
|
||||
"github.com/minio/blake2b-simd"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
@@ -751,11 +755,13 @@ func (mp *MessagePool) Add(ctx context.Context, m *types.SignedMessage) error {
|
||||
func sigCacheKey(m *types.SignedMessage) (string, error) {
|
||||
switch m.Signature.Type {
|
||||
case crypto.SigTypeBLS:
|
||||
if len(m.Signature.Data) < 90 {
|
||||
return "", fmt.Errorf("bls signature too short")
|
||||
if len(m.Signature.Data) != ffi.SignatureBytes {
|
||||
return "", fmt.Errorf("bls signature incorrectly sized")
|
||||
}
|
||||
|
||||
return string(m.Cid().Bytes()) + string(m.Signature.Data[64:]), nil
|
||||
hashCache := blake2b.Sum256(append(m.Cid().Bytes(), m.Signature.Data...))
|
||||
|
||||
return string(hashCache[:]), nil
|
||||
case crypto.SigTypeSecp256k1:
|
||||
return string(m.Cid().Bytes()), nil
|
||||
default:
|
||||
|
||||
@@ -152,7 +152,16 @@ func VersionForNetwork(ver network.Version) (types.StateTreeVersion, error) {
|
||||
return types.StateTreeVersion2, nil
|
||||
case network.Version12:
|
||||
return types.StateTreeVersion3, nil
|
||||
|
||||
/* inline-gen template
|
||||
{{$lastNv := .latestNetworkVersion}}
|
||||
case{{range .networkVersions}} {{if (ge . 13.)}} network.Version{{.}}{{if (lt . $lastNv)}},{{end}}{{end}}{{end}}:
|
||||
|
||||
/* inline-gen start */
|
||||
|
||||
case network.Version13, network.Version14:
|
||||
|
||||
/* inline-gen end */
|
||||
return types.StateTreeVersion4, nil
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported network version %d", ver))
|
||||
|
||||
+19
-14
@@ -252,22 +252,27 @@ func (sm *StateManager) tipsetExecutedMessage(ts *types.TipSet, msg cid.Cid, vmm
|
||||
|
||||
if m.VMMessage().From == vmm.From { // cheaper to just check origin first
|
||||
if m.VMMessage().Nonce == vmm.Nonce {
|
||||
if allowReplaced && m.VMMessage().EqualCall(vmm) {
|
||||
if m.Cid() != msg {
|
||||
log.Warnw("found message with equal nonce and call params but different CID",
|
||||
"wanted", msg, "found", m.Cid(), "nonce", vmm.Nonce, "from", vmm.From)
|
||||
}
|
||||
|
||||
pr, err := sm.cs.GetParentReceipt(ts.Blocks()[0], i)
|
||||
if err != nil {
|
||||
return nil, cid.Undef, err
|
||||
}
|
||||
return pr, m.Cid(), nil
|
||||
if !m.VMMessage().EqualCall(vmm) {
|
||||
// this is an entirely different message, fail
|
||||
return nil, cid.Undef, xerrors.Errorf("found message with equal nonce as the one we are looking for that is NOT a valid replacement message (F:%s n %d, TS: %s n%d)",
|
||||
msg, vmm.Nonce, m.Cid(), m.VMMessage().Nonce)
|
||||
}
|
||||
|
||||
// this should be that message
|
||||
return nil, cid.Undef, xerrors.Errorf("found message with equal nonce as the one we are looking for (F:%s n %d, TS: %s n%d)",
|
||||
msg, vmm.Nonce, m.Cid(), m.VMMessage().Nonce)
|
||||
if m.Cid() != msg {
|
||||
if !allowReplaced {
|
||||
log.Warnw("found message with equal nonce and call params but different CID",
|
||||
"wanted", msg, "found", m.Cid(), "nonce", vmm.Nonce, "from", vmm.From)
|
||||
return nil, cid.Undef, xerrors.Errorf("found message with equal nonce as the one we are looking for (F:%s n %d, TS: %s n%d)",
|
||||
msg, vmm.Nonce, m.Cid(), m.VMMessage().Nonce)
|
||||
}
|
||||
}
|
||||
|
||||
pr, err := sm.cs.GetParentReceipt(ts.Blocks()[0], i)
|
||||
if err != nil {
|
||||
return nil, cid.Undef, err
|
||||
}
|
||||
|
||||
return pr, m.Cid(), nil
|
||||
}
|
||||
if m.VMMessage().Nonce < vmm.Nonce {
|
||||
return nil, cid.Undef, nil // don't bother looking further
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package stmgr_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
)
|
||||
|
||||
func TestSearchForMessageReplacements(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cg, err := gen.NewGenerator()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
mts1, err := cg.NextTipSet()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
m := mts1.Messages[0]
|
||||
|
||||
mts2, err := cg.NextTipSet()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Step 1: Searching for the executed msg with replacements allowed succeeds
|
||||
ts, r, mcid, err := cg.StateManager().SearchForMessage(ctx, mts2.TipSet.TipSet(), m.Cid(), 100, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !ts.Equals(mts2.TipSet.TipSet()) {
|
||||
t.Fatal("searched tipset wasn't as expected")
|
||||
}
|
||||
|
||||
if r.ExitCode != 0 {
|
||||
t.Fatal("searched msg wasn't successfully executed")
|
||||
}
|
||||
|
||||
if mcid != m.Cid() {
|
||||
t.Fatal("searched msg wasn't identical to queried msg as expected")
|
||||
}
|
||||
|
||||
// Step 2: Searching for the executed msg with replacements disallowed also succeeds
|
||||
ts, r, mcid, err = cg.StateManager().SearchForMessage(ctx, mts2.TipSet.TipSet(), m.Cid(), 100, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !ts.Equals(mts2.TipSet.TipSet()) {
|
||||
t.Fatal("searched tipset wasn't as expected")
|
||||
}
|
||||
|
||||
if r.ExitCode != 0 {
|
||||
t.Fatal("searched msg wasn't successfully executed")
|
||||
}
|
||||
|
||||
if mcid != m.Cid() {
|
||||
t.Fatal("searched msg wasn't identical to queried msg as expected")
|
||||
}
|
||||
|
||||
// rm is a valid replacement message for m
|
||||
rm := m.Message
|
||||
rm.GasLimit = m.Message.GasLimit + 1
|
||||
|
||||
rmb, err := rm.ToStorageBlock()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = cg.Blockstore().Put(rmb)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Step 3: Searching for the replacement msg with replacements allowed succeeds
|
||||
ts, r, mcid, err = cg.StateManager().SearchForMessage(ctx, mts2.TipSet.TipSet(), rm.Cid(), 100, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !ts.Equals(mts2.TipSet.TipSet()) {
|
||||
t.Fatal("searched tipset wasn't as expected")
|
||||
}
|
||||
|
||||
if r.ExitCode != 0 {
|
||||
t.Fatal("searched msg wasn't successfully executed")
|
||||
}
|
||||
|
||||
if mcid == rm.Cid() {
|
||||
t.Fatal("searched msg was identical to queried msg, not as expected")
|
||||
}
|
||||
|
||||
if mcid != m.Cid() {
|
||||
t.Fatal("searched msg wasn't identical to executed msg as expected")
|
||||
}
|
||||
|
||||
// Step 4: Searching for the replacement msg with replacements disallowed fails
|
||||
_, _, _, err = cg.StateManager().SearchForMessage(ctx, mts2.TipSet.TipSet(), rm.Cid(), 100, false)
|
||||
if err == nil {
|
||||
t.Fatal("expected search to fail")
|
||||
}
|
||||
|
||||
// nrm is NOT a valid replacement message for m
|
||||
nrm := m.Message
|
||||
nrm.Value = big.Add(m.Message.Value, m.Message.Value)
|
||||
|
||||
nrmb, err := nrm.ToStorageBlock()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = cg.Blockstore().Put(nrmb)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Step 5: Searching for the not-replacement msg with replacements allowed fails
|
||||
_, _, _, err = cg.StateManager().SearchForMessage(ctx, mts2.TipSet.TipSet(), nrm.Cid(), 100, true)
|
||||
if err == nil {
|
||||
t.Fatal("expected search to fail")
|
||||
}
|
||||
|
||||
// Step 6: Searching for the not-replacement msg with replacements disallowed also fails
|
||||
_, _, _, err = cg.StateManager().SearchForMessage(ctx, mts2.TipSet.TipSet(), nrm.Cid(), 100, false)
|
||||
if err == nil {
|
||||
t.Fatal("expected search to fail")
|
||||
}
|
||||
|
||||
}
|
||||
+17
-2
@@ -14,6 +14,12 @@ import (
|
||||
"github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
|
||||
/* inline-gen template
|
||||
{{range .actorVersions}}
|
||||
builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin"{{end}}
|
||||
|
||||
/* inline-gen start */
|
||||
|
||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
|
||||
@@ -21,6 +27,8 @@ import (
|
||||
builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin"
|
||||
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
|
||||
|
||||
/* inline-gen end */
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
@@ -60,7 +68,7 @@ func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, add
|
||||
return nil, address.Undef, aerrors.Escalate(err, "unsupported network version")
|
||||
}
|
||||
|
||||
act, aerr := makeActor(av, addr)
|
||||
act, aerr := makeAccountActor(av, addr)
|
||||
if aerr != nil {
|
||||
return nil, address.Undef, aerr
|
||||
}
|
||||
@@ -87,7 +95,7 @@ func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, add
|
||||
return act, addrID, nil
|
||||
}
|
||||
|
||||
func makeActor(ver actors.Version, addr address.Address) (*types.Actor, aerrors.ActorError) {
|
||||
func makeAccountActor(ver actors.Version, addr address.Address) (*types.Actor, aerrors.ActorError) {
|
||||
switch addr.Protocol() {
|
||||
case address.BLS, address.SECP256K1:
|
||||
return newAccountActor(ver), nil
|
||||
@@ -104,6 +112,12 @@ func newAccountActor(ver actors.Version) *types.Actor {
|
||||
// TODO: ActorsUpgrade use a global actor registry?
|
||||
var code cid.Cid
|
||||
switch ver {
|
||||
/* inline-gen template
|
||||
{{range .actorVersions}}
|
||||
case actors.Version{{.}}:
|
||||
code = builtin{{.}}.AccountActorCodeID{{end}}
|
||||
/* inline-gen start */
|
||||
|
||||
case actors.Version0:
|
||||
code = builtin0.AccountActorCodeID
|
||||
case actors.Version2:
|
||||
@@ -116,6 +130,7 @@ func newAccountActor(ver actors.Version) *types.Actor {
|
||||
code = builtin5.AccountActorCodeID
|
||||
case actors.Version6:
|
||||
code = builtin6.AccountActorCodeID
|
||||
/* inline-gen end */
|
||||
default:
|
||||
panic("unsupported actors version")
|
||||
}
|
||||
|
||||
@@ -218,6 +218,7 @@ func (rt *Runtime) GetRandomnessFromTickets(personalization crypto.DomainSeparat
|
||||
var res []byte
|
||||
|
||||
rnv := rt.vm.ntwkVersion(rt.ctx, randEpoch)
|
||||
|
||||
if rnv >= network.Version13 {
|
||||
res, err = rt.vm.rand.GetChainRandomnessV2(rt.ctx, personalization, randEpoch, entropy)
|
||||
} else {
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-cidutil/cidenc"
|
||||
textselector "github.com/ipld/go-ipld-selector-text-lite"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/multiformats/go-multibase"
|
||||
"github.com/urfave/cli/v2"
|
||||
@@ -1047,6 +1048,10 @@ var clientRetrieveCmd = &cli.Command{
|
||||
Name: "miner",
|
||||
Usage: "miner address for retrieval, if not present it'll use local discovery",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "datamodel-path-selector",
|
||||
Usage: "a rudimentary (DM-level-only) text-path selector, allowing for sub-selection within a deal",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "maxPrice",
|
||||
Usage: fmt.Sprintf("maximum price the client is willing to consider (default: %s FIL)", DefaultMaxRetrievePrice),
|
||||
@@ -1182,6 +1187,10 @@ var clientRetrieveCmd = &cli.Command{
|
||||
IsCAR: cctx.Bool("car"),
|
||||
}
|
||||
|
||||
if sel := textselector.Expression(cctx.String("datamodel-path-selector")); sel != "" {
|
||||
order.DatamodelPathSelector = &sel
|
||||
}
|
||||
|
||||
updates, err := fapi.ClientRetrieveWithEvents(ctx, *order, ref)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error setting up retrieval: %w", err)
|
||||
|
||||
+2
-2
@@ -220,8 +220,8 @@ var filplusCheckClientCmd = &cli.Command{
|
||||
}
|
||||
|
||||
var filplusCheckNotaryCmd = &cli.Command{
|
||||
Name: "check-notaries-datacap",
|
||||
Usage: "check notaries remaining bytes",
|
||||
Name: "check-notary-datacap",
|
||||
Usage: "check a notary's remaining bytes",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if !cctx.Args().Present() {
|
||||
return fmt.Errorf("must specify notary address to check")
|
||||
|
||||
+2
-2
@@ -647,9 +647,9 @@ var walletMarketWithdraw = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully withdrew %s FIL\n", withdrawn)
|
||||
fmt.Printf("Successfully withdrew %s \n", types.FIL(withdrawn))
|
||||
if withdrawn.LessThan(amt) {
|
||||
fmt.Printf("Note that this is less than the requested amount of %s FIL\n", amt)
|
||||
fmt.Printf("Note that this is less than the requested amount of %s \n", types.FIL(amt))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ var watchHeadCmd = &cli.Command{
|
||||
return
|
||||
}()
|
||||
|
||||
restart, err := notifyHandler(name, nCh, sCh)
|
||||
restart, err := notifyHandler(ctx, name, nCh, sCh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/coreos/go-systemd/v22/dbus"
|
||||
)
|
||||
|
||||
func notifyHandler(n string, ch chan interface{}, sCh chan os.Signal) (string, error) {
|
||||
func notifyHandler(ctx context.Context, n string, ch chan interface{}, sCh chan os.Signal) (string, error) {
|
||||
select {
|
||||
// alerts to restart systemd unit
|
||||
case <-ch:
|
||||
statusCh := make(chan string, 1)
|
||||
c, err := dbus.New()
|
||||
c, err := dbus.NewWithContext(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
_, err = c.TryRestartUnit(n, "fail", statusCh)
|
||||
_, err = c.TryRestartUnitContext(ctx, n, "fail", statusCh)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ var actorWithdrawCmd = &cli.Command{
|
||||
amount = abi.TokenAmount(f)
|
||||
|
||||
if amount.GreaterThan(available) {
|
||||
return xerrors.Errorf("can't withdraw more funds than available; requested: %s; available: %s", amount, available)
|
||||
return xerrors.Errorf("can't withdraw more funds than available; requested: %s; available: %s", types.FIL(amount), types.FIL(available))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,6 +283,7 @@ var actorWithdrawCmd = &cli.Command{
|
||||
|
||||
// wait for it to get mined into a block
|
||||
fmt.Printf("waiting for %d epochs for confirmation..\n", uint64(cctx.Int("confidence")))
|
||||
|
||||
wait, err := api.StateWaitMsg(ctx, smsg.Cid(), uint64(cctx.Int("confidence")))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -305,9 +306,9 @@ var actorWithdrawCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully withdrew %s FIL\n", withdrawn)
|
||||
fmt.Printf("Successfully withdrew %s \n", types.FIL(withdrawn))
|
||||
if withdrawn.LessThan(amount) {
|
||||
fmt.Printf("Note that this is less than the requested amount of %s FIL\n", amount)
|
||||
fmt.Printf("Note that this is less than the requested amount of %s\n", types.FIL(amount))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -729,12 +730,6 @@ var actorSetOwnerCmd = &cli.Command{
|
||||
return fmt.Errorf("must pass new owner address and sender address")
|
||||
}
|
||||
|
||||
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
|
||||
api, acloser, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -763,7 +758,7 @@ var actorSetOwnerCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
maddr, err := nodeApi.ActorAddress(ctx)
|
||||
maddr, err := getActorAddress(ctx, cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+12
-8
@@ -377,14 +377,18 @@ func handleMarketsInfo(ctx context.Context, nodeApi api.StorageMiner) error {
|
||||
}
|
||||
|
||||
showDealStates := map[storagemarket.StorageDealStatus]struct{}{
|
||||
storagemarket.StorageDealActive: {},
|
||||
storagemarket.StorageDealTransferring: {},
|
||||
storagemarket.StorageDealStaged: {},
|
||||
storagemarket.StorageDealAwaitingPreCommit: {},
|
||||
storagemarket.StorageDealSealing: {},
|
||||
storagemarket.StorageDealPublish: {},
|
||||
storagemarket.StorageDealCheckForAcceptance: {},
|
||||
storagemarket.StorageDealPublishing: {},
|
||||
storagemarket.StorageDealActive: {},
|
||||
storagemarket.StorageDealAcceptWait: {},
|
||||
storagemarket.StorageDealReserveProviderFunds: {},
|
||||
storagemarket.StorageDealProviderFunding: {},
|
||||
storagemarket.StorageDealTransferring: {},
|
||||
storagemarket.StorageDealValidating: {},
|
||||
storagemarket.StorageDealStaged: {},
|
||||
storagemarket.StorageDealAwaitingPreCommit: {},
|
||||
storagemarket.StorageDealSealing: {},
|
||||
storagemarket.StorageDealPublish: {},
|
||||
storagemarket.StorageDealCheckForAcceptance: {},
|
||||
storagemarket.StorageDealPublishing: {},
|
||||
}
|
||||
|
||||
var total dealStat
|
||||
|
||||
@@ -76,6 +76,21 @@ var infoAllCmd = &cli.Command{
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Proving Info")
|
||||
if err := provingInfoCmd.Action(cctx); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Proving Deadlines")
|
||||
if err := provingDeadlinesCmd.Action(cctx); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Proving Faults")
|
||||
if err := provingFaultsCmd.Action(cctx); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Sealing Jobs")
|
||||
if err := sealingJobsCmd.Action(cctx); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
@@ -92,8 +107,37 @@ var infoAllCmd = &cli.Command{
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Storage Deals")
|
||||
if err := dealsListCmd.Action(cctx); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
{
|
||||
fs := &flag.FlagSet{}
|
||||
for _, f := range dealsListCmd.Flags {
|
||||
if err := f.Apply(fs); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
}
|
||||
if err := fs.Parse([]string{"--verbose"}); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
if err := dealsListCmd.Action(cli.NewContext(cctx.App, fs, cctx)); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Storage Deals JSON")
|
||||
{
|
||||
fs := &flag.FlagSet{}
|
||||
for _, f := range dealsListCmd.Flags {
|
||||
if err := f.Apply(fs); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
}
|
||||
if err := fs.Parse([]string{"--verbose", "--format=json"}); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
if err := dealsListCmd.Action(cli.NewContext(cctx.App, fs, cctx)); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Retrieval Deals")
|
||||
@@ -101,11 +145,58 @@ var infoAllCmd = &cli.Command{
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Data Transfers")
|
||||
{
|
||||
fs := &flag.FlagSet{}
|
||||
for _, f := range transfersListCmd.Flags {
|
||||
if err := f.Apply(fs); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
}
|
||||
if err := fs.Parse([]string{"--verbose", "--completed", "--show-failed"}); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
if err := transfersListCmd.Action(cli.NewContext(cctx.App, fs, cctx)); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("\n#: DAGStore shards")
|
||||
if err := dagstoreListShardsCmd.Action(cctx); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Pending Batch Deals")
|
||||
if err := dealsPendingPublish.Action(cctx); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Pending Batch Terminations")
|
||||
if err := sectorsTerminatePendingCmd.Action(cctx); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Pending Batch PreCommit")
|
||||
if err := sectorsBatchingPendingPreCommit.Action(cctx); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Pending Batch Commit")
|
||||
if err := sectorsBatchingPendingCommit.Action(cctx); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Sector List")
|
||||
if err := sectorsListCmd.Action(cctx); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Expired Sectors")
|
||||
if err := sectorsExpiredCmd.Action(cctx); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("\n#: Sector Refs")
|
||||
if err := sectorsRefsCmd.Action(cctx); err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
|
||||
@@ -564,7 +564,7 @@ func makeHostKey(lr repo.LockedRepo) (crypto.PrivKey, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
kbytes, err := pk.Bytes()
|
||||
kbytes, err := crypto.MarshalPrivateKey(pk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+15
-1
@@ -104,7 +104,7 @@ func main() {
|
||||
&cli.StringFlag{
|
||||
Name: "actor",
|
||||
Value: "",
|
||||
Usage: "specify other actor to check state for (read only)",
|
||||
Usage: "specify other actor to query / manipulate",
|
||||
Aliases: []string{"a"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
@@ -113,6 +113,12 @@ func main() {
|
||||
Usage: "use color in display output",
|
||||
DefaultText: "depends on output being a TTY",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "panic-reports",
|
||||
EnvVars: []string{"LOTUS_PANIC_REPORT_PATH"},
|
||||
Hidden: true,
|
||||
Value: "~/.lotusminer", // should follow --repo default
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "repo",
|
||||
EnvVars: []string{"LOTUS_PATH"},
|
||||
@@ -146,6 +152,14 @@ func main() {
|
||||
}
|
||||
return nil
|
||||
},
|
||||
After: func(c *cli.Context) error {
|
||||
if r := recover(); r != nil {
|
||||
// Generate report in LOTUS_PATH and re-raise panic
|
||||
build.GeneratePanicReport(c.String("panic-reports"), c.String(FlagMinerRepo), c.App.Name)
|
||||
panic(r)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
app.Setup()
|
||||
app.Metadata["repoType"] = repo.StorageMiner
|
||||
|
||||
+159
-37
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -28,6 +29,7 @@ import (
|
||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
@@ -350,6 +352,7 @@ var storageDealsCmd = &cli.Command{
|
||||
resetBlocklistCmd,
|
||||
setSealDurationCmd,
|
||||
dealsPendingPublish,
|
||||
dealsRetryPublish,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -386,6 +389,11 @@ var dealsListCmd = &cli.Command{
|
||||
Name: "list",
|
||||
Usage: "List all deals for this miner",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "format",
|
||||
Usage: "output format of data, supported: table, json",
|
||||
Value: "table",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
Aliases: []string{"v"},
|
||||
@@ -396,63 +404,74 @@ var dealsListCmd = &cli.Command{
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := lcli.GetMarketsAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
switch cctx.String("format") {
|
||||
case "table":
|
||||
return listDealsWithTable(cctx)
|
||||
case "json":
|
||||
return listDealsWithJSON(cctx)
|
||||
}
|
||||
defer closer()
|
||||
|
||||
ctx := lcli.DaemonContext(cctx)
|
||||
return fmt.Errorf("unknown format: %s; use `table` or `json`", cctx.String("format"))
|
||||
},
|
||||
}
|
||||
|
||||
deals, err := api.MarketListIncompleteDeals(ctx)
|
||||
func listDealsWithTable(cctx *cli.Context) error {
|
||||
api, closer, err := lcli.GetMarketsAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
|
||||
ctx := lcli.DaemonContext(cctx)
|
||||
|
||||
deals, err := api.MarketListIncompleteDeals(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
verbose := cctx.Bool("verbose")
|
||||
watch := cctx.Bool("watch")
|
||||
|
||||
if watch {
|
||||
updates, err := api.MarketGetDealUpdates(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
verbose := cctx.Bool("verbose")
|
||||
watch := cctx.Bool("watch")
|
||||
for {
|
||||
tm.Clear()
|
||||
tm.MoveCursor(1, 1)
|
||||
|
||||
if watch {
|
||||
updates, err := api.MarketGetDealUpdates(ctx)
|
||||
err = outputStorageDealsTable(tm.Output, deals, verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
tm.Clear()
|
||||
tm.MoveCursor(1, 1)
|
||||
tm.Flush()
|
||||
|
||||
err = outputStorageDeals(tm.Output, deals, verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case updated := <-updates:
|
||||
var found bool
|
||||
for i, existing := range deals {
|
||||
if existing.ProposalCid.Equals(updated.ProposalCid) {
|
||||
deals[i] = updated
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
tm.Flush()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case updated := <-updates:
|
||||
var found bool
|
||||
for i, existing := range deals {
|
||||
if existing.ProposalCid.Equals(updated.ProposalCid) {
|
||||
deals[i] = updated
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
deals = append(deals, updated)
|
||||
}
|
||||
if !found {
|
||||
deals = append(deals, updated)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputStorageDeals(os.Stdout, deals, verbose)
|
||||
},
|
||||
return outputStorageDealsTable(os.Stdout, deals, verbose)
|
||||
}
|
||||
|
||||
func outputStorageDeals(out io.Writer, deals []storagemarket.MinerDeal, verbose bool) error {
|
||||
func outputStorageDealsTable(out io.Writer, deals []storagemarket.MinerDeal, verbose bool) error {
|
||||
sort.Slice(deals, func(i, j int) bool {
|
||||
return deals[i].CreationTime.Time().Before(deals[j].CreationTime.Time())
|
||||
})
|
||||
@@ -891,3 +910,106 @@ var dealsPendingPublish = &cli.Command{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var dealsRetryPublish = &cli.Command{
|
||||
Name: "retry-publish",
|
||||
Usage: "retry publishing a deal",
|
||||
ArgsUsage: "<proposal CID>",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if !cctx.Args().Present() {
|
||||
return cli.ShowCommandHelp(cctx, cctx.Command.Name)
|
||||
}
|
||||
api, closer, err := lcli.GetMarketsAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
propcid := cctx.Args().First()
|
||||
fmt.Printf("retrying deal with proposal-cid: %s\n", propcid)
|
||||
|
||||
cid, err := cid.Decode(propcid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := api.MarketRetryPublishDeal(ctx, cid); err != nil {
|
||||
return xerrors.Errorf("retrying publishing deal: %w", err)
|
||||
}
|
||||
fmt.Println("retried to publish deal")
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func listDealsWithJSON(cctx *cli.Context) error {
|
||||
node, closer, err := lcli.GetMarketsAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
|
||||
ctx := lcli.DaemonContext(cctx)
|
||||
|
||||
deals, err := node.MarketListIncompleteDeals(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
channels, err := node.MarketListDataTransfers(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sort.Slice(deals, func(i, j int) bool {
|
||||
return deals[i].CreationTime.Time().Before(deals[j].CreationTime.Time())
|
||||
})
|
||||
|
||||
channelsByTransferID := map[datatransfer.TransferID]api.DataTransferChannel{}
|
||||
for _, c := range channels {
|
||||
channelsByTransferID[c.TransferID] = c
|
||||
}
|
||||
|
||||
w := json.NewEncoder(os.Stdout)
|
||||
|
||||
for _, deal := range deals {
|
||||
val := struct {
|
||||
DateTime string `json:"datetime"`
|
||||
VerifiedDeal bool `json:"verified-deal"`
|
||||
ProposalCID string `json:"proposal-cid"`
|
||||
DealID abi.DealID `json:"deal-id"`
|
||||
DealStatus string `json:"deal-status"`
|
||||
Client string `json:"client"`
|
||||
PieceSize string `json:"piece-size"`
|
||||
Price types.FIL `json:"price"`
|
||||
DurationEpochs abi.ChainEpoch `json:"duration-epochs"`
|
||||
TransferID *datatransfer.TransferID `json:"transfer-id,omitempty"`
|
||||
TransferStatus string `json:"transfer-status,omitempty"`
|
||||
TransferredData string `json:"transferred-data,omitempty"`
|
||||
}{}
|
||||
|
||||
val.DateTime = deal.CreationTime.Time().Format(time.RFC3339)
|
||||
val.VerifiedDeal = deal.Proposal.VerifiedDeal
|
||||
val.ProposalCID = deal.ProposalCid.String()
|
||||
val.DealID = deal.DealID
|
||||
val.DealStatus = storagemarket.DealStates[deal.State]
|
||||
val.Client = deal.Proposal.Client.String()
|
||||
val.PieceSize = units.BytesSize(float64(deal.Proposal.PieceSize))
|
||||
val.Price = types.FIL(types.BigMul(deal.Proposal.StoragePricePerEpoch, types.NewInt(uint64(deal.Proposal.Duration()))))
|
||||
val.DurationEpochs = deal.Proposal.Duration()
|
||||
|
||||
if deal.TransferChannelId != nil {
|
||||
if c, ok := channelsByTransferID[deal.TransferChannelId.ID]; ok {
|
||||
val.TransferID = &c.TransferID
|
||||
val.TransferStatus = datatransfer.Statuses[c.Status]
|
||||
val.TransferredData = units.BytesSize(float64(c.Transferred))
|
||||
}
|
||||
}
|
||||
|
||||
err := w.Encode(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||
"github.com/filecoin-project/specs-storage/storage"
|
||||
)
|
||||
|
||||
@@ -360,6 +361,10 @@ var provingCheckProvableCmd = &cli.Command{
|
||||
Name: "slow",
|
||||
Usage: "run slower checks",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "storage-id",
|
||||
Usage: "filter sectors by storage path (path id)",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if cctx.Args().Len() != 1 {
|
||||
@@ -408,6 +413,21 @@ var provingCheckProvableCmd = &cli.Command{
|
||||
tw := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0)
|
||||
_, _ = fmt.Fprintln(tw, "deadline\tpartition\tsector\tstatus")
|
||||
|
||||
var filter map[abi.SectorID]struct{}
|
||||
|
||||
if cctx.IsSet("storage-id") {
|
||||
sl, err := sapi.StorageList(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
decls := sl[stores.ID(cctx.String("storage-id"))]
|
||||
|
||||
filter = map[abi.SectorID]struct{}{}
|
||||
for _, decl := range decls {
|
||||
filter[decl.SectorID] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
for parIdx, par := range partitions {
|
||||
sectors := make(map[abi.SectorNumber]struct{})
|
||||
|
||||
@@ -418,13 +438,21 @@ var provingCheckProvableCmd = &cli.Command{
|
||||
|
||||
var tocheck []storage.SectorRef
|
||||
for _, info := range sectorInfos {
|
||||
si := abi.SectorID{
|
||||
Miner: abi.ActorID(mid),
|
||||
Number: info.SectorNumber,
|
||||
}
|
||||
|
||||
if filter != nil {
|
||||
if _, found := filter[si]; !found {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
sectors[info.SectorNumber] = struct{}{}
|
||||
tocheck = append(tocheck, storage.SectorRef{
|
||||
ProofType: info.SealProof,
|
||||
ID: abi.SectorID{
|
||||
Miner: abi.ActorID(mid),
|
||||
Number: info.SectorNumber,
|
||||
},
|
||||
ID: si,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -224,8 +224,10 @@ var sealingJobsCmd = &cli.Command{
|
||||
for _, l := range lines {
|
||||
state := "running"
|
||||
switch {
|
||||
case l.RunWait > 0:
|
||||
case l.RunWait > 1:
|
||||
state = fmt.Sprintf("assigned(%d)", l.RunWait-1)
|
||||
case l.RunWait == storiface.RWPrepared:
|
||||
state = "prepared"
|
||||
case l.RunWait == storiface.RWRetDone:
|
||||
if !cctx.Bool("show-ret-done") {
|
||||
continue
|
||||
|
||||
+38
-14
@@ -266,8 +266,9 @@ var sectorsListCmd = &cli.Command{
|
||||
Usage: "List sectors",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "show-removed",
|
||||
Usage: "show removed sectors",
|
||||
Name: "show-removed",
|
||||
Usage: "show removed sectors",
|
||||
Aliases: []string{"r"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "color",
|
||||
@@ -276,12 +277,14 @@ var sectorsListCmd = &cli.Command{
|
||||
Aliases: []string{"c"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "fast",
|
||||
Usage: "don't show on-chain info for better performance",
|
||||
Name: "fast",
|
||||
Usage: "don't show on-chain info for better performance",
|
||||
Aliases: []string{"f"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "events",
|
||||
Usage: "display number of events the sector has received",
|
||||
Name: "events",
|
||||
Usage: "display number of events the sector has received",
|
||||
Aliases: []string{"e"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "seal-time",
|
||||
@@ -291,6 +294,11 @@ var sectorsListCmd = &cli.Command{
|
||||
Name: "states",
|
||||
Usage: "filter sectors by a comma-separated list of states",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "unproven",
|
||||
Usage: "only show sectors which aren't in the 'Proving' state",
|
||||
Aliases: []string{"u"},
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if cctx.IsSet("color") {
|
||||
@@ -314,17 +322,33 @@ var sectorsListCmd = &cli.Command{
|
||||
var list []abi.SectorNumber
|
||||
|
||||
showRemoved := cctx.Bool("show-removed")
|
||||
states := cctx.String("states")
|
||||
var states []api.SectorState
|
||||
if cctx.IsSet("states") && cctx.IsSet("unproven") {
|
||||
return xerrors.Errorf("only one of --states or --unproven can be specified at once")
|
||||
}
|
||||
|
||||
if cctx.IsSet("states") {
|
||||
showRemoved = true
|
||||
sList := strings.Split(cctx.String("states"), ",")
|
||||
states = make([]api.SectorState, len(sList))
|
||||
for i := range sList {
|
||||
states[i] = api.SectorState(sList[i])
|
||||
}
|
||||
}
|
||||
|
||||
if cctx.Bool("unproven") {
|
||||
for state := range sealing.ExistSectorStateList {
|
||||
if state == sealing.Proving {
|
||||
continue
|
||||
}
|
||||
states = append(states, api.SectorState(state))
|
||||
}
|
||||
}
|
||||
|
||||
if len(states) == 0 {
|
||||
list, err = nodeApi.SectorsList(ctx)
|
||||
} else {
|
||||
showRemoved = true
|
||||
sList := strings.Split(states, ",")
|
||||
ss := make([]api.SectorState, len(sList))
|
||||
for i := range sList {
|
||||
ss[i] = api.SectorState(sList[i])
|
||||
}
|
||||
list, err = nodeApi.SectorsListInStates(ctx, ss)
|
||||
list, err = nodeApi.SectorsListInStates(ctx, states)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/lib/lotuslog"
|
||||
"github.com/filecoin-project/lotus/lib/rpcenc"
|
||||
"github.com/filecoin-project/lotus/metrics"
|
||||
"github.com/filecoin-project/lotus/metrics/proxy"
|
||||
"github.com/filecoin-project/lotus/node/modules"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
)
|
||||
@@ -75,6 +76,12 @@ func main() {
|
||||
Value: "~/.lotusworker", // TODO: Consider XDG_DATA_HOME
|
||||
Usage: fmt.Sprintf("Specify worker repo path. flag %s and env WORKER_PATH are DEPRECATION, will REMOVE SOON", FlagWorkerRepoDeprecation),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "panic-reports",
|
||||
EnvVars: []string{"LOTUS_PANIC_REPORT_PATH"},
|
||||
Hidden: true,
|
||||
Value: "~/.lotusworker", // should follow --repo default
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "miner-repo",
|
||||
Aliases: []string{"storagerepo"},
|
||||
@@ -89,6 +96,14 @@ func main() {
|
||||
},
|
||||
},
|
||||
|
||||
After: func(c *cli.Context) error {
|
||||
if r := recover(); r != nil {
|
||||
// Generate report in LOTUS_PATH and re-raise panic
|
||||
build.GeneratePanicReport(c.String("panic-reports"), c.String(FlagWorkerRepo), c.App.Name)
|
||||
panic(r)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Commands: local,
|
||||
}
|
||||
app.Setup()
|
||||
@@ -395,7 +410,7 @@ var runCmd = &cli.Command{
|
||||
|
||||
readerHandler, readerServerOpt := rpcenc.ReaderParamDecoder()
|
||||
rpcServer := jsonrpc.NewServer(readerServerOpt)
|
||||
rpcServer.Register("Filecoin", api.PermissionedWorkerAPI(metrics.MetricedWorkerAPI(workerApi)))
|
||||
rpcServer.Register("Filecoin", api.PermissionedWorkerAPI(proxy.MetricedWorkerAPI(workerApi)))
|
||||
|
||||
mux.Handle("/rpc/v0", rpcServer)
|
||||
mux.Handle("/rpc/streams/v0/push/{uuid}", readerHandler)
|
||||
|
||||
@@ -94,9 +94,10 @@ var preSealCmd = &cli.Command{
|
||||
Name: "fake-sectors",
|
||||
Value: false,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
&cli.UintFlag{
|
||||
Name: "network-version",
|
||||
Usage: "specify network version",
|
||||
Value: uint(build.NewestNetworkVersion),
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
|
||||
@@ -104,7 +104,7 @@ var actorWithdrawCmd = &cli.Command{
|
||||
amount = abi.TokenAmount(f)
|
||||
|
||||
if amount.GreaterThan(available) {
|
||||
return xerrors.Errorf("can't withdraw more funds than available; requested: %s; available: %s", amount, available)
|
||||
return xerrors.Errorf("can't withdraw more funds than available; requested: %s; available: %s", types.FIL(amount), types.FIL(available))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,9 +151,9 @@ var actorWithdrawCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully withdrew %s FIL\n", withdrawn)
|
||||
fmt.Printf("Successfully withdrew %s \n", types.FIL(withdrawn))
|
||||
if withdrawn.LessThan(amount) {
|
||||
fmt.Printf("Note that this is less than the requested amount of %s FIL\n", amount)
|
||||
fmt.Printf("Note that this is less than the requested amount of %s \n", types.FIL(amount))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var chainCmd = &cli.Command{
|
||||
Name: "chain",
|
||||
Usage: "chain-related utilities",
|
||||
Subcommands: []*cli.Command{
|
||||
chainNullTsCmd,
|
||||
},
|
||||
}
|
||||
|
||||
var chainNullTsCmd = &cli.Command{
|
||||
Name: "latest-null",
|
||||
Usage: "finds the most recent null tipset",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer closer()
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
ts, err := lcli.LoadTipSet(ctx, cctx, api)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
pts, err := api.ChainGetTipSet(ctx, ts.Parents())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ts.Height() != pts.Height()+1 {
|
||||
fmt.Println("null tipset at height ", ts.Height()-1)
|
||||
return nil
|
||||
}
|
||||
|
||||
ts = pts
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/fr32"
|
||||
)
|
||||
|
||||
var fr32Cmd = &cli.Command{
|
||||
Name: "fr32",
|
||||
Description: "fr32 encode/decode",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "decode",
|
||||
Aliases: []string{"d"},
|
||||
},
|
||||
},
|
||||
Action: func(context *cli.Context) error {
|
||||
if context.Bool("decode") {
|
||||
st, err := os.Stdin.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pps := abi.PaddedPieceSize(st.Size())
|
||||
if pps == 0 {
|
||||
return xerrors.Errorf("zero size input")
|
||||
}
|
||||
|
||||
if err := pps.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := fr32.NewUnpadReader(os.Stdin, pps)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(os.Stdout, r); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
w := fr32.NewPadWriter(os.Stdout)
|
||||
if _, err := io.Copy(w, os.Stdin); err != nil {
|
||||
return err
|
||||
}
|
||||
return w.Close()
|
||||
},
|
||||
}
|
||||
@@ -59,8 +59,11 @@ func main() {
|
||||
signaturesCmd,
|
||||
actorCmd,
|
||||
minerTypesCmd,
|
||||
minerPeeridCmd,
|
||||
minerMultisigsCmd,
|
||||
splitstoreCmd,
|
||||
fr32Cmd,
|
||||
chainCmd,
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/consensus/filcns"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
"github.com/filecoin-project/specs-actors/v4/actors/util/adt"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
var minerPeeridCmd = &cli.Command{
|
||||
Name: "miner-peerid",
|
||||
Usage: "Scrape state to find a miner based on peerid", Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "repo",
|
||||
Value: "~/.lotus",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
ctx := context.TODO()
|
||||
|
||||
if cctx.NArg() != 2 {
|
||||
return fmt.Errorf("must pass peer id and state root")
|
||||
}
|
||||
|
||||
pid, err := peer.Decode(cctx.Args().Get(0))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse input as a peerId: %w", err)
|
||||
}
|
||||
|
||||
sroot, err := cid.Decode(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse state root: %w", err)
|
||||
}
|
||||
|
||||
fsrepo, err := repo.NewFS(cctx.String("repo"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lkrepo, err := fsrepo.Lock(repo.FullNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer lkrepo.Close() //nolint:errcheck
|
||||
|
||||
bs, err := lkrepo.Blockstore(ctx, repo.UniversalBlockstore)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open blockstore: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if c, ok := bs.(io.Closer); ok {
|
||||
if err := c.Close(); err != nil {
|
||||
log.Warnf("failed to close blockstore: %s", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
mds, err := lkrepo.Datastore(context.Background(), "/metadata")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cs := store.NewChainStore(bs, bs, mds, filcns.Weight, nil)
|
||||
defer cs.Close() //nolint:errcheck
|
||||
|
||||
cst := cbor.NewCborStore(bs)
|
||||
store := adt.WrapStore(ctx, cst)
|
||||
|
||||
tree, err := state.LoadStateTree(cst, sroot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tree.ForEach(func(addr address.Address, act *types.Actor) error {
|
||||
if act.Code == builtin5.StorageMinerActorCodeID {
|
||||
ms, err := miner.Load(store, act)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mi, err := ms.Info()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if mi.PeerId != nil && *mi.PeerId == pid {
|
||||
fmt.Println(addr)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to loop over actors: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/lotus/lib/lotuslog"
|
||||
"github.com/filecoin-project/lotus/metrics"
|
||||
"github.com/filecoin-project/lotus/metrics/proxy"
|
||||
"github.com/filecoin-project/lotus/node/modules"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
)
|
||||
@@ -204,7 +205,7 @@ var runCmd = &cli.Command{
|
||||
w = &LoggedWallet{under: w}
|
||||
}
|
||||
|
||||
rpcApi := metrics.MetricedWalletAPI(w)
|
||||
rpcApi := proxy.MetricedWalletAPI(w)
|
||||
if !cctx.Bool("disable-auth") {
|
||||
rpcApi = api.PermissionedWalletAPI(rpcApi)
|
||||
}
|
||||
|
||||
@@ -67,6 +67,12 @@ func main() {
|
||||
Version: build.UserVersion(),
|
||||
EnableBashCompletion: true,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "panic-reports",
|
||||
EnvVars: []string{"LOTUS_PANIC_REPORT_PATH"},
|
||||
Hidden: true,
|
||||
Value: "~/.lotus", // should follow --repo default
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "repo",
|
||||
EnvVars: []string{"LOTUS_PATH"},
|
||||
@@ -84,6 +90,14 @@ func main() {
|
||||
},
|
||||
cliutil.FlagVeryVerbose,
|
||||
},
|
||||
After: func(c *cli.Context) error {
|
||||
if r := recover(); r != nil {
|
||||
// Generate report in LOTUS_PATH and re-raise panic
|
||||
build.GeneratePanicReport(c.String("panic-reports"), c.String("repo"), c.App.Name)
|
||||
panic(r)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
||||
Commands: append(local, lcli.Commands...),
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
* [MarketPendingDeals](#MarketPendingDeals)
|
||||
* [MarketPublishPendingDeals](#MarketPublishPendingDeals)
|
||||
* [MarketRestartDataTransfer](#MarketRestartDataTransfer)
|
||||
* [MarketRetryPublishDeal](#MarketRetryPublishDeal)
|
||||
* [MarketSetAsk](#MarketSetAsk)
|
||||
* [MarketSetRetrievalAsk](#MarketSetRetrievalAsk)
|
||||
* [Mining](#Mining)
|
||||
@@ -949,6 +950,22 @@ Inputs:
|
||||
|
||||
Response: `{}`
|
||||
|
||||
### MarketRetryPublishDeal
|
||||
|
||||
|
||||
Perms: admin
|
||||
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Response: `{}`
|
||||
|
||||
### MarketSetAsk
|
||||
|
||||
|
||||
|
||||
@@ -1469,6 +1469,7 @@ Inputs:
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Piece": null,
|
||||
"DatamodelPathSelector": "Links/21/Hash/Links/42/Hash",
|
||||
"Size": 42,
|
||||
"FromLocalCAR": "string value",
|
||||
"Total": "0",
|
||||
@@ -1523,6 +1524,7 @@ Inputs:
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Piece": null,
|
||||
"DatamodelPathSelector": "Links/21/Hash/Links/42/Hash",
|
||||
"Size": 42,
|
||||
"FromLocalCAR": "string value",
|
||||
"Total": "0",
|
||||
|
||||
@@ -1481,6 +1481,7 @@ Inputs:
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Piece": null,
|
||||
"DatamodelPathSelector": "Links/21/Hash/Links/42/Hash",
|
||||
"Size": 42,
|
||||
"FromLocalCAR": "string value",
|
||||
"Total": "0",
|
||||
@@ -1535,6 +1536,7 @@ Inputs:
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Piece": null,
|
||||
"DatamodelPathSelector": "Links/21/Hash/Links/42/Hash",
|
||||
"Size": 42,
|
||||
"FromLocalCAR": "string value",
|
||||
"Total": "0",
|
||||
|
||||
@@ -7,7 +7,7 @@ USAGE:
|
||||
lotus-miner [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
1.12.0
|
||||
1.13.1
|
||||
|
||||
COMMANDS:
|
||||
init Initialize a lotus miner repo
|
||||
@@ -41,7 +41,7 @@ COMMANDS:
|
||||
sealing interact with sealing pipeline
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
--actor value, -a value specify other actor to check state for (read only)
|
||||
--actor value, -a value specify other actor to query / manipulate
|
||||
--color use color in display output (default: depends on output being a TTY)
|
||||
--miner-repo value, --storagerepo value Specify miner repo path. flag(storagerepo) and env(LOTUS_STORAGE_PATH) are DEPRECATION, will REMOVE SOON (default: "~/.lotusminer") [$LOTUS_MINER_PATH, $LOTUS_STORAGE_PATH]
|
||||
--markets-repo value Markets repo path [$LOTUS_MARKETS_PATH]
|
||||
@@ -629,6 +629,7 @@ COMMANDS:
|
||||
reset-blocklist Remove all entries from the miner's piece CID blocklist
|
||||
set-seal-duration Set the expected time, in minutes, that you expect sealing sectors to take. Deals that start before this duration will be rejected.
|
||||
pending-publish list deals waiting in publish queue
|
||||
retry-publish retry publishing a deal
|
||||
help, h Shows a list of commands or help for one command
|
||||
|
||||
OPTIONS:
|
||||
@@ -659,9 +660,10 @@ USAGE:
|
||||
lotus-miner storage-deals list [command options] [arguments...]
|
||||
|
||||
OPTIONS:
|
||||
--verbose, -v (default: false)
|
||||
--watch watch deal updates in real-time, rather than a one time list (default: false)
|
||||
--help, -h show help (default: false)
|
||||
--format value output format of data, supported: table, json (default: "table")
|
||||
--verbose, -v (default: false)
|
||||
--watch watch deal updates in real-time, rather than a one time list (default: false)
|
||||
--help, -h show help (default: false)
|
||||
|
||||
```
|
||||
|
||||
@@ -824,6 +826,19 @@ OPTIONS:
|
||||
|
||||
```
|
||||
|
||||
### lotus-miner storage-deals retry-publish
|
||||
```
|
||||
NAME:
|
||||
lotus-miner storage-deals retry-publish - retry publishing a deal
|
||||
|
||||
USAGE:
|
||||
lotus-miner storage-deals retry-publish [command options] <proposal CID>
|
||||
|
||||
OPTIONS:
|
||||
--help, -h show help (default: false)
|
||||
|
||||
```
|
||||
|
||||
## lotus-miner retrieval-deals
|
||||
```
|
||||
NAME:
|
||||
@@ -1533,13 +1548,14 @@ USAGE:
|
||||
lotus-miner sectors list [command options] [arguments...]
|
||||
|
||||
OPTIONS:
|
||||
--show-removed show removed sectors (default: false)
|
||||
--color, -c use color in display output (default: depends on output being a TTY)
|
||||
--fast don't show on-chain info for better performance (default: false)
|
||||
--events display number of events the sector has received (default: false)
|
||||
--seal-time display how long it took for the sector to be sealed (default: false)
|
||||
--states value filter sectors by a comma-separated list of states
|
||||
--help, -h show help (default: false)
|
||||
--show-removed, -r show removed sectors (default: false)
|
||||
--color, -c use color in display output (default: depends on output being a TTY)
|
||||
--fast, -f don't show on-chain info for better performance (default: false)
|
||||
--events, -e display number of events the sector has received (default: false)
|
||||
--seal-time display how long it took for the sector to be sealed (default: false)
|
||||
--states value filter sectors by a comma-separated list of states
|
||||
--unproven, -u only show sectors which aren't in the 'Proving' state (default: false)
|
||||
--help, -h show help (default: false)
|
||||
|
||||
```
|
||||
|
||||
@@ -1897,9 +1913,10 @@ USAGE:
|
||||
lotus-miner proving check [command options] <deadlineIdx>
|
||||
|
||||
OPTIONS:
|
||||
--only-bad print only bad sectors (default: false)
|
||||
--slow run slower checks (default: false)
|
||||
--help, -h show help (default: false)
|
||||
--only-bad print only bad sectors (default: false)
|
||||
--slow run slower checks (default: false)
|
||||
--storage-id value filter sectors by storage path (path id)
|
||||
--help, -h show help (default: false)
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ USAGE:
|
||||
lotus-worker [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
1.12.0
|
||||
1.13.1
|
||||
|
||||
COMMANDS:
|
||||
run Start lotus worker
|
||||
|
||||
@@ -7,7 +7,7 @@ USAGE:
|
||||
lotus [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
1.12.0
|
||||
1.13.1
|
||||
|
||||
COMMANDS:
|
||||
daemon Start a lotus daemon process
|
||||
@@ -545,13 +545,14 @@ CATEGORY:
|
||||
RETRIEVAL
|
||||
|
||||
OPTIONS:
|
||||
--from value address to send transactions from
|
||||
--car export to a car file instead of a regular file (default: false)
|
||||
--miner value miner address for retrieval, if not present it'll use local discovery
|
||||
--maxPrice value maximum price the client is willing to consider (default: 0.01 FIL)
|
||||
--pieceCid value require data to be retrieved from a specific Piece CID
|
||||
--allow-local (default: false)
|
||||
--help, -h show help (default: false)
|
||||
--from value address to send transactions from
|
||||
--car export to a car file instead of a regular file (default: false)
|
||||
--miner value miner address for retrieval, if not present it'll use local discovery
|
||||
--datamodel-path-selector value a rudimentary (DM-level-only) text-path selector, allowing for sub-selection within a deal
|
||||
--maxPrice value maximum price the client is willing to consider (default: 0.01 FIL)
|
||||
--pieceCid value require data to be retrieved from a specific Piece CID
|
||||
--allow-local (default: false)
|
||||
--help, -h show help (default: false)
|
||||
|
||||
```
|
||||
|
||||
@@ -1116,12 +1117,12 @@ USAGE:
|
||||
lotus filplus command [command options] [arguments...]
|
||||
|
||||
COMMANDS:
|
||||
grant-datacap give allowance to the specified verified client address
|
||||
list-notaries list all notaries
|
||||
list-clients list all verified clients
|
||||
check-client-datacap check verified client remaining bytes
|
||||
check-notaries-datacap check notaries remaining bytes
|
||||
help, h Shows a list of commands or help for one command
|
||||
grant-datacap give allowance to the specified verified client address
|
||||
list-notaries list all notaries
|
||||
list-clients list all verified clients
|
||||
check-client-datacap check verified client remaining bytes
|
||||
check-notary-datacap check a notary's remaining bytes
|
||||
help, h Shows a list of commands or help for one command
|
||||
|
||||
OPTIONS:
|
||||
--help, -h show help (default: false)
|
||||
@@ -1182,13 +1183,13 @@ OPTIONS:
|
||||
|
||||
```
|
||||
|
||||
### lotus filplus check-notaries-datacap
|
||||
### lotus filplus check-notary-datacap
|
||||
```
|
||||
NAME:
|
||||
lotus filplus check-notaries-datacap - check notaries remaining bytes
|
||||
lotus filplus check-notary-datacap - check a notary's remaining bytes
|
||||
|
||||
USAGE:
|
||||
lotus filplus check-notaries-datacap [command options] [arguments...]
|
||||
lotus filplus check-notary-datacap [command options] [arguments...]
|
||||
|
||||
OPTIONS:
|
||||
--help, -h show help (default: false)
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
[API]
|
||||
# Binding address for the Lotus API
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_API_LISTENADDRESS
|
||||
#ListenAddress = "/ip4/127.0.0.1/tcp/1234/http"
|
||||
|
||||
# type: string
|
||||
# env var: LOTUS_API_REMOTELISTENADDRESS
|
||||
#RemoteListenAddress = ""
|
||||
|
||||
# type: Duration
|
||||
# env var: LOTUS_API_TIMEOUT
|
||||
#Timeout = "30s"
|
||||
|
||||
|
||||
[Backup]
|
||||
# Note that in case of metadata corruption it might be much harder to recover
|
||||
# your node if metadata log is disabled
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_BACKUP_DISABLEMETADATALOG
|
||||
#DisableMetadataLog = false
|
||||
|
||||
|
||||
[Libp2p]
|
||||
# Binding address for the libp2p host - 0 means random port.
|
||||
# Format: multiaddress; see https://multiformats.io/multiaddr/
|
||||
#
|
||||
# type: []string
|
||||
# env var: LOTUS_LIBP2P_LISTENADDRESSES
|
||||
#ListenAddresses = ["/ip4/0.0.0.0/tcp/0", "/ip6/::/tcp/0"]
|
||||
|
||||
# Addresses to explicitally announce to other peers. If not specified,
|
||||
# all interface addresses are announced
|
||||
# Format: multiaddress
|
||||
#
|
||||
# type: []string
|
||||
# env var: LOTUS_LIBP2P_ANNOUNCEADDRESSES
|
||||
#AnnounceAddresses = []
|
||||
|
||||
# Addresses to not announce
|
||||
# Format: multiaddress
|
||||
#
|
||||
# type: []string
|
||||
# env var: LOTUS_LIBP2P_NOANNOUNCEADDRESSES
|
||||
#NoAnnounceAddresses = []
|
||||
|
||||
# When not disabled (default), lotus asks NAT devices (e.g., routers), to
|
||||
# open up an external port and forward it to the port lotus is running on.
|
||||
# When this works (i.e., when your router supports NAT port forwarding),
|
||||
# it makes the local lotus node accessible from the public internet
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_LIBP2P_DISABLENATPORTMAP
|
||||
#DisableNatPortMap = false
|
||||
|
||||
# ConnMgrLow is the number of connections that the basic connection manager
|
||||
# will trim down to.
|
||||
#
|
||||
# type: uint
|
||||
# env var: LOTUS_LIBP2P_CONNMGRLOW
|
||||
#ConnMgrLow = 150
|
||||
|
||||
# ConnMgrHigh is the number of connections that, when exceeded, will trigger
|
||||
# a connection GC operation. Note: protected/recently formed connections don't
|
||||
# count towards this limit.
|
||||
#
|
||||
# type: uint
|
||||
# env var: LOTUS_LIBP2P_CONNMGRHIGH
|
||||
#ConnMgrHigh = 180
|
||||
|
||||
# ConnMgrGrace is a time duration that new connections are immune from being
|
||||
# closed by the connection manager.
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_LIBP2P_CONNMGRGRACE
|
||||
#ConnMgrGrace = "20s"
|
||||
|
||||
|
||||
[Pubsub]
|
||||
# Run the node in bootstrap-node mode
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_PUBSUB_BOOTSTRAPPER
|
||||
#Bootstrapper = false
|
||||
|
||||
# type: string
|
||||
# env var: LOTUS_PUBSUB_REMOTETRACER
|
||||
#RemoteTracer = ""
|
||||
|
||||
|
||||
[Client]
|
||||
# type: bool
|
||||
# env var: LOTUS_CLIENT_USEIPFS
|
||||
#UseIpfs = false
|
||||
|
||||
# type: bool
|
||||
# env var: LOTUS_CLIENT_IPFSONLINEMODE
|
||||
#IpfsOnlineMode = false
|
||||
|
||||
# type: string
|
||||
# env var: LOTUS_CLIENT_IPFSMADDR
|
||||
#IpfsMAddr = ""
|
||||
|
||||
# type: bool
|
||||
# env var: LOTUS_CLIENT_IPFSUSEFORRETRIEVAL
|
||||
#IpfsUseForRetrieval = false
|
||||
|
||||
# The maximum number of simultaneous data transfers between the client
|
||||
# and storage providers for storage deals
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_CLIENT_SIMULTANEOUSTRANSFERSFORSTORAGE
|
||||
#SimultaneousTransfersForStorage = 20
|
||||
|
||||
# The maximum number of simultaneous data transfers between the client
|
||||
# and storage providers for retrieval deals
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_CLIENT_SIMULTANEOUSTRANSFERSFORRETRIEVAL
|
||||
#SimultaneousTransfersForRetrieval = 20
|
||||
|
||||
|
||||
[Wallet]
|
||||
# type: string
|
||||
# env var: LOTUS_WALLET_REMOTEBACKEND
|
||||
#RemoteBackend = ""
|
||||
|
||||
# type: bool
|
||||
# env var: LOTUS_WALLET_ENABLELEDGER
|
||||
#EnableLedger = false
|
||||
|
||||
# type: bool
|
||||
# env var: LOTUS_WALLET_DISABLELOCAL
|
||||
#DisableLocal = false
|
||||
|
||||
|
||||
[Fees]
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_FEES_DEFAULTMAXFEE
|
||||
#DefaultMaxFee = "0.07 FIL"
|
||||
|
||||
|
||||
[Chainstore]
|
||||
# type: bool
|
||||
# env var: LOTUS_CHAINSTORE_ENABLESPLITSTORE
|
||||
#EnableSplitstore = false
|
||||
|
||||
[Chainstore.Splitstore]
|
||||
# ColdStoreType specifies the type of the coldstore.
|
||||
# It can be "universal" (default) or "discard" for discarding cold blocks.
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_CHAINSTORE_SPLITSTORE_COLDSTORETYPE
|
||||
#ColdStoreType = "universal"
|
||||
|
||||
# HotStoreType specifies the type of the hotstore.
|
||||
# Only currently supported value is "badger".
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_CHAINSTORE_SPLITSTORE_HOTSTORETYPE
|
||||
#HotStoreType = "badger"
|
||||
|
||||
# MarkSetType specifies the type of the markset.
|
||||
# It can be "map" (default) for in memory marking or "badger" for on-disk marking.
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_CHAINSTORE_SPLITSTORE_MARKSETTYPE
|
||||
#MarkSetType = "map"
|
||||
|
||||
# HotStoreMessageRetention specifies the retention policy for messages, in finalities beyond
|
||||
# the compaction boundary; default is 0.
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_CHAINSTORE_SPLITSTORE_HOTSTOREMESSAGERETENTION
|
||||
#HotStoreMessageRetention = 0
|
||||
|
||||
# HotStoreFullGCFrequency specifies how often to perform a full (moving) GC on the hotstore.
|
||||
# A value of 0 disables, while a value 1 will do full GC in every compaction.
|
||||
# Default is 20 (about once a week).
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_CHAINSTORE_SPLITSTORE_HOTSTOREFULLGCFREQUENCY
|
||||
#HotStoreFullGCFrequency = 20
|
||||
|
||||
|
||||
@@ -0,0 +1,552 @@
|
||||
[API]
|
||||
# Binding address for the Lotus API
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_API_LISTENADDRESS
|
||||
#ListenAddress = "/ip4/127.0.0.1/tcp/2345/http"
|
||||
|
||||
# type: string
|
||||
# env var: LOTUS_API_REMOTELISTENADDRESS
|
||||
#RemoteListenAddress = "127.0.0.1:2345"
|
||||
|
||||
# type: Duration
|
||||
# env var: LOTUS_API_TIMEOUT
|
||||
#Timeout = "30s"
|
||||
|
||||
|
||||
[Backup]
|
||||
# Note that in case of metadata corruption it might be much harder to recover
|
||||
# your node if metadata log is disabled
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_BACKUP_DISABLEMETADATALOG
|
||||
#DisableMetadataLog = false
|
||||
|
||||
|
||||
[Libp2p]
|
||||
# Binding address for the libp2p host - 0 means random port.
|
||||
# Format: multiaddress; see https://multiformats.io/multiaddr/
|
||||
#
|
||||
# type: []string
|
||||
# env var: LOTUS_LIBP2P_LISTENADDRESSES
|
||||
#ListenAddresses = ["/ip4/0.0.0.0/tcp/0", "/ip6/::/tcp/0"]
|
||||
|
||||
# Addresses to explicitally announce to other peers. If not specified,
|
||||
# all interface addresses are announced
|
||||
# Format: multiaddress
|
||||
#
|
||||
# type: []string
|
||||
# env var: LOTUS_LIBP2P_ANNOUNCEADDRESSES
|
||||
#AnnounceAddresses = []
|
||||
|
||||
# Addresses to not announce
|
||||
# Format: multiaddress
|
||||
#
|
||||
# type: []string
|
||||
# env var: LOTUS_LIBP2P_NOANNOUNCEADDRESSES
|
||||
#NoAnnounceAddresses = []
|
||||
|
||||
# When not disabled (default), lotus asks NAT devices (e.g., routers), to
|
||||
# open up an external port and forward it to the port lotus is running on.
|
||||
# When this works (i.e., when your router supports NAT port forwarding),
|
||||
# it makes the local lotus node accessible from the public internet
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_LIBP2P_DISABLENATPORTMAP
|
||||
#DisableNatPortMap = false
|
||||
|
||||
# ConnMgrLow is the number of connections that the basic connection manager
|
||||
# will trim down to.
|
||||
#
|
||||
# type: uint
|
||||
# env var: LOTUS_LIBP2P_CONNMGRLOW
|
||||
#ConnMgrLow = 150
|
||||
|
||||
# ConnMgrHigh is the number of connections that, when exceeded, will trigger
|
||||
# a connection GC operation. Note: protected/recently formed connections don't
|
||||
# count towards this limit.
|
||||
#
|
||||
# type: uint
|
||||
# env var: LOTUS_LIBP2P_CONNMGRHIGH
|
||||
#ConnMgrHigh = 180
|
||||
|
||||
# ConnMgrGrace is a time duration that new connections are immune from being
|
||||
# closed by the connection manager.
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_LIBP2P_CONNMGRGRACE
|
||||
#ConnMgrGrace = "20s"
|
||||
|
||||
|
||||
[Pubsub]
|
||||
# Run the node in bootstrap-node mode
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_PUBSUB_BOOTSTRAPPER
|
||||
#Bootstrapper = false
|
||||
|
||||
# type: string
|
||||
# env var: LOTUS_PUBSUB_REMOTETRACER
|
||||
#RemoteTracer = ""
|
||||
|
||||
|
||||
[Subsystems]
|
||||
# type: bool
|
||||
# env var: LOTUS_SUBSYSTEMS_ENABLEMINING
|
||||
#EnableMining = true
|
||||
|
||||
# type: bool
|
||||
# env var: LOTUS_SUBSYSTEMS_ENABLESEALING
|
||||
#EnableSealing = true
|
||||
|
||||
# type: bool
|
||||
# env var: LOTUS_SUBSYSTEMS_ENABLESECTORSTORAGE
|
||||
#EnableSectorStorage = true
|
||||
|
||||
# type: bool
|
||||
# env var: LOTUS_SUBSYSTEMS_ENABLEMARKETS
|
||||
#EnableMarkets = true
|
||||
|
||||
# type: string
|
||||
# env var: LOTUS_SUBSYSTEMS_SEALERAPIINFO
|
||||
#SealerApiInfo = ""
|
||||
|
||||
# type: string
|
||||
# env var: LOTUS_SUBSYSTEMS_SECTORINDEXAPIINFO
|
||||
#SectorIndexApiInfo = ""
|
||||
|
||||
|
||||
[Dealmaking]
|
||||
# When enabled, the miner can accept online deals
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_DEALMAKING_CONSIDERONLINESTORAGEDEALS
|
||||
#ConsiderOnlineStorageDeals = true
|
||||
|
||||
# When enabled, the miner can accept offline deals
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_DEALMAKING_CONSIDEROFFLINESTORAGEDEALS
|
||||
#ConsiderOfflineStorageDeals = true
|
||||
|
||||
# When enabled, the miner can accept retrieval deals
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_DEALMAKING_CONSIDERONLINERETRIEVALDEALS
|
||||
#ConsiderOnlineRetrievalDeals = true
|
||||
|
||||
# When enabled, the miner can accept offline retrieval deals
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_DEALMAKING_CONSIDEROFFLINERETRIEVALDEALS
|
||||
#ConsiderOfflineRetrievalDeals = true
|
||||
|
||||
# When enabled, the miner can accept verified deals
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_DEALMAKING_CONSIDERVERIFIEDSTORAGEDEALS
|
||||
#ConsiderVerifiedStorageDeals = true
|
||||
|
||||
# When enabled, the miner can accept unverified deals
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_DEALMAKING_CONSIDERUNVERIFIEDSTORAGEDEALS
|
||||
#ConsiderUnverifiedStorageDeals = true
|
||||
|
||||
# A list of Data CIDs to reject when making deals
|
||||
#
|
||||
# type: []cid.Cid
|
||||
# env var: LOTUS_DEALMAKING_PIECECIDBLOCKLIST
|
||||
#PieceCidBlocklist = []
|
||||
|
||||
# Maximum expected amount of time getting the deal into a sealed sector will take
|
||||
# This includes the time the deal will need to get transferred and published
|
||||
# before being assigned to a sector
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_DEALMAKING_EXPECTEDSEALDURATION
|
||||
#ExpectedSealDuration = "24h0m0s"
|
||||
|
||||
# Maximum amount of time proposed deal StartEpoch can be in future
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_DEALMAKING_MAXDEALSTARTDELAY
|
||||
#MaxDealStartDelay = "336h0m0s"
|
||||
|
||||
# When a deal is ready to publish, the amount of time to wait for more
|
||||
# deals to be ready to publish before publishing them all as a batch
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_DEALMAKING_PUBLISHMSGPERIOD
|
||||
#PublishMsgPeriod = "1h0m0s"
|
||||
|
||||
# The maximum number of deals to include in a single PublishStorageDeals
|
||||
# message
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_DEALMAKING_MAXDEALSPERPUBLISHMSG
|
||||
#MaxDealsPerPublishMsg = 8
|
||||
|
||||
# The maximum collateral that the provider will put up against a deal,
|
||||
# as a multiplier of the minimum collateral bound
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_DEALMAKING_MAXPROVIDERCOLLATERALMULTIPLIER
|
||||
#MaxProviderCollateralMultiplier = 2
|
||||
|
||||
# The maximum allowed disk usage size in bytes of staging deals not yet
|
||||
# passed to the sealing node by the markets service. 0 is unlimited.
|
||||
#
|
||||
# type: int64
|
||||
# env var: LOTUS_DEALMAKING_MAXSTAGINGDEALSBYTES
|
||||
#MaxStagingDealsBytes = 0
|
||||
|
||||
# The maximum number of parallel online data transfers for storage deals
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_DEALMAKING_SIMULTANEOUSTRANSFERSFORSTORAGE
|
||||
#SimultaneousTransfersForStorage = 20
|
||||
|
||||
# The maximum number of parallel online data transfers for retrieval deals
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_DEALMAKING_SIMULTANEOUSTRANSFERSFORRETRIEVAL
|
||||
#SimultaneousTransfersForRetrieval = 20
|
||||
|
||||
# Minimum start epoch buffer to give time for sealing of sector with deal.
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_DEALMAKING_STARTEPOCHSEALINGBUFFER
|
||||
#StartEpochSealingBuffer = 480
|
||||
|
||||
# A command used for fine-grained evaluation of storage deals
|
||||
# see https://docs.filecoin.io/mine/lotus/miner-configuration/#using-filters-for-fine-grained-storage-and-retrieval-deal-acceptance for more details
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_DEALMAKING_FILTER
|
||||
#Filter = ""
|
||||
|
||||
# A command used for fine-grained evaluation of retrieval deals
|
||||
# see https://docs.filecoin.io/mine/lotus/miner-configuration/#using-filters-for-fine-grained-storage-and-retrieval-deal-acceptance for more details
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_DEALMAKING_RETRIEVALFILTER
|
||||
#RetrievalFilter = ""
|
||||
|
||||
[Dealmaking.RetrievalPricing]
|
||||
# env var: LOTUS_DEALMAKING_RETRIEVALPRICING_STRATEGY
|
||||
#Strategy = "default"
|
||||
|
||||
[Dealmaking.RetrievalPricing.Default]
|
||||
# env var: LOTUS_DEALMAKING_RETRIEVALPRICING_DEFAULT_VERIFIEDDEALSFREETRANSFER
|
||||
#VerifiedDealsFreeTransfer = true
|
||||
|
||||
[Dealmaking.RetrievalPricing.External]
|
||||
# env var: LOTUS_DEALMAKING_RETRIEVALPRICING_EXTERNAL_PATH
|
||||
#Path = ""
|
||||
|
||||
|
||||
[Sealing]
|
||||
# Upper bound on how many sectors can be waiting for more deals to be packed in it before it begins sealing at any given time.
|
||||
# If the miner is accepting multiple deals in parallel, up to MaxWaitDealsSectors of new sectors will be created.
|
||||
# If more than MaxWaitDealsSectors deals are accepted in parallel, only MaxWaitDealsSectors deals will be processed in parallel
|
||||
# Note that setting this number too high in relation to deal ingestion rate may result in poor sector packing efficiency
|
||||
# 0 = no limit
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_SEALING_MAXWAITDEALSSECTORS
|
||||
#MaxWaitDealsSectors = 2
|
||||
|
||||
# Upper bound on how many sectors can be sealing at the same time when creating new CC sectors (0 = unlimited)
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_SEALING_MAXSEALINGSECTORS
|
||||
#MaxSealingSectors = 0
|
||||
|
||||
# Upper bound on how many sectors can be sealing at the same time when creating new sectors with deals (0 = unlimited)
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_SEALING_MAXSEALINGSECTORSFORDEALS
|
||||
#MaxSealingSectorsForDeals = 0
|
||||
|
||||
# CommittedCapacitySectorLifetime is the duration a Committed Capacity (CC) sector will
|
||||
# live before it must be extended or converted into sector containing deals before it is
|
||||
# terminated. Value must be between 180-540 days inclusive
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_SEALING_COMMITTEDCAPACITYSECTORLIFETIME
|
||||
#CommittedCapacitySectorLifetime = "12960h0m0s"
|
||||
|
||||
# Period of time that a newly created sector will wait for more deals to be packed in to before it starts to seal.
|
||||
# Sectors which are fully filled will start sealing immediately
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_SEALING_WAITDEALSDELAY
|
||||
#WaitDealsDelay = "6h0m0s"
|
||||
|
||||
# Whether to keep unsealed copies of deal data regardless of whether the client requested that. This lets the miner
|
||||
# avoid the relatively high cost of unsealing the data later, at the cost of more storage space
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_SEALING_ALWAYSKEEPUNSEALEDCOPY
|
||||
#AlwaysKeepUnsealedCopy = true
|
||||
|
||||
# Run sector finalization before submitting sector proof to the chain
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_SEALING_FINALIZEEARLY
|
||||
#FinalizeEarly = false
|
||||
|
||||
# Whether to use available miner balance for sector collateral instead of sending it with each message
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_SEALING_COLLATERALFROMMINERBALANCE
|
||||
#CollateralFromMinerBalance = false
|
||||
|
||||
# Minimum available balance to keep in the miner actor before sending it with messages
|
||||
#
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_SEALING_AVAILABLEBALANCEBUFFER
|
||||
#AvailableBalanceBuffer = "0 FIL"
|
||||
|
||||
# Don't send collateral with messages even if there is no available balance in the miner actor
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_SEALING_DISABLECOLLATERALFALLBACK
|
||||
#DisableCollateralFallback = false
|
||||
|
||||
# enable / disable precommit batching (takes effect after nv13)
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_SEALING_BATCHPRECOMMITS
|
||||
#BatchPreCommits = true
|
||||
|
||||
# maximum precommit batch size - batches will be sent immediately above this size
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_SEALING_MAXPRECOMMITBATCH
|
||||
#MaxPreCommitBatch = 256
|
||||
|
||||
# how long to wait before submitting a batch after crossing the minimum batch size
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_SEALING_PRECOMMITBATCHWAIT
|
||||
#PreCommitBatchWait = "24h0m0s"
|
||||
|
||||
# time buffer for forceful batch submission before sectors/deal in batch would start expiring
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_SEALING_PRECOMMITBATCHSLACK
|
||||
#PreCommitBatchSlack = "3h0m0s"
|
||||
|
||||
# enable / disable commit aggregation (takes effect after nv13)
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_SEALING_AGGREGATECOMMITS
|
||||
#AggregateCommits = true
|
||||
|
||||
# maximum batched commit size - batches will be sent immediately above this size
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_SEALING_MINCOMMITBATCH
|
||||
#MinCommitBatch = 4
|
||||
|
||||
# type: int
|
||||
# env var: LOTUS_SEALING_MAXCOMMITBATCH
|
||||
#MaxCommitBatch = 819
|
||||
|
||||
# how long to wait before submitting a batch after crossing the minimum batch size
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_SEALING_COMMITBATCHWAIT
|
||||
#CommitBatchWait = "24h0m0s"
|
||||
|
||||
# time buffer for forceful batch submission before sectors/deals in batch would start expiring
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_SEALING_COMMITBATCHSLACK
|
||||
#CommitBatchSlack = "1h0m0s"
|
||||
|
||||
# network BaseFee below which to stop doing precommit batching, instead
|
||||
# sending precommit messages to the chain individually
|
||||
#
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_SEALING_BATCHPRECOMMITABOVEBASEFEE
|
||||
#BatchPreCommitAboveBaseFee = "0.00000000032 FIL"
|
||||
|
||||
# network BaseFee below which to stop doing commit aggregation, instead
|
||||
# submitting proofs to the chain individually
|
||||
#
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_SEALING_AGGREGATEABOVEBASEFEE
|
||||
#AggregateAboveBaseFee = "0.00000000032 FIL"
|
||||
|
||||
# type: uint64
|
||||
# env var: LOTUS_SEALING_TERMINATEBATCHMAX
|
||||
#TerminateBatchMax = 100
|
||||
|
||||
# type: uint64
|
||||
# env var: LOTUS_SEALING_TERMINATEBATCHMIN
|
||||
#TerminateBatchMin = 1
|
||||
|
||||
# type: Duration
|
||||
# env var: LOTUS_SEALING_TERMINATEBATCHWAIT
|
||||
#TerminateBatchWait = "5m0s"
|
||||
|
||||
|
||||
[Storage]
|
||||
# env var: LOTUS_STORAGE_PARALLELFETCHLIMIT
|
||||
#ParallelFetchLimit = 10
|
||||
|
||||
# env var: LOTUS_STORAGE_ALLOWADDPIECE
|
||||
#AllowAddPiece = true
|
||||
|
||||
# env var: LOTUS_STORAGE_ALLOWPRECOMMIT1
|
||||
#AllowPreCommit1 = true
|
||||
|
||||
# env var: LOTUS_STORAGE_ALLOWPRECOMMIT2
|
||||
#AllowPreCommit2 = true
|
||||
|
||||
# env var: LOTUS_STORAGE_ALLOWCOMMIT
|
||||
#AllowCommit = true
|
||||
|
||||
# env var: LOTUS_STORAGE_ALLOWUNSEAL
|
||||
#AllowUnseal = true
|
||||
|
||||
# env var: LOTUS_STORAGE_RESOURCEFILTERING
|
||||
#ResourceFiltering = "hardware"
|
||||
|
||||
|
||||
[Fees]
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_FEES_MAXPRECOMMITGASFEE
|
||||
#MaxPreCommitGasFee = "0.025 FIL"
|
||||
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_FEES_MAXCOMMITGASFEE
|
||||
#MaxCommitGasFee = "0.05 FIL"
|
||||
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_FEES_MAXTERMINATEGASFEE
|
||||
#MaxTerminateGasFee = "0.5 FIL"
|
||||
|
||||
# WindowPoSt is a high-value operation, so the default fee should be high.
|
||||
#
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_FEES_MAXWINDOWPOSTGASFEE
|
||||
#MaxWindowPoStGasFee = "5 FIL"
|
||||
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_FEES_MAXPUBLISHDEALSFEE
|
||||
#MaxPublishDealsFee = "0.05 FIL"
|
||||
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_FEES_MAXMARKETBALANCEADDFEE
|
||||
#MaxMarketBalanceAddFee = "0.007 FIL"
|
||||
|
||||
[Fees.MaxPreCommitBatchGasFee]
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_FEES_MAXPRECOMMITBATCHGASFEE_BASE
|
||||
#Base = "0 FIL"
|
||||
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_FEES_MAXPRECOMMITBATCHGASFEE_PERSECTOR
|
||||
#PerSector = "0.02 FIL"
|
||||
|
||||
[Fees.MaxCommitBatchGasFee]
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_FEES_MAXCOMMITBATCHGASFEE_BASE
|
||||
#Base = "0 FIL"
|
||||
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_FEES_MAXCOMMITBATCHGASFEE_PERSECTOR
|
||||
#PerSector = "0.03 FIL"
|
||||
|
||||
|
||||
[Addresses]
|
||||
# Addresses to send PreCommit messages from
|
||||
#
|
||||
# type: []string
|
||||
# env var: LOTUS_ADDRESSES_PRECOMMITCONTROL
|
||||
#PreCommitControl = []
|
||||
|
||||
# Addresses to send Commit messages from
|
||||
#
|
||||
# type: []string
|
||||
# env var: LOTUS_ADDRESSES_COMMITCONTROL
|
||||
#CommitControl = []
|
||||
|
||||
# type: []string
|
||||
# env var: LOTUS_ADDRESSES_TERMINATECONTROL
|
||||
#TerminateControl = []
|
||||
|
||||
# type: []string
|
||||
# env var: LOTUS_ADDRESSES_DEALPUBLISHCONTROL
|
||||
#DealPublishControl = []
|
||||
|
||||
# DisableOwnerFallback disables usage of the owner address for messages
|
||||
# sent automatically
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_ADDRESSES_DISABLEOWNERFALLBACK
|
||||
#DisableOwnerFallback = false
|
||||
|
||||
# DisableWorkerFallback disables usage of the worker address for messages
|
||||
# sent automatically, if control addresses are configured.
|
||||
# A control address that doesn't have enough funds will still be chosen
|
||||
# over the worker address if this flag is set.
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_ADDRESSES_DISABLEWORKERFALLBACK
|
||||
#DisableWorkerFallback = false
|
||||
|
||||
|
||||
[DAGStore]
|
||||
# Path to the dagstore root directory. This directory contains three
|
||||
# subdirectories, which can be symlinked to alternative locations if
|
||||
# need be:
|
||||
# - ./transients: caches unsealed deals that have been fetched from the
|
||||
# storage subsystem for serving retrievals.
|
||||
# - ./indices: stores shard indices.
|
||||
# - ./datastore: holds the KV store tracking the state of every shard
|
||||
# known to the DAG store.
|
||||
# Default value: <LOTUS_MARKETS_PATH>/dagstore (split deployment) or
|
||||
# <LOTUS_MINER_PATH>/dagstore (monolith deployment)
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_DAGSTORE_ROOTDIR
|
||||
#RootDir = ""
|
||||
|
||||
# The maximum amount of indexing jobs that can run simultaneously.
|
||||
# 0 means unlimited.
|
||||
# Default value: 5.
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_DAGSTORE_MAXCONCURRENTINDEX
|
||||
#MaxConcurrentIndex = 5
|
||||
|
||||
# The maximum amount of unsealed deals that can be fetched simultaneously
|
||||
# from the storage subsystem. 0 means unlimited.
|
||||
# Default value: 0 (unlimited).
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_DAGSTORE_MAXCONCURRENTREADYFETCHES
|
||||
#MaxConcurrentReadyFetches = 0
|
||||
|
||||
# The maximum number of simultaneous inflight API calls to the storage
|
||||
# subsystem.
|
||||
# Default value: 100.
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_DAGSTORE_MAXCONCURRENCYSTORAGECALLS
|
||||
#MaxConcurrencyStorageCalls = 100
|
||||
|
||||
# The time between calls to periodic dagstore GC, in time.Duration string
|
||||
# representation, e.g. 1m, 5m, 1h.
|
||||
# Default value: 1 minute.
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_DAGSTORE_GCINTERVAL
|
||||
#GCInterval = "1m0s"
|
||||
|
||||
|
||||
@@ -3,17 +3,11 @@
|
||||
- [ ] Import new actors
|
||||
- [ ] Define upgrade heights in `build/params_`
|
||||
- [ ] Generate adapters
|
||||
- [ ] Add the new version in `chain/actors/agen/main.go`
|
||||
- [ ] Update `gen/inlinegen-data.json`
|
||||
- [ ] Update `chain/actors/version.go`
|
||||
- [ ] Update adapter code in `chain/actors/builtin` if needed
|
||||
- [ ] Update `chain/actors/policy/policy.go`
|
||||
- [ ] Update `chain/actors/version.go`
|
||||
- [ ] Register in `chain/vm/invoker.go`
|
||||
- [ ] Register in `chain/vm/mkactor.go`
|
||||
- [ ] Update `chain/types/state.go`
|
||||
- [ ] Update `chain/state/statetree.go` (New / Load)
|
||||
- [ ] Update `chain/stmgr/forks.go`
|
||||
- [ ] Run `make actors-gen`
|
||||
- [ ] Update `chain/consensus/filcns/upgrades.go`
|
||||
- [ ] Schedule
|
||||
- [ ] Migration
|
||||
- [ ] Update upgrade schedule in `api/test/test.go` and `chain/sync_test.go`
|
||||
- [ ] Update `NewestNetworkVersion` in `build/params_shared_vals.go`
|
||||
- [ ] Register in init in `chain/stmgr/utils.go`
|
||||
- [ ] Update upgrade schedule in `chain/sync_test.go`
|
||||
|
||||
Vendored
+1
-1
Submodule extern/filecoin-ffi updated: dc585c4860...7912389334
+2
-1
@@ -622,7 +622,8 @@ func requireFDsClosed(t *testing.T, start int) {
|
||||
}
|
||||
|
||||
log.Infow("open FDs", "start", start, "now", openNow)
|
||||
require.Equal(t, start, openNow, "FDs shouldn't leak")
|
||||
// todo make work with cuda somehow
|
||||
// require.Equal(t, start, openNow, "FDs shouldn't leak")
|
||||
}
|
||||
|
||||
func TestGenerateUnsealedCID(t *testing.T) {
|
||||
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package fsutil
|
||||
|
||||
import (
|
||||
|
||||
Vendored
+3
-3
@@ -588,13 +588,13 @@ func (m *Manager) Remove(ctx context.Context, sector storage.SectorRef) error {
|
||||
|
||||
var err error
|
||||
|
||||
if rerr := m.storage.Remove(ctx, sector.ID, storiface.FTSealed, true); rerr != nil {
|
||||
if rerr := m.storage.Remove(ctx, sector.ID, storiface.FTSealed, true, nil); rerr != nil {
|
||||
err = multierror.Append(err, xerrors.Errorf("removing sector (sealed): %w", rerr))
|
||||
}
|
||||
if rerr := m.storage.Remove(ctx, sector.ID, storiface.FTCache, true); rerr != nil {
|
||||
if rerr := m.storage.Remove(ctx, sector.ID, storiface.FTCache, true, nil); rerr != nil {
|
||||
err = multierror.Append(err, xerrors.Errorf("removing sector (cache): %w", rerr))
|
||||
}
|
||||
if rerr := m.storage.Remove(ctx, sector.ID, storiface.FTUnsealed, true); rerr != nil {
|
||||
if rerr := m.storage.Remove(ctx, sector.ID, storiface.FTUnsealed, true, nil); rerr != nil {
|
||||
err = multierror.Append(err, xerrors.Errorf("removing sector (unsealed): %w", rerr))
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -298,7 +298,7 @@ func (p *pieceProviderTestHarness) addRemoteWorker(t *testing.T, tasks []sealtas
|
||||
func (p *pieceProviderTestHarness) removeAllUnsealedSectorFiles(t *testing.T) {
|
||||
for i := range p.localStores {
|
||||
ls := p.localStores[i]
|
||||
require.NoError(t, ls.Remove(p.ctx, p.sector.ID, storiface.FTUnsealed, false))
|
||||
require.NoError(t, ls.Remove(p.ctx, p.sector.ID, storiface.FTUnsealed, false, nil))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+9
-7
@@ -78,12 +78,12 @@ type workerHandle struct {
|
||||
|
||||
info storiface.WorkerInfo
|
||||
|
||||
preparing *activeResources
|
||||
active *activeResources
|
||||
preparing *activeResources // use with workerHandle.lk
|
||||
active *activeResources // use with workerHandle.lk
|
||||
|
||||
lk sync.Mutex
|
||||
lk sync.Mutex // can be taken inside sched.workersLk.RLock
|
||||
|
||||
wndLk sync.Mutex
|
||||
wndLk sync.Mutex // can be taken inside sched.workersLk.RLock
|
||||
activeWindows []*schedWindow
|
||||
|
||||
enabled bool
|
||||
@@ -117,7 +117,8 @@ type activeResources struct {
|
||||
gpuUsed bool
|
||||
cpuUse uint64
|
||||
|
||||
cond *sync.Cond
|
||||
cond *sync.Cond
|
||||
waiting int
|
||||
}
|
||||
|
||||
type workerRequest struct {
|
||||
@@ -154,8 +155,9 @@ func newScheduler() *scheduler {
|
||||
schedQueue: &requestQueue{},
|
||||
|
||||
workTracker: &workTracker{
|
||||
done: map[storiface.CallID]struct{}{},
|
||||
running: map[storiface.CallID]trackedWork{},
|
||||
done: map[storiface.CallID]struct{}{},
|
||||
running: map[storiface.CallID]trackedWork{},
|
||||
prepared: map[uuid.UUID]trackedWork{},
|
||||
},
|
||||
|
||||
info: make(chan func(interface{})),
|
||||
|
||||
+11
-3
@@ -11,7 +11,9 @@ func (a *activeResources) withResources(id WorkerID, wr storiface.WorkerInfo, r
|
||||
if a.cond == nil {
|
||||
a.cond = sync.NewCond(locker)
|
||||
}
|
||||
a.waiting++
|
||||
a.cond.Wait()
|
||||
a.waiting--
|
||||
}
|
||||
|
||||
a.add(wr.Resources, r)
|
||||
@@ -19,13 +21,15 @@ func (a *activeResources) withResources(id WorkerID, wr storiface.WorkerInfo, r
|
||||
err := cb()
|
||||
|
||||
a.free(wr.Resources, r)
|
||||
if a.cond != nil {
|
||||
a.cond.Broadcast()
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// must be called with the same lock as the one passed to withResources
|
||||
func (a *activeResources) hasWorkWaiting() bool {
|
||||
return a.waiting > 0
|
||||
}
|
||||
|
||||
func (a *activeResources) add(wr storiface.WorkerResources, r Resources) {
|
||||
if r.CanGPU {
|
||||
a.gpuUsed = true
|
||||
@@ -42,6 +46,10 @@ func (a *activeResources) free(wr storiface.WorkerResources, r Resources) {
|
||||
a.cpuUse -= r.Threads(wr.CPUs)
|
||||
a.memUsedMin -= r.MinMemory
|
||||
a.memUsedMax -= r.MaxMemory
|
||||
|
||||
if a.cond != nil {
|
||||
a.cond.Broadcast()
|
||||
}
|
||||
}
|
||||
|
||||
// canHandleRequest evaluates if the worker has enough available resources to
|
||||
|
||||
+132
-14
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/sealtasks"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||
@@ -338,6 +339,11 @@ func (sw *schedWorker) workerCompactWindows() {
|
||||
}
|
||||
|
||||
func (sw *schedWorker) processAssignedWindows() {
|
||||
sw.assignReadyWork()
|
||||
sw.assignPreparingWork()
|
||||
}
|
||||
|
||||
func (sw *schedWorker) assignPreparingWork() {
|
||||
worker := sw.worker
|
||||
|
||||
assignLoop:
|
||||
@@ -366,7 +372,7 @@ assignLoop:
|
||||
todo := firstWindow.todo[tidx]
|
||||
|
||||
log.Debugf("assign worker sector %d", todo.sector.ID.Number)
|
||||
err := sw.startProcessingTask(sw.taskDone, todo)
|
||||
err := sw.startProcessingTask(todo)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("startProcessingTask error: %+v", err)
|
||||
@@ -387,7 +393,67 @@ assignLoop:
|
||||
}
|
||||
}
|
||||
|
||||
func (sw *schedWorker) startProcessingTask(taskDone chan struct{}, req *workerRequest) error {
|
||||
func (sw *schedWorker) assignReadyWork() {
|
||||
worker := sw.worker
|
||||
|
||||
worker.lk.Lock()
|
||||
defer worker.lk.Unlock()
|
||||
|
||||
if worker.active.hasWorkWaiting() {
|
||||
// prepared tasks have priority
|
||||
return
|
||||
}
|
||||
|
||||
assignLoop:
|
||||
// process windows in order
|
||||
for len(worker.activeWindows) > 0 {
|
||||
firstWindow := worker.activeWindows[0]
|
||||
|
||||
// process tasks within a window, preferring tasks at lower indexes
|
||||
for len(firstWindow.todo) > 0 {
|
||||
tidx := -1
|
||||
|
||||
for t, todo := range firstWindow.todo {
|
||||
if todo.taskType != sealtasks.TTCommit1 && todo.taskType != sealtasks.TTCommit2 { // todo put in task
|
||||
continue
|
||||
}
|
||||
|
||||
needRes := ResourceTable[todo.taskType][todo.sector.ProofType]
|
||||
if worker.active.canHandleRequest(needRes, sw.wid, "startPreparing", worker.info) {
|
||||
tidx = t
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if tidx == -1 {
|
||||
break assignLoop
|
||||
}
|
||||
|
||||
todo := firstWindow.todo[tidx]
|
||||
|
||||
log.Debugf("assign worker sector %d (ready)", todo.sector.ID.Number)
|
||||
err := sw.startProcessingReadyTask(todo)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("startProcessingTask error: %+v", err)
|
||||
go todo.respond(xerrors.Errorf("startProcessingTask error: %w", err))
|
||||
}
|
||||
|
||||
// Note: we're not freeing window.allocated resources here very much on purpose
|
||||
copy(firstWindow.todo[tidx:], firstWindow.todo[tidx+1:])
|
||||
firstWindow.todo[len(firstWindow.todo)-1] = nil
|
||||
firstWindow.todo = firstWindow.todo[:len(firstWindow.todo)-1]
|
||||
}
|
||||
|
||||
copy(worker.activeWindows, worker.activeWindows[1:])
|
||||
worker.activeWindows[len(worker.activeWindows)-1] = nil
|
||||
worker.activeWindows = worker.activeWindows[:len(worker.activeWindows)-1]
|
||||
|
||||
sw.windowsRequested--
|
||||
}
|
||||
}
|
||||
|
||||
func (sw *schedWorker) startProcessingTask(req *workerRequest) error {
|
||||
w, sh := sw.worker, sw.sched
|
||||
|
||||
needRes := ResourceTable[req.taskType][req.sector.ProofType]
|
||||
@@ -398,19 +464,20 @@ func (sw *schedWorker) startProcessingTask(taskDone chan struct{}, req *workerRe
|
||||
|
||||
go func() {
|
||||
// first run the prepare step (e.g. fetching sector data from other worker)
|
||||
err := req.prepare(req.ctx, sh.workTracker.worker(sw.wid, w.info, w.workerRpc))
|
||||
sh.workersLk.Lock()
|
||||
tw := sh.workTracker.worker(sw.wid, w.info, w.workerRpc)
|
||||
tw.start()
|
||||
err := req.prepare(req.ctx, tw)
|
||||
w.lk.Lock()
|
||||
|
||||
if err != nil {
|
||||
w.lk.Lock()
|
||||
w.preparing.free(w.info.Resources, needRes)
|
||||
w.lk.Unlock()
|
||||
sh.workersLk.Unlock()
|
||||
|
||||
select {
|
||||
case taskDone <- struct{}{}:
|
||||
case sw.taskDone <- struct{}{}:
|
||||
case <-sh.closing:
|
||||
log.Warnf("scheduler closed while sending response (prepare error: %+v)", err)
|
||||
default: // there is a notification pending already
|
||||
}
|
||||
|
||||
select {
|
||||
@@ -423,21 +490,29 @@ func (sw *schedWorker) startProcessingTask(taskDone chan struct{}, req *workerRe
|
||||
return
|
||||
}
|
||||
|
||||
tw = sh.workTracker.worker(sw.wid, w.info, w.workerRpc)
|
||||
|
||||
// start tracking work first early in case we need to wait for resources
|
||||
werr := make(chan error, 1)
|
||||
go func() {
|
||||
werr <- req.work(req.ctx, tw)
|
||||
}()
|
||||
|
||||
// wait (if needed) for resources in the 'active' window
|
||||
err = w.active.withResources(sw.wid, w.info, needRes, &sh.workersLk, func() error {
|
||||
w.lk.Lock()
|
||||
err = w.active.withResources(sw.wid, w.info, needRes, &w.lk, func() error {
|
||||
w.preparing.free(w.info.Resources, needRes)
|
||||
w.lk.Unlock()
|
||||
sh.workersLk.Unlock()
|
||||
defer sh.workersLk.Lock() // we MUST return locked from this function
|
||||
defer w.lk.Lock() // we MUST return locked from this function
|
||||
|
||||
select {
|
||||
case taskDone <- struct{}{}:
|
||||
case sw.taskDone <- struct{}{}:
|
||||
case <-sh.closing:
|
||||
default: // there is a notification pending already
|
||||
}
|
||||
|
||||
// Do the work!
|
||||
err = req.work(req.ctx, sh.workTracker.worker(sw.wid, w.info, w.workerRpc))
|
||||
tw.start()
|
||||
err = <-werr
|
||||
|
||||
select {
|
||||
case req.ret <- workerResponse{err: err}:
|
||||
@@ -450,7 +525,7 @@ func (sw *schedWorker) startProcessingTask(taskDone chan struct{}, req *workerRe
|
||||
return nil
|
||||
})
|
||||
|
||||
sh.workersLk.Unlock()
|
||||
w.lk.Unlock()
|
||||
|
||||
// This error should always be nil, since nothing is setting it, but just to be safe:
|
||||
if err != nil {
|
||||
@@ -461,6 +536,49 @@ func (sw *schedWorker) startProcessingTask(taskDone chan struct{}, req *workerRe
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sw *schedWorker) startProcessingReadyTask(req *workerRequest) error {
|
||||
w, sh := sw.worker, sw.sched
|
||||
|
||||
needRes := ResourceTable[req.taskType][req.sector.ProofType]
|
||||
|
||||
w.active.add(w.info.Resources, needRes)
|
||||
|
||||
go func() {
|
||||
// Do the work!
|
||||
tw := sh.workTracker.worker(sw.wid, w.info, w.workerRpc)
|
||||
tw.start()
|
||||
err := req.work(req.ctx, tw)
|
||||
|
||||
select {
|
||||
case req.ret <- workerResponse{err: err}:
|
||||
case <-req.ctx.Done():
|
||||
log.Warnf("request got cancelled before we could respond")
|
||||
case <-sh.closing:
|
||||
log.Warnf("scheduler closed while sending response")
|
||||
}
|
||||
|
||||
w.lk.Lock()
|
||||
|
||||
w.active.free(w.info.Resources, needRes)
|
||||
|
||||
select {
|
||||
case sw.taskDone <- struct{}{}:
|
||||
case <-sh.closing:
|
||||
log.Warnf("scheduler closed while sending response (prepare error: %+v)", err)
|
||||
default: // there is a notification pending already
|
||||
}
|
||||
|
||||
w.lk.Unlock()
|
||||
|
||||
// This error should always be nil, since nothing is setting it, but just to be safe:
|
||||
if err != nil {
|
||||
log.Errorf("error executing worker (ready): %+v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sh *scheduler) workerCleanup(wid WorkerID, w *workerHandle) {
|
||||
select {
|
||||
case <-w.closingMgr:
|
||||
|
||||
Vendored
+10
-2
@@ -15,6 +15,7 @@ func (m *Manager) WorkerStats() map[uuid.UUID]storiface.WorkerStats {
|
||||
out := map[uuid.UUID]storiface.WorkerStats{}
|
||||
|
||||
for id, handle := range m.sched.workers {
|
||||
handle.lk.Lock()
|
||||
out[uuid.UUID(id)] = storiface.WorkerStats{
|
||||
Info: handle.info,
|
||||
Enabled: handle.enabled,
|
||||
@@ -24,6 +25,7 @@ func (m *Manager) WorkerStats() map[uuid.UUID]storiface.WorkerStats {
|
||||
GpuUsed: handle.active.gpuUsed,
|
||||
CpuUse: handle.active.cpuUse,
|
||||
}
|
||||
handle.lk.Unlock()
|
||||
}
|
||||
|
||||
return out
|
||||
@@ -33,7 +35,13 @@ func (m *Manager) WorkerJobs() map[uuid.UUID][]storiface.WorkerJob {
|
||||
out := map[uuid.UUID][]storiface.WorkerJob{}
|
||||
calls := map[storiface.CallID]struct{}{}
|
||||
|
||||
for _, t := range m.sched.workTracker.Running() {
|
||||
running, preparing := m.sched.workTracker.Running()
|
||||
|
||||
for _, t := range running {
|
||||
out[uuid.UUID(t.worker)] = append(out[uuid.UUID(t.worker)], t.job)
|
||||
calls[t.job.ID] = struct{}{}
|
||||
}
|
||||
for _, t := range preparing {
|
||||
out[uuid.UUID(t.worker)] = append(out[uuid.UUID(t.worker)], t.job)
|
||||
calls[t.job.ID] = struct{}{}
|
||||
}
|
||||
@@ -48,7 +56,7 @@ func (m *Manager) WorkerJobs() map[uuid.UUID][]storiface.WorkerJob {
|
||||
ID: storiface.UndefCall,
|
||||
Sector: request.sector.ID,
|
||||
Task: request.taskType,
|
||||
RunWait: wi + 1,
|
||||
RunWait: wi + 2,
|
||||
Start: request.start,
|
||||
})
|
||||
}
|
||||
|
||||
+4
-4
@@ -21,9 +21,9 @@ import (
|
||||
|
||||
var log = logging.Logger("stores")
|
||||
|
||||
var _ partialFileHandler = &DefaultPartialFileHandler{}
|
||||
var _ PartialFileHandler = &DefaultPartialFileHandler{}
|
||||
|
||||
// DefaultPartialFileHandler is the default implementation of the partialFileHandler interface.
|
||||
// DefaultPartialFileHandler is the default implementation of the PartialFileHandler interface.
|
||||
// This is probably the only implementation we'll ever use because the purpose of the
|
||||
// interface to is to mock out partial file related functionality during testing.
|
||||
type DefaultPartialFileHandler struct{}
|
||||
@@ -46,7 +46,7 @@ func (d *DefaultPartialFileHandler) Close(pf *partialfile.PartialFile) error {
|
||||
|
||||
type FetchHandler struct {
|
||||
Local Store
|
||||
PfHandler partialFileHandler
|
||||
PfHandler PartialFileHandler
|
||||
}
|
||||
|
||||
func (handler *FetchHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // /remote/
|
||||
@@ -179,7 +179,7 @@ func (handler *FetchHandler) remoteDeleteSector(w http.ResponseWriter, r *http.R
|
||||
return
|
||||
}
|
||||
|
||||
if err := handler.Local.Remove(r.Context(), id, ft, false); err != nil {
|
||||
if err := handler.Local.Remove(r.Context(), id, ft, false, []ID{ID(r.FormValue("keep"))}); err != nil {
|
||||
log.Errorf("%+v", err)
|
||||
w.WriteHeader(500)
|
||||
return
|
||||
|
||||
+7
-7
@@ -63,7 +63,7 @@ func TestRemoteGetAllocated(t *testing.T) {
|
||||
tcs := map[string]struct {
|
||||
piFnc func(pi *pieceInfo)
|
||||
storeFnc func(s *mocks.MockStore)
|
||||
pfFunc func(s *mocks.MockpartialFileHandler)
|
||||
pfFunc func(s *mocks.MockPartialFileHandler)
|
||||
|
||||
// expectation
|
||||
expectedStatusCode int
|
||||
@@ -129,7 +129,7 @@ func TestRemoteGetAllocated(t *testing.T) {
|
||||
storiface.SectorPaths{}, nil).Times(1)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
pf.EXPECT().OpenPartialFile(abi.PaddedPieceSize(sectorSize), pfPath).Return(&partialfile.PartialFile{},
|
||||
xerrors.New("some error")).Times(1)
|
||||
},
|
||||
@@ -146,7 +146,7 @@ func TestRemoteGetAllocated(t *testing.T) {
|
||||
storiface.SectorPaths{}, nil).Times(1)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
pf.EXPECT().OpenPartialFile(abi.PaddedPieceSize(sectorSize), pfPath).Return(emptyPartialFile,
|
||||
nil).Times(1)
|
||||
|
||||
@@ -165,7 +165,7 @@ func TestRemoteGetAllocated(t *testing.T) {
|
||||
storiface.SectorPaths{}, nil).Times(1)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
pf.EXPECT().OpenPartialFile(abi.PaddedPieceSize(sectorSize), pfPath).Return(emptyPartialFile,
|
||||
nil).Times(1)
|
||||
|
||||
@@ -184,7 +184,7 @@ func TestRemoteGetAllocated(t *testing.T) {
|
||||
storiface.SectorPaths{}, nil).Times(1)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
pf.EXPECT().OpenPartialFile(abi.PaddedPieceSize(sectorSize), pfPath).Return(emptyPartialFile,
|
||||
nil).Times(1)
|
||||
|
||||
@@ -203,7 +203,7 @@ func TestRemoteGetAllocated(t *testing.T) {
|
||||
defer mockCtrl.Finish()
|
||||
|
||||
lstore := mocks.NewMockStore(mockCtrl)
|
||||
pfhandler := mocks.NewMockpartialFileHandler(mockCtrl)
|
||||
pfhandler := mocks.NewMockPartialFileHandler(mockCtrl)
|
||||
|
||||
handler := &stores.FetchHandler{
|
||||
lstore,
|
||||
@@ -371,7 +371,7 @@ func TestRemoteGetSector(t *testing.T) {
|
||||
// when test is done, assert expectations on all mock objects.
|
||||
defer mockCtrl.Finish()
|
||||
lstore := mocks.NewMockStore(mockCtrl)
|
||||
pfhandler := mocks.NewMockpartialFileHandler(mockCtrl)
|
||||
pfhandler := mocks.NewMockPartialFileHandler(mockCtrl)
|
||||
|
||||
var path string
|
||||
|
||||
|
||||
+24
@@ -10,6 +10,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go.opencensus.io/stats"
|
||||
"go.opencensus.io/tag"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
@@ -17,6 +19,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
|
||||
"github.com/filecoin-project/lotus/metrics"
|
||||
)
|
||||
|
||||
var HeartbeatInterval = 10 * time.Second
|
||||
@@ -52,6 +55,8 @@ type SectorStorageInfo struct {
|
||||
Primary bool
|
||||
}
|
||||
|
||||
//go:generate go run github.com/golang/mock/mockgen -destination=mocks/index.go -package=mocks . SectorIndex
|
||||
|
||||
type SectorIndex interface { // part of storage-miner api
|
||||
StorageAttach(context.Context, StorageInfo, fsutil.FsStat) error
|
||||
StorageInfo(context.Context, ID) (StorageInfo, error)
|
||||
@@ -192,6 +197,25 @@ func (i *Index) StorageReportHealth(ctx context.Context, id ID, report HealthRep
|
||||
}
|
||||
ent.lastHeartbeat = time.Now()
|
||||
|
||||
if report.Stat.Capacity > 0 {
|
||||
ctx, _ = tag.New(ctx, tag.Upsert(metrics.StorageID, string(id)))
|
||||
|
||||
stats.Record(ctx, metrics.StorageFSAvailable.M(float64(report.Stat.FSAvailable)/float64(report.Stat.Capacity)))
|
||||
stats.Record(ctx, metrics.StorageAvailable.M(float64(report.Stat.Available)/float64(report.Stat.Capacity)))
|
||||
stats.Record(ctx, metrics.StorageReserved.M(float64(report.Stat.Reserved)/float64(report.Stat.Capacity)))
|
||||
|
||||
stats.Record(ctx, metrics.StorageCapacityBytes.M(report.Stat.Capacity))
|
||||
stats.Record(ctx, metrics.StorageFSAvailableBytes.M(report.Stat.FSAvailable))
|
||||
stats.Record(ctx, metrics.StorageAvailableBytes.M(report.Stat.Available))
|
||||
stats.Record(ctx, metrics.StorageReservedBytes.M(report.Stat.Reserved))
|
||||
|
||||
if report.Stat.Max > 0 {
|
||||
stats.Record(ctx, metrics.StorageLimitUsed.M(float64(report.Stat.Used)/float64(report.Stat.Max)))
|
||||
stats.Record(ctx, metrics.StorageLimitUsedBytes.M(report.Stat.Used))
|
||||
stats.Record(ctx, metrics.StorageLimitMaxBytes.M(report.Stat.Max))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -13,8 +13,10 @@ import (
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/golang/mock/mockgen -destination=mocks/pf.go -package=mocks . PartialFileHandler
|
||||
|
||||
// PartialFileHandler helps mock out the partial file functionality during testing.
|
||||
type partialFileHandler interface {
|
||||
type PartialFileHandler interface {
|
||||
// OpenPartialFile opens and returns a partial file at the given path and also verifies it has the given
|
||||
// size
|
||||
OpenPartialFile(maxPieceSize abi.PaddedPieceSize, path string) (*partialfile.PartialFile, error)
|
||||
@@ -30,9 +32,11 @@ type partialFileHandler interface {
|
||||
Close(pf *partialfile.PartialFile) error
|
||||
}
|
||||
|
||||
//go:generate go run github.com/golang/mock/mockgen -destination=mocks/store.go -package=mocks . Store
|
||||
|
||||
type Store interface {
|
||||
AcquireSector(ctx context.Context, s storage.SectorRef, existing storiface.SectorFileType, allocate storiface.SectorFileType, sealing storiface.PathType, op storiface.AcquireMode) (paths storiface.SectorPaths, stores storiface.SectorPaths, err error)
|
||||
Remove(ctx context.Context, s abi.SectorID, types storiface.SectorFileType, force bool) error
|
||||
Remove(ctx context.Context, s abi.SectorID, types storiface.SectorFileType, force bool, keepIn []ID) error
|
||||
|
||||
// like remove, but doesn't remove the primary sector copy, nor the last
|
||||
// non-primary copy if there no primary copies
|
||||
|
||||
+8
-1
@@ -544,7 +544,7 @@ func (st *Local) Local(ctx context.Context) ([]StoragePath, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (st *Local) Remove(ctx context.Context, sid abi.SectorID, typ storiface.SectorFileType, force bool) error {
|
||||
func (st *Local) Remove(ctx context.Context, sid abi.SectorID, typ storiface.SectorFileType, force bool, keepIn []ID) error {
|
||||
if bits.OnesCount(uint(typ)) != 1 {
|
||||
return xerrors.New("delete expects one file type")
|
||||
}
|
||||
@@ -558,7 +558,14 @@ func (st *Local) Remove(ctx context.Context, sid abi.SectorID, typ storiface.Sec
|
||||
return xerrors.Errorf("can't delete sector %v(%d), not found", sid, typ)
|
||||
}
|
||||
|
||||
storeLoop:
|
||||
for _, info := range si {
|
||||
for _, id := range keepIn {
|
||||
if id == info.ID {
|
||||
continue storeLoop
|
||||
}
|
||||
}
|
||||
|
||||
if err := st.removeSector(ctx, sid, typ, info.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+29
-29
@@ -1,5 +1,5 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: index.go
|
||||
// Source: github.com/filecoin-project/lotus/extern/sector-storage/stores (interfaces: SectorIndex)
|
||||
|
||||
// Package mocks is a generated GoMock package.
|
||||
package mocks
|
||||
@@ -53,61 +53,61 @@ func (mr *MockSectorIndexMockRecorder) StorageAttach(arg0, arg1, arg2 interface{
|
||||
}
|
||||
|
||||
// StorageBestAlloc mocks base method.
|
||||
func (m *MockSectorIndex) StorageBestAlloc(ctx context.Context, allocate storiface.SectorFileType, ssize abi.SectorSize, pathType storiface.PathType) ([]stores.StorageInfo, error) {
|
||||
func (m *MockSectorIndex) StorageBestAlloc(arg0 context.Context, arg1 storiface.SectorFileType, arg2 abi.SectorSize, arg3 storiface.PathType) ([]stores.StorageInfo, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StorageBestAlloc", ctx, allocate, ssize, pathType)
|
||||
ret := m.ctrl.Call(m, "StorageBestAlloc", arg0, arg1, arg2, arg3)
|
||||
ret0, _ := ret[0].([]stores.StorageInfo)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// StorageBestAlloc indicates an expected call of StorageBestAlloc.
|
||||
func (mr *MockSectorIndexMockRecorder) StorageBestAlloc(ctx, allocate, ssize, pathType interface{}) *gomock.Call {
|
||||
func (mr *MockSectorIndexMockRecorder) StorageBestAlloc(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageBestAlloc", reflect.TypeOf((*MockSectorIndex)(nil).StorageBestAlloc), ctx, allocate, ssize, pathType)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageBestAlloc", reflect.TypeOf((*MockSectorIndex)(nil).StorageBestAlloc), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// StorageDeclareSector mocks base method.
|
||||
func (m *MockSectorIndex) StorageDeclareSector(ctx context.Context, storageID stores.ID, s abi.SectorID, ft storiface.SectorFileType, primary bool) error {
|
||||
func (m *MockSectorIndex) StorageDeclareSector(arg0 context.Context, arg1 stores.ID, arg2 abi.SectorID, arg3 storiface.SectorFileType, arg4 bool) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StorageDeclareSector", ctx, storageID, s, ft, primary)
|
||||
ret := m.ctrl.Call(m, "StorageDeclareSector", arg0, arg1, arg2, arg3, arg4)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// StorageDeclareSector indicates an expected call of StorageDeclareSector.
|
||||
func (mr *MockSectorIndexMockRecorder) StorageDeclareSector(ctx, storageID, s, ft, primary interface{}) *gomock.Call {
|
||||
func (mr *MockSectorIndexMockRecorder) StorageDeclareSector(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageDeclareSector", reflect.TypeOf((*MockSectorIndex)(nil).StorageDeclareSector), ctx, storageID, s, ft, primary)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageDeclareSector", reflect.TypeOf((*MockSectorIndex)(nil).StorageDeclareSector), arg0, arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
// StorageDropSector mocks base method.
|
||||
func (m *MockSectorIndex) StorageDropSector(ctx context.Context, storageID stores.ID, s abi.SectorID, ft storiface.SectorFileType) error {
|
||||
func (m *MockSectorIndex) StorageDropSector(arg0 context.Context, arg1 stores.ID, arg2 abi.SectorID, arg3 storiface.SectorFileType) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StorageDropSector", ctx, storageID, s, ft)
|
||||
ret := m.ctrl.Call(m, "StorageDropSector", arg0, arg1, arg2, arg3)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// StorageDropSector indicates an expected call of StorageDropSector.
|
||||
func (mr *MockSectorIndexMockRecorder) StorageDropSector(ctx, storageID, s, ft interface{}) *gomock.Call {
|
||||
func (mr *MockSectorIndexMockRecorder) StorageDropSector(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageDropSector", reflect.TypeOf((*MockSectorIndex)(nil).StorageDropSector), ctx, storageID, s, ft)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageDropSector", reflect.TypeOf((*MockSectorIndex)(nil).StorageDropSector), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// StorageFindSector mocks base method.
|
||||
func (m *MockSectorIndex) StorageFindSector(ctx context.Context, sector abi.SectorID, ft storiface.SectorFileType, ssize abi.SectorSize, allowFetch bool) ([]stores.SectorStorageInfo, error) {
|
||||
func (m *MockSectorIndex) StorageFindSector(arg0 context.Context, arg1 abi.SectorID, arg2 storiface.SectorFileType, arg3 abi.SectorSize, arg4 bool) ([]stores.SectorStorageInfo, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StorageFindSector", ctx, sector, ft, ssize, allowFetch)
|
||||
ret := m.ctrl.Call(m, "StorageFindSector", arg0, arg1, arg2, arg3, arg4)
|
||||
ret0, _ := ret[0].([]stores.SectorStorageInfo)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// StorageFindSector indicates an expected call of StorageFindSector.
|
||||
func (mr *MockSectorIndexMockRecorder) StorageFindSector(ctx, sector, ft, ssize, allowFetch interface{}) *gomock.Call {
|
||||
func (mr *MockSectorIndexMockRecorder) StorageFindSector(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageFindSector", reflect.TypeOf((*MockSectorIndex)(nil).StorageFindSector), ctx, sector, ft, ssize, allowFetch)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageFindSector", reflect.TypeOf((*MockSectorIndex)(nil).StorageFindSector), arg0, arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
// StorageInfo mocks base method.
|
||||
@@ -126,32 +126,32 @@ func (mr *MockSectorIndexMockRecorder) StorageInfo(arg0, arg1 interface{}) *gomo
|
||||
}
|
||||
|
||||
// StorageList mocks base method.
|
||||
func (m *MockSectorIndex) StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error) {
|
||||
func (m *MockSectorIndex) StorageList(arg0 context.Context) (map[stores.ID][]stores.Decl, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StorageList", ctx)
|
||||
ret := m.ctrl.Call(m, "StorageList", arg0)
|
||||
ret0, _ := ret[0].(map[stores.ID][]stores.Decl)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// StorageList indicates an expected call of StorageList.
|
||||
func (mr *MockSectorIndexMockRecorder) StorageList(ctx interface{}) *gomock.Call {
|
||||
func (mr *MockSectorIndexMockRecorder) StorageList(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageList", reflect.TypeOf((*MockSectorIndex)(nil).StorageList), ctx)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageList", reflect.TypeOf((*MockSectorIndex)(nil).StorageList), arg0)
|
||||
}
|
||||
|
||||
// StorageLock mocks base method.
|
||||
func (m *MockSectorIndex) StorageLock(ctx context.Context, sector abi.SectorID, read, write storiface.SectorFileType) error {
|
||||
func (m *MockSectorIndex) StorageLock(arg0 context.Context, arg1 abi.SectorID, arg2, arg3 storiface.SectorFileType) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StorageLock", ctx, sector, read, write)
|
||||
ret := m.ctrl.Call(m, "StorageLock", arg0, arg1, arg2, arg3)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// StorageLock indicates an expected call of StorageLock.
|
||||
func (mr *MockSectorIndexMockRecorder) StorageLock(ctx, sector, read, write interface{}) *gomock.Call {
|
||||
func (mr *MockSectorIndexMockRecorder) StorageLock(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageLock", reflect.TypeOf((*MockSectorIndex)(nil).StorageLock), ctx, sector, read, write)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageLock", reflect.TypeOf((*MockSectorIndex)(nil).StorageLock), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// StorageReportHealth mocks base method.
|
||||
@@ -169,16 +169,16 @@ func (mr *MockSectorIndexMockRecorder) StorageReportHealth(arg0, arg1, arg2 inte
|
||||
}
|
||||
|
||||
// StorageTryLock mocks base method.
|
||||
func (m *MockSectorIndex) StorageTryLock(ctx context.Context, sector abi.SectorID, read, write storiface.SectorFileType) (bool, error) {
|
||||
func (m *MockSectorIndex) StorageTryLock(arg0 context.Context, arg1 abi.SectorID, arg2, arg3 storiface.SectorFileType) (bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StorageTryLock", ctx, sector, read, write)
|
||||
ret := m.ctrl.Call(m, "StorageTryLock", arg0, arg1, arg2, arg3)
|
||||
ret0, _ := ret[0].(bool)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// StorageTryLock indicates an expected call of StorageTryLock.
|
||||
func (mr *MockSectorIndexMockRecorder) StorageTryLock(ctx, sector, read, write interface{}) *gomock.Call {
|
||||
func (mr *MockSectorIndexMockRecorder) StorageTryLock(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageTryLock", reflect.TypeOf((*MockSectorIndex)(nil).StorageTryLock), ctx, sector, read, write)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageTryLock", reflect.TypeOf((*MockSectorIndex)(nil).StorageTryLock), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/filecoin-project/lotus/extern/sector-storage/stores (interfaces: PartialFileHandler)
|
||||
|
||||
// Package mocks is a generated GoMock package.
|
||||
package mocks
|
||||
|
||||
import (
|
||||
os "os"
|
||||
reflect "reflect"
|
||||
|
||||
abi "github.com/filecoin-project/go-state-types/abi"
|
||||
partialfile "github.com/filecoin-project/lotus/extern/sector-storage/partialfile"
|
||||
storiface "github.com/filecoin-project/lotus/extern/sector-storage/storiface"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockPartialFileHandler is a mock of PartialFileHandler interface.
|
||||
type MockPartialFileHandler struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockPartialFileHandlerMockRecorder
|
||||
}
|
||||
|
||||
// MockPartialFileHandlerMockRecorder is the mock recorder for MockPartialFileHandler.
|
||||
type MockPartialFileHandlerMockRecorder struct {
|
||||
mock *MockPartialFileHandler
|
||||
}
|
||||
|
||||
// NewMockPartialFileHandler creates a new mock instance.
|
||||
func NewMockPartialFileHandler(ctrl *gomock.Controller) *MockPartialFileHandler {
|
||||
mock := &MockPartialFileHandler{ctrl: ctrl}
|
||||
mock.recorder = &MockPartialFileHandlerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockPartialFileHandler) EXPECT() *MockPartialFileHandlerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Close mocks base method.
|
||||
func (m *MockPartialFileHandler) Close(arg0 *partialfile.PartialFile) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Close", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Close indicates an expected call of Close.
|
||||
func (mr *MockPartialFileHandlerMockRecorder) Close(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockPartialFileHandler)(nil).Close), arg0)
|
||||
}
|
||||
|
||||
// HasAllocated mocks base method.
|
||||
func (m *MockPartialFileHandler) HasAllocated(arg0 *partialfile.PartialFile, arg1 storiface.UnpaddedByteIndex, arg2 abi.UnpaddedPieceSize) (bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HasAllocated", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(bool)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// HasAllocated indicates an expected call of HasAllocated.
|
||||
func (mr *MockPartialFileHandlerMockRecorder) HasAllocated(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasAllocated", reflect.TypeOf((*MockPartialFileHandler)(nil).HasAllocated), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// OpenPartialFile mocks base method.
|
||||
func (m *MockPartialFileHandler) OpenPartialFile(arg0 abi.PaddedPieceSize, arg1 string) (*partialfile.PartialFile, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "OpenPartialFile", arg0, arg1)
|
||||
ret0, _ := ret[0].(*partialfile.PartialFile)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// OpenPartialFile indicates an expected call of OpenPartialFile.
|
||||
func (mr *MockPartialFileHandlerMockRecorder) OpenPartialFile(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OpenPartialFile", reflect.TypeOf((*MockPartialFileHandler)(nil).OpenPartialFile), arg0, arg1)
|
||||
}
|
||||
|
||||
// Reader mocks base method.
|
||||
func (m *MockPartialFileHandler) Reader(arg0 *partialfile.PartialFile, arg1 storiface.PaddedByteIndex, arg2 abi.PaddedPieceSize) (*os.File, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Reader", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(*os.File)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Reader indicates an expected call of Reader.
|
||||
func (mr *MockPartialFileHandlerMockRecorder) Reader(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reader", reflect.TypeOf((*MockPartialFileHandler)(nil).Reader), arg0, arg1, arg2)
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/filecoin-project/lotus/extern/sector-storage/stores (interfaces: Store)
|
||||
|
||||
// Package mocks is a generated GoMock package.
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
abi "github.com/filecoin-project/go-state-types/abi"
|
||||
fsutil "github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
||||
stores "github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||
storiface "github.com/filecoin-project/lotus/extern/sector-storage/storiface"
|
||||
storage "github.com/filecoin-project/specs-storage/storage"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockStore is a mock of Store interface.
|
||||
type MockStore struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockStoreMockRecorder
|
||||
}
|
||||
|
||||
// MockStoreMockRecorder is the mock recorder for MockStore.
|
||||
type MockStoreMockRecorder struct {
|
||||
mock *MockStore
|
||||
}
|
||||
|
||||
// NewMockStore creates a new mock instance.
|
||||
func NewMockStore(ctrl *gomock.Controller) *MockStore {
|
||||
mock := &MockStore{ctrl: ctrl}
|
||||
mock.recorder = &MockStoreMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockStore) EXPECT() *MockStoreMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// AcquireSector mocks base method.
|
||||
func (m *MockStore) AcquireSector(arg0 context.Context, arg1 storage.SectorRef, arg2, arg3 storiface.SectorFileType, arg4 storiface.PathType, arg5 storiface.AcquireMode) (storiface.SectorPaths, storiface.SectorPaths, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AcquireSector", arg0, arg1, arg2, arg3, arg4, arg5)
|
||||
ret0, _ := ret[0].(storiface.SectorPaths)
|
||||
ret1, _ := ret[1].(storiface.SectorPaths)
|
||||
ret2, _ := ret[2].(error)
|
||||
return ret0, ret1, ret2
|
||||
}
|
||||
|
||||
// AcquireSector indicates an expected call of AcquireSector.
|
||||
func (mr *MockStoreMockRecorder) AcquireSector(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AcquireSector", reflect.TypeOf((*MockStore)(nil).AcquireSector), arg0, arg1, arg2, arg3, arg4, arg5)
|
||||
}
|
||||
|
||||
// FsStat mocks base method.
|
||||
func (m *MockStore) FsStat(arg0 context.Context, arg1 stores.ID) (fsutil.FsStat, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "FsStat", arg0, arg1)
|
||||
ret0, _ := ret[0].(fsutil.FsStat)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// FsStat indicates an expected call of FsStat.
|
||||
func (mr *MockStoreMockRecorder) FsStat(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FsStat", reflect.TypeOf((*MockStore)(nil).FsStat), arg0, arg1)
|
||||
}
|
||||
|
||||
// MoveStorage mocks base method.
|
||||
func (m *MockStore) MoveStorage(arg0 context.Context, arg1 storage.SectorRef, arg2 storiface.SectorFileType) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MoveStorage", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MoveStorage indicates an expected call of MoveStorage.
|
||||
func (mr *MockStoreMockRecorder) MoveStorage(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MoveStorage", reflect.TypeOf((*MockStore)(nil).MoveStorage), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// Remove mocks base method.
|
||||
func (m *MockStore) Remove(arg0 context.Context, arg1 abi.SectorID, arg2 storiface.SectorFileType, arg3 bool, arg4 []stores.ID) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Remove", arg0, arg1, arg2, arg3, arg4)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Remove indicates an expected call of Remove.
|
||||
func (mr *MockStoreMockRecorder) Remove(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Remove", reflect.TypeOf((*MockStore)(nil).Remove), arg0, arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
// RemoveCopies mocks base method.
|
||||
func (m *MockStore) RemoveCopies(arg0 context.Context, arg1 abi.SectorID, arg2 storiface.SectorFileType) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RemoveCopies", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// RemoveCopies indicates an expected call of RemoveCopies.
|
||||
func (mr *MockStoreMockRecorder) RemoveCopies(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveCopies", reflect.TypeOf((*MockStore)(nil).RemoveCopies), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// Reserve mocks base method.
|
||||
func (m *MockStore) Reserve(arg0 context.Context, arg1 storage.SectorRef, arg2 storiface.SectorFileType, arg3 storiface.SectorPaths, arg4 map[storiface.SectorFileType]int) (func(), error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Reserve", arg0, arg1, arg2, arg3, arg4)
|
||||
ret0, _ := ret[0].(func())
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Reserve indicates an expected call of Reserve.
|
||||
func (mr *MockStoreMockRecorder) Reserve(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reserve", reflect.TypeOf((*MockStore)(nil).Reserve), arg0, arg1, arg2, arg3, arg4)
|
||||
}
|
||||
-212
@@ -1,212 +0,0 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: interface.go
|
||||
|
||||
// Package mocks is a generated GoMock package.
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
os "os"
|
||||
reflect "reflect"
|
||||
|
||||
abi "github.com/filecoin-project/go-state-types/abi"
|
||||
fsutil "github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
||||
partialfile "github.com/filecoin-project/lotus/extern/sector-storage/partialfile"
|
||||
stores "github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||
storiface "github.com/filecoin-project/lotus/extern/sector-storage/storiface"
|
||||
storage "github.com/filecoin-project/specs-storage/storage"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockpartialFileHandler is a mock of partialFileHandler interface.
|
||||
type MockpartialFileHandler struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockpartialFileHandlerMockRecorder
|
||||
}
|
||||
|
||||
// MockpartialFileHandlerMockRecorder is the mock recorder for MockpartialFileHandler.
|
||||
type MockpartialFileHandlerMockRecorder struct {
|
||||
mock *MockpartialFileHandler
|
||||
}
|
||||
|
||||
// NewMockpartialFileHandler creates a new mock instance.
|
||||
func NewMockpartialFileHandler(ctrl *gomock.Controller) *MockpartialFileHandler {
|
||||
mock := &MockpartialFileHandler{ctrl: ctrl}
|
||||
mock.recorder = &MockpartialFileHandlerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockpartialFileHandler) EXPECT() *MockpartialFileHandlerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Close mocks base method.
|
||||
func (m *MockpartialFileHandler) Close(pf *partialfile.PartialFile) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Close", pf)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Close indicates an expected call of Close.
|
||||
func (mr *MockpartialFileHandlerMockRecorder) Close(pf interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockpartialFileHandler)(nil).Close), pf)
|
||||
}
|
||||
|
||||
// HasAllocated mocks base method.
|
||||
func (m *MockpartialFileHandler) HasAllocated(pf *partialfile.PartialFile, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HasAllocated", pf, offset, size)
|
||||
ret0, _ := ret[0].(bool)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// HasAllocated indicates an expected call of HasAllocated.
|
||||
func (mr *MockpartialFileHandlerMockRecorder) HasAllocated(pf, offset, size interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasAllocated", reflect.TypeOf((*MockpartialFileHandler)(nil).HasAllocated), pf, offset, size)
|
||||
}
|
||||
|
||||
// OpenPartialFile mocks base method.
|
||||
func (m *MockpartialFileHandler) OpenPartialFile(maxPieceSize abi.PaddedPieceSize, path string) (*partialfile.PartialFile, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "OpenPartialFile", maxPieceSize, path)
|
||||
ret0, _ := ret[0].(*partialfile.PartialFile)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// OpenPartialFile indicates an expected call of OpenPartialFile.
|
||||
func (mr *MockpartialFileHandlerMockRecorder) OpenPartialFile(maxPieceSize, path interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OpenPartialFile", reflect.TypeOf((*MockpartialFileHandler)(nil).OpenPartialFile), maxPieceSize, path)
|
||||
}
|
||||
|
||||
// Reader mocks base method.
|
||||
func (m *MockpartialFileHandler) Reader(pf *partialfile.PartialFile, offset storiface.PaddedByteIndex, size abi.PaddedPieceSize) (*os.File, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Reader", pf, offset, size)
|
||||
ret0, _ := ret[0].(*os.File)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Reader indicates an expected call of Reader.
|
||||
func (mr *MockpartialFileHandlerMockRecorder) Reader(pf, offset, size interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reader", reflect.TypeOf((*MockpartialFileHandler)(nil).Reader), pf, offset, size)
|
||||
}
|
||||
|
||||
// MockStore is a mock of Store interface.
|
||||
type MockStore struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockStoreMockRecorder
|
||||
}
|
||||
|
||||
// MockStoreMockRecorder is the mock recorder for MockStore.
|
||||
type MockStoreMockRecorder struct {
|
||||
mock *MockStore
|
||||
}
|
||||
|
||||
// NewMockStore creates a new mock instance.
|
||||
func NewMockStore(ctrl *gomock.Controller) *MockStore {
|
||||
mock := &MockStore{ctrl: ctrl}
|
||||
mock.recorder = &MockStoreMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockStore) EXPECT() *MockStoreMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// AcquireSector mocks base method.
|
||||
func (m *MockStore) AcquireSector(ctx context.Context, s storage.SectorRef, existing, allocate storiface.SectorFileType, sealing storiface.PathType, op storiface.AcquireMode) (storiface.SectorPaths, storiface.SectorPaths, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AcquireSector", ctx, s, existing, allocate, sealing, op)
|
||||
ret0, _ := ret[0].(storiface.SectorPaths)
|
||||
ret1, _ := ret[1].(storiface.SectorPaths)
|
||||
ret2, _ := ret[2].(error)
|
||||
return ret0, ret1, ret2
|
||||
}
|
||||
|
||||
// AcquireSector indicates an expected call of AcquireSector.
|
||||
func (mr *MockStoreMockRecorder) AcquireSector(ctx, s, existing, allocate, sealing, op interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AcquireSector", reflect.TypeOf((*MockStore)(nil).AcquireSector), ctx, s, existing, allocate, sealing, op)
|
||||
}
|
||||
|
||||
// FsStat mocks base method.
|
||||
func (m *MockStore) FsStat(ctx context.Context, id stores.ID) (fsutil.FsStat, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "FsStat", ctx, id)
|
||||
ret0, _ := ret[0].(fsutil.FsStat)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// FsStat indicates an expected call of FsStat.
|
||||
func (mr *MockStoreMockRecorder) FsStat(ctx, id interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FsStat", reflect.TypeOf((*MockStore)(nil).FsStat), ctx, id)
|
||||
}
|
||||
|
||||
// MoveStorage mocks base method.
|
||||
func (m *MockStore) MoveStorage(ctx context.Context, s storage.SectorRef, types storiface.SectorFileType) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MoveStorage", ctx, s, types)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MoveStorage indicates an expected call of MoveStorage.
|
||||
func (mr *MockStoreMockRecorder) MoveStorage(ctx, s, types interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MoveStorage", reflect.TypeOf((*MockStore)(nil).MoveStorage), ctx, s, types)
|
||||
}
|
||||
|
||||
// Remove mocks base method.
|
||||
func (m *MockStore) Remove(ctx context.Context, s abi.SectorID, types storiface.SectorFileType, force bool) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Remove", ctx, s, types, force)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Remove indicates an expected call of Remove.
|
||||
func (mr *MockStoreMockRecorder) Remove(ctx, s, types, force interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Remove", reflect.TypeOf((*MockStore)(nil).Remove), ctx, s, types, force)
|
||||
}
|
||||
|
||||
// RemoveCopies mocks base method.
|
||||
func (m *MockStore) RemoveCopies(ctx context.Context, s abi.SectorID, types storiface.SectorFileType) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RemoveCopies", ctx, s, types)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// RemoveCopies indicates an expected call of RemoveCopies.
|
||||
func (mr *MockStoreMockRecorder) RemoveCopies(ctx, s, types interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveCopies", reflect.TypeOf((*MockStore)(nil).RemoveCopies), ctx, s, types)
|
||||
}
|
||||
|
||||
// Reserve mocks base method.
|
||||
func (m *MockStore) Reserve(ctx context.Context, sid storage.SectorRef, ft storiface.SectorFileType, storageIDs storiface.SectorPaths, overheadTab map[storiface.SectorFileType]int) (func(), error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Reserve", ctx, sid, ft, storageIDs, overheadTab)
|
||||
ret0, _ := ret[0].(func())
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Reserve indicates an expected call of Reserve.
|
||||
func (mr *MockStoreMockRecorder) Reserve(ctx, sid, ft, storageIDs, overheadTab interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reserve", reflect.TypeOf((*MockStore)(nil).Reserve), ctx, sid, ft, storageIDs, overheadTab)
|
||||
}
|
||||
+18
-7
@@ -41,7 +41,7 @@ type Remote struct {
|
||||
fetchLk sync.Mutex
|
||||
fetching map[abi.SectorID]chan struct{}
|
||||
|
||||
pfHandler partialFileHandler
|
||||
pfHandler PartialFileHandler
|
||||
}
|
||||
|
||||
func (r *Remote) RemoveCopies(ctx context.Context, s abi.SectorID, types storiface.SectorFileType) error {
|
||||
@@ -52,7 +52,7 @@ func (r *Remote) RemoveCopies(ctx context.Context, s abi.SectorID, types storifa
|
||||
return r.local.RemoveCopies(ctx, s, types)
|
||||
}
|
||||
|
||||
func NewRemote(local Store, index SectorIndex, auth http.Header, fetchLimit int, pfHandler partialFileHandler) *Remote {
|
||||
func NewRemote(local Store, index SectorIndex, auth http.Header, fetchLimit int, pfHandler PartialFileHandler) *Remote {
|
||||
return &Remote{
|
||||
local: local,
|
||||
index: index,
|
||||
@@ -155,7 +155,8 @@ func (r *Remote) AcquireSector(ctx context.Context, s storage.SectorRef, existin
|
||||
}
|
||||
|
||||
if op == storiface.AcquireMove {
|
||||
if err := r.deleteFromRemote(ctx, url); err != nil {
|
||||
id := ID(storageID)
|
||||
if err := r.deleteFromRemote(ctx, url, &id); err != nil {
|
||||
log.Warnf("deleting sector %v from %s (delete %s): %+v", s, storageID, url, err)
|
||||
}
|
||||
}
|
||||
@@ -333,12 +334,12 @@ func (r *Remote) MoveStorage(ctx context.Context, s storage.SectorRef, types sto
|
||||
return r.local.MoveStorage(ctx, s, types)
|
||||
}
|
||||
|
||||
func (r *Remote) Remove(ctx context.Context, sid abi.SectorID, typ storiface.SectorFileType, force bool) error {
|
||||
func (r *Remote) Remove(ctx context.Context, sid abi.SectorID, typ storiface.SectorFileType, force bool, keepIn []ID) error {
|
||||
if bits.OnesCount(uint(typ)) != 1 {
|
||||
return xerrors.New("delete expects one file type")
|
||||
}
|
||||
|
||||
if err := r.local.Remove(ctx, sid, typ, force); err != nil {
|
||||
if err := r.local.Remove(ctx, sid, typ, force, keepIn); err != nil {
|
||||
return xerrors.Errorf("remove from local: %w", err)
|
||||
}
|
||||
|
||||
@@ -347,9 +348,15 @@ func (r *Remote) Remove(ctx context.Context, sid abi.SectorID, typ storiface.Sec
|
||||
return xerrors.Errorf("finding existing sector %d(t:%d) failed: %w", sid, typ, err)
|
||||
}
|
||||
|
||||
storeLoop:
|
||||
for _, info := range si {
|
||||
for _, id := range keepIn {
|
||||
if id == info.ID {
|
||||
continue storeLoop
|
||||
}
|
||||
}
|
||||
for _, url := range info.URLs {
|
||||
if err := r.deleteFromRemote(ctx, url); err != nil {
|
||||
if err := r.deleteFromRemote(ctx, url, nil); err != nil {
|
||||
log.Warnf("remove %s: %+v", url, err)
|
||||
continue
|
||||
}
|
||||
@@ -360,7 +367,11 @@ func (r *Remote) Remove(ctx context.Context, sid abi.SectorID, typ storiface.Sec
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Remote) deleteFromRemote(ctx context.Context, url string) error {
|
||||
func (r *Remote) deleteFromRemote(ctx context.Context, url string, keepIn *ID) error {
|
||||
if keepIn != nil {
|
||||
url = url + "?keep=" + string(*keepIn)
|
||||
}
|
||||
|
||||
log.Infof("Delete %s", url)
|
||||
|
||||
req, err := http.NewRequest("DELETE", url, nil)
|
||||
|
||||
+155
-25
@@ -2,26 +2,156 @@ package stores_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/google/uuid"
|
||||
"github.com/gorilla/mux"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/partialfile"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/stores/mocks"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
"github.com/filecoin-project/specs-storage/storage"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/gorilla/mux"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
const metaFile = "sectorstore.json"
|
||||
|
||||
func createTestStorage(t *testing.T, p string, seal bool, att ...*stores.Local) stores.ID {
|
||||
if err := os.MkdirAll(p, 0755); err != nil {
|
||||
if !os.IsExist(err) {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
cfg := &stores.LocalStorageMeta{
|
||||
ID: stores.ID(uuid.New().String()),
|
||||
Weight: 10,
|
||||
CanSeal: seal,
|
||||
CanStore: !seal,
|
||||
}
|
||||
|
||||
b, err := json.MarshalIndent(cfg, "", " ")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, ioutil.WriteFile(filepath.Join(p, metaFile), b, 0644))
|
||||
|
||||
for _, s := range att {
|
||||
require.NoError(t, s.OpenPath(context.Background(), p))
|
||||
}
|
||||
|
||||
return cfg.ID
|
||||
}
|
||||
|
||||
func TestMoveShared(t *testing.T) {
|
||||
logging.SetAllLoggers(logging.LevelDebug)
|
||||
|
||||
index := stores.NewIndex()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
dir, err := ioutil.TempDir("", "stores-remote-test-")
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
_ = os.RemoveAll(dir)
|
||||
})
|
||||
|
||||
openRepo := func(dir string) repo.LockedRepo {
|
||||
r, err := repo.NewFS(dir)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, r.Init(repo.Worker))
|
||||
lr, err := r.Lock(repo.Worker)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
_ = lr.Close()
|
||||
})
|
||||
|
||||
err = lr.SetStorage(func(config *stores.StorageConfig) {
|
||||
*config = stores.StorageConfig{}
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
return lr
|
||||
}
|
||||
|
||||
// setup two repos with two storage paths:
|
||||
// repo 1 with both paths
|
||||
// repo 2 with one path (shared)
|
||||
|
||||
lr1 := openRepo(filepath.Join(dir, "l1"))
|
||||
lr2 := openRepo(filepath.Join(dir, "l2"))
|
||||
|
||||
mux1 := mux.NewRouter()
|
||||
mux2 := mux.NewRouter()
|
||||
hs1 := httptest.NewServer(mux1)
|
||||
hs2 := httptest.NewServer(mux2)
|
||||
|
||||
ls1, err := stores.NewLocal(ctx, lr1, index, []string{hs1.URL + "/remote"})
|
||||
require.NoError(t, err)
|
||||
ls2, err := stores.NewLocal(ctx, lr2, index, []string{hs2.URL + "/remote"})
|
||||
require.NoError(t, err)
|
||||
|
||||
dirStor := filepath.Join(dir, "stor")
|
||||
dirSeal := filepath.Join(dir, "seal")
|
||||
|
||||
id1 := createTestStorage(t, dirStor, false, ls1, ls2)
|
||||
id2 := createTestStorage(t, dirSeal, true, ls1)
|
||||
|
||||
rs1 := stores.NewRemote(ls1, index, nil, 20, &stores.DefaultPartialFileHandler{})
|
||||
rs2 := stores.NewRemote(ls2, index, nil, 20, &stores.DefaultPartialFileHandler{})
|
||||
_ = rs2
|
||||
mux1.PathPrefix("/").Handler(&stores.FetchHandler{Local: ls1, PfHandler: &stores.DefaultPartialFileHandler{}})
|
||||
mux2.PathPrefix("/").Handler(&stores.FetchHandler{Local: ls2, PfHandler: &stores.DefaultPartialFileHandler{}})
|
||||
|
||||
// add a sealed replica file to the sealing (non-shared) path
|
||||
|
||||
s1ref := storage.SectorRef{
|
||||
ID: abi.SectorID{
|
||||
Miner: 12,
|
||||
Number: 1,
|
||||
},
|
||||
ProofType: abi.RegisteredSealProof_StackedDrg2KiBV1,
|
||||
}
|
||||
|
||||
sp, sid, err := rs1.AcquireSector(ctx, s1ref, storiface.FTNone, storiface.FTSealed, storiface.PathSealing, storiface.AcquireMove)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, id2, stores.ID(sid.Sealed))
|
||||
|
||||
data := make([]byte, 2032)
|
||||
data[1] = 54
|
||||
require.NoError(t, ioutil.WriteFile(sp.Sealed, data, 0666))
|
||||
fmt.Println("write to ", sp.Sealed)
|
||||
|
||||
require.NoError(t, index.StorageDeclareSector(ctx, stores.ID(sid.Sealed), s1ref.ID, storiface.FTSealed, true))
|
||||
|
||||
// move to the shared path from the second node (remote move / delete)
|
||||
|
||||
require.NoError(t, rs2.MoveStorage(ctx, s1ref, storiface.FTSealed))
|
||||
|
||||
// check that the file still exists
|
||||
sp, sid, err = rs2.AcquireSector(ctx, s1ref, storiface.FTSealed, storiface.FTNone, storiface.PathStorage, storiface.AcquireMove)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, id1, stores.ID(sid.Sealed))
|
||||
fmt.Println("read from ", sp.Sealed)
|
||||
|
||||
read, err := ioutil.ReadFile(sp.Sealed)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, data, read)
|
||||
}
|
||||
|
||||
func TestReader(t *testing.T) {
|
||||
logging.SetAllLoggers(logging.LevelDebug)
|
||||
bz := []byte("Hello World")
|
||||
@@ -46,7 +176,7 @@ func TestReader(t *testing.T) {
|
||||
|
||||
tcs := map[string]struct {
|
||||
storeFnc func(s *mocks.MockStore)
|
||||
pfFunc func(s *mocks.MockpartialFileHandler)
|
||||
pfFunc func(s *mocks.MockPartialFileHandler)
|
||||
indexFnc func(s *mocks.MockSectorIndex, serverURL string)
|
||||
|
||||
needHttpServer bool
|
||||
@@ -76,7 +206,7 @@ func TestReader(t *testing.T) {
|
||||
mockSectorAcquire(l, sectorRef, pfPath, nil)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
mockPartialFileOpen(pf, sectorSize, pfPath, xerrors.New("pf open error"))
|
||||
},
|
||||
errStr: "pf open error",
|
||||
@@ -87,7 +217,7 @@ func TestReader(t *testing.T) {
|
||||
mockSectorAcquire(l, sectorRef, pfPath, nil)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
mockPartialFileOpen(pf, sectorSize, pfPath, nil)
|
||||
mockCheckAllocation(pf, offset, size, emptyPartialFile,
|
||||
true, xerrors.New("piece check error"))
|
||||
@@ -101,7 +231,7 @@ func TestReader(t *testing.T) {
|
||||
mockSectorAcquire(l, sectorRef, pfPath, nil)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
mockPartialFileOpen(pf, sectorSize, pfPath, nil)
|
||||
mockCheckAllocation(pf, offset, size, emptyPartialFile,
|
||||
false, nil)
|
||||
@@ -115,7 +245,7 @@ func TestReader(t *testing.T) {
|
||||
mockSectorAcquire(l, sectorRef, pfPath, nil)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
mockPartialFileOpen(pf, sectorSize, pfPath, nil)
|
||||
mockCheckAllocation(pf, offset, size, emptyPartialFile,
|
||||
true, nil)
|
||||
@@ -157,7 +287,7 @@ func TestReader(t *testing.T) {
|
||||
mockSectorAcquire(l, sectorRef, pfPath, nil)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
mockPartialFileOpen(pf, sectorSize, pfPath, nil)
|
||||
mockCheckAllocation(pf, offset, size, emptyPartialFile,
|
||||
false, nil)
|
||||
@@ -223,7 +353,7 @@ func TestReader(t *testing.T) {
|
||||
mockSectorAcquire(l, sectorRef, pfPath, nil)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
mockPartialFileOpen(pf, sectorSize, pfPath, nil)
|
||||
mockCheckAllocation(pf, offset, size, emptyPartialFile,
|
||||
true, nil)
|
||||
@@ -251,7 +381,7 @@ func TestReader(t *testing.T) {
|
||||
mockSectorAcquire(l, sectorRef, pfPath, nil)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
mockPartialFileOpen(pf, sectorSize, pfPath, nil)
|
||||
mockCheckAllocation(pf, offset, size, emptyPartialFile,
|
||||
false, nil)
|
||||
@@ -308,7 +438,7 @@ func TestReader(t *testing.T) {
|
||||
|
||||
// create them mocks
|
||||
lstore := mocks.NewMockStore(mockCtrl)
|
||||
pfhandler := mocks.NewMockpartialFileHandler(mockCtrl)
|
||||
pfhandler := mocks.NewMockPartialFileHandler(mockCtrl)
|
||||
index := mocks.NewMockSectorIndex(mockCtrl)
|
||||
|
||||
if tc.storeFnc != nil {
|
||||
@@ -393,7 +523,7 @@ func TestCheckIsUnsealed(t *testing.T) {
|
||||
|
||||
tcs := map[string]struct {
|
||||
storeFnc func(s *mocks.MockStore)
|
||||
pfFunc func(s *mocks.MockpartialFileHandler)
|
||||
pfFunc func(s *mocks.MockPartialFileHandler)
|
||||
indexFnc func(s *mocks.MockSectorIndex, serverURL string)
|
||||
|
||||
needHttpServer bool
|
||||
@@ -421,7 +551,7 @@ func TestCheckIsUnsealed(t *testing.T) {
|
||||
mockSectorAcquire(l, sectorRef, pfPath, nil)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
mockPartialFileOpen(pf, sectorSize, pfPath, xerrors.New("pf open error"))
|
||||
},
|
||||
errStr: "pf open error",
|
||||
@@ -432,7 +562,7 @@ func TestCheckIsUnsealed(t *testing.T) {
|
||||
mockSectorAcquire(l, sectorRef, pfPath, nil)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
mockPartialFileOpen(pf, sectorSize, pfPath, nil)
|
||||
mockCheckAllocation(pf, offset, size, emptyPartialFile,
|
||||
true, xerrors.New("piece check error"))
|
||||
@@ -446,7 +576,7 @@ func TestCheckIsUnsealed(t *testing.T) {
|
||||
mockSectorAcquire(l, sectorRef, pfPath, nil)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
mockPartialFileOpen(pf, sectorSize, pfPath, nil)
|
||||
|
||||
mockCheckAllocation(pf, offset, size, emptyPartialFile,
|
||||
@@ -488,7 +618,7 @@ func TestCheckIsUnsealed(t *testing.T) {
|
||||
mockSectorAcquire(l, sectorRef, pfPath, nil)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
mockPartialFileOpen(pf, sectorSize, pfPath, nil)
|
||||
mockCheckAllocation(pf, offset, size, emptyPartialFile,
|
||||
false, nil)
|
||||
@@ -533,7 +663,7 @@ func TestCheckIsUnsealed(t *testing.T) {
|
||||
mockSectorAcquire(l, sectorRef, pfPath, nil)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
mockPartialFileOpen(pf, sectorSize, pfPath, nil)
|
||||
mockCheckAllocation(pf, offset, size, emptyPartialFile,
|
||||
true, nil)
|
||||
@@ -569,7 +699,7 @@ func TestCheckIsUnsealed(t *testing.T) {
|
||||
mockSectorAcquire(l, sectorRef, pfPath, nil)
|
||||
},
|
||||
|
||||
pfFunc: func(pf *mocks.MockpartialFileHandler) {
|
||||
pfFunc: func(pf *mocks.MockPartialFileHandler) {
|
||||
mockPartialFileOpen(pf, sectorSize, pfPath, nil)
|
||||
mockCheckAllocation(pf, offset, size, emptyPartialFile,
|
||||
false, nil)
|
||||
@@ -602,7 +732,7 @@ func TestCheckIsUnsealed(t *testing.T) {
|
||||
|
||||
// create them mocks
|
||||
lstore := mocks.NewMockStore(mockCtrl)
|
||||
pfhandler := mocks.NewMockpartialFileHandler(mockCtrl)
|
||||
pfhandler := mocks.NewMockPartialFileHandler(mockCtrl)
|
||||
index := mocks.NewMockSectorIndex(mockCtrl)
|
||||
|
||||
if tc.storeFnc != nil {
|
||||
@@ -656,18 +786,18 @@ func mockSectorAcquire(l *mocks.MockStore, sectorRef storage.SectorRef, pfPath s
|
||||
storiface.SectorPaths{}, err).Times(1)
|
||||
}
|
||||
|
||||
func mockPartialFileOpen(pf *mocks.MockpartialFileHandler, sectorSize abi.SectorSize, pfPath string, err error) {
|
||||
func mockPartialFileOpen(pf *mocks.MockPartialFileHandler, sectorSize abi.SectorSize, pfPath string, err error) {
|
||||
pf.EXPECT().OpenPartialFile(abi.PaddedPieceSize(sectorSize), pfPath).Return(&partialfile.PartialFile{},
|
||||
err).Times(1)
|
||||
}
|
||||
|
||||
func mockCheckAllocation(pf *mocks.MockpartialFileHandler, offset, size abi.PaddedPieceSize, file *partialfile.PartialFile,
|
||||
func mockCheckAllocation(pf *mocks.MockPartialFileHandler, offset, size abi.PaddedPieceSize, file *partialfile.PartialFile,
|
||||
out bool, err error) {
|
||||
pf.EXPECT().HasAllocated(file, storiface.UnpaddedByteIndex(offset.Unpadded()),
|
||||
size.Unpadded()).Return(out, err).Times(1)
|
||||
}
|
||||
|
||||
func mockPfReader(pf *mocks.MockpartialFileHandler, file *partialfile.PartialFile, offset, size abi.PaddedPieceSize,
|
||||
func mockPfReader(pf *mocks.MockPartialFileHandler, file *partialfile.PartialFile, offset, size abi.PaddedPieceSize,
|
||||
outFile *os.File, err error) {
|
||||
pf.EXPECT().Reader(file, storiface.PaddedByteIndex(offset), size).Return(outFile, err)
|
||||
}
|
||||
|
||||
+4
-1
@@ -47,6 +47,8 @@ type WorkerStats struct {
|
||||
}
|
||||
|
||||
const (
|
||||
RWPrepared = 1
|
||||
RWRunning = 0
|
||||
RWRetWait = -1
|
||||
RWReturned = -2
|
||||
RWRetDone = -3
|
||||
@@ -57,7 +59,8 @@ type WorkerJob struct {
|
||||
Sector abi.SectorID
|
||||
Task sealtasks.TaskType
|
||||
|
||||
// 1+ - assigned
|
||||
// 2+ - assigned
|
||||
// 1 - prepared
|
||||
// 0 - running
|
||||
// -1 - ret-wait
|
||||
// -2 - returned
|
||||
|
||||
+6
-6
@@ -331,11 +331,11 @@ func (l *LocalWorker) SealPreCommit1(ctx context.Context, sector storage.SectorR
|
||||
|
||||
{
|
||||
// cleanup previous failed attempts if they exist
|
||||
if err := l.storage.Remove(ctx, sector.ID, storiface.FTSealed, true); err != nil {
|
||||
if err := l.storage.Remove(ctx, sector.ID, storiface.FTSealed, true, nil); err != nil {
|
||||
return nil, xerrors.Errorf("cleaning up sealed data: %w", err)
|
||||
}
|
||||
|
||||
if err := l.storage.Remove(ctx, sector.ID, storiface.FTCache, true); err != nil {
|
||||
if err := l.storage.Remove(ctx, sector.ID, storiface.FTCache, true, nil); err != nil {
|
||||
return nil, xerrors.Errorf("cleaning up cache data: %w", err)
|
||||
}
|
||||
}
|
||||
@@ -394,7 +394,7 @@ func (l *LocalWorker) FinalizeSector(ctx context.Context, sector storage.SectorR
|
||||
}
|
||||
|
||||
if len(keepUnsealed) == 0 {
|
||||
if err := l.storage.Remove(ctx, sector.ID, storiface.FTUnsealed, true); err != nil {
|
||||
if err := l.storage.Remove(ctx, sector.ID, storiface.FTUnsealed, true, nil); err != nil {
|
||||
return nil, xerrors.Errorf("removing unsealed data: %w", err)
|
||||
}
|
||||
}
|
||||
@@ -410,13 +410,13 @@ func (l *LocalWorker) ReleaseUnsealed(ctx context.Context, sector storage.Sector
|
||||
func (l *LocalWorker) Remove(ctx context.Context, sector abi.SectorID) error {
|
||||
var err error
|
||||
|
||||
if rerr := l.storage.Remove(ctx, sector, storiface.FTSealed, true); rerr != nil {
|
||||
if rerr := l.storage.Remove(ctx, sector, storiface.FTSealed, true, nil); rerr != nil {
|
||||
err = multierror.Append(err, xerrors.Errorf("removing sector (sealed): %w", rerr))
|
||||
}
|
||||
if rerr := l.storage.Remove(ctx, sector, storiface.FTCache, true); rerr != nil {
|
||||
if rerr := l.storage.Remove(ctx, sector, storiface.FTCache, true, nil); rerr != nil {
|
||||
err = multierror.Append(err, xerrors.Errorf("removing sector (cache): %w", rerr))
|
||||
}
|
||||
if rerr := l.storage.Remove(ctx, sector, storiface.FTUnsealed, true); rerr != nil {
|
||||
if rerr := l.storage.Remove(ctx, sector, storiface.FTUnsealed, true, nil); rerr != nil {
|
||||
err = multierror.Append(err, xerrors.Errorf("removing sector (unsealed): %w", rerr))
|
||||
}
|
||||
|
||||
|
||||
+84
-41
@@ -5,6 +5,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/ipfs/go-cid"
|
||||
"go.opencensus.io/stats"
|
||||
"go.opencensus.io/tag"
|
||||
@@ -26,8 +27,9 @@ type trackedWork struct {
|
||||
type workTracker struct {
|
||||
lk sync.Mutex
|
||||
|
||||
done map[storiface.CallID]struct{}
|
||||
running map[storiface.CallID]trackedWork
|
||||
done map[storiface.CallID]struct{}
|
||||
running map[storiface.CallID]trackedWork
|
||||
prepared map[uuid.UUID]trackedWork
|
||||
|
||||
// TODO: done, aggregate stats, queue stats, scheduler feedback
|
||||
}
|
||||
@@ -56,63 +58,96 @@ func (wt *workTracker) onDone(ctx context.Context, callID storiface.CallID) {
|
||||
delete(wt.running, callID)
|
||||
}
|
||||
|
||||
func (wt *workTracker) track(ctx context.Context, wid WorkerID, wi storiface.WorkerInfo, sid storage.SectorRef, task sealtasks.TaskType) func(storiface.CallID, error) (storiface.CallID, error) {
|
||||
return func(callID storiface.CallID, err error) (storiface.CallID, error) {
|
||||
if err != nil {
|
||||
return callID, err
|
||||
}
|
||||
|
||||
wt.lk.Lock()
|
||||
defer wt.lk.Unlock()
|
||||
|
||||
_, done := wt.done[callID]
|
||||
if done {
|
||||
delete(wt.done, callID)
|
||||
return callID, err
|
||||
}
|
||||
|
||||
wt.running[callID] = trackedWork{
|
||||
func (wt *workTracker) track(ctx context.Context, ready chan struct{}, wid WorkerID, wi storiface.WorkerInfo, sid storage.SectorRef, task sealtasks.TaskType, cb func() (storiface.CallID, error)) (storiface.CallID, error) {
|
||||
tracked := func(rw int, callID storiface.CallID) trackedWork {
|
||||
return trackedWork{
|
||||
job: storiface.WorkerJob{
|
||||
ID: callID,
|
||||
Sector: sid.ID,
|
||||
Task: task,
|
||||
Start: time.Now(),
|
||||
ID: callID,
|
||||
Sector: sid.ID,
|
||||
Task: task,
|
||||
Start: time.Now(),
|
||||
RunWait: rw,
|
||||
},
|
||||
worker: wid,
|
||||
workerHostname: wi.Hostname,
|
||||
}
|
||||
}
|
||||
|
||||
ctx, _ = tag.New(
|
||||
ctx,
|
||||
tag.Upsert(metrics.TaskType, string(task)),
|
||||
tag.Upsert(metrics.WorkerHostname, wi.Hostname),
|
||||
)
|
||||
stats.Record(ctx, metrics.WorkerCallsStarted.M(1))
|
||||
wt.lk.Lock()
|
||||
defer wt.lk.Unlock()
|
||||
|
||||
select {
|
||||
case <-ready:
|
||||
case <-ctx.Done():
|
||||
return storiface.UndefCall, ctx.Err()
|
||||
default:
|
||||
prepID := uuid.New()
|
||||
|
||||
wt.prepared[prepID] = tracked(storiface.RWPrepared, storiface.UndefCall)
|
||||
|
||||
wt.lk.Unlock()
|
||||
|
||||
select {
|
||||
case <-ready:
|
||||
case <-ctx.Done():
|
||||
wt.lk.Lock()
|
||||
delete(wt.prepared, prepID)
|
||||
return storiface.UndefCall, ctx.Err()
|
||||
}
|
||||
|
||||
wt.lk.Lock()
|
||||
delete(wt.prepared, prepID)
|
||||
}
|
||||
|
||||
callID, err := cb()
|
||||
if err != nil {
|
||||
return callID, err
|
||||
}
|
||||
|
||||
_, done := wt.done[callID]
|
||||
if done {
|
||||
delete(wt.done, callID)
|
||||
return callID, err
|
||||
}
|
||||
|
||||
wt.running[callID] = tracked(storiface.RWRunning, callID)
|
||||
|
||||
ctx, _ = tag.New(
|
||||
ctx,
|
||||
tag.Upsert(metrics.TaskType, string(task)),
|
||||
tag.Upsert(metrics.WorkerHostname, wi.Hostname),
|
||||
)
|
||||
stats.Record(ctx, metrics.WorkerCallsStarted.M(1))
|
||||
|
||||
return callID, err
|
||||
}
|
||||
|
||||
func (wt *workTracker) worker(wid WorkerID, wi storiface.WorkerInfo, w Worker) Worker {
|
||||
func (wt *workTracker) worker(wid WorkerID, wi storiface.WorkerInfo, w Worker) *trackedWorker {
|
||||
return &trackedWorker{
|
||||
Worker: w,
|
||||
wid: wid,
|
||||
workerInfo: wi,
|
||||
|
||||
execute: make(chan struct{}),
|
||||
|
||||
tracker: wt,
|
||||
}
|
||||
}
|
||||
|
||||
func (wt *workTracker) Running() []trackedWork {
|
||||
func (wt *workTracker) Running() ([]trackedWork, []trackedWork) {
|
||||
wt.lk.Lock()
|
||||
defer wt.lk.Unlock()
|
||||
|
||||
out := make([]trackedWork, 0, len(wt.running))
|
||||
running := make([]trackedWork, 0, len(wt.running))
|
||||
for _, job := range wt.running {
|
||||
out = append(out, job)
|
||||
running = append(running, job)
|
||||
}
|
||||
prepared := make([]trackedWork, 0, len(wt.prepared))
|
||||
for _, job := range wt.prepared {
|
||||
prepared = append(prepared, job)
|
||||
}
|
||||
|
||||
return out
|
||||
return running, prepared
|
||||
}
|
||||
|
||||
type trackedWorker struct {
|
||||
@@ -120,39 +155,47 @@ type trackedWorker struct {
|
||||
wid WorkerID
|
||||
workerInfo storiface.WorkerInfo
|
||||
|
||||
execute chan struct{} // channel blocking execution in case we're waiting for resources but the task is ready to execute
|
||||
|
||||
tracker *workTracker
|
||||
}
|
||||
|
||||
func (t *trackedWorker) start() {
|
||||
close(t.execute)
|
||||
}
|
||||
|
||||
func (t *trackedWorker) SealPreCommit1(ctx context.Context, sector storage.SectorRef, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) {
|
||||
return t.tracker.track(ctx, t.wid, t.workerInfo, sector, sealtasks.TTPreCommit1)(t.Worker.SealPreCommit1(ctx, sector, ticket, pieces))
|
||||
return t.tracker.track(ctx, t.execute, t.wid, t.workerInfo, sector, sealtasks.TTPreCommit1, func() (storiface.CallID, error) { return t.Worker.SealPreCommit1(ctx, sector, ticket, pieces) })
|
||||
}
|
||||
|
||||
func (t *trackedWorker) SealPreCommit2(ctx context.Context, sector storage.SectorRef, pc1o storage.PreCommit1Out) (storiface.CallID, error) {
|
||||
return t.tracker.track(ctx, t.wid, t.workerInfo, sector, sealtasks.TTPreCommit2)(t.Worker.SealPreCommit2(ctx, sector, pc1o))
|
||||
return t.tracker.track(ctx, t.execute, t.wid, t.workerInfo, sector, sealtasks.TTPreCommit2, func() (storiface.CallID, error) { return t.Worker.SealPreCommit2(ctx, sector, pc1o) })
|
||||
}
|
||||
|
||||
func (t *trackedWorker) SealCommit1(ctx context.Context, sector storage.SectorRef, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) {
|
||||
return t.tracker.track(ctx, t.wid, t.workerInfo, sector, sealtasks.TTCommit1)(t.Worker.SealCommit1(ctx, sector, ticket, seed, pieces, cids))
|
||||
return t.tracker.track(ctx, t.execute, t.wid, t.workerInfo, sector, sealtasks.TTCommit1, func() (storiface.CallID, error) { return t.Worker.SealCommit1(ctx, sector, ticket, seed, pieces, cids) })
|
||||
}
|
||||
|
||||
func (t *trackedWorker) SealCommit2(ctx context.Context, sector storage.SectorRef, c1o storage.Commit1Out) (storiface.CallID, error) {
|
||||
return t.tracker.track(ctx, t.wid, t.workerInfo, sector, sealtasks.TTCommit2)(t.Worker.SealCommit2(ctx, sector, c1o))
|
||||
return t.tracker.track(ctx, t.execute, t.wid, t.workerInfo, sector, sealtasks.TTCommit2, func() (storiface.CallID, error) { return t.Worker.SealCommit2(ctx, sector, c1o) })
|
||||
}
|
||||
|
||||
func (t *trackedWorker) FinalizeSector(ctx context.Context, sector storage.SectorRef, keepUnsealed []storage.Range) (storiface.CallID, error) {
|
||||
return t.tracker.track(ctx, t.wid, t.workerInfo, sector, sealtasks.TTFinalize)(t.Worker.FinalizeSector(ctx, sector, keepUnsealed))
|
||||
return t.tracker.track(ctx, t.execute, t.wid, t.workerInfo, sector, sealtasks.TTFinalize, func() (storiface.CallID, error) { return t.Worker.FinalizeSector(ctx, sector, keepUnsealed) })
|
||||
}
|
||||
|
||||
func (t *trackedWorker) AddPiece(ctx context.Context, sector storage.SectorRef, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (storiface.CallID, error) {
|
||||
return t.tracker.track(ctx, t.wid, t.workerInfo, sector, sealtasks.TTAddPiece)(t.Worker.AddPiece(ctx, sector, pieceSizes, newPieceSize, pieceData))
|
||||
return t.tracker.track(ctx, t.execute, t.wid, t.workerInfo, sector, sealtasks.TTAddPiece, func() (storiface.CallID, error) {
|
||||
return t.Worker.AddPiece(ctx, sector, pieceSizes, newPieceSize, pieceData)
|
||||
})
|
||||
}
|
||||
|
||||
func (t *trackedWorker) Fetch(ctx context.Context, s storage.SectorRef, ft storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) (storiface.CallID, error) {
|
||||
return t.tracker.track(ctx, t.wid, t.workerInfo, s, sealtasks.TTFetch)(t.Worker.Fetch(ctx, s, ft, ptype, am))
|
||||
return t.tracker.track(ctx, t.execute, t.wid, t.workerInfo, s, sealtasks.TTFetch, func() (storiface.CallID, error) { return t.Worker.Fetch(ctx, s, ft, ptype, am) })
|
||||
}
|
||||
|
||||
func (t *trackedWorker) UnsealPiece(ctx context.Context, id storage.SectorRef, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, cid cid.Cid) (storiface.CallID, error) {
|
||||
return t.tracker.track(ctx, t.wid, t.workerInfo, id, sealtasks.TTUnseal)(t.Worker.UnsealPiece(ctx, id, index, size, randomness, cid))
|
||||
return t.tracker.track(ctx, t.execute, t.wid, t.workerInfo, id, sealtasks.TTUnseal, func() (storiface.CallID, error) { return t.Worker.UnsealPiece(ctx, id, index, size, randomness, cid) })
|
||||
}
|
||||
|
||||
var _ Worker = &trackedWorker{}
|
||||
|
||||
Vendored
+11
-5
@@ -135,7 +135,11 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto
|
||||
|
||||
// Sealing errors
|
||||
|
||||
AddPieceFailed: planOne(),
|
||||
AddPieceFailed: planOne(
|
||||
on(SectorRetryWaitDeals{}, WaitDeals),
|
||||
apply(SectorStartPacking{}),
|
||||
apply(SectorAddPiece{}),
|
||||
),
|
||||
SealPreCommit1Failed: planOne(
|
||||
on(SectorRetrySealPreCommit1{}, PreCommit1),
|
||||
),
|
||||
@@ -331,9 +335,9 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta
|
||||
*<- Committing |
|
||||
| | ^--> CommitFailed
|
||||
| v ^
|
||||
| SubmitCommit |
|
||||
| | |
|
||||
| v |
|
||||
| SubmitCommit |
|
||||
| | |
|
||||
| v |
|
||||
*<- CommitWait ---/
|
||||
| |
|
||||
| v
|
||||
@@ -400,6 +404,8 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta
|
||||
return m.handleFinalizeSector, processed, nil
|
||||
|
||||
// Handled failure modes
|
||||
case AddPieceFailed:
|
||||
return m.handleAddPieceFailed, processed, nil
|
||||
case SealPreCommit1Failed:
|
||||
return m.handleSealPrecommit1Failed, processed, nil
|
||||
case SealPreCommit2Failed:
|
||||
@@ -469,7 +475,7 @@ func (m *Sealing) onUpdateSector(ctx context.Context, state *SectorInfo) error {
|
||||
return xerrors.Errorf("getting config: %w", err)
|
||||
}
|
||||
|
||||
shouldUpdateInput := m.stats.updateSector(cfg, m.minerSectorID(state.SectorNumber), state.State)
|
||||
shouldUpdateInput := m.stats.updateSector(ctx, cfg, m.minerSectorID(state.SectorNumber), state.State)
|
||||
|
||||
// trigger more input processing when we've dipped below max sealing limits
|
||||
if shouldUpdateInput {
|
||||
|
||||
Vendored
+4
@@ -98,6 +98,10 @@ type SectorAddPieceFailed struct{ error }
|
||||
func (evt SectorAddPieceFailed) FormatError(xerrors.Printer) (next error) { return evt.error }
|
||||
func (evt SectorAddPieceFailed) apply(si *SectorInfo) {}
|
||||
|
||||
type SectorRetryWaitDeals struct{}
|
||||
|
||||
func (evt SectorRetryWaitDeals) apply(si *SectorInfo) {}
|
||||
|
||||
type SectorStartPacking struct{}
|
||||
|
||||
func (evt SectorStartPacking) apply(*SectorInfo) {}
|
||||
|
||||
Vendored
+14
-7
@@ -33,7 +33,8 @@ func TestHappyPath(t *testing.T) {
|
||||
s: &Sealing{
|
||||
maddr: ma,
|
||||
stats: SectorStats{
|
||||
bySector: map[abi.SectorID]statSectorState{},
|
||||
bySector: map[abi.SectorID]SectorState{},
|
||||
byState: map[SectorState]int64{},
|
||||
},
|
||||
notifee: func(before, after SectorInfo) {
|
||||
notif = append(notif, struct{ before, after SectorInfo }{before, after})
|
||||
@@ -94,7 +95,8 @@ func TestHappyPathFinalizeEarly(t *testing.T) {
|
||||
s: &Sealing{
|
||||
maddr: ma,
|
||||
stats: SectorStats{
|
||||
bySector: map[abi.SectorID]statSectorState{},
|
||||
bySector: map[abi.SectorID]SectorState{},
|
||||
byState: map[SectorState]int64{},
|
||||
},
|
||||
notifee: func(before, after SectorInfo) {
|
||||
notif = append(notif, struct{ before, after SectorInfo }{before, after})
|
||||
@@ -161,7 +163,8 @@ func TestCommitFinalizeFailed(t *testing.T) {
|
||||
s: &Sealing{
|
||||
maddr: ma,
|
||||
stats: SectorStats{
|
||||
bySector: map[abi.SectorID]statSectorState{},
|
||||
bySector: map[abi.SectorID]SectorState{},
|
||||
byState: map[SectorState]int64{},
|
||||
},
|
||||
notifee: func(before, after SectorInfo) {
|
||||
notif = append(notif, struct{ before, after SectorInfo }{before, after})
|
||||
@@ -199,7 +202,8 @@ func TestSeedRevert(t *testing.T) {
|
||||
s: &Sealing{
|
||||
maddr: ma,
|
||||
stats: SectorStats{
|
||||
bySector: map[abi.SectorID]statSectorState{},
|
||||
bySector: map[abi.SectorID]SectorState{},
|
||||
byState: map[SectorState]int64{},
|
||||
},
|
||||
},
|
||||
t: t,
|
||||
@@ -252,7 +256,8 @@ func TestPlanCommittingHandlesSectorCommitFailed(t *testing.T) {
|
||||
s: &Sealing{
|
||||
maddr: ma,
|
||||
stats: SectorStats{
|
||||
bySector: map[abi.SectorID]statSectorState{},
|
||||
bySector: map[abi.SectorID]SectorState{},
|
||||
byState: map[SectorState]int64{},
|
||||
},
|
||||
},
|
||||
t: t,
|
||||
@@ -289,7 +294,8 @@ func TestBrokenState(t *testing.T) {
|
||||
s: &Sealing{
|
||||
maddr: ma,
|
||||
stats: SectorStats{
|
||||
bySector: map[abi.SectorID]statSectorState{},
|
||||
bySector: map[abi.SectorID]SectorState{},
|
||||
byState: map[SectorState]int64{},
|
||||
},
|
||||
notifee: func(before, after SectorInfo) {
|
||||
notif = append(notif, struct{ before, after SectorInfo }{before, after})
|
||||
@@ -324,7 +330,8 @@ func TestTicketExpired(t *testing.T) {
|
||||
s: &Sealing{
|
||||
maddr: ma,
|
||||
stats: SectorStats{
|
||||
bySector: map[abi.SectorID]statSectorState{},
|
||||
bySector: map[abi.SectorID]SectorState{},
|
||||
byState: map[SectorState]int64{},
|
||||
},
|
||||
notifee: func(before, after SectorInfo) {
|
||||
notif = append(notif, struct{ before, after SectorInfo }{before, after})
|
||||
|
||||
Vendored
+21
-4
@@ -60,6 +60,10 @@ func (m *Sealing) handleWaitDeals(ctx statemachine.Context, sector SectorInfo) e
|
||||
return ctx.Send(SectorAddPiece{})
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// make sure we're only accounting for pieces which were correctly added
|
||||
// (note that m.assignedPieces[sid] will always be empty here)
|
||||
m.openSectors[sid].used = used
|
||||
}
|
||||
|
||||
go func() {
|
||||
@@ -245,9 +249,7 @@ func (m *Sealing) handleAddPiece(ctx statemachine.Context, sector SectorInfo) er
|
||||
}
|
||||
|
||||
func (m *Sealing) handleAddPieceFailed(ctx statemachine.Context, sector SectorInfo) error {
|
||||
log.Errorf("No recovery plan for AddPiece failing")
|
||||
// todo: cleanup sector / just go retry (requires adding offset param to AddPiece in sector-storage for this to be safe)
|
||||
return nil
|
||||
return ctx.Send(SectorRetryWaitDeals{})
|
||||
}
|
||||
|
||||
func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPieceSize, data storage.Data, deal api.PieceDealInfo) (api.SectorOffset, error) {
|
||||
@@ -274,6 +276,21 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec
|
||||
return api.SectorOffset{}, xerrors.Errorf("getting proposal CID: %w", err)
|
||||
}
|
||||
|
||||
cfg, err := m.getConfig()
|
||||
if err != nil {
|
||||
return api.SectorOffset{}, xerrors.Errorf("getting config: %w", err)
|
||||
}
|
||||
|
||||
_, head, err := m.Api.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return api.SectorOffset{}, xerrors.Errorf("couldnt get chain head: %w", err)
|
||||
}
|
||||
if head+cfg.StartEpochSealingBuffer > deal.DealProposal.StartEpoch {
|
||||
return api.SectorOffset{}, xerrors.Errorf(
|
||||
"cannot add piece for deal with piece CID %s: current epoch %d has passed deal proposal start epoch %d",
|
||||
deal.DealProposal.PieceCID, head, deal.DealProposal.StartEpoch)
|
||||
}
|
||||
|
||||
m.inputLk.Lock()
|
||||
if _, exist := m.pendingPieces[proposalCID(deal)]; exist {
|
||||
m.inputLk.Unlock()
|
||||
@@ -456,7 +473,7 @@ func (m *Sealing) createSector(ctx context.Context, cfg sealiface.Config, sp abi
|
||||
}
|
||||
|
||||
// update stats early, fsm planner would do that async
|
||||
m.stats.updateSector(cfg, m.minerSectorID(sid), UndefinedSectorState)
|
||||
m.stats.updateSector(ctx, cfg, m.minerSectorID(sid), UndefinedSectorState)
|
||||
|
||||
return sid, nil
|
||||
}
|
||||
|
||||
+2
@@ -22,6 +22,8 @@ type Config struct {
|
||||
|
||||
CommittedCapacitySectorLifetime time.Duration
|
||||
|
||||
StartEpochSealingBuffer abi.ChainEpoch
|
||||
|
||||
AlwaysKeepUnsealedCopy bool
|
||||
|
||||
FinalizeEarly bool
|
||||
|
||||
Vendored
+2
-1
@@ -166,7 +166,8 @@ func New(mctx context.Context, api SealingAPI, fc config.MinerFeeConfig, events
|
||||
getConfig: gc,
|
||||
|
||||
stats: SectorStats{
|
||||
bySector: map[abi.SectorID]statSectorState{},
|
||||
bySector: map[abi.SectorID]SectorState{},
|
||||
byState: map[SectorState]int64{},
|
||||
},
|
||||
}
|
||||
s.startupWait.Add(1)
|
||||
|
||||
+1
-1
@@ -108,7 +108,7 @@ const (
|
||||
|
||||
func toStatState(st SectorState, finEarly bool) statSectorState {
|
||||
switch st {
|
||||
case UndefinedSectorState, Empty, WaitDeals, AddPiece:
|
||||
case UndefinedSectorState, Empty, WaitDeals, AddPiece, AddPieceFailed:
|
||||
return sstStaging
|
||||
case Packing, GetTicket, PreCommit1, PreCommit2, PreCommitting, PreCommitWait, SubmitPreCommitBatch, PreCommitBatchWait, WaitSeed, Committing, CommitFinalize, FinalizeSector:
|
||||
return sstSealing
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ func (m *Sealing) padSector(ctx context.Context, sectorID storage.SectorRef, exi
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("add piece: %w", err)
|
||||
}
|
||||
if !expectCid.Equals(expectCid) {
|
||||
if !expectCid.Equals(ppi.PieceCID) {
|
||||
return nil, xerrors.Errorf("got unexpected padding piece CID: expected:%s, got:%s", expectCid, ppi.PieceCID)
|
||||
}
|
||||
|
||||
|
||||
Vendored
+19
-4
@@ -1,10 +1,16 @@
|
||||
package sealing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"go.opencensus.io/stats"
|
||||
"go.opencensus.io/tag"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/extern/storage-sealing/sealiface"
|
||||
"github.com/filecoin-project/lotus/metrics"
|
||||
)
|
||||
|
||||
type statSectorState int
|
||||
@@ -20,11 +26,12 @@ const (
|
||||
type SectorStats struct {
|
||||
lk sync.Mutex
|
||||
|
||||
bySector map[abi.SectorID]statSectorState
|
||||
bySector map[abi.SectorID]SectorState
|
||||
byState map[SectorState]int64
|
||||
totals [nsst]uint64
|
||||
}
|
||||
|
||||
func (ss *SectorStats) updateSector(cfg sealiface.Config, id abi.SectorID, st SectorState) (updateInput bool) {
|
||||
func (ss *SectorStats) updateSector(ctx context.Context, cfg sealiface.Config, id abi.SectorID, st SectorState) (updateInput bool) {
|
||||
ss.lk.Lock()
|
||||
defer ss.lk.Unlock()
|
||||
|
||||
@@ -34,12 +41,20 @@ func (ss *SectorStats) updateSector(cfg sealiface.Config, id abi.SectorID, st Se
|
||||
// update totals
|
||||
oldst, found := ss.bySector[id]
|
||||
if found {
|
||||
ss.totals[oldst]--
|
||||
ss.totals[toStatState(oldst, cfg.FinalizeEarly)]--
|
||||
ss.byState[oldst]--
|
||||
|
||||
mctx, _ := tag.New(ctx, tag.Upsert(metrics.SectorState, string(oldst)))
|
||||
stats.Record(mctx, metrics.SectorStates.M(ss.byState[oldst]))
|
||||
}
|
||||
|
||||
sst := toStatState(st, cfg.FinalizeEarly)
|
||||
ss.bySector[id] = sst
|
||||
ss.bySector[id] = st
|
||||
ss.totals[sst]++
|
||||
ss.byState[st]++
|
||||
|
||||
mctx, _ := tag.New(ctx, tag.Upsert(metrics.SectorState, string(st)))
|
||||
stats.Record(mctx, metrics.SectorStates.M(ss.byState[st]))
|
||||
|
||||
// check if we may need be able to process more deals
|
||||
sealing := ss.curSealingLocked()
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/v0api"
|
||||
"github.com/filecoin-project/lotus/api/v1api"
|
||||
"github.com/filecoin-project/lotus/metrics"
|
||||
"github.com/filecoin-project/lotus/metrics/proxy"
|
||||
"github.com/gorilla/mux"
|
||||
promclient "github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
@@ -23,7 +23,7 @@ func Handler(a api.Gateway, opts ...jsonrpc.ServerOption) (http.Handler, error)
|
||||
m.Handle(path, rpcServer)
|
||||
}
|
||||
|
||||
ma := metrics.MetricedGatewayAPI(a)
|
||||
ma := proxy.MetricedGatewayAPI(a)
|
||||
|
||||
serveRpc("/rpc/v1", ma)
|
||||
serveRpc("/rpc/v0", api.Wrap(new(v1api.FullNodeStruct), new(v0api.WrapperV1Full), ma))
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
const (
|
||||
stateGlobal = iota
|
||||
stateTemplate
|
||||
stateGen
|
||||
)
|
||||
|
||||
func main() {
|
||||
db, err := ioutil.ReadFile(os.Args[2])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var data map[string]interface{}
|
||||
if err := json.Unmarshal(db, &data); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = filepath.WalkDir(os.Args[1], func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if filepath.Ext(path) != ".go" {
|
||||
return nil
|
||||
}
|
||||
fb, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(fb), "\n")
|
||||
|
||||
outLines := make([]string, 0, len(lines))
|
||||
var templateLines []string
|
||||
|
||||
state := stateGlobal
|
||||
|
||||
rewrite := false
|
||||
|
||||
for i, line := range lines {
|
||||
ln := i + 1
|
||||
switch state {
|
||||
case stateGlobal:
|
||||
outLines = append(outLines, line)
|
||||
if strings.TrimSpace(line) == `/* inline-gen template` {
|
||||
state = stateTemplate
|
||||
fmt.Printf("template section start %s:%d\n", path, ln)
|
||||
}
|
||||
case stateTemplate:
|
||||
outLines = append(outLines, line) // output all template lines
|
||||
|
||||
if strings.TrimSpace(line) == `/* inline-gen start */` {
|
||||
state = stateGen
|
||||
fmt.Printf("generated section start %s:%d\n", path, ln)
|
||||
continue
|
||||
}
|
||||
templateLines = append(templateLines, line)
|
||||
case stateGen:
|
||||
if strings.TrimSpace(line) != `/* inline-gen end */` {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("generated section end %s:%d\n", path, ln)
|
||||
|
||||
state = stateGlobal
|
||||
rewrite = true
|
||||
|
||||
tpl, err := template.New("").Funcs(template.FuncMap{
|
||||
"import": func(v float64) string {
|
||||
if v == 0 {
|
||||
return "/"
|
||||
}
|
||||
return fmt.Sprintf("/v%d/", int(v))
|
||||
},
|
||||
"add": func(a, b float64) float64 {
|
||||
return a + b
|
||||
},
|
||||
}).Parse(strings.Join(templateLines, "\n"))
|
||||
if err != nil {
|
||||
fmt.Printf("%s:%d: parsing template: %s\n", path, ln, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
err = tpl.Execute(&b, data)
|
||||
if err != nil {
|
||||
fmt.Printf("%s:%d: executing template: %s\n", path, ln, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
outLines = append(outLines, strings.Split(b.String(), "\n")...)
|
||||
outLines = append(outLines, line)
|
||||
templateLines = nil
|
||||
}
|
||||
}
|
||||
|
||||
if rewrite {
|
||||
fmt.Printf("write %s\n", path)
|
||||
if err := ioutil.WriteFile(path, []byte(strings.Join(outLines, "\n")), 0664); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"actorVersions": [0, 2, 3, 4, 5, 6],
|
||||
"latestActorsVersion": 6,
|
||||
|
||||
"networkVersions": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
|
||||
"latestNetworkVersion": 14
|
||||
}
|
||||
@@ -3,43 +3,43 @@ module github.com/filecoin-project/lotus
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
contrib.go.opencensus.io/exporter/jaeger v0.1.0
|
||||
contrib.go.opencensus.io/exporter/prometheus v0.1.0
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/GeertJohan/go.rice v1.0.0
|
||||
contrib.go.opencensus.io/exporter/jaeger v0.2.1
|
||||
contrib.go.opencensus.io/exporter/prometheus v0.4.0
|
||||
github.com/BurntSushi/toml v0.4.1
|
||||
github.com/GeertJohan/go.rice v1.0.2
|
||||
github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee
|
||||
github.com/Kubuxu/imtui v0.0.0-20210401140320-41663d68d0fa
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
||||
github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921
|
||||
github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129
|
||||
github.com/buger/goterm v1.0.3
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
||||
github.com/cockroachdb/pebble v0.0.0-20201001221639-879f3bfeef07
|
||||
github.com/coreos/go-systemd/v22 v22.1.0
|
||||
github.com/coreos/go-systemd/v22 v22.3.2
|
||||
github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e
|
||||
github.com/dgraph-io/badger/v2 v2.2007.2
|
||||
github.com/docker/go-units v0.4.0
|
||||
github.com/drand/drand v1.2.1
|
||||
github.com/drand/kyber v1.1.4
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/elastic/go-sysinfo v1.3.0
|
||||
github.com/elastic/gosigar v0.12.0
|
||||
github.com/elastic/go-sysinfo v1.7.0
|
||||
github.com/elastic/gosigar v0.14.1
|
||||
github.com/etclabscore/go-openrpc-reflect v0.0.36
|
||||
github.com/fatih/color v1.9.0
|
||||
github.com/fatih/color v1.13.0
|
||||
github.com/filecoin-project/dagstore v0.4.3
|
||||
github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f
|
||||
github.com/filecoin-project/go-address v0.0.5
|
||||
github.com/filecoin-project/go-address v0.0.6
|
||||
github.com/filecoin-project/go-bitfield v0.2.4
|
||||
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2
|
||||
github.com/filecoin-project/go-commp-utils v0.1.1-0.20210427191551-70bf140d31c7
|
||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
|
||||
github.com/filecoin-project/go-data-transfer v1.10.1
|
||||
github.com/filecoin-project/go-cbor-util v0.0.1
|
||||
github.com/filecoin-project/go-commp-utils v0.1.2
|
||||
github.com/filecoin-project/go-crypto v0.0.1
|
||||
github.com/filecoin-project/go-data-transfer v1.11.4
|
||||
github.com/filecoin-project/go-fil-commcid v0.1.0
|
||||
github.com/filecoin-project/go-fil-commp-hashhash v0.1.0
|
||||
github.com/filecoin-project/go-fil-markets v1.12.0
|
||||
github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec
|
||||
github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1
|
||||
github.com/filecoin-project/go-paramfetch v0.0.2-0.20210614165157-25a6c7769498
|
||||
github.com/filecoin-project/go-fil-markets v1.13.3
|
||||
github.com/filecoin-project/go-jsonrpc v0.1.5
|
||||
github.com/filecoin-project/go-padreader v0.0.1
|
||||
github.com/filecoin-project/go-paramfetch v0.0.2
|
||||
github.com/filecoin-project/go-state-types v0.1.1-0.20210915140513-d354ccf10379
|
||||
github.com/filecoin-project/go-statemachine v1.0.1
|
||||
github.com/filecoin-project/go-statestore v0.1.1
|
||||
@@ -49,90 +49,91 @@ require (
|
||||
github.com/filecoin-project/specs-actors/v3 v3.1.1
|
||||
github.com/filecoin-project/specs-actors/v4 v4.0.1
|
||||
github.com/filecoin-project/specs-actors/v5 v5.0.4
|
||||
github.com/filecoin-project/specs-actors/v6 v6.0.0
|
||||
github.com/filecoin-project/specs-actors/v6 v6.0.1
|
||||
github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506
|
||||
github.com/filecoin-project/test-vectors/schema v0.0.5
|
||||
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
|
||||
github.com/gbrlsnchs/jwt/v3 v3.0.1
|
||||
github.com/gdamore/tcell/v2 v2.2.0
|
||||
github.com/go-kit/kit v0.10.0
|
||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||
github.com/go-kit/kit v0.12.0
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/google/uuid v1.2.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/mux v1.7.4
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026
|
||||
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e
|
||||
github.com/hashicorp/go-multierror v1.1.0
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hashicorp/golang-lru v0.5.4
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d
|
||||
github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab
|
||||
github.com/ipfs/bbloom v0.0.4
|
||||
github.com/ipfs/go-bitswap v0.3.4
|
||||
github.com/ipfs/go-block-format v0.0.3
|
||||
github.com/ipfs/go-blockservice v0.1.5
|
||||
github.com/ipfs/go-blockservice v0.1.7
|
||||
github.com/ipfs/go-cid v0.1.0
|
||||
github.com/ipfs/go-cidutil v0.0.2
|
||||
github.com/ipfs/go-datastore v0.4.5
|
||||
github.com/ipfs/go-datastore v0.4.6
|
||||
github.com/ipfs/go-ds-badger2 v0.1.1-0.20200708190120-187fc06f714e
|
||||
github.com/ipfs/go-ds-leveldb v0.4.2
|
||||
github.com/ipfs/go-ds-measure v0.1.0
|
||||
github.com/ipfs/go-ds-pebble v0.0.2-0.20200921225637-ce220f8ac459
|
||||
github.com/ipfs/go-filestore v1.0.0
|
||||
github.com/ipfs/go-fs-lock v0.0.6
|
||||
github.com/ipfs/go-graphsync v0.9.3
|
||||
github.com/ipfs/go-graphsync v0.10.4
|
||||
github.com/ipfs/go-ipfs-blockstore v1.0.4
|
||||
github.com/ipfs/go-ipfs-blocksutil v0.0.1
|
||||
github.com/ipfs/go-ipfs-chunker v0.0.5
|
||||
github.com/ipfs/go-ipfs-ds-help v1.0.0
|
||||
github.com/ipfs/go-ipfs-exchange-interface v0.0.1
|
||||
github.com/ipfs/go-ipfs-exchange-offline v0.0.1
|
||||
github.com/ipfs/go-ipfs-files v0.0.8
|
||||
github.com/ipfs/go-ipfs-http-client v0.0.5
|
||||
github.com/ipfs/go-ipfs-files v0.0.9
|
||||
github.com/ipfs/go-ipfs-http-client v0.0.6
|
||||
github.com/ipfs/go-ipfs-routing v0.1.0
|
||||
github.com/ipfs/go-ipfs-util v0.0.2
|
||||
github.com/ipfs/go-ipld-cbor v0.0.5
|
||||
github.com/ipfs/go-ipld-format v0.2.0
|
||||
github.com/ipfs/go-log/v2 v2.3.0
|
||||
github.com/ipfs/go-merkledag v0.3.2
|
||||
github.com/ipfs/go-merkledag v0.4.1
|
||||
github.com/ipfs/go-metrics-interface v0.0.1
|
||||
github.com/ipfs/go-metrics-prometheus v0.0.2
|
||||
github.com/ipfs/go-path v0.0.7
|
||||
github.com/ipfs/go-unixfs v0.2.6
|
||||
github.com/ipfs/interface-go-ipfs-core v0.2.3
|
||||
github.com/ipld/go-car v0.3.1-0.20210601190600-f512dac51e8e
|
||||
github.com/ipfs/interface-go-ipfs-core v0.4.0
|
||||
github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823
|
||||
github.com/ipld/go-car/v2 v2.0.3-0.20210811121346-c514a30114d7
|
||||
github.com/ipld/go-ipld-prime v0.12.0
|
||||
github.com/ipld/go-codec-dagpb v1.3.0
|
||||
github.com/ipld/go-ipld-prime v0.12.3
|
||||
github.com/ipld/go-ipld-selector-text-lite v0.0.0
|
||||
github.com/kelseyhightower/envconfig v1.4.0
|
||||
github.com/libp2p/go-buffer-pool v0.0.2
|
||||
github.com/libp2p/go-eventbus v0.2.1
|
||||
github.com/libp2p/go-libp2p v0.14.2
|
||||
github.com/libp2p/go-libp2p v0.15.0
|
||||
github.com/libp2p/go-libp2p-connmgr v0.2.4
|
||||
github.com/libp2p/go-libp2p-core v0.8.6
|
||||
github.com/libp2p/go-libp2p-core v0.9.0
|
||||
github.com/libp2p/go-libp2p-discovery v0.5.1
|
||||
github.com/libp2p/go-libp2p-kad-dht v0.11.0
|
||||
github.com/libp2p/go-libp2p-kad-dht v0.13.0
|
||||
github.com/libp2p/go-libp2p-mplex v0.4.1
|
||||
github.com/libp2p/go-libp2p-noise v0.2.0
|
||||
github.com/libp2p/go-libp2p-peerstore v0.2.8
|
||||
github.com/libp2p/go-libp2p-pubsub v0.5.4
|
||||
github.com/libp2p/go-libp2p-noise v0.2.2
|
||||
github.com/libp2p/go-libp2p-peerstore v0.3.0
|
||||
github.com/libp2p/go-libp2p-pubsub v0.5.6
|
||||
github.com/libp2p/go-libp2p-quic-transport v0.11.2
|
||||
github.com/libp2p/go-libp2p-record v0.1.3
|
||||
github.com/libp2p/go-libp2p-routing-helpers v0.2.3
|
||||
github.com/libp2p/go-libp2p-swarm v0.5.3
|
||||
github.com/libp2p/go-libp2p-tls v0.1.3
|
||||
github.com/libp2p/go-libp2p-tls v0.2.0
|
||||
github.com/libp2p/go-libp2p-yamux v0.5.4
|
||||
github.com/libp2p/go-maddr-filter v0.1.0
|
||||
github.com/mattn/go-isatty v0.0.13
|
||||
github.com/mattn/go-isatty v0.0.14
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/multiformats/go-base32 v0.0.3
|
||||
github.com/multiformats/go-multiaddr v0.3.3
|
||||
github.com/multiformats/go-base32 v0.0.4
|
||||
github.com/multiformats/go-multiaddr v0.4.1
|
||||
github.com/multiformats/go-multiaddr-dns v0.3.1
|
||||
github.com/multiformats/go-multibase v0.0.3
|
||||
github.com/multiformats/go-multihash v0.0.15
|
||||
github.com/multiformats/go-multihash v0.0.16
|
||||
github.com/multiformats/go-varint v0.0.6
|
||||
github.com/open-rpc/meta-schema v0.0.0-20201029221707-1b72ef2ea333
|
||||
github.com/opentracing/opentracing-go v1.2.0
|
||||
github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e
|
||||
github.com/prometheus/client_golang v1.10.0
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/raulk/clock v1.1.0
|
||||
github.com/raulk/go-watchdog v1.0.1
|
||||
github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25
|
||||
@@ -149,19 +150,17 @@ require (
|
||||
go.uber.org/dig v1.10.0 // indirect
|
||||
go.uber.org/fx v1.9.0
|
||||
go.uber.org/multierr v1.7.0
|
||||
go.uber.org/zap v1.16.0
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781
|
||||
go.uber.org/zap v1.19.1
|
||||
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0
|
||||
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
|
||||
golang.org/x/tools v0.1.5
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.28
|
||||
gotest.tools v2.2.0+incompatible
|
||||
)
|
||||
|
||||
replace github.com/libp2p/go-libp2p-yamux => github.com/libp2p/go-libp2p-yamux v0.5.1
|
||||
|
||||
replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi
|
||||
|
||||
replace github.com/filecoin-project/test-vectors => ./extern/test-vectors
|
||||
|
||||
@@ -139,8 +139,8 @@ func TestSimultanenousTransferLimit(t *testing.T) {
|
||||
)
|
||||
runTest := func(t *testing.T) {
|
||||
client, miner, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ConstructorOpts(
|
||||
node.ApplyIf(node.IsType(repo.StorageMiner), node.Override(new(dtypes.StagingGraphsync), modules.StagingGraphsync(graphsyncThrottle))),
|
||||
node.Override(new(dtypes.Graphsync), modules.Graphsync(graphsyncThrottle)),
|
||||
node.ApplyIf(node.IsType(repo.StorageMiner), node.Override(new(dtypes.StagingGraphsync), modules.StagingGraphsync(graphsyncThrottle, graphsyncThrottle))),
|
||||
node.Override(new(dtypes.Graphsync), modules.Graphsync(graphsyncThrottle, graphsyncThrottle)),
|
||||
))
|
||||
ens.InterconnectAll().BeginMining(250 * time.Millisecond)
|
||||
dh := kit.NewDealHarness(t, client, miner, miner)
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
package itests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipld/go-car"
|
||||
textselector "github.com/ipld/go-ipld-selector-text-lite"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// use the mainnet carfile as text fixture: it will always be here
|
||||
// https://dweb.link/ipfs/bafy2bzacecnamqgqmifpluoeldx7zzglxcljo6oja4vrmtj7432rphldpdmm2/8/1/8/1/0/1/0
|
||||
var (
|
||||
sourceCar = "../build/genesis/mainnet.car"
|
||||
carRoot, _ = cid.Parse("bafy2bzacecnamqgqmifpluoeldx7zzglxcljo6oja4vrmtj7432rphldpdmm2")
|
||||
carCommp, _ = cid.Parse("baga6ea4seaqmrivgzei3fmx5qxtppwankmtou6zvigyjaveu3z2zzwhysgzuina")
|
||||
carPieceSize = abi.PaddedPieceSize(2097152)
|
||||
textSelector = textselector.Expression("8/1/8/1/0/1/0")
|
||||
textSelectorNonLink = textselector.Expression("8/1/8/1/0/1")
|
||||
textSelectorNonexistent = textselector.Expression("42")
|
||||
expectedResult = "fil/1/storagepower"
|
||||
)
|
||||
|
||||
func TestPartialRetrieval(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
policy.SetPreCommitChallengeDelay(2)
|
||||
kit.EnableLargeSectors(t)
|
||||
kit.QuietMiningLogs()
|
||||
client, miner, ens := kit.EnsembleMinimal(t, kit.ThroughRPC(), kit.MockProofs(), kit.SectorSize(512<<20))
|
||||
dh := kit.NewDealHarness(t, client, miner, miner)
|
||||
ens.InterconnectAll().BeginMining(50 * time.Millisecond)
|
||||
|
||||
_, err := client.ClientImport(ctx, api.FileRef{Path: sourceCar, IsCAR: true})
|
||||
require.NoError(t, err)
|
||||
|
||||
caddr, err := client.WalletDefaultAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// first test retrieval from local car, then do an actual deal
|
||||
for _, fullCycle := range []bool{false, true} {
|
||||
|
||||
var retOrder api.RetrievalOrder
|
||||
|
||||
if !fullCycle {
|
||||
|
||||
retOrder.FromLocalCAR = sourceCar
|
||||
retOrder.Root = carRoot
|
||||
|
||||
} else {
|
||||
|
||||
dp := dh.DefaultStartDealParams()
|
||||
dp.Data = &storagemarket.DataRef{
|
||||
// FIXME: figure out how to do this with an online partial transfer
|
||||
TransferType: storagemarket.TTManual,
|
||||
Root: carRoot,
|
||||
PieceCid: &carCommp,
|
||||
PieceSize: carPieceSize.Unpadded(),
|
||||
}
|
||||
proposalCid := dh.StartDeal(ctx, dp)
|
||||
|
||||
// Wait for the deal to reach StorageDealCheckForAcceptance on the client
|
||||
cd, err := client.ClientGetDealInfo(ctx, *proposalCid)
|
||||
require.NoError(t, err)
|
||||
require.Eventually(t, func() bool {
|
||||
cd, _ := client.ClientGetDealInfo(ctx, *proposalCid)
|
||||
return cd.State == storagemarket.StorageDealCheckForAcceptance
|
||||
}, 30*time.Second, 1*time.Second, "actual deal status is %s", storagemarket.DealStates[cd.State])
|
||||
|
||||
err = miner.DealsImportData(ctx, *proposalCid, sourceCar)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Wait for the deal to be published, we should be able to start retrieval right away
|
||||
dh.WaitDealPublished(ctx, proposalCid)
|
||||
|
||||
offers, err := client.ClientFindData(ctx, carRoot, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, offers, "no offers")
|
||||
|
||||
retOrder = offers[0].Order(caddr)
|
||||
}
|
||||
|
||||
retOrder.DatamodelPathSelector = &textSelector
|
||||
|
||||
// test retrieval of either data or constructing a partial selective-car
|
||||
for _, retrieveAsCar := range []bool{false, true} {
|
||||
outFile, err := ioutil.TempFile(t.TempDir(), "ret-file")
|
||||
require.NoError(t, err)
|
||||
defer outFile.Close() //nolint:errcheck
|
||||
|
||||
require.NoError(t, testGenesisRetrieval(
|
||||
ctx,
|
||||
client,
|
||||
retOrder,
|
||||
&api.FileRef{
|
||||
Path: outFile.Name(),
|
||||
IsCAR: retrieveAsCar,
|
||||
},
|
||||
outFile,
|
||||
))
|
||||
|
||||
// UGH if I do not sleep here, I get things like:
|
||||
/*
|
||||
retrieval failed: Retrieve failed: there is an active retrieval deal with peer 12D3KooWK9fB9a3HZ4PQLVmEQ6pweMMn5CAyKtumB71CPTnuBDi6 for payload CID bafy2bzacecnamqgqmifpluoeldx7zzglxcljo6oja4vrmtj7432rphldpdmm2 (retrieval deal ID 1631259332180384709, state DealStatusFinalizingBlockstore) - existing deal must be cancelled before starting a new retrieval deal:
|
||||
github.com/filecoin-project/lotus/node/impl/client.(*API).ClientRetrieve
|
||||
/home/circleci/project/node/impl/client/client.go:774
|
||||
*/
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
// ensure non-existent paths fail
|
||||
require.EqualError(
|
||||
t,
|
||||
testGenesisRetrieval(
|
||||
ctx,
|
||||
client,
|
||||
api.RetrievalOrder{
|
||||
FromLocalCAR: sourceCar,
|
||||
Root: carRoot,
|
||||
DatamodelPathSelector: &textSelectorNonexistent,
|
||||
},
|
||||
&api.FileRef{},
|
||||
nil,
|
||||
),
|
||||
fmt.Sprintf("retrieval failed: path selection '%s' does not match a node within %s", textSelectorNonexistent, carRoot),
|
||||
)
|
||||
|
||||
// ensure non-boundary retrievals fail
|
||||
require.EqualError(
|
||||
t,
|
||||
testGenesisRetrieval(
|
||||
ctx,
|
||||
client,
|
||||
api.RetrievalOrder{
|
||||
FromLocalCAR: sourceCar,
|
||||
Root: carRoot,
|
||||
DatamodelPathSelector: &textSelectorNonLink,
|
||||
},
|
||||
&api.FileRef{},
|
||||
nil,
|
||||
),
|
||||
fmt.Sprintf("retrieval failed: error while locating partial retrieval sub-root: unsupported selection path '%s' does not correspond to a block boundary (a.k.a. CID link)", textSelectorNonLink),
|
||||
)
|
||||
}
|
||||
|
||||
func testGenesisRetrieval(ctx context.Context, client *kit.TestFullNode, retOrder api.RetrievalOrder, retRef *api.FileRef, outFile *os.File) error {
|
||||
|
||||
if retOrder.Total.Nil() {
|
||||
retOrder.Total = big.Zero()
|
||||
}
|
||||
if retOrder.UnsealPrice.Nil() {
|
||||
retOrder.UnsealPrice = big.Zero()
|
||||
}
|
||||
|
||||
err := client.ClientRetrieve(ctx, retOrder, retRef)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var data []byte
|
||||
if !retRef.IsCAR {
|
||||
|
||||
data, err = io.ReadAll(outFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
cr, err := car.NewCarReader(outFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(cr.Header.Roots) != 1 {
|
||||
return fmt.Errorf("expected a single root in result car, got %d", len(cr.Header.Roots))
|
||||
} else if cr.Header.Roots[0].String() != carRoot.String() {
|
||||
return fmt.Errorf("expected root cid '%s', got '%s'", carRoot.String(), cr.Header.Roots[0].String())
|
||||
}
|
||||
|
||||
blks := make([]blocks.Block, 0)
|
||||
for {
|
||||
b, err := cr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
blks = append(blks, b)
|
||||
}
|
||||
|
||||
if len(blks) != 3 {
|
||||
return fmt.Errorf("expected a car file with 3 blocks, got one with %d instead", len(blks))
|
||||
}
|
||||
|
||||
data = blks[2].RawData()
|
||||
}
|
||||
|
||||
if string(data) != expectedResult {
|
||||
return fmt.Errorf("retrieved data mismatch: expected '%s' got '%s'", expectedResult, data)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
package itests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
"github.com/filecoin-project/lotus/markets/storageadapter"
|
||||
"github.com/filecoin-project/lotus/node"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
"github.com/filecoin-project/lotus/node/modules"
|
||||
"github.com/filecoin-project/lotus/storage"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
publishPeriod = 1 * time.Second
|
||||
maxDealsPerMsg = uint64(2) // Set max deals per publish deals message to 2
|
||||
|
||||
blockTime = 3 * time.Millisecond
|
||||
)
|
||||
|
||||
func TestDealsRetryLackOfFunds(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
oldDelay := policy.GetPreCommitChallengeDelay()
|
||||
policy.SetPreCommitChallengeDelay(5)
|
||||
|
||||
t.Cleanup(func() {
|
||||
policy.SetPreCommitChallengeDelay(oldDelay)
|
||||
})
|
||||
|
||||
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg8MiBV1)
|
||||
kit.QuietMiningLogs()
|
||||
|
||||
// Allow 8MB sectors
|
||||
eightMBSectorsOpt := kit.SectorSize(8 << 20)
|
||||
|
||||
publishStorageDealKey, err := wallet.GenerateKey(types.KTSecp256k1)
|
||||
require.NoError(t, err)
|
||||
|
||||
opts := node.Options(
|
||||
node.Override(new(*storageadapter.DealPublisher),
|
||||
storageadapter.NewDealPublisher(nil, storageadapter.PublishMsgConfig{
|
||||
Period: publishPeriod,
|
||||
MaxDealsPerMsg: maxDealsPerMsg,
|
||||
}),
|
||||
),
|
||||
node.Override(new(*storage.AddressSelector), modules.AddressSelector(&config.MinerAddressConfig{
|
||||
DealPublishControl: []string{
|
||||
publishStorageDealKey.Address.String(),
|
||||
},
|
||||
DisableOwnerFallback: true,
|
||||
DisableWorkerFallback: true,
|
||||
})),
|
||||
)
|
||||
|
||||
publishStorageAccountFunds := types.NewInt(1020000000000)
|
||||
minerFullNode, clientFullNode, miner, ens := kit.EnsembleTwoOne(t, kit.Account(publishStorageDealKey, publishStorageAccountFunds), kit.ConstructorOpts(opts), kit.MockProofs(), eightMBSectorsOpt)
|
||||
|
||||
kit.QuietMiningLogs()
|
||||
|
||||
ens.
|
||||
Start().
|
||||
InterconnectAll().
|
||||
BeginMining(blockTime)
|
||||
|
||||
_, err = minerFullNode.WalletImport(ctx, &publishStorageDealKey.KeyInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
miner.SetControlAddresses(publishStorageDealKey.Address)
|
||||
|
||||
dh := kit.NewDealHarness(t, clientFullNode, miner, miner)
|
||||
|
||||
res, _ := clientFullNode.CreateImportFile(ctx, 0, 4<<20) // 4MiB file.
|
||||
list, err := clientFullNode.ClientListImports(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, list, 1)
|
||||
require.Equal(t, res.Root, *list[0].Root)
|
||||
|
||||
dp := dh.DefaultStartDealParams()
|
||||
dp.Data.Root = res.Root
|
||||
dp.FastRetrieval = true
|
||||
dp.EpochPrice = abi.NewTokenAmount(62500000) // minimum asking price.
|
||||
deal := dh.StartDeal(ctx, dp)
|
||||
|
||||
propcid := *deal
|
||||
|
||||
go func() {
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
kit.SendFunds(ctx, t, minerFullNode, publishStorageDealKey.Address, types.FromFil(1))
|
||||
|
||||
err := miner.MarketRetryPublishDeal(ctx, propcid)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
dh.WaitDealSealed(ctx, deal, false, false, nil)
|
||||
}
|
||||
|
||||
func TestDealsRetryLackOfFunds_blockInPublishDeal(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
oldDelay := policy.GetPreCommitChallengeDelay()
|
||||
policy.SetPreCommitChallengeDelay(5)
|
||||
|
||||
t.Cleanup(func() {
|
||||
policy.SetPreCommitChallengeDelay(oldDelay)
|
||||
})
|
||||
|
||||
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg8MiBV1)
|
||||
kit.QuietMiningLogs()
|
||||
|
||||
// Allow 8MB sectors
|
||||
eightMBSectorsOpt := kit.SectorSize(8 << 20)
|
||||
|
||||
publishStorageDealKey, err := wallet.GenerateKey(types.KTSecp256k1)
|
||||
require.NoError(t, err)
|
||||
|
||||
opts := node.Options(
|
||||
node.Override(new(*storageadapter.DealPublisher),
|
||||
storageadapter.NewDealPublisher(nil, storageadapter.PublishMsgConfig{
|
||||
Period: publishPeriod,
|
||||
MaxDealsPerMsg: maxDealsPerMsg,
|
||||
}),
|
||||
),
|
||||
node.Override(new(*storage.AddressSelector), modules.AddressSelector(&config.MinerAddressConfig{
|
||||
DealPublishControl: []string{
|
||||
publishStorageDealKey.Address.String(),
|
||||
},
|
||||
DisableOwnerFallback: true,
|
||||
DisableWorkerFallback: true,
|
||||
})),
|
||||
)
|
||||
|
||||
publishStorageAccountFunds := types.NewInt(1020000000000)
|
||||
minerFullNode, clientFullNode, miner, ens := kit.EnsembleTwoOne(t, kit.Account(publishStorageDealKey, publishStorageAccountFunds), kit.ConstructorOpts(opts), kit.MockProofs(), eightMBSectorsOpt)
|
||||
|
||||
kit.QuietMiningLogs()
|
||||
|
||||
ens.
|
||||
Start().
|
||||
InterconnectAll().
|
||||
BeginMining(blockTime)
|
||||
|
||||
_, err = minerFullNode.WalletImport(ctx, &publishStorageDealKey.KeyInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
miner.SetControlAddresses(publishStorageDealKey.Address)
|
||||
|
||||
dh := kit.NewDealHarness(t, clientFullNode, miner, miner)
|
||||
|
||||
res, _ := clientFullNode.CreateImportFile(ctx, 0, 4<<20) // 4MiB file.
|
||||
list, err := clientFullNode.ClientListImports(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, list, 1)
|
||||
require.Equal(t, res.Root, *list[0].Root)
|
||||
|
||||
dp := dh.DefaultStartDealParams()
|
||||
dp.Data.Root = res.Root
|
||||
dp.FastRetrieval = true
|
||||
dp.EpochPrice = abi.NewTokenAmount(62500000) // minimum asking price.
|
||||
deal := dh.StartDeal(ctx, dp)
|
||||
|
||||
dealSealed := make(chan struct{})
|
||||
go func() {
|
||||
dh.WaitDealSealedQuiet(ctx, deal, false, false, nil)
|
||||
dealSealed <- struct{}{}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-dealSealed:
|
||||
t.Fatal("deal shouldn't have sealed")
|
||||
case <-time.After(time.Second * 15):
|
||||
}
|
||||
}
|
||||
|
||||
func TestDealsRetryLackOfFunds_belowLimit(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
oldDelay := policy.GetPreCommitChallengeDelay()
|
||||
policy.SetPreCommitChallengeDelay(5)
|
||||
|
||||
t.Cleanup(func() {
|
||||
policy.SetPreCommitChallengeDelay(oldDelay)
|
||||
})
|
||||
|
||||
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg8MiBV1)
|
||||
kit.QuietMiningLogs()
|
||||
|
||||
// Allow 8MB sectors
|
||||
eightMBSectorsOpt := kit.SectorSize(8 << 20)
|
||||
|
||||
publishStorageDealKey, err := wallet.GenerateKey(types.KTSecp256k1)
|
||||
require.NoError(t, err)
|
||||
|
||||
opts := node.Options(
|
||||
node.Override(new(*storageadapter.DealPublisher),
|
||||
storageadapter.NewDealPublisher(nil, storageadapter.PublishMsgConfig{
|
||||
Period: publishPeriod,
|
||||
MaxDealsPerMsg: maxDealsPerMsg,
|
||||
}),
|
||||
),
|
||||
node.Override(new(*storage.AddressSelector), modules.AddressSelector(&config.MinerAddressConfig{
|
||||
DealPublishControl: []string{
|
||||
publishStorageDealKey.Address.String(),
|
||||
},
|
||||
DisableOwnerFallback: true,
|
||||
DisableWorkerFallback: true,
|
||||
})),
|
||||
)
|
||||
|
||||
publishStorageAccountFunds := types.NewInt(1)
|
||||
minerFullNode, clientFullNode, miner, ens := kit.EnsembleTwoOne(t, kit.Account(publishStorageDealKey, publishStorageAccountFunds), kit.ConstructorOpts(opts), kit.MockProofs(), eightMBSectorsOpt)
|
||||
|
||||
kit.QuietMiningLogs()
|
||||
|
||||
ens.
|
||||
Start().
|
||||
InterconnectAll().
|
||||
BeginMining(blockTime)
|
||||
|
||||
_, err = minerFullNode.WalletImport(ctx, &publishStorageDealKey.KeyInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
miner.SetControlAddresses(publishStorageDealKey.Address)
|
||||
|
||||
dh := kit.NewDealHarness(t, clientFullNode, miner, miner)
|
||||
|
||||
res, _ := clientFullNode.CreateImportFile(ctx, 0, 4<<20) // 4MiB file.
|
||||
list, err := clientFullNode.ClientListImports(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, list, 1)
|
||||
require.Equal(t, res.Root, *list[0].Root)
|
||||
|
||||
dp := dh.DefaultStartDealParams()
|
||||
dp.Data.Root = res.Root
|
||||
dp.FastRetrieval = true
|
||||
dp.EpochPrice = abi.NewTokenAmount(62500000) // minimum asking price.
|
||||
deal := dh.StartDeal(ctx, dp)
|
||||
|
||||
err = dh.ExpectDealFailure(ctx, deal, "actor balance less than needed")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user