Compare commits

..
Author SHA1 Message Date
Raúl Kripalani 72391cca20 LOTUS_DAGSTORE_COPY_CONCURRENCY for controlling copy concurrency. 2021-07-29 21:36:43 +01:00
Aarsh Shah 88efbfa6ff go fmt 2021-07-30 01:44:47 +05:30
Aarsh Shah fcd630e529 call dagstore start 2021-07-30 01:43:34 +05:30
Raúl Kripalani 073150a306 Merge branch 'release/v1.11.1' into feat/replace-multistore-carv2 2021-07-29 18:42:09 +01:00
Raúl Kripalani 94318da0e6 update go-fil-markets; better log. 2021-07-28 17:14:33 +01:00
Raúl Kripalani 9ba6a41ef4 fix dagstore/piecestore lifecycle. 2021-07-28 17:08:04 +01:00
Raúl Kripalani 5d047c59b1 bubble up better migrator logging. 2021-07-28 16:48:38 +01:00
raulk 80fcad5ad5 Merge pull request #6908 from filecoin-project/fix/dagstore-throttle
dagstore: throttle calls to storage except actual unseals.
2021-07-28 16:44:04 +01:00
Raúl Kripalani b6112c6fc9 wire in copy throttling. 2021-07-28 16:28:27 +01:00
Raúl Kripalani 650d6efb1a dagstore: throttle calls to storage except actual unseals. 2021-07-28 15:39:23 +01:00
Raúl Kripalani db6b94cf1e Merge commit '56d80030001b8c443f486a48e8c8ac70d8e1ba77' into feat/replace-multistore-carv2 2021-07-27 23:20:15 +01:00
Raúl Kripalani 7c2341b43c Merge branch 'master' into feat/replace-multistore-carv2 2021-07-27 22:23:28 +01:00
Raúl Kripalani 19182999dd Merge branch 'master' into feat/replace-multistore-carv2 2021-07-27 22:06:07 +01:00
Raúl Kripalani 2a2b442aae pacify the linter. 2021-07-27 21:25:22 +01:00
Raúl Kripalani d0353d1ef1 Merge branch 'feat/cli-super-verbose' into feat/replace-multistore-carv2 2021-07-27 21:23:31 +01:00
Raúl Kripalani 1250f8009f upgrade go-fil-markets. 2021-07-27 21:15:24 +01:00
Raúl Kripalani 4b70d13a4b update dependencies. 2021-07-27 21:04:59 +01:00
Raúl Kripalani 987fc0b77d Merge branch 'master' into feat/replace-multistore-carv2 2021-07-27 21:02:52 +01:00
Raúl Kripalani 6e9f480063 markets event logger: avoid creating a slice with every event. 2021-07-27 19:34:16 +01:00
Raúl Kripalani 80b334d04f upgrade dagstore to v0.3.1. 2021-07-27 18:24:23 +01:00
aarshkshah1992 944aeed13e remove dead code 2021-07-27 22:16:45 +05:30
Raúl Kripalani 109a8242ae implement conditional throttling in lotus mount. 2021-07-27 17:24:48 +01:00
Raúl Kripalani 18f5997d02 add throttling to dagstore; increase GC frequency to 1min. 2021-07-27 15:11:49 +01:00
Raúl Kripalani 160fab08aa fix lint and gen errors. 2021-07-26 23:32:51 +01:00
Raúl Kripalani 9bdbbf33cb Merge branch 'master' into feat/replace-multistore-carv2 2021-07-26 22:15:36 +01:00
aarshkshah1992 50e1dc6b6e bubble up markets and dagstore changes for m1.1 2021-07-26 19:44:59 +05:30
Aarsh Shah 48e8f54c6a Merge pull request #6835 from filecoin-project/feat/dag-store-ds
Create DAG store datastore under DAG store dir
2021-07-22 17:34:44 +05:30
Dirk McCormick 776c216072 feat: create DAG store datastore under DAG store dir 2021-07-22 13:58:25 +02:00
Anton Evangelatov c60959ea9f fetch peer id from chain 2021-07-22 10:50:55 +02:00
Aarsh Shah 62044c34b1 Merge pull request #6826 from filecoin-project/fix/dagstore-wrapper-bugs
Fix bugs in the DAGStore wrapper
2021-07-22 11:30:38 +05:30
aarshkshah1992 c8d328d386 fix bugs in the dagstore wrapper 2021-07-22 09:44:14 +05:30
aarshkshah1992 fd879e0426 update ds 2021-07-22 00:21:39 +05:30
aarshkshah1992 27f3170022 update dagstore 2021-07-21 23:38:22 +05:30
aarshkshah1992 5b1241d213 fix dagstore errors 2021-07-21 23:15:39 +05:30
aarshkshah1992 eaee1578dd log more 2021-07-21 22:47:31 +05:30
aarshkshah1992 9e5c5b624b update dagstore logs 2021-07-21 22:22:26 +05:30
aarshkshah1992 640d69f5cb update dagstire 2021-07-21 21:54:28 +05:30
aarshkshah1992 36876c2601 update deps 2021-07-21 20:50:47 +05:30
Dirk McCormick 39c1594505 feat: add logs to wrapper load shard 2021-07-21 17:18:23 +02:00
Aarsh Shah 86e1c854fa Merge pull request #6814 from filecoin-project/nonsense/add-sealproof-in-sectorbuilder
add SealProof in sector builder
2021-07-21 20:44:01 +05:30
Anton Evangelatov 1af89236da add SealProof in sector builder 2021-07-21 15:49:45 +02:00
aarshkshah1992 9741867426 remove dev.gen 2021-07-21 17:55:53 +05:30
Aarsh Shah b7b98f94a6 Delete localnet.json 2021-07-21 17:50:52 +05:30
Aarsh Shah fb50d68c32 Merge pull request #6812 from filecoin-project/fix/ensure-mount-started
Ensure piece store starts before calling lotus accessor methods
2021-07-21 17:49:35 +05:30
aarshkshah1992 692961e019 fix error handling 2021-07-21 17:49:09 +05:30
aarshkshah1992 312cc94e6d Merge branch 'feat/replace-multistore-carv2' of github.com:filecoin-project/lotus into feat/replace-multistore-carv2 2021-07-21 17:42:52 +05:30
aarshkshah1992 ea71e4de60 update dagstore fix 2021-07-21 17:42:19 +05:30
aarshkshah1992 4ed9cd152c fix lotus accessor startup 2021-07-21 17:34:07 +05:30
Dirk McCormick 0dbb1940f0 fix: ensure piece store starts before calling lotus accessor methods 2021-07-21 13:31:20 +02:00
dirkmc 1452a361a9 Merge pull request #6809 from filecoin-project/fix/dagstore-tests
fix dagstore tests
2021-07-21 12:24:53 +02:00
Dirk McCormick 503c08f999 fix: dagstore tests 2021-07-21 12:23:55 +02:00
aarshkshah1992 6bee14d6fa update dagstore and markets 2021-07-21 15:34:38 +05:30
dirkmc 839abdf910 Merge pull request #6808 from filecoin-project/fix/wait-piece-store-start
Wait for piece store to start before starting DAG store wrapper
2021-07-21 11:57:31 +02:00
Dirk McCormick 6057f2e6d9 fix: wait for piece store to start before starting DAG store wrapper 2021-07-21 11:56:48 +02:00
aarshkshah1992 213dbc6bc8 update dagstore 2021-07-21 14:54:33 +05:30
Aarsh Shah fc77705229 Merge pull request #6806 from filecoin-project/fix/lotus-mount-caps
capitalize lotus mount fields for deserialization
2021-07-21 14:24:11 +05:30
Dirk McCormick 12d7db4efb fix: capitalize lotus mount fields for deserialization 2021-07-21 10:45:14 +02:00
aarshkshah1992 d7827da5bb update deps 2021-07-21 09:30:33 +05:30
Aarsh Shah b2ff2edd0c Merge branch 'master' into feat/replace-multistore-carv2 2021-07-20 22:03:18 +05:30
aarshkshah1992 13e845ae51 fix import test 2021-07-20 21:47:55 +05:30
aarshkshah1992 0c90868929 get it compiling 2021-07-20 21:44:25 +05:30
Aarsh Shah 44496afc66 Merge pull request #6793 from filecoin-project/refactor/mv-lotus-mount
move lotus mount, dag store etc from markets to lotus
2021-07-20 20:33:46 +05:30
Dirk McCormick 8becd922cf test: for dag store wrapper 2021-07-20 15:05:08 +02:00
Dirk McCormick 16be5b5478 fix: add comment about car path 2021-07-20 12:52:45 +02:00
Dirk McCormick 1e7095995b refactor: use concrete type in DI for dag store wrapper 2021-07-20 12:45:20 +02:00
Dirk McCormick ffb995035f feat: log trace events 2021-07-20 12:37:52 +02:00
Dirk McCormick ffe7185443 fix: simplify recover shard processing 2021-07-20 11:50:40 +02:00
Dirk McCormick 44036d9a4a fix: address review comments 2021-07-20 11:04:47 +02:00
Dirk McCormick b6a7a8c987 refactor: move lotus mount, dag store etc from markets to lotus 2021-07-19 15:53:34 +02:00
aarshkshah1992 905592a3dc integrate unsealing changes with Lotus 2021-07-19 16:12:58 +05:30
aarshkshah1992 9724248a49 update lotus soup go mod 2021-07-15 18:33:15 +05:30
aarshkshah1992 ed058ae193 update go mod 2021-07-15 18:21:35 +05:30
aarshkshah1992 ca5a2eaa74 update lotus soup and address nit 2021-07-15 18:08:41 +05:30
aarshkshah1992 35b39063ac add tests and merge master 2021-07-15 17:50:35 +05:30
aarshkshah1992 33c347956c rebased and fixed tests 2021-07-15 14:47:10 +05:30
aarshkshah1992 a259ee307f resolve conflicts 2021-07-15 14:27:48 +05:30
aarshkshah1992 46b78406b1 replace badger in storage client 2021-07-15 14:26:02 +05:30
Dirk McCormick 872843e491 feat: integrate dag store into lotus 2021-07-09 10:59:10 +02:00
aarshkshah1992 a5ba556fff fix lint 2021-07-07 14:47:00 +05:30
aarshkshah1992 44d088be1e use filestore to create the Unixfs dag 2021-07-07 14:43:12 +05:30
aarshkshah1992 b40985a57c Merge remote-tracking branch 'origin/nonsense/split-market-miner-processes' into feat/replace-multistore-carv2 2021-07-07 14:11:55 +05:30
aarshkshah1992 f8d32f5328 changes as per review 2021-07-07 14:10:59 +05:30
aarshkshah1992 ba236fe258 have a typed importID 2021-07-07 12:02:48 +05:30
aarshkshah1992 2b5164c956 Merge remote-tracking branch 'origin/feat/replace-multistore-carv2-rtrvl-pr' into feat/replace-multistore-carv2 2021-07-07 11:11:53 +05:30
aarshkshah1992 ca2d441b6d integrate dagstore 2021-07-07 11:11:29 +05:30
Anton Evangelatov 51696bb35d fix SectorsStatus to query full node for on-chain data 2021-07-06 16:34:07 +02:00
Dirk McCormick bed4c03a50 feat: integrate go-fil-markets#560 2021-07-06 11:09:05 +02:00
aarshkshah1992 e041fe130b tests for storage client import impls 2021-07-06 12:40:57 +05:30
aarshkshah1992 a07a0935fe fix bug in CAR generation 2021-07-06 09:31:52 +05:30
aarshkshah1992 de13b6edc5 dont upgrade multihash 2021-07-03 14:26:03 +05:30
aarshkshah1992 303d5d6ff6 removed combined blockstore 2021-07-03 14:12:08 +05:30
aarshkshah1992 40b30d1fb1 remove multistore from Lotus 2021-07-03 14:12:08 +05:30
aarshkshah1992 dae6c757b5 lotus changes for the DAG Store 2021-07-03 14:12:08 +05:30
aarshkshah1992 31ecce3a72 draft lotus storage client CARv2 changes 2021-07-03 14:12:08 +05:30
820 changed files with 23343 additions and 67477 deletions
+49 -108
View File
@@ -44,13 +44,13 @@ commands:
- restore_cache: - restore_cache:
name: Restore parameters cache name: Restore parameters cache
keys: keys:
- 'v26-2k-lotus-params' - 'v25-2k-lotus-params'
paths: paths:
- /var/tmp/filecoin-proof-parameters/ - /var/tmp/filecoin-proof-parameters/
- run: ./lotus fetch-params 2048 - run: ./lotus fetch-params 2048
- save_cache: - save_cache:
name: Save parameters cache name: Save parameters cache
key: 'v26-2k-lotus-params' key: 'v25-2k-lotus-params'
paths: paths:
- /var/tmp/filecoin-proof-parameters/ - /var/tmp/filecoin-proof-parameters/
install_ipfs: install_ipfs:
@@ -92,9 +92,6 @@ jobs:
- run: sudo apt-get install npm - run: sudo apt-get install npm
- run: - run:
command: make buildall command: make buildall
- run:
name: check tag and version output match
command: ./scripts/version-check.sh ./lotus
- store_artifacts: - store_artifacts:
path: lotus path: lotus
- store_artifacts: - store_artifacts:
@@ -285,6 +282,21 @@ jobs:
root: "." root: "."
paths: paths:
- linux-butterflynet - 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: build-lotus-soup:
description: | description: |
Compile `lotus-soup` Testground test plan Compile `lotus-soup` Testground test plan
@@ -318,7 +330,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 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: - run:
name: "prepare testground home dir and link test plans" 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 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
- run: - run:
name: "go get lotus@master" name: "go get lotus@master"
command: cd testplans/lotus-soup && go get github.com/filecoin-project/lotus@master command: cd testplans/lotus-soup && go get github.com/filecoin-project/lotus@master
@@ -328,11 +340,15 @@ jobs:
- run: - run:
name: "trigger payment channel stress testplan on taas" 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 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: build-macos:
description: build darwin lotus binary description: build darwin lotus binary
macos: macos:
xcode: "12.5.0" xcode: "10.0.0"
working_directory: ~/go/src/github.com/filecoin-project/lotus working_directory: ~/go/src/github.com/filecoin-project/lotus
steps: steps:
- prepare: - prepare:
@@ -351,6 +367,11 @@ jobs:
name: Install Rust name: Install Rust
command: | command: |
curl https://sh.rustup.rs -sSf | sh -s -- -y curl https://sh.rustup.rs -sSf | sh -s -- -y
- run:
name: Install jq
command: |
curl --location https://github.com/stedolan/jq/releases/download/jq-1.6/jq-osx-amd64 --output /usr/local/bin/jq
chmod +x /usr/local/bin/jq
- run: - run:
name: Install hwloc name: Install hwloc
command: | command: |
@@ -367,9 +388,6 @@ jobs:
- run: - run:
command: make build command: make build
no_output_timeout: 30m no_output_timeout: 30m
- run:
name: check tag and version output match
command: ./scripts/version-check.sh ./lotus
- store_artifacts: - store_artifacts:
path: lotus path: lotus
- store_artifacts: - store_artifacts:
@@ -390,7 +408,7 @@ jobs:
build-appimage: build-appimage:
machine: machine:
image: ubuntu-2004:202111-02 image: ubuntu-2004:202104-01
steps: steps:
- checkout - checkout
- attach_workspace: - attach_workspace:
@@ -398,16 +416,6 @@ jobs:
- run: - run:
name: install appimage-builder name: install appimage-builder
command: | command: |
# appimage-builder requires /dev/snd to exist. It creates containers during the testing phase
# that pass sound devices from the host to the testing container. (hard coded!)
# https://github.com/AppImageCrafters/appimage-builder/blob/master/appimagebuilder/modules/test/execution_test.py#L54
# Circleci doesn't provide a working sound device; this is enough to fake it.
if [ ! -e /dev/snd ]
then
sudo mkdir /dev/snd
sudo mknod /dev/snd/ControlC0 c 1 2
fi
# docs: https://appimage-builder.readthedocs.io/en/latest/intro/install.html # docs: https://appimage-builder.readthedocs.io/en/latest/intro/install.html
sudo apt update sudo apt update
sudo apt install -y python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace sudo apt install -y python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace
@@ -628,11 +636,6 @@ jobs:
default: "latest" default: "latest"
description: A comma-separated string containing docker image tags to build and push (default = latest) description: A comma-separated string containing docker image tags to build and push (default = latest)
target:
type: string
default: "lotus-all-in-one"
description: Docker target to build
steps: steps:
- run: - run:
name: Confirm that environment variables are set name: Confirm that environment variables are set
@@ -672,7 +675,6 @@ jobs:
docker build \ docker build \
<<#parameters.extra-build-args>><<parameters.extra-build-args>><</parameters.extra-build-args>> \ <<#parameters.extra-build-args>><<parameters.extra-build-args>><</parameters.extra-build-args>> \
--target <<parameters.target>> \
-f <<parameters.path>>/<<parameters.dockerfile>> \ -f <<parameters.path>>/<<parameters.dockerfile>> \
$docker_tag_args \ $docker_tag_args \
<<parameters.path>> <<parameters.path>>
@@ -721,8 +723,8 @@ jobs:
- packer/build: - packer/build:
template: tools/packer/lotus.pkr.hcl template: tools/packer/lotus.pkr.hcl
args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG"
publish-packer-snap: publish-packer-nerpanet:
description: build packer image with snap. mainnet only. description: build and push AWS IAM and DigitalOcean droplet.
executor: executor:
name: packer/default name: packer/default
packer-version: 1.6.6 packer-version: 1.6.6
@@ -731,7 +733,8 @@ jobs:
- attach_workspace: - attach_workspace:
at: "." at: "."
- packer/build: - packer/build:
template: tools/packer/lotus-snap.pkr.hcl template: tools/packer/lotus.pkr.hcl
args: "-var ci_workspace_bins=./linux-nerpanet -var lotus_network=nerpanet -var git_tag=$CIRCLE_TAG"
publish-dockerhub: publish-dockerhub:
description: publish to dockerhub description: publish to dockerhub
machine: machine:
@@ -807,26 +810,11 @@ workflows:
suite: itest-deadlines suite: itest-deadlines
target: "./itests/deadlines_test.go" target: "./itests/deadlines_test.go"
- test:
name: test-itest-deals_512mb
suite: itest-deals_512mb
target: "./itests/deals_512mb_test.go"
- test:
name: test-itest-deals_anycid
suite: itest-deals_anycid
target: "./itests/deals_anycid_test.go"
- test: - test:
name: test-itest-deals_concurrent name: test-itest-deals_concurrent
suite: itest-deals_concurrent suite: itest-deals_concurrent
target: "./itests/deals_concurrent_test.go" target: "./itests/deals_concurrent_test.go"
- test:
name: test-itest-deals_max_staging_deals
suite: itest-deals_max_staging_deals
target: "./itests/deals_max_staging_deals_test.go"
- test: - test:
name: test-itest-deals_offline name: test-itest-deals_offline
suite: itest-deals_offline suite: itest-deals_offline
@@ -837,16 +825,6 @@ workflows:
suite: itest-deals_padding suite: itest-deals_padding
target: "./itests/deals_padding_test.go" target: "./itests/deals_padding_test.go"
- test:
name: test-itest-deals_partial_retrieval_dm-level
suite: itest-deals_partial_retrieval_dm-level
target: "./itests/deals_partial_retrieval_dm-level_test.go"
- test:
name: test-itest-deals_partial_retrieval
suite: itest-deals_partial_retrieval
target: "./itests/deals_partial_retrieval_test.go"
- test: - test:
name: test-itest-deals_power name: test-itest-deals_power
suite: itest-deals_power suite: itest-deals_power
@@ -862,11 +840,6 @@ workflows:
suite: itest-deals_publish suite: itest-deals_publish
target: "./itests/deals_publish_test.go" 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: - test:
name: test-itest-deals name: test-itest-deals
suite: itest-deals suite: itest-deals
@@ -882,11 +855,6 @@ workflows:
suite: itest-get_messages_in_ts suite: itest-get_messages_in_ts
target: "./itests/get_messages_in_ts_test.go" target: "./itests/get_messages_in_ts_test.go"
- test:
name: test-itest-mempool
suite: itest-mempool
target: "./itests/mempool_test.go"
- test: - test:
name: test-itest-multisig name: test-itest-multisig
suite: itest-multisig suite: itest-multisig
@@ -917,11 +885,6 @@ workflows:
suite: itest-sector_finalize_early suite: itest-sector_finalize_early
target: "./itests/sector_finalize_early_test.go" target: "./itests/sector_finalize_early_test.go"
- test:
name: test-itest-sector_make_cc_avail
suite: itest-sector_make_cc_avail
target: "./itests/sector_make_cc_avail_test.go"
- test: - test:
name: test-itest-sector_miner_collateral name: test-itest-sector_miner_collateral
suite: itest-sector_miner_collateral suite: itest-sector_miner_collateral
@@ -932,26 +895,11 @@ workflows:
suite: itest-sector_pledge suite: itest-sector_pledge
target: "./itests/sector_pledge_test.go" target: "./itests/sector_pledge_test.go"
- test:
name: test-itest-sector_prefer_no_upgrade
suite: itest-sector_prefer_no_upgrade
target: "./itests/sector_prefer_no_upgrade_test.go"
- test:
name: test-itest-sector_revert_available
suite: itest-sector_revert_available
target: "./itests/sector_revert_available_test.go"
- test: - test:
name: test-itest-sector_terminate name: test-itest-sector_terminate
suite: itest-sector_terminate suite: itest-sector_terminate
target: "./itests/sector_terminate_test.go" target: "./itests/sector_terminate_test.go"
- test:
name: test-itest-self_sent_txn
suite: itest-self_sent_txn
target: "./itests/self_sent_txn_test.go"
- test: - test:
name: test-itest-tape name: test-itest-tape
suite: itest-tape suite: itest-tape
@@ -972,11 +920,6 @@ workflows:
suite: itest-wdpost suite: itest-wdpost
target: "./itests/wdpost_test.go" target: "./itests/wdpost_test.go"
- test:
name: test-itest-worker
suite: itest-worker
target: "./itests/worker_test.go"
- test: - test:
name: test-unit-cli name: test-unit-cli
suite: utest-unit-cli suite: utest-unit-cli
@@ -1007,7 +950,7 @@ workflows:
codecov-upload: false codecov-upload: false
suite: conformance-bleeding-edge suite: conformance-bleeding-edge
target: "./conformance" target: "./conformance"
vectors-branch: specs-actors-v7 vectors-branch: master
- trigger-testplans: - trigger-testplans:
filters: filters:
branches: branches:
@@ -1029,6 +972,11 @@ workflows:
tags: tags:
only: only:
- /^v\d+\.\d+\.\d+(-rc\d+)?$/ - /^v\d+\.\d+\.\d+(-rc\d+)?$/
- build-ntwk-nerpa:
filters:
tags:
only:
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
- build-lotus-soup - build-lotus-soup
- build-macos: - build-macos:
filters: filters:
@@ -1063,13 +1011,6 @@ workflows:
path: . path: .
repo: lotus-dev repo: lotus-dev
tag: '${CIRCLE_SHA1:0:8}' tag: '${CIRCLE_SHA1:0:8}'
target: lotus-all-in-one
- build-and-push-image:
dockerfile: Dockerfile.lotus
path: .
repo: lotus-test
tag: '${CIRCLE_SHA1:0:8}'
target: lotus-test
- publish-packer-mainnet: - publish-packer-mainnet:
requires: requires:
- build-all - build-all
@@ -1100,6 +1041,16 @@ workflows:
tags: tags:
only: only:
- /^v\d+\.\d+\.\d+(-rc\d+)?$/ - /^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: - publish-snapcraft:
name: publish-snapcraft-stable name: publish-snapcraft-stable
channel: stable channel: stable
@@ -1136,13 +1087,3 @@ workflows:
- publish-dockerhub: - publish-dockerhub:
name: publish-dockerhub-nightly name: publish-dockerhub-nightly
tag: nightly tag: nightly
monthly:
triggers:
- schedule:
cron: "0 0 1 * *"
filters:
branches:
only:
- master
jobs:
- publish-packer-snap
+49 -48
View File
@@ -44,13 +44,13 @@ commands:
- restore_cache: - restore_cache:
name: Restore parameters cache name: Restore parameters cache
keys: keys:
- 'v26-2k-lotus-params' - 'v25-2k-lotus-params'
paths: paths:
- /var/tmp/filecoin-proof-parameters/ - /var/tmp/filecoin-proof-parameters/
- run: ./lotus fetch-params 2048 - run: ./lotus fetch-params 2048
- save_cache: - save_cache:
name: Save parameters cache name: Save parameters cache
key: 'v26-2k-lotus-params' key: 'v25-2k-lotus-params'
paths: paths:
- /var/tmp/filecoin-proof-parameters/ - /var/tmp/filecoin-proof-parameters/
install_ipfs: install_ipfs:
@@ -92,9 +92,6 @@ jobs:
- run: sudo apt-get install npm - run: sudo apt-get install npm
- run: - run:
command: make buildall command: make buildall
- run:
name: check tag and version output match
command: ./scripts/version-check.sh ./lotus
- store_artifacts: - store_artifacts:
path: lotus path: lotus
- store_artifacts: - store_artifacts:
@@ -285,6 +282,21 @@ jobs:
root: "." root: "."
paths: paths:
- linux-butterflynet - 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: build-lotus-soup:
description: | description: |
Compile `lotus-soup` Testground test plan Compile `lotus-soup` Testground test plan
@@ -318,7 +330,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 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: - run:
name: "prepare testground home dir and link test plans" 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 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
- run: - run:
name: "go get lotus@master" name: "go get lotus@master"
command: cd testplans/lotus-soup && go get github.com/filecoin-project/lotus@master command: cd testplans/lotus-soup && go get github.com/filecoin-project/lotus@master
@@ -328,11 +340,15 @@ jobs:
- run: - run:
name: "trigger payment channel stress testplan on taas" 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 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: build-macos:
description: build darwin lotus binary description: build darwin lotus binary
macos: macos:
xcode: "12.5.0" xcode: "10.0.0"
working_directory: ~/go/src/github.com/filecoin-project/lotus working_directory: ~/go/src/github.com/filecoin-project/lotus
steps: steps:
- prepare: - prepare:
@@ -351,6 +367,11 @@ jobs:
name: Install Rust name: Install Rust
command: | command: |
curl https://sh.rustup.rs -sSf | sh -s -- -y curl https://sh.rustup.rs -sSf | sh -s -- -y
- run:
name: Install jq
command: |
curl --location https://github.com/stedolan/jq/releases/download/jq-1.6/jq-osx-amd64 --output /usr/local/bin/jq
chmod +x /usr/local/bin/jq
- run: - run:
name: Install hwloc name: Install hwloc
command: | command: |
@@ -367,9 +388,6 @@ jobs:
- run: - run:
command: make build command: make build
no_output_timeout: 30m no_output_timeout: 30m
- run:
name: check tag and version output match
command: ./scripts/version-check.sh ./lotus
- store_artifacts: - store_artifacts:
path: lotus path: lotus
- store_artifacts: - store_artifacts:
@@ -390,7 +408,7 @@ jobs:
build-appimage: build-appimage:
machine: machine:
image: ubuntu-2004:202111-02 image: ubuntu-2004:202104-01
steps: steps:
- checkout - checkout
- attach_workspace: - attach_workspace:
@@ -398,16 +416,6 @@ jobs:
- run: - run:
name: install appimage-builder name: install appimage-builder
command: | command: |
# appimage-builder requires /dev/snd to exist. It creates containers during the testing phase
# that pass sound devices from the host to the testing container. (hard coded!)
# https://github.com/AppImageCrafters/appimage-builder/blob/master/appimagebuilder/modules/test/execution_test.py#L54
# Circleci doesn't provide a working sound device; this is enough to fake it.
if [ ! -e /dev/snd ]
then
sudo mkdir /dev/snd
sudo mknod /dev/snd/ControlC0 c 1 2
fi
# docs: https://appimage-builder.readthedocs.io/en/latest/intro/install.html # docs: https://appimage-builder.readthedocs.io/en/latest/intro/install.html
sudo apt update sudo apt update
sudo apt install -y python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace sudo apt install -y python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace
@@ -628,11 +636,6 @@ jobs:
default: "latest" default: "latest"
description: A comma-separated string containing docker image tags to build and push (default = latest) description: A comma-separated string containing docker image tags to build and push (default = latest)
target:
type: string
default: "lotus-all-in-one"
description: Docker target to build
steps: steps:
- run: - run:
name: Confirm that environment variables are set name: Confirm that environment variables are set
@@ -672,7 +675,6 @@ jobs:
docker build \ docker build \
<<#parameters.extra-build-args>><<parameters.extra-build-args>><</parameters.extra-build-args>> \ <<#parameters.extra-build-args>><<parameters.extra-build-args>><</parameters.extra-build-args>> \
--target <<parameters.target>> \
-f <<parameters.path>>/<<parameters.dockerfile>> \ -f <<parameters.path>>/<<parameters.dockerfile>> \
$docker_tag_args \ $docker_tag_args \
<<parameters.path>> <<parameters.path>>
@@ -721,8 +723,8 @@ jobs:
- packer/build: - packer/build:
template: tools/packer/lotus.pkr.hcl template: tools/packer/lotus.pkr.hcl
args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG"
publish-packer-snap: publish-packer-nerpanet:
description: build packer image with snap. mainnet only. description: build and push AWS IAM and DigitalOcean droplet.
executor: executor:
name: packer/default name: packer/default
packer-version: 1.6.6 packer-version: 1.6.6
@@ -731,7 +733,8 @@ jobs:
- attach_workspace: - attach_workspace:
at: "." at: "."
- packer/build: - packer/build:
template: tools/packer/lotus-snap.pkr.hcl template: tools/packer/lotus.pkr.hcl
args: "-var ci_workspace_bins=./linux-nerpanet -var lotus_network=nerpanet -var git_tag=$CIRCLE_TAG"
publish-dockerhub: publish-dockerhub:
description: publish to dockerhub description: publish to dockerhub
machine: machine:
@@ -812,7 +815,7 @@ workflows:
codecov-upload: false codecov-upload: false
suite: conformance-bleeding-edge suite: conformance-bleeding-edge
target: "./conformance" target: "./conformance"
vectors-branch: specs-actors-v7 vectors-branch: master
- trigger-testplans: - trigger-testplans:
filters: filters:
branches: branches:
@@ -834,6 +837,11 @@ workflows:
tags: tags:
only: only:
- /^v\d+\.\d+\.\d+(-rc\d+)?$/ - /^v\d+\.\d+\.\d+(-rc\d+)?$/
- build-ntwk-nerpa:
filters:
tags:
only:
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
- build-lotus-soup - build-lotus-soup
- build-macos: - build-macos:
filters: filters:
@@ -868,13 +876,6 @@ workflows:
path: . path: .
repo: lotus-dev repo: lotus-dev
tag: '${CIRCLE_SHA1:0:8}' tag: '${CIRCLE_SHA1:0:8}'
target: lotus-all-in-one
- build-and-push-image:
dockerfile: Dockerfile.lotus
path: .
repo: lotus-test
tag: '${CIRCLE_SHA1:0:8}'
target: lotus-test
- publish-packer-mainnet: - publish-packer-mainnet:
requires: requires:
- build-all - build-all
@@ -905,6 +906,16 @@ workflows:
tags: tags:
only: only:
- /^v\d+\.\d+\.\d+(-rc\d+)?$/ - /^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: - publish-snapcraft:
name: publish-snapcraft-stable name: publish-snapcraft-stable
channel: stable channel: stable
@@ -941,13 +952,3 @@ workflows:
- publish-dockerhub: - publish-dockerhub:
name: publish-dockerhub-nightly name: publish-dockerhub-nightly
tag: nightly tag: nightly
monthly:
triggers:
- schedule:
cron: "0 0 1 * *"
filters:
branches:
only:
- master
jobs:
- publish-packer-snap
+18 -72
View File
@@ -1,73 +1,19 @@
comment: off
ignore: ignore:
# Auto generated - "**/cbor_gen.go"
- "^.*_gen.go$" - "api/test/**/*"
- "^.*/mock_full.go$" - "api/test/*"
# Old actors. - "gen/**/*"
- "^chain/actors/builtin/[^/]*/(message|state|v)[0-4]\\.go$" # We test the latest version only. - "gen/*"
# Tests - "cmd/lotus-shed/*"
- "api/test/**" - "cmd/tvx/*"
- "conformance/**" - "cmd/lotus-pcr/*"
# Generators - "cmd/tvx/*"
- "gen/**" - "cmd/lotus-chainwatch/*"
- "chain/actors/agen/**" - "cmd/lotus-health/*"
# Non-critical utilities - "cmd/lotus-fountain/*"
- "api/docgen/**" - "cmd/lotus-townhall/*"
- "api/docgen-openrpc/**" - "cmd/lotus-stats/*"
coverage: - "cmd/lotus-pcr/*"
status: github_checks:
patch: off annotations: false
project:
tools-and-tests:
target: auto
threshold: 1%
informational: true
paths:
- "testplans"
- "tools"
- "system"
- "snap"
- "lotuspond"
- "conformance"
- "scripts"
- "gen"
- "build"
markets:
target: auto
threshold: 1%
informational: false
paths:
- "markets"
- "paychmgr"
miner:
target: auto
threshold: 1.5%
informational: false
paths:
- "miner"
- "storage"
chain:
target: auto
threshold: 1%
informational: false
paths:
- "chain"
node:
target: auto
threshold: 1%
informational: false
paths:
- "node"
- "blockstore"
- "metrics"
- "lib"
- "genesis"
- "gateway"
- "api"
- "journal"
cli:
target: auto
threshold: 1%
informational: true
paths:
- "cli"
- "cmd"
+19 -27
View File
@@ -21,45 +21,35 @@ body:
required: true required: true
- label: I did not make any code changes to lotus. - label: I did not make any code changes to lotus.
required: false required: false
- type: checkboxes - type: dropdown
id: component-and-area
validations:
required: true
attributes: attributes:
label: Lotus component label: Lotus component
description: Please select the lotus component you are filing a bug for description: Please select the lotus component you are filing a bug for
options: options:
- label: lotus daemon - chain sync - lotus daemon - chain sync
required: false - lotus miner - mining and block production
- label: lotus miner - mining and block production - lotus miner/worker - sealing
required: false - lotus miner - proving(WindowPoSt)
- label: lotus miner/worker - sealing - lotus miner/market - storage deal
required: false - lotus miner/market - retrieval deal
- label: lotus miner - proving(WindowPoSt) - lotus client
required: false - lotus JSON-RPC API
- label: lotus miner/market - storage deal - lotus message management (mpool)
required: false - Other
- label: lotus miner/market - retrieval deal
required: false
- label: lotus miner/market - data transfer
required: false
- label: lotus client
required: false
- label: lotus JSON-RPC API
required: false
- label: lotus message management (mpool)
required: false
- label: Other
required: false
- type: textarea - type: textarea
id: version id: version
attributes: attributes:
label: Lotus Version label: Lotus Version
render: text
description: Enter the output of `lotus version` and `lotus-miner version` if applicable. description: Enter the output of `lotus version` and `lotus-miner version` if applicable.
placeholder: | placeholder: |
e.g. e.g.
Daemon:1.11.0-rc2+debug+git.0519cd371.dirty+api1.3.0 Daemon:1.11.0-rc2+debug+git.0519cd371.dirty+api1.3.0
Local: lotus version 1.11.0-rc2+debug+git.0519cd371.dirty Local: lotus version 1.11.0-rc2+debug+git.0519cd371.dirty
validations: validations:
required: true reuiqred: true
- type: textarea - type: textarea
id: Description id: Description
attributes: attributes:
@@ -72,18 +62,19 @@ body:
* For sealing issues, include the output of `lotus-miner sectors status --log <sectorId>` for the failed sector(s). * For sealing issues, include the output of `lotus-miner sectors status --log <sectorId>` for the failed sector(s).
* For proving issues, include the output of `lotus-miner proving` info. * For proving issues, include the output of `lotus-miner proving` info.
* For deal making issues, include the output of `lotus client list-deals -v` and/or `lotus-miner storage-deals|retrieval-deals|data-transfers list [-v]` commands for the deal(s) in question. * For deal making issues, include the output of `lotus client list-deals -v` and/or `lotus-miner storage-deals|retrieval-deals|data-transfers list [-v]` commands for the deal(s) in question.
render: bash
validations: validations:
required: true required: true
- type: textarea - type: textarea
id: extraInfo id: extraInfo
attributes: attributes:
label: Logging Information label: Logging Information
render: text
description: | description: |
Please provide debug logs of the problem, remember you can get set log level control for: Please provide debug logs of the problem, remember you can get set log level control for:
* lotus: use `lotus log list` to get all log systems available and set level by `lotus log set-level`. An example can be found [here](https://docs.filecoin.io/get-started/lotus/configuration-and-advanced-usage/#log-level-control). * lotus: use `lotus log list` to get all log systems available and set level by `lotus log set-level`. An example can be found [here](https://docs.filecoin.io/get-started/lotus/configuration-and-advanced-usage/#log-level-control).
* lotus-miner:`lotus-miner log list` to get all log systems available and set level by `lotus-miner log set-level * lotus-miner:`lotus-miner log list` to get all log systems available and set level by `lotus-miner log set-level
If you don't provide detailed logs when you raise the issue it will almost certainly be the first request I make before furthur diagnosing the problem. If you don't provide detailed logs when you raise the issue it will almost certainly be the first request I make before furthur diagnosing the problem.
render: bash
validations: validations:
required: true required: true
- type: textarea - type: textarea
@@ -96,5 +87,6 @@ body:
2. Do '...' 2. Do '...'
3. See error '...' 3. See error '...'
... ...
render: bash
validations: validations:
required: false required: false
+15 -24
View File
@@ -15,33 +15,24 @@ body:
required: true required: true
- label: I **have** a specific, actionable, and well motivated improvement to propose. - label: I **have** a specific, actionable, and well motivated improvement to propose.
required: true required: true
- type: checkboxes - type: dropdown
id: component
validations:
required: true
attributes: attributes:
label: Lotus component label: Lotus component
description: Please select the lotus component you are filing an improvement request for description: Please select the lotus component you are propoing improvement for
options: options:
- label: lotus daemon - chain sync - lotus daemon - chain sync
required: false - lotus miner - mining and block production
- label: lotus miner - mining and block production - lotus miner/worker - sealing
required: false - lotus miner - proving(WindowPoSt)
- label: lotus miner/worker - sealing - lotus miner/market - storage deal
required: false - lotus miner/market - retrieval deal
- label: lotus miner - proving(WindowPoSt) - lotus client
required: false - lotus JSON-RPC API
- label: lotus miner/market - storage deal - lotus message management (mpool)
required: false - Other
- label: lotus miner/market - retrieval deal
required: false
- label: lotus miner/market - data transfer
required: false
- label: lotus client
required: false
- label: lotus JSON-RPC API
required: false
- label: lotus message management (mpool)
required: false
- label: Other
required: false
- type: textarea - type: textarea
id: request id: request
attributes: attributes:
+15 -24
View File
@@ -13,33 +13,24 @@ body:
required: true required: true
- label: I **have** a specific, actionable, and well motivated feature request to propose. - label: I **have** a specific, actionable, and well motivated feature request to propose.
required: true required: true
- type: checkboxes - type: dropdown
id: component
validations:
required: true
attributes: attributes:
label: Lotus component label: Lotus component
description: Please select the lotus component you are filing a new feature request for description: Please select the lotus component you are requesting a new feature for
options: options:
- label: lotus daemon - chain sync - lotus daemon - chain sync
required: false - lotus miner - mining and block production
- label: lotus miner - mining and block production - lotus miner/worker - sealing
required: false - lotus miner - proving(WindowPoSt)
- label: lotus miner/worker - sealing - lotus miner/market - storage deal
required: false - lotus miner/market - retrieval deal
- label: lotus miner - proving(WindowPoSt) - lotus client
required: false - lotus JSON-RPC API
- label: lotus miner/market - storage deal - lotus message management (mpool)
required: false - Other
- label: lotus miner/market - retrieval deal
required: false
- label: lotus miner/market - data transfer
required: false
- label: lotus client
required: false
- label: lotus JSON-RPC API
required: false
- label: lotus message management (mpool)
required: false
- label: Other
required: false
- type: textarea - type: textarea
id: request id: request
attributes: attributes:
@@ -0,0 +1,91 @@
name: "M1 Bug Report For Deal Making"
description: "File a bug report around deal making for the M1 releases"
labels: [need/triage, kind/bug, M1-release]
body:
- type: checkboxes
id: checklist
attributes:
label: Checklist
description: Please check off the following boxes before continuing to file a bug report!
options:
- label: This is **not** a question or a support request. If you have any lotus related questions, please ask in the [lotus forum](https://github.com/filecoin-project/lotus/discussions).
required: true
- label: I **am** reporting a bug w.r.t one of the [M1 tags](https://github.com/filecoin-project/lotus/discussions/6852#discussioncomment-1043951). If not, choose another issue option [here](https://github.com/filecoin-project/lotus/issues/new/choose).
required: true
- label: I **am** reporting a bug around deal making. If not, create a [M1 Bug Report For Non Deal Making Issue](https://github.com/filecoin-project/lotus/issues/new?assignees=&labels=need%2Ftriage%2Ckind%2Fbug%2CM1-release&template=m1_bug_report_non_deal.yml).
required: true
- label: I have my log level set as instructed [here](https://github.com/filecoin-project/lotus/discussions/6852#discussioncomment-1043678) and have logs available for troubleshooting.
required: true
- label: The deal is coming from one of the M1 clients(communitcated in the coordination slack channel).
required: true
- label: I **have** searched on the [issue tracker](https://github.com/filecoin-project/lotus/issues) and the [lotus forum](https://github.com/filecoin-project/lotus/discussions), and there is no existing related issue or discussion.
required: true
- type: dropdown
id: lotus-componets
validations:
required: true
attributes:
label: Lotus Component
description: Please select the lotus component you are filing a bug for
options:
- lotus miner market subsystem - storage deal
- lotus miner market subsystem - retrieval deal
- lotus miner - storage deal
- lotus miner - retrieval deal
- type: textarea
id: version
attributes:
label: Lotus Tag and Version
description: Enter the lotus tag, output of `lotus version` and `lotus-miner version`.
validations:
reuiqred: true
- type: textarea
id: Description
attributes:
label: Describe the Bug
description: |
This is where you get to tell us what went wrong, when doing so, please try to provide a clear and concise description of the bug with all related information:
* What you were doding when you experienced the bug?
* Any *error* messages you saw, *where* you saw them, and what you believe may have caused them (if you have any ideas).
* What is the expected behaviour?
render: bash
validations:
required: true
- type: textarea
id: deal-status
attributes:
label: Deal Status
description: What's the status of the deal?
placeholder: |
Please share the output of `lotus-miner storage-deals|retrieval-deals list [-v]` commands for the deal(s) in question.
validations:
required: true
- type: textarea
id: data-transfer-status
attributes:
label: Data Transfer Status
description: What's the status of the data transfer?
placeholder: |
Please share the output of `lotus-miner data-transfers list -v` commands for the deal(s) in question.
validations:
required: true
- type: textarea
id: logging
attributes:
label: Logging Information
description: Please link to the whole of the miner logs on your side of the transaction. You can upload the logs to a [gist](https://gist.github.com).
validations:
required: true
- type: textarea
id: RepoSteps
attributes:
label: Repo Steps (optional)
description: "Steps to reproduce the behavior"
value: |
1. Run '...'
2. Do '...'
3. See error '...'
...
render: bash
validations:
required: false
@@ -0,0 +1,81 @@
name: "M1 Bug Report For Non Deal Making Issue"
description: "File a bug report around non deal making issue for the M1 releases"
labels: [need/triage, kind/bug, M1-release]
body:
- type: checkboxes
id: checklist
attributes:
label: Checklist
description: Please check off the following boxes before continuing to file a bug report!
options:
- label: This is **not** a question or a support request. If you have any lotus related questions, please ask in the [lotus forum](https://github.com/filecoin-project/lotus/discussions).
required: true
- label: I **am** reporting a bug w.r.t one of the [M1 tags](https://github.com/filecoin-project/lotus/discussions/6852#discussioncomment-1043951). If not, choose another issue option [here](https://github.com/filecoin-project/lotus/issues/new/choose).
required: true
- label: I am **not** reporting a bug around deal making. If yes, create a [M1 Bug Report For Deal Making](https://github.com/filecoin-project/lotus/issues/new?assignees=&labels=need%2Ftriage%2Ckind%2Fbug%2CM1-release&template=m1_bug_report_deal.yml).
required: true
- label: I **have** searched on the [issue tracker](https://github.com/filecoin-project/lotus/issues) and the [lotus forum](https://github.com/filecoin-project/lotus/discussions), and there is no existing related issue or discussion.
required: true
- type: dropdown
id: component-and-area
validations:
required: true
attributes:
label: Lotus component
description: Please select the lotus component you are filing a bug for
options:
- lotus daemon - chain sync **with** splitstore enabled
- lotus daemon - chain sync **without** splitstore enabled
- lotus miner - mining and block production
- lotus miner/worker - sealing
- lotus miner - proving(WindowPoSt)
- lotus client
- lotus JSON-RPC API
- lotus message management (mpool)
- Other
- type: textarea
id: version
attributes:
label: Lotus Tag and Version
description: Enter the lotus tag, output of `lotus version` and `lotus-miner version`.
validations:
reuiqred: true
- type: textarea
id: Description
attributes:
label: Describe the Bug
description: |
This is where you get to tell us what went wrong, when doing so, please try to provide a clear and concise description of the bug with all related information:
* What you were doding when you experienced the bug?
* Any *error* messages you saw, *where* you saw them, and what you believe may have caused them (if you have any ideas).
* What is the expected behaviour?
* For sealing issues, include the output of `lotus-miner sectors status --log <sectorId>` for the failed sector(s).
* For proving issues, include the output of `lotus-miner proving` info.
render: bash
validations:
required: true
- type: textarea
id: extraInfo
attributes:
label: Logging Information
description: |
Please provide debug logs of the problem, remember you can get set log level control for:
* lotus: use `lotus log list` to get all log systems available and set level by `lotus log set-level`. An example can be found [here](https://docs.filecoin.io/get-started/lotus/configuration-and-advanced-usage/#log-level-control).
* lotus-miner:`lotus-miner log list` to get all log systems available and set level by `lotus-miner log set-level
If you don't provide detailed logs when you raise the issue it will almost certainly be the first request I make before furthur diagnosing the problem.
render: bash
validations:
required: true
- type: textarea
id: RepoSteps
attributes:
label: Repo Steps
description: "Steps to reproduce the behavior"
value: |
1. Run '...'
2. Do '...'
3. See error '...'
...
render: bash
validations:
required: false
-21
View File
@@ -1,21 +0,0 @@
## Related Issues
<!-- link all issues that this PR might resolve/fix. If an issue doesn't exist, include a brief motivation for the change being made.-->
## Proposed Changes
<!-- provide a clear list of the changes being made-->
## Additional Info
<!-- callouts, links to documentation, and etc-->
## Checklist
Before you mark the PR ready for review, please make sure that:
- [ ] All commits have a clear commit message.
- [ ] The PR title is in the form of of `<PR type>: <area>: <change being made>`
- example: ` fix: mempool: Introduce a cache for valid signatures`
- `PR type`: _fix_, _feat_, _INTERFACE BREAKING CHANGE_, _CONSENSUS BREAKING_, _build_, _chore_, _ci_, _docs_,_perf_, _refactor_, _revert_, _style_, _test_
- `area`: _api_, _chain_, _state_, _vm_, _data transfer_, _market_, _mempool_, _message_, _block production_, _multisig_, _networking_, _paychan_, _proving_, _sealing_, _wallet_, _deps_
- [ ] This PR has tests for new functionality or change in behaviour
- [ ] If new user-facing features are introduced, clear usage guidelines and / or documentation updates should be included in https://lotus.filecoin.io or [Discussion Tutorials.](https://github.com/filecoin-project/lotus/discussions/categories/tutorials)
- [ ] CI is green
+1 -1
View File
@@ -29,5 +29,5 @@ jobs:
days-before-pr-close: 2 days-before-pr-close: 2
remove-stale-when-updated: true remove-stale-when-updated: true
enable-statistics: true enable-statistics: true
-14
View File
@@ -1,14 +0,0 @@
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
-1
View File
@@ -40,7 +40,6 @@ build/paramfetch.sh
/bundle /bundle
/darwin /darwin
/linux /linux
*.snap
*-fuzz.zip *-fuzz.zip
/chain/types/work_msg/ /chain/types/work_msg/
+5 -5
View File
@@ -49,23 +49,23 @@ AppDir:
fedora: fedora:
image: appimagecrafters/tests-env:fedora-30 image: appimagecrafters/tests-env:fedora-30
command: ./AppRun command: ./AppRun
use_host_x: false use_host_x: true
debian: debian:
image: appimagecrafters/tests-env:debian-stable image: appimagecrafters/tests-env:debian-stable
command: ./AppRun command: ./AppRun
use_host_x: false use_host_x: true
arch: arch:
image: appimagecrafters/tests-env:archlinux-latest image: appimagecrafters/tests-env:archlinux-latest
command: ./AppRun command: ./AppRun
use_host_x: false use_host_x: true
centos: centos:
image: appimagecrafters/tests-env:centos-7 image: appimagecrafters/tests-env:centos-7
command: ./AppRun command: ./AppRun
use_host_x: false use_host_x: true
ubuntu: ubuntu:
image: appimagecrafters/tests-env:ubuntu-xenial image: appimagecrafters/tests-env:ubuntu-xenial
command: ./AppRun command: ./AppRun
use_host_x: false use_host_x: true
AppImage: AppImage:
arch: x86_64 arch: x86_64
update-information: guess update-information: guess
+183 -1012
View File
File diff suppressed because it is too large Load Diff
+23 -50
View File
@@ -28,14 +28,6 @@ WORKDIR /opt/filecoin
RUN make clean deps RUN make clean deps
FROM builder-local AS builder-test
MAINTAINER Lotus Development Team
WORKDIR /opt/filecoin
RUN make debug
FROM builder-local AS builder FROM builder-local AS builder
MAINTAINER Lotus Development Team MAINTAINER Lotus Development Team
@@ -44,7 +36,7 @@ WORKDIR /opt/filecoin
ARG RUSTFLAGS="" ARG RUSTFLAGS=""
ARG GOFLAGS="" ARG GOFLAGS=""
RUN make lotus lotus-miner lotus-worker lotus-shed lotus-wallet lotus-gateway lotus-stats RUN make lotus lotus-miner lotus-worker lotus-shed lotus-wallet lotus-gateway
FROM ubuntu:20.04 AS base FROM ubuntu:20.04 AS base
@@ -61,9 +53,8 @@ COPY --from=builder /usr/lib/x86_64-linux-gnu/libnuma.so.1 /lib/
COPY --from=builder /usr/lib/x86_64-linux-gnu/libhwloc.so.5 /lib/ COPY --from=builder /usr/lib/x86_64-linux-gnu/libhwloc.so.5 /lib/
COPY --from=builder /usr/lib/x86_64-linux-gnu/libOpenCL.so.1 /lib/ COPY --from=builder /usr/lib/x86_64-linux-gnu/libOpenCL.so.1 /lib/
RUN useradd -r -u 532 -U fc \ RUN useradd -r -u 532 -U fc
&& mkdir -p /etc/OpenCL/vendors \
&& echo "libnvidia-opencl.so.1" > /etc/OpenCL/vendors/nvidia.icd
### ###
FROM base AS lotus FROM base AS lotus
@@ -75,6 +66,8 @@ COPY scripts/docker-lotus-entrypoint.sh /
ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters
ENV LOTUS_PATH /var/lib/lotus ENV LOTUS_PATH /var/lib/lotus
ENV LOTUS_JAEGER_AGENT_HOST 127.0.0.1
ENV LOTUS_JAEGER_AGENT_PORT 6831
ENV DOCKER_LOTUS_IMPORT_SNAPSHOT https://fil-chain-snapshots-fallback.s3.amazonaws.com/mainnet/minimal_finality_stateroots_latest.car ENV DOCKER_LOTUS_IMPORT_SNAPSHOT https://fil-chain-snapshots-fallback.s3.amazonaws.com/mainnet/minimal_finality_stateroots_latest.car
ENV DOCKER_LOTUS_IMPORT_WALLET "" ENV DOCKER_LOTUS_IMPORT_WALLET ""
@@ -99,6 +92,8 @@ MAINTAINER Lotus Development Team
COPY --from=builder /opt/filecoin/lotus-wallet /usr/local/bin/ COPY --from=builder /opt/filecoin/lotus-wallet /usr/local/bin/
ENV WALLET_PATH /var/lib/lotus-wallet ENV WALLET_PATH /var/lib/lotus-wallet
ENV LOTUS_JAEGER_AGENT_HOST 127.0.0.1
ENV LOTUS_JAEGER_AGENT_PORT 6831
RUN mkdir /var/lib/lotus-wallet RUN mkdir /var/lib/lotus-wallet
RUN chown fc: /var/lib/lotus-wallet RUN chown fc: /var/lib/lotus-wallet
@@ -119,6 +114,10 @@ MAINTAINER Lotus Development Team
COPY --from=builder /opt/filecoin/lotus-gateway /usr/local/bin/ COPY --from=builder /opt/filecoin/lotus-gateway /usr/local/bin/
ENV LOTUS_JAEGER_AGENT_HOST 127.0.0.1
ENV LOTUS_JAEGER_AGENT_PORT 6831
ENV FULLNODE_API_INFO /ip4/127.0.0.1/tcp/1234/http
USER fc USER fc
EXPOSE 1234 EXPOSE 1234
@@ -136,7 +135,11 @@ COPY --from=builder /opt/filecoin/lotus-miner /usr/local/bin/
COPY scripts/docker-lotus-miner-entrypoint.sh / COPY scripts/docker-lotus-miner-entrypoint.sh /
ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters
ENV FULLNODE_API_INFO /ip4/127.0.0.1/tcp/1234/http
ENV LOTUS_MINER_PATH /var/lib/lotus-miner ENV LOTUS_MINER_PATH /var/lib/lotus-miner
ENV LOTUS_JAEGER_AGENT_HOST 127.0.0.1
ENV LOTUS_JAEGER_AGENT_PORT 6831
ENV DOCKER_LOTUS_MINER_INIT true
RUN mkdir /var/lib/lotus-miner /var/tmp/filecoin-proof-parameters RUN mkdir /var/lib/lotus-miner /var/tmp/filecoin-proof-parameters
RUN chown fc: /var/lib/lotus-miner /var/tmp/filecoin-proof-parameters RUN chown fc: /var/lib/lotus-miner /var/tmp/filecoin-proof-parameters
@@ -160,7 +163,10 @@ MAINTAINER Lotus Development Team
COPY --from=builder /opt/filecoin/lotus-worker /usr/local/bin/ COPY --from=builder /opt/filecoin/lotus-worker /usr/local/bin/
ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters
ENV MINER_API_INFO /ip4/127.0.0.1/tcp/2345/http
ENV LOTUS_WORKER_PATH /var/lib/lotus-worker ENV LOTUS_WORKER_PATH /var/lib/lotus-worker
ENV LOTUS_JAEGER_AGENT_HOST 127.0.0.1
ENV LOTUS_JAEGER_AGENT_PORT 6831
RUN mkdir /var/lib/lotus-worker RUN mkdir /var/lib/lotus-worker
RUN chown fc: /var/lib/lotus-worker RUN chown fc: /var/lib/lotus-worker
@@ -180,11 +186,16 @@ CMD ["-help"]
from base as lotus-all-in-one from base as lotus-all-in-one
ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters
ENV FULLNODE_API_INFO /ip4/127.0.0.1/tcp/1234/http
ENV LOTUS_JAEGER_AGENT_HOST 127.0.0.1
ENV LOTUS_JAEGER_AGENT_PORT 6831
ENV LOTUS_MINER_PATH /var/lib/lotus-miner ENV LOTUS_MINER_PATH /var/lib/lotus-miner
ENV LOTUS_PATH /var/lib/lotus ENV LOTUS_PATH /var/lib/lotus
ENV LOTUS_WORKER_PATH /var/lib/lotus-worker ENV LOTUS_WORKER_PATH /var/lib/lotus-worker
ENV MINER_API_INFO /ip4/127.0.0.1/tcp/2345/http
ENV WALLET_PATH /var/lib/lotus-wallet ENV WALLET_PATH /var/lib/lotus-wallet
ENV DOCKER_LOTUS_IMPORT_SNAPSHOT https://fil-chain-snapshots-fallback.s3.amazonaws.com/mainnet/minimal_finality_stateroots_latest.car ENV DOCKER_LOTUS_IMPORT_SNAPSHOT https://fil-chain-snapshots-fallback.s3.amazonaws.com/mainnet/minimal_finality_stateroots_latest.car
ENV DOCKER_LOTUS_MINER_INIT true
COPY --from=builder /opt/filecoin/lotus /usr/local/bin/ COPY --from=builder /opt/filecoin/lotus /usr/local/bin/
COPY --from=builder /opt/filecoin/lotus-shed /usr/local/bin/ COPY --from=builder /opt/filecoin/lotus-shed /usr/local/bin/
@@ -192,44 +203,6 @@ COPY --from=builder /opt/filecoin/lotus-wallet /usr/local/bin/
COPY --from=builder /opt/filecoin/lotus-gateway /usr/local/bin/ COPY --from=builder /opt/filecoin/lotus-gateway /usr/local/bin/
COPY --from=builder /opt/filecoin/lotus-miner /usr/local/bin/ COPY --from=builder /opt/filecoin/lotus-miner /usr/local/bin/
COPY --from=builder /opt/filecoin/lotus-worker /usr/local/bin/ COPY --from=builder /opt/filecoin/lotus-worker /usr/local/bin/
COPY --from=builder /opt/filecoin/lotus-stats /usr/local/bin/
RUN mkdir /var/tmp/filecoin-proof-parameters
RUN mkdir /var/lib/lotus
RUN mkdir /var/lib/lotus-miner
RUN mkdir /var/lib/lotus-worker
RUN mkdir /var/lib/lotus-wallet
RUN chown fc: /var/tmp/filecoin-proof-parameters
RUN chown fc: /var/lib/lotus
RUN chown fc: /var/lib/lotus-miner
RUN chown fc: /var/lib/lotus-worker
RUN chown fc: /var/lib/lotus-wallet
VOLUME /var/tmp/filecoin-proof-parameters
VOLUME /var/lib/lotus
VOLUME /var/lib/lotus-miner
VOLUME /var/lib/lotus-worker
VOLUME /var/lib/lotus-wallet
EXPOSE 1234
EXPOSE 2345
EXPOSE 3456
EXPOSE 1777
###
from base as lotus-test
ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters
ENV LOTUS_MINER_PATH /var/lib/lotus-miner
ENV LOTUS_PATH /var/lib/lotus
ENV LOTUS_WORKER_PATH /var/lib/lotus-worker
ENV WALLET_PATH /var/lib/lotus-wallet
COPY --from=builder-test /opt/filecoin/lotus /usr/local/bin/
COPY --from=builder-test /opt/filecoin/lotus-miner /usr/local/bin/
COPY --from=builder-test /opt/filecoin/lotus-worker /usr/local/bin/
COPY --from=builder-test /opt/filecoin/lotus-seed /usr/local/bin/
RUN mkdir /var/tmp/filecoin-proof-parameters RUN mkdir /var/tmp/filecoin-proof-parameters
RUN mkdir /var/lib/lotus RUN mkdir /var/lib/lotus
-142
View File
@@ -1,142 +0,0 @@
<!-- TOC -->
- [`lotus` Release Flow](#lotus-release-flow)
- [Purpose](#purpose)
- [High-level Summary](#high-level-summary)
- [Motivation and Requirements](#motivation-and-requirements)
- [Adopted Conventions](#adopted-conventions)
- [Major Releases](#major-releases)
- [Mandatory Releases](#mandatory-releases)
- [Feature Releases](#feature-releases)
- [Examples Scenarios](#examples-scenarios)
- [Release Cycle](#release-cycle)
- [Patch Releases](#patch-releases)
- [Performing a Release](#performing-a-release)
- [Security Fix Policy](#security-fix-policy)
- [FAQ](#faq)
- [Why aren't Go major versions used more?](#why-arent-go-major-versions-used-more)
- [Related Items](#related-items)
<!-- /TOC -->
# `lotus` Release Flow
## Purpose
This document aims to describe how the Lotus team plans to ship releases of the Lotus implementation of Filecoin network. Interested parties can expect new releases to come out as described in this document.
## High-level Summary
- **Major releases** (1.0.0, 2.0.0, etc.) are reserved for significant changes to the Filecoin protocol that transform the network and its usecases. Such changes could include the addition of new Virtual Machines to the protocol, major upgrades to the Proofs of Replication used by Filecoin, etc.
- Even minor releases (1.2.0, 1.4.0, etc.) of the Lotus software correspond to **mandatory releases** as they ship Filecoin network upgrades. Users **must** upgrade to these releases before a certain time in order to keep in sync with the Filecoin network. We aim to ensure there is at least one week before the upgrade deadline.
- Patch versions of even minor releases (1.2.1, 1.4.2, etc.) correspond to **hotfix releases**. Such releases will only be shipped when a critical fix is needed to be applied on top of a mandatory release.
- Odd minor releases (1.3.0, 1.5.0, etc.), as well as patch releases in these series (1.3.1, 1.5.2, etc.) correspond to **feature releases** with new development and bugfixes. These releases are not mandatory, but still highly recommended, **as they may contain critical security fixes**.
- We aim to ship a new feature release of the Lotus software every 3 weeks, so users can expect a regular cadence of Lotus feature releases. Note that mandatory releases for network upgrades may disrupt this schedule.
## Motivation and Requirements
Our primary motivation is for users of the Lotus software (storage providers, storage clients, developers, etc.) to have a clear idea about when they can expect Lotus releases, and what they can expect in a release.
In order to achieve this, we need the following from our release process and conventions:
- Lotus version conventions make it immediately obvious whether a new Lotus release is mandatory or not. A release is mandatory if it ships a network upgrade to the Filecoin protocol.
- The ability to ship critical fixes on top of mandatory releases, so as to avoid forcing users to consume larger unrelated changes.
- A regular cadence of feature releases, so that users can know when a new Lotus release will be available for consumption.
- The ability to ship any number of feature releases between two mandatory releases.
- A clear description of the various stages of testing that a Lotus Release Candidate (RC) goes through.
- Lotus Release issues will present a single source of truth for what may be contained in Lotus releases, including security fixes, and how they will be disclosed.
## Adopted Conventions
This section describes the conventions we have adopted. Users of Lotus are encouraged to review this in detail so as to be informed when new Lotus releases are shipped.
### Major Releases
Bumps to the Lotus major version number (1.0.0, 2.0.0, etc.) are reserved for significant changes to the Filecoin protocol that dramatically transform the network itself. Such changes could include the addition of new Virtual Machines to the protocol, major upgrades to the Proofs of Replication used by Filecoin, etc. These releases are expected to take lots of time to develop and will be rare. See also "Why aren't Go major versions used more?" below.
### Mandatory Releases
Even bumps to the Lotus minor version number (1.2.0, 1.4.0, etc.) are reserved for **mandatory releases** that ship Filecoin network upgrades. Users **must** upgrade to these releases before a certain time in order to keep in sync with the Filecoin network.
Depending on the scope of the upgrade, these releases may take up to several weeks to fully develop and test. We aim to ensure there are at least 2 weeks between the publication of the final Lotus release and the Filecoin network upgrade deadline.
These releases do not follow a regular cadence, as they are developed in lockstep with the other implementations of the Filecoin protocol. As of August 2021, the developers aim to ship 3-4 Filecoin network upgrades a year, though smaller security-critical upgrades may occur unpredictably.
Mandatory releases are somewhat sensitive since all Lotus users are forced to upgrade to them at the same time. As a result, they will be shipped on top of the most recent stable release of Lotus, which will generally be the latest Lotus release that has been in production for more than 2 weeks. (Note: given this rule, the basis of a mandatory release could be a mandatory release or a feature release depending on timing). Mandatory releases will not include any new feature development or bugfixes that haven't already baked in production for 2+ weeks, except for the changes needed for the network upgrade itself. Further, any critical fixes that are needed after the network upgrade will be shipped as patch version bumps to the mandatory release (1.2.1, 1.2.2, etc.) This prevents users from being forced to quickly digest unnecessary changes.
Users should generally aim to always upgrade to a new even minor version release since they either introduce a mandatory network upgrade or a critical fix.
### Feature Releases
All releases under an odd minor version number indicate **feature releases**. These could include releases such as 1.3.0, 1.3.1, 1.5.2, etc.
Feature releases include new development and bug fixes. They are not mandatory, but still highly recommended, **as they may contain critical security fixes**. Note that some of these releases may be very small patch releases that include critical hotfixes. There is no way to distinguish between a bug fix release and a feature release on the "feature" version. Both cases will use the "patch" version number.
We aim to ship a new feature release of the Lotus software from our development (master) branch every 3 weeks, so users can expect a regular cadence of Lotus feature releases. Note that mandatory releases for network upgrades may disrupt this schedule. For more, see the Release Cycle section (TODO: Link).
### Examples Scenarios
- **Scenario 1**: **Lotus 1.12.0 shipped a network upgrade, and no network upgrades are needed for a long while.**
In this case, the next feature release will be Lotus 1.13.0. In three-week intervals, we will ship Lotus 1.13.1, 1.13.2, and 1.13.3, all containing new features and bug fixes.
Let us assume that after the release of 1.13.3, a critical issue is discovered and a hotfix quickly developed. This hotfix will then be shipped in **both** 1.12.1 and 1.13.4. Users who have already upgrade to the 1.13 series can simply upgrade to 1.13.4. Users who have chosen to still be on 1.12.0, however, can use 1.12.1 to patch the critical issue without being forced to consume all the changes in the 1.13 series.
- **Scenario 2**: **Lotus 1.12.0 shipped a network upgrade, but the need for an unexpected network upgrade soon arises**
In this case, the Lotus 1.13 series will be dropped entirely, including any RCs that may have been undergoing testing. Instead, the network upgrade will be shipped as Lotus 1.14.0, built on top of Lotus 1.12.0. It will thus include no unnecessary changes, only the work needed to support the new network upgrade.
Any changes that were being worked on in the 1.13.0 series will then get applied on top of Lotus 1.14.0 and get shipped as Lotus 1.15.0.
## Release Cycle
A mandatory release process should take about 3-6 weeks, depending on the amount and the overall complexity of new features being introduced to the network protocol. It may also be shorter if there is a network incident that requires an emergency upgrade. A feature release process should take about 2-3 weeks.
The start time of the mandatory release process is subject to the network upgrade timeline. We will start a new feature release process every 3 weeks on Tuesdays, regardless of when the previous release landed unless it's still ongoing.
### Patch Releases
**Mandatory Release**
If we encounter a serious bug in a mandatory release post a network upgrade, we will create a patch release based on this release. Strictly only the fix to the bug will be included in the patch, and the bug fix will be backported to the master (dev) branch, and any ongoing feature release branch if applicable.
Patch release process for the mandatory releases will follow a compressed release cycle from hours to days depending on the severity and the impact to the network of the bug. In a patch release:
1. Automated and internal testing (stage 0 and 1) will be compressed into a few hours.
2. Stage 2-3 will be skipped or shortened case by case.
Some patch releases, especially ones fixing one or more complex bugs that doesn't require a follow-up mandatory upgrade, may undergo the full release process.
**Feature Release**
Patch releases in odd minor releases (1.3.0, 1.5.0, etc.) like 1.3.1, 1.5.2 and etc are corresponding to another **feature releases** with new development and bugfixes. These releases are not mandatory, but still **highly** recommended, **as they may contain critical security fixes**.
---
### Performing a Release
At the beginning of each release cycle, we will generate our "Release tracking issue", which is populated with the content at [https://github.com/filecoin-project/lotus/blob/master/documentation/misc/RELEASE_ISSUE_TEMPLATE.md](https://github.com/filecoin-project/lotus/blob/master/documentation/misc/RELEASE_ISSUE_TEMPLATE.md)
This template will be used to track major goals we have, a planned shipping date, and a complete release checklist tied to a specific release.
### Security Fix Policy
Any release may contain security fixes. Unless the fix addresses a bug being exploited in the wild, the fix will *not* be called out in the release notes. Please make sure to update ASAP.
By policy, the team will usually wait until about 3 weeks after the final release to announce any fixed security issues. However, depending on the impact and ease of discovery of the issue, the team may wait more or less time.
It is important to always update to the latest version ASAP and file issues if you're unable to update for some reason.
Finally, unless a security issue is actively being exploited or a significant number of users are unable to update to the latest version (e.g., due to a difficult migration, breaking changes, etc.), security fixes will *not* be backported to previous releases.
## FAQ
### Why aren't Go major versions used more?
Golang tightly couples source code with versioning (major versions beyond v1 leak into import paths). This poses logistical difficulties to using major versions here. Concretely, if we were to pick a policy that bumped the major version on every network upgrade, we would disrupt every single downstream library/application that consumed the native Lotus API (e.g., libraries depending on the JSON-RPC client, testground tests). They would need to update their code every single time that we released a network breaking change, even if it brought on zero expectation of breakage for the Golang APIs that they depend on. In this scenario, we are signaling breakage on the wrong API surface! We're signaling breakage on the Go level, when what breaks is the network protocol.
## Related Items
1. [Release Issue template](https://github.com/filecoin-project/lotus/blob/master/documentation/misc/RELEASE_ISSUE_TEMPLATE.md)
2. [Lotus Release Flow Discussion](https://github.com/filecoin-project/lotus/discussions/7053): Leave a comment if you have any questions or feedbacks with regard to the lotus release flow.
+71 -40
View File
@@ -5,9 +5,7 @@ all: build
unexport GOFLAGS unexport GOFLAGS
GOCC?=go GOVERSION:=$(shell go version | cut -d' ' -f 3 | sed 's/^go//' | awk -F. '{printf "%d%03d%03d", $$1, $$2, $$3}')
GOVERSION:=$(shell $(GOCC) version | tr ' ' '\n' | grep go1 | sed 's/^go//' | awk -F. '{printf "%d%03d%03d", $$1, $$2, $$3}')
ifeq ($(shell expr $(GOVERSION) \< 1016000), 1) ifeq ($(shell expr $(GOVERSION) \< 1016000), 1)
$(warning Your Golang version is go$(shell expr $(GOVERSION) / 1000000).$(shell expr $(GOVERSION) % 1000000 / 1000).$(shell expr $(GOVERSION) % 1000)) $(warning Your Golang version is go$(shell expr $(GOVERSION) / 1000000).$(shell expr $(GOVERSION) % 1000000 / 1000).$(shell expr $(GOVERSION) % 1000))
$(error Update Golang to version to at least 1.16.0) $(error Update Golang to version to at least 1.16.0)
@@ -76,6 +74,9 @@ debug: build-devnets
calibnet: GOFLAGS+=-tags=calibnet calibnet: GOFLAGS+=-tags=calibnet
calibnet: build-devnets calibnet: build-devnets
nerpanet: GOFLAGS+=-tags=nerpanet
nerpanet: build-devnets
butterflynet: GOFLAGS+=-tags=butterflynet butterflynet: GOFLAGS+=-tags=butterflynet
butterflynet: build-devnets butterflynet: build-devnets
@@ -84,32 +85,32 @@ interopnet: build-devnets
lotus: $(BUILD_DEPS) lotus: $(BUILD_DEPS)
rm -f lotus rm -f lotus
$(GOCC) build $(GOFLAGS) -o lotus ./cmd/lotus go build $(GOFLAGS) -o lotus ./cmd/lotus
.PHONY: lotus .PHONY: lotus
BINS+=lotus BINS+=lotus
lotus-miner: $(BUILD_DEPS) lotus-miner: $(BUILD_DEPS)
rm -f lotus-miner rm -f lotus-miner
$(GOCC) build $(GOFLAGS) -o lotus-miner ./cmd/lotus-miner go build $(GOFLAGS) -o lotus-miner ./cmd/lotus-miner
.PHONY: lotus-miner .PHONY: lotus-miner
BINS+=lotus-miner BINS+=lotus-miner
lotus-worker: $(BUILD_DEPS) lotus-worker: $(BUILD_DEPS)
rm -f lotus-worker rm -f lotus-worker
$(GOCC) build $(GOFLAGS) -o lotus-worker ./cmd/lotus-worker go build $(GOFLAGS) -o lotus-worker ./cmd/lotus-seal-worker
.PHONY: lotus-worker .PHONY: lotus-worker
BINS+=lotus-worker BINS+=lotus-worker
lotus-shed: $(BUILD_DEPS) lotus-shed: $(BUILD_DEPS)
rm -f lotus-shed rm -f lotus-shed
$(GOCC) build $(GOFLAGS) -o lotus-shed ./cmd/lotus-shed go build $(GOFLAGS) -o lotus-shed ./cmd/lotus-shed
.PHONY: lotus-shed .PHONY: lotus-shed
BINS+=lotus-shed BINS+=lotus-shed
lotus-gateway: $(BUILD_DEPS) lotus-gateway: $(BUILD_DEPS)
rm -f lotus-gateway rm -f lotus-gateway
$(GOCC) build $(GOFLAGS) -o lotus-gateway ./cmd/lotus-gateway go build $(GOFLAGS) -o lotus-gateway ./cmd/lotus-gateway
.PHONY: lotus-gateway .PHONY: lotus-gateway
BINS+=lotus-gateway BINS+=lotus-gateway
@@ -137,19 +138,19 @@ install-app:
lotus-seed: $(BUILD_DEPS) lotus-seed: $(BUILD_DEPS)
rm -f lotus-seed rm -f lotus-seed
$(GOCC) build $(GOFLAGS) -o lotus-seed ./cmd/lotus-seed go build $(GOFLAGS) -o lotus-seed ./cmd/lotus-seed
.PHONY: lotus-seed .PHONY: lotus-seed
BINS+=lotus-seed BINS+=lotus-seed
benchmarks: benchmarks:
$(GOCC) run github.com/whyrusleeping/bencher ./... > bench.json go run github.com/whyrusleeping/bencher ./... > bench.json
@echo Submitting results @echo Submitting results
@curl -X POST 'http://benchmark.kittyhawk.wtf/benchmark' -d '@bench.json' -u "${benchmark_http_cred}" @curl -X POST 'http://benchmark.kittyhawk.wtf/benchmark' -d '@bench.json' -u "${benchmark_http_cred}"
.PHONY: benchmarks .PHONY: benchmarks
lotus-pond: 2k lotus-pond: 2k
$(GOCC) build -o lotus-pond ./lotuspond go build -o lotus-pond ./lotuspond
.PHONY: lotus-pond .PHONY: lotus-pond
BINS+=lotus-pond BINS+=lotus-pond
@@ -160,64 +161,85 @@ lotus-pond-front:
lotus-pond-app: lotus-pond-front lotus-pond lotus-pond-app: lotus-pond-front lotus-pond
.PHONY: lotus-pond-app .PHONY: lotus-pond-app
lotus-townhall:
rm -f lotus-townhall
go build -o lotus-townhall ./cmd/lotus-townhall
.PHONY: lotus-townhall
BINS+=lotus-townhall
lotus-townhall-front:
(cd ./cmd/lotus-townhall/townhall && npm i && npm run build)
.PHONY: lotus-townhall-front
lotus-townhall-app: lotus-touch lotus-townhall-front
.PHONY: lotus-townhall-app
lotus-fountain: lotus-fountain:
rm -f lotus-fountain rm -f lotus-fountain
go build $(GOFLAGS) -o lotus-fountain ./cmd/lotus-fountain go build -o lotus-fountain ./cmd/lotus-fountain
go run github.com/GeertJohan/go.rice/rice append --exec lotus-fountain -i ./cmd/lotus-fountain -i ./build
.PHONY: lotus-fountain .PHONY: lotus-fountain
BINS+=lotus-fountain BINS+=lotus-fountain
lotus-chainwatch:
rm -f lotus-chainwatch
go build $(GOFLAGS) -o lotus-chainwatch ./cmd/lotus-chainwatch
.PHONY: lotus-chainwatch
BINS+=lotus-chainwatch
lotus-bench: lotus-bench:
rm -f lotus-bench rm -f lotus-bench
$(GOCC) build -o lotus-bench ./cmd/lotus-bench go build -o lotus-bench ./cmd/lotus-bench
.PHONY: lotus-bench .PHONY: lotus-bench
BINS+=lotus-bench BINS+=lotus-bench
lotus-stats: lotus-stats:
rm -f lotus-stats rm -f lotus-stats
$(GOCC) build $(GOFLAGS) -o lotus-stats ./cmd/lotus-stats go build $(GOFLAGS) -o lotus-stats ./cmd/lotus-stats
.PHONY: lotus-stats .PHONY: lotus-stats
BINS+=lotus-stats BINS+=lotus-stats
lotus-pcr: lotus-pcr:
rm -f lotus-pcr rm -f lotus-pcr
$(GOCC) build $(GOFLAGS) -o lotus-pcr ./cmd/lotus-pcr go build $(GOFLAGS) -o lotus-pcr ./cmd/lotus-pcr
.PHONY: lotus-pcr .PHONY: lotus-pcr
BINS+=lotus-pcr BINS+=lotus-pcr
lotus-health: lotus-health:
rm -f lotus-health rm -f lotus-health
$(GOCC) build -o lotus-health ./cmd/lotus-health go build -o lotus-health ./cmd/lotus-health
.PHONY: lotus-health .PHONY: lotus-health
BINS+=lotus-health BINS+=lotus-health
lotus-wallet: lotus-wallet:
rm -f lotus-wallet rm -f lotus-wallet
$(GOCC) build -o lotus-wallet ./cmd/lotus-wallet go build -o lotus-wallet ./cmd/lotus-wallet
.PHONY: lotus-wallet .PHONY: lotus-wallet
BINS+=lotus-wallet BINS+=lotus-wallet
lotus-keygen: lotus-keygen:
rm -f lotus-keygen rm -f lotus-keygen
$(GOCC) build -o lotus-keygen ./cmd/lotus-keygen go build -o lotus-keygen ./cmd/lotus-keygen
.PHONY: lotus-keygen .PHONY: lotus-keygen
BINS+=lotus-keygen BINS+=lotus-keygen
testground: testground:
$(GOCC) build -tags testground -o /dev/null ./cmd/lotus go build -tags testground -o /dev/null ./cmd/lotus
.PHONY: testground .PHONY: testground
BINS+=testground BINS+=testground
tvx: tvx:
rm -f tvx rm -f tvx
$(GOCC) build -o tvx ./cmd/tvx go build -o tvx ./cmd/tvx
.PHONY: tvx .PHONY: tvx
BINS+=tvx BINS+=tvx
install-chainwatch: lotus-chainwatch
install -C ./lotus-chainwatch /usr/local/bin/lotus-chainwatch
lotus-sim: $(BUILD_DEPS) lotus-sim: $(BUILD_DEPS)
rm -f lotus-sim rm -f lotus-sim
$(GOCC) build $(GOFLAGS) -o lotus-sim ./cmd/lotus-sim go build $(GOFLAGS) -o lotus-sim ./cmd/lotus-sim
.PHONY: lotus-sim .PHONY: lotus-sim
BINS+=lotus-sim BINS+=lotus-sim
@@ -239,13 +261,21 @@ install-miner-service: install-miner install-daemon-service
@echo @echo
@echo "lotus-miner service installed. Don't forget to run 'sudo systemctl start lotus-miner' to start it and 'sudo systemctl enable lotus-miner' for it to be enabled on startup." @echo "lotus-miner service installed. Don't forget to run 'sudo systemctl start lotus-miner' to start it and 'sudo systemctl enable lotus-miner' for it to be enabled on startup."
install-chainwatch-service: install-chainwatch install-daemon-service
mkdir -p /etc/systemd/system
mkdir -p /var/log/lotus
install -C -m 0644 ./scripts/lotus-chainwatch.service /etc/systemd/system/lotus-chainwatch.service
systemctl daemon-reload
@echo
@echo "chainwatch service installed. Don't forget to run 'sudo systemctl start lotus-chainwatch' to start it and 'sudo systemctl enable lotus-chainwatch' for it to be enabled on startup."
install-main-services: install-miner-service install-main-services: install-miner-service
install-all-services: install-main-services install-all-services: install-main-services install-chainwatch-service
install-services: install-main-services install-services: install-main-services
clean-daemon-service: clean-miner-service clean-daemon-service: clean-miner-service clean-chainwatch-service
-systemctl stop lotus-daemon -systemctl stop lotus-daemon
-systemctl disable lotus-daemon -systemctl disable lotus-daemon
rm -f /etc/systemd/system/lotus-daemon.service rm -f /etc/systemd/system/lotus-daemon.service
@@ -257,6 +287,12 @@ clean-miner-service:
rm -f /etc/systemd/system/lotus-miner.service rm -f /etc/systemd/system/lotus-miner.service
systemctl daemon-reload systemctl daemon-reload
clean-chainwatch-service:
-systemctl stop lotus-chainwatch
-systemctl disable lotus-chainwatch
rm -f /etc/systemd/system/lotus-chainwatch.service
systemctl daemon-reload
clean-main-services: clean-daemon-service clean-main-services: clean-daemon-service
clean-all-services: clean-main-services clean-all-services: clean-main-services
@@ -283,26 +319,25 @@ dist-clean:
.PHONY: dist-clean .PHONY: dist-clean
type-gen: api-gen type-gen: api-gen
$(GOCC) run ./gen/main.go go run ./gen/main.go
$(GOCC) generate -x ./... go generate -x ./...
goimports -w api/ goimports -w api/
method-gen: api-gen method-gen: api-gen
(cd ./lotuspond/front/src/chain && $(GOCC) run ./methodgen.go) (cd ./lotuspond/front/src/chain && go run ./methodgen.go)
actors-gen: actors-gen:
$(GOCC) run ./gen/inline-gen . gen/inlinegen-data.json go run ./chain/actors/agen
$(GOCC) run ./chain/actors/agen go fmt ./...
$(GOCC) fmt ./...
api-gen: api-gen:
$(GOCC) run ./gen/api go run ./gen/api
goimports -w api goimports -w api
goimports -w api goimports -w api
.PHONY: api-gen .PHONY: api-gen
cfgdoc-gen: cfgdoc-gen:
$(GOCC) run ./node/config/cfgdocgen > ./node/config/doc_gen.go go run ./node/config/cfgdocgen > ./node/config/doc_gen.go
appimage: lotus appimage: lotus
rm -rf appimage-builder-cache || true rm -rf appimage-builder-cache || true
@@ -316,9 +351,9 @@ appimage: lotus
docsgen: docsgen-md docsgen-openrpc docsgen: docsgen-md docsgen-openrpc
docsgen-md-bin: api-gen actors-gen docsgen-md-bin: api-gen actors-gen
$(GOCC) build $(GOFLAGS) -o docgen-md ./api/docgen/cmd go build $(GOFLAGS) -o docgen-md ./api/docgen/cmd
docsgen-openrpc-bin: api-gen actors-gen docsgen-openrpc-bin: api-gen actors-gen
$(GOCC) build $(GOFLAGS) -o docgen-openrpc ./api/docgen-openrpc/cmd go build $(GOFLAGS) -o docgen-openrpc ./api/docgen-openrpc/cmd
docsgen-md: docsgen-md-full docsgen-md-storage docsgen-md-worker docsgen-md: docsgen-md-full docsgen-md-storage docsgen-md-worker
@@ -342,11 +377,9 @@ docsgen-openrpc-worker: docsgen-openrpc-bin
.PHONY: docsgen docsgen-md-bin docsgen-openrpc-bin .PHONY: docsgen docsgen-md-bin docsgen-openrpc-bin
gen: actors-gen type-gen method-gen cfgdoc-gen docsgen api-gen circleci gen: actors-gen type-gen method-gen cfgdoc-gen docsgen api-gen circleci
@echo ">>> IF YOU'VE MODIFIED THE CLI OR CONFIG, REMEMBER TO ALSO MAKE docsgen-cli" @echo ">>> IF YOU'VE MODIFIED THE CLI, REMEMBER TO ALSO MAKE docsgen-cli"
.PHONY: gen .PHONY: gen
jen: gen
snap: lotus lotus-miner lotus-worker snap: lotus lotus-miner lotus-worker
snapcraft snapcraft
# snapcraft upload ./lotus_*.snap # snapcraft upload ./lotus_*.snap
@@ -354,12 +387,10 @@ snap: lotus lotus-miner lotus-worker
# separate from gen because it needs binaries # separate from gen because it needs binaries
docsgen-cli: lotus lotus-miner lotus-worker docsgen-cli: lotus lotus-miner lotus-worker
python ./scripts/generate-lotus-cli.py 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 .PHONY: docsgen-cli
print-%: print-%:
@echo $*=$($*) @echo $*=$($*)
circleci: circleci:
go generate -x ./.circleci go generate -x ./.circleci
+1
View File
@@ -123,6 +123,7 @@ Note: The default branch `master` is the dev branch where the latest new feature
# Or to join a testnet or devnet: # Or to join a testnet or devnet:
make clean calibnet # Calibration with min 32GiB sectors make clean calibnet # Calibration with min 32GiB sectors
make clean nerpanet # Nerpa with min 512MiB sectors
sudo make install sudo make install
``` ```
-5
View File
@@ -5,7 +5,6 @@ import (
"fmt" "fmt"
apitypes "github.com/filecoin-project/lotus/api/types" apitypes "github.com/filecoin-project/lotus/api/types"
"github.com/filecoin-project/lotus/journal/alerting"
"github.com/google/uuid" "github.com/google/uuid"
@@ -34,10 +33,6 @@ type Common interface {
LogList(context.Context) ([]string, error) //perm:write LogList(context.Context) ([]string, error) //perm:write
LogSetLevel(context.Context, string, string) error //perm:write LogSetLevel(context.Context, string, string) error //perm:write
// LogAlerts returns list of all, active and inactive alerts tracked by the
// node
LogAlerts(ctx context.Context) ([]alerting.Alert, error) //perm:admin
// MethodGroup: Common // MethodGroup: Common
// Version provides information about API provider // Version provides information about API provider
+33 -77
View File
@@ -6,20 +6,20 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/filecoin-project/lotus/node/repo/importmgr"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-bitfield"
datatransfer "github.com/filecoin-project/go-data-transfer" datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-fil-markets/storagemarket"
apitypes "github.com/filecoin-project/lotus/api/types" apitypes "github.com/filecoin-project/lotus/api/types"
"github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/market" "github.com/filecoin-project/lotus/chain/actors/builtin/market"
@@ -27,8 +27,8 @@ import (
"github.com/filecoin-project/lotus/chain/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/actors/builtin/power" "github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
marketevents "github.com/filecoin-project/lotus/markets/loggers"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/repo/imports"
) )
//go:generate go run github.com/golang/mock/mockgen -destination=mocks/mock_full.go -package=mocks . FullNode //go:generate go run github.com/golang/mock/mockgen -destination=mocks/mock_full.go -package=mocks . FullNode
@@ -71,6 +71,12 @@ type FullNode interface {
// ChainHead returns the current head of the chain. // ChainHead returns the current head of the chain.
ChainHead(context.Context) (*types.TipSet, error) //perm:read ChainHead(context.Context) (*types.TipSet, error) //perm:read
// ChainGetRandomnessFromTickets is used to sample the chain for randomness.
ChainGetRandomnessFromTickets(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) //perm:read
// ChainGetRandomnessFromBeacon is used to sample the beacon for randomness.
ChainGetRandomnessFromBeacon(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) //perm:read
// ChainGetBlock returns the block specified by the given CID. // ChainGetBlock returns the block specified by the given CID.
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error) //perm:read ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error) //perm:read
// ChainGetTipSet returns the tipset specified by the given TipSetKey. // ChainGetTipSet returns the tipset specified by the given TipSetKey.
@@ -107,11 +113,6 @@ type FullNode interface {
// will be returned. // will be returned.
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) //perm:read ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) //perm:read
// ChainGetTipSetAfterHeight looks back for a tipset at the specified epoch.
// If there are no blocks at the specified epoch, the first non-nil tipset at a later epoch
// will be returned.
ChainGetTipSetAfterHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) //perm:read
// ChainReadObj reads ipld nodes referenced by the specified CID from chain // ChainReadObj reads ipld nodes referenced by the specified CID from chain
// blockstore and returns raw bytes. // blockstore and returns raw bytes.
ChainReadObj(context.Context, cid.Cid) ([]byte, error) //perm:read ChainReadObj(context.Context, cid.Cid) ([]byte, error) //perm:read
@@ -289,7 +290,7 @@ type FullNode interface {
// // UX ? // // UX ?
// MethodGroup: WalletF // MethodGroup: Wallet
// WalletNew creates a new address in the wallet with the given sigType. // WalletNew creates a new address in the wallet with the given sigType.
// Available key types: bls, secp256k1, secp256k1-ledger // Available key types: bls, secp256k1, secp256k1-ledger
@@ -330,7 +331,7 @@ type FullNode interface {
// ClientImport imports file under the specified path into filestore. // ClientImport imports file under the specified path into filestore.
ClientImport(ctx context.Context, ref FileRef) (*ImportRes, error) //perm:admin ClientImport(ctx context.Context, ref FileRef) (*ImportRes, error) //perm:admin
// ClientRemoveImport removes file import // ClientRemoveImport removes file import
ClientRemoveImport(ctx context.Context, importID imports.ID) error //perm:admin ClientRemoveImport(ctx context.Context, importID importmgr.ImportID) error //perm:admin
// ClientStartDeal proposes a deal with a miner. // ClientStartDeal proposes a deal with a miner.
ClientStartDeal(ctx context.Context, params *StartDealParams) (*cid.Cid, error) //perm:admin ClientStartDeal(ctx context.Context, params *StartDealParams) (*cid.Cid, error) //perm:admin
// ClientStatelessDeal fire-and-forget-proposes an offline deal to a miner without subsequent tracking. // ClientStatelessDeal fire-and-forget-proposes an offline deal to a miner without subsequent tracking.
@@ -350,11 +351,10 @@ type FullNode interface {
// ClientMinerQueryOffer returns a QueryOffer for the specific miner and file. // ClientMinerQueryOffer returns a QueryOffer for the specific miner and file.
ClientMinerQueryOffer(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (QueryOffer, error) //perm:read ClientMinerQueryOffer(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (QueryOffer, error) //perm:read
// ClientRetrieve initiates the retrieval of a file, as specified in the order. // ClientRetrieve initiates the retrieval of a file, as specified in the order.
ClientRetrieve(ctx context.Context, params RetrievalOrder) (*RestrievalRes, error) //perm:admin ClientRetrieve(ctx context.Context, order RetrievalOrder, ref *FileRef) error //perm:admin
// ClientRetrieveWait waits for retrieval to be complete // ClientRetrieveWithEvents initiates the retrieval of a file, as specified in the order, and provides a channel
ClientRetrieveWait(ctx context.Context, deal retrievalmarket.DealID) error //perm:admin // of status updates.
// ClientExport exports a file stored in the local filestore to a system file ClientRetrieveWithEvents(ctx context.Context, order RetrievalOrder, ref *FileRef) (<-chan marketevents.RetrievalEvent, error) //perm:admin
ClientExport(ctx context.Context, exportRef ExportRef, fileRef FileRef) error //perm:admin
// ClientListRetrievals returns information about retrievals made by the local client // ClientListRetrievals returns information about retrievals made by the local client
ClientListRetrievals(ctx context.Context) ([]RetrievalInfo, error) //perm:write ClientListRetrievals(ctx context.Context) ([]RetrievalInfo, error) //perm:write
// ClientGetRetrievalUpdates returns status of updated retrieval deals // ClientGetRetrievalUpdates returns status of updated retrieval deals
@@ -428,8 +428,6 @@ type FullNode interface {
StateListMessages(ctx context.Context, match *MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) //perm:read StateListMessages(ctx context.Context, match *MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) //perm:read
// StateDecodeParams attempts to decode the provided params, based on the recipient actor address and method number. // StateDecodeParams attempts to decode the provided params, based on the recipient actor address and method number.
StateDecodeParams(ctx context.Context, toAddr address.Address, method abi.MethodNum, params []byte, tsk types.TipSetKey) (interface{}, error) //perm:read StateDecodeParams(ctx context.Context, toAddr address.Address, method abi.MethodNum, params []byte, tsk types.TipSetKey) (interface{}, error) //perm:read
// StateEncodeParams attempts to encode the provided json params to the binary from
StateEncodeParams(ctx context.Context, toActCode cid.Cid, method abi.MethodNum, params json.RawMessage) ([]byte, error) //perm:read
// StateNetworkName returns the name of the network the node is synced to // StateNetworkName returns the name of the network the node is synced to
StateNetworkName(context.Context) (dtypes.NetworkName, error) //perm:read StateNetworkName(context.Context) (dtypes.NetworkName, error) //perm:read
@@ -585,11 +583,6 @@ type FullNode interface {
// StateNetworkVersion returns the network version at the given tipset // StateNetworkVersion returns the network version at the given tipset
StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, error) //perm:read StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, error) //perm:read
// StateGetRandomnessFromTickets is used to sample the chain for randomness.
StateGetRandomnessFromTickets(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) //perm:read
// StateGetRandomnessFromBeacon is used to sample the beacon for randomness.
StateGetRandomnessFromBeacon(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) //perm:read
// MethodGroup: Msig // MethodGroup: Msig
// The Msig methods are used to interact with multisig wallets on the // The Msig methods are used to interact with multisig wallets on the
// filecoin network // filecoin network
@@ -629,14 +622,10 @@ type FullNode interface {
// <sender address of the approve msg>, <method to call in the proposed message>, <params to include in the proposed message> // <sender address of the approve msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigApproveTxnHash(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (*MessagePrototype, error) //perm:sign MsigApproveTxnHash(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (*MessagePrototype, error) //perm:sign
// MsigCancel cancels a previously-proposed multisig message
// It takes the following params: <multisig address>, <proposed transaction ID> <signer address>
MsigCancel(context.Context, address.Address, uint64, address.Address) (*MessagePrototype, error) //perm:sign
// MsigCancel cancels a previously-proposed multisig message // MsigCancel cancels a previously-proposed multisig message
// It takes the following params: <multisig address>, <proposed transaction ID>, <recipient address>, <value to transfer>, // It takes the following params: <multisig address>, <proposed transaction ID>, <recipient address>, <value to transfer>,
// <sender address of the cancel msg>, <method to call in the proposed message>, <params to include in the proposed message> // <sender address of the cancel msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigCancelTxnHash(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (*MessagePrototype, error) //perm:sign MsigCancel(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (*MessagePrototype, error) //perm:sign
// MsigAddPropose proposes adding a signer in the multisig // MsigAddPropose proposes adding a signer in the multisig
// It takes the following params: <multisig address>, <sender address of the propose msg>, // It takes the following params: <multisig address>, <sender address of the propose msg>,
@@ -689,17 +678,7 @@ type FullNode interface {
// MethodGroup: Paych // MethodGroup: Paych
// The Paych methods are for interacting with and managing payment channels // The Paych methods are for interacting with and managing payment channels
// PaychGet gets or creates a payment channel between address pair PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*ChannelInfo, error) //perm:sign
// The specified amount will be reserved for use. If there aren't enough non-reserved funds
// available, funds will be added through an on-chain message.
// - When opts.OffChain is true, this call will not cause any messages to be sent to the chain (no automatic
// channel creation/funds adding). If the operation can't be performed without sending a message an error will be
// returned. Note that even when this option is specified, this call can be blocked by previous operations on the
// channel waiting for on-chain operations.
PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt, opts PaychGetOpts) (*ChannelInfo, error) //perm:sign
// PaychFund gets or creates a payment channel between address pair.
// The specified amount will be added to the channel through on-chain send for future use
PaychFund(ctx context.Context, from, to address.Address, amt types.BigInt) (*ChannelInfo, error) //perm:sign
PaychGetWaitReady(context.Context, cid.Cid) (address.Address, error) //perm:sign PaychGetWaitReady(context.Context, cid.Cid) (address.Address, error) //perm:sign
PaychAvailableFunds(ctx context.Context, ch address.Address) (*ChannelAvailableFunds, error) //perm:sign PaychAvailableFunds(ctx context.Context, ch address.Address) (*ChannelAvailableFunds, error) //perm:sign
PaychAvailableFundsByFromTo(ctx context.Context, from, to address.Address) (*ChannelAvailableFunds, error) //perm:sign PaychAvailableFundsByFromTo(ctx context.Context, from, to address.Address) (*ChannelAvailableFunds, error) //perm:sign
@@ -744,28 +723,17 @@ type MinerSectors struct {
type ImportRes struct { type ImportRes struct {
Root cid.Cid Root cid.Cid
ImportID imports.ID ImportID importmgr.ImportID
} }
type Import struct { type Import struct {
Key imports.ID Key importmgr.ImportID
Err string Err string
Root *cid.Cid Root *cid.Cid
Source string
// Source is the provenance of the import, e.g. "import", "unknown", else. FilePath string
// Currently useless but may be used in the future. CARv2FilePath string
Source string
// FilePath is the path of the original file. It is important that the file
// is retained at this path, because it will be referenced during
// the transfer (when we do the UnixFS chunking, we don't duplicate the
// leaves, but rather point to chunks of the original data through
// positional references).
FilePath string
// CARPath is the path of the CAR file containing the DAG for this import.
CARPath string
} }
type DealInfo struct { type DealInfo struct {
@@ -838,10 +806,6 @@ const (
PCHOutbound PCHOutbound
) )
type PaychGetOpts struct {
OffChain bool
}
type PaychStatus struct { type PaychStatus struct {
ControlAddr address.Address ControlAddr address.Address
Direction PCHDir Direction PCHDir
@@ -859,23 +823,16 @@ type ChannelAvailableFunds struct {
From address.Address From address.Address
// To is the to address of the channel // To is the to address of the channel
To address.Address To address.Address
// ConfirmedAmt is the amount of funds that have been confirmed on-chain
// ConfirmedAmt is the total amount of funds that have been confirmed on-chain for the channel // for the channel
ConfirmedAmt types.BigInt ConfirmedAmt types.BigInt
// PendingAmt is the amount of funds that are pending confirmation on-chain // PendingAmt is the amount of funds that are pending confirmation on-chain
PendingAmt types.BigInt PendingAmt types.BigInt
// NonReservedAmt is part of ConfirmedAmt that is available for use (e.g. when the payment channel was pre-funded)
NonReservedAmt types.BigInt
// PendingAvailableAmt is the amount of funds that are pending confirmation on-chain that will become available once confirmed
PendingAvailableAmt types.BigInt
// PendingWaitSentinel can be used with PaychGetWaitReady to wait for // PendingWaitSentinel can be used with PaychGetWaitReady to wait for
// confirmation of pending funds // confirmation of pending funds
PendingWaitSentinel *cid.Cid PendingWaitSentinel *cid.Cid
// QueuedAmt is the amount that is queued up behind a pending request // QueuedAmt is the amount that is queued up behind a pending request
QueuedAmt types.BigInt QueuedAmt types.BigInt
// VoucherRedeemedAmt is the amount that is redeemed by vouchers on-chain // VoucherRedeemedAmt is the amount that is redeemed by vouchers on-chain
// and in the local datastore // and in the local datastore
VoucherReedeemedAmt types.BigInt VoucherReedeemedAmt types.BigInt
@@ -921,7 +878,6 @@ type QueryOffer struct {
Size uint64 Size uint64
MinPrice types.BigInt MinPrice types.BigInt
UnsealPrice types.BigInt UnsealPrice types.BigInt
PricePerByte abi.TokenAmount
PaymentInterval uint64 PaymentInterval uint64
PaymentIntervalIncrease uint64 PaymentIntervalIncrease uint64
Miner address.Address Miner address.Address
@@ -955,14 +911,14 @@ type MarketDeal struct {
} }
type RetrievalOrder struct { type RetrievalOrder struct {
Root cid.Cid // TODO: make this less unixfs specific
Piece *cid.Cid Root cid.Cid
DataSelector *Selector Piece *cid.Cid
// todo: Size/Total are only used for calculating price per byte; we should let users just pass that
Size uint64 Size uint64
Total types.BigInt
LocalCARV2FilePath string // if specified, get data from a local CARv2 file.
// TODO: support offset
Total types.BigInt
UnsealPrice types.BigInt UnsealPrice types.BigInt
PaymentInterval uint64 PaymentInterval uint64
PaymentIntervalIncrease uint64 PaymentIntervalIncrease uint64
@@ -1105,7 +1061,7 @@ type CirculatingSupply struct {
type MiningBaseInfo struct { type MiningBaseInfo struct {
MinerPower types.BigInt MinerPower types.BigInt
NetworkPower types.BigInt NetworkPower types.BigInt
Sectors []builtin.ExtendedSectorInfo Sectors []builtin.SectorInfo
WorkerKey address.Address WorkerKey address.Address
SectorSize abi.SectorSize SectorSize abi.SectorSize
PrevBeaconEntry types.BeaconEntry PrevBeaconEntry types.BeaconEntry
+1 -7
View File
@@ -31,23 +31,17 @@ import (
type Gateway interface { type Gateway interface {
ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHasObj(context.Context, cid.Cid) (bool, error)
ChainHead(ctx context.Context) (*types.TipSet, error) ChainHead(ctx context.Context) (*types.TipSet, error)
ChainGetParentMessages(context.Context, cid.Cid) ([]Message, error)
ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error) ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error)
ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*HeadChange, error)
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetAfterHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
ChainNotify(context.Context) (<-chan []*HeadChange, error) ChainNotify(context.Context) (<-chan []*HeadChange, error)
ChainReadObj(context.Context, cid.Cid) ([]byte, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error)
ChainGetGenesis(context.Context) (*types.TipSet, error)
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*MsigTransaction, error)
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
MsigGetVestingSchedule(ctx context.Context, addr address.Address, tsk types.TipSetKey) (MsigVesting, error) MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*MsigTransaction, error)
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (DealCollateralBounds, error) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (DealCollateralBounds, error)
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
-11
View File
@@ -2,7 +2,6 @@ package api
import ( import (
"context" "context"
"time"
metrics "github.com/libp2p/go-libp2p-core/metrics" metrics "github.com/libp2p/go-libp2p-core/metrics"
"github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/network"
@@ -26,7 +25,6 @@ type Net interface {
NetConnectedness(context.Context, peer.ID) (network.Connectedness, error) //perm:read NetConnectedness(context.Context, peer.ID) (network.Connectedness, error) //perm:read
NetPeers(context.Context) ([]peer.AddrInfo, error) //perm:read NetPeers(context.Context) ([]peer.AddrInfo, error) //perm:read
NetPing(context.Context, peer.ID) (time.Duration, error) //perm:read
NetConnect(context.Context, peer.AddrInfo) error //perm:write NetConnect(context.Context, peer.AddrInfo) error //perm:write
NetAddrsListen(context.Context) (peer.AddrInfo, error) //perm:read NetAddrsListen(context.Context) (peer.AddrInfo, error) //perm:read
NetDisconnect(context.Context, peer.ID) error //perm:write NetDisconnect(context.Context, peer.ID) error //perm:write
@@ -53,15 +51,6 @@ type Net interface {
NetBlockRemove(ctx context.Context, acl NetBlockList) error //perm:admin NetBlockRemove(ctx context.Context, acl NetBlockList) error //perm:admin
NetBlockList(ctx context.Context) (NetBlockList, error) //perm:read NetBlockList(ctx context.Context) (NetBlockList, error) //perm:read
NetProtectAdd(ctx context.Context, acl []peer.ID) error //perm:admin
NetProtectRemove(ctx context.Context, acl []peer.ID) error //perm:admin
NetProtectList(ctx context.Context) ([]peer.ID, error) //perm:read
// ResourceManager API
NetStat(ctx context.Context, scope string) (NetStat, error) //perm:read
NetLimit(ctx context.Context, scope string) (NetLimit, error) //perm:read
NetSetLimit(ctx context.Context, scope string, limit NetLimit) error //perm:admin
// ID returns peerID of libp2p node backing this API // ID returns peerID of libp2p node backing this API
ID(context.Context) (peer.ID, error) //perm:read ID(context.Context) (peer.ID, error) //perm:read
} }
+45 -147
View File
@@ -13,17 +13,16 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
datatransfer "github.com/filecoin-project/go-data-transfer" datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-state-types/abi"
abinetwork "github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/specs-actors/v2/actors/builtin/market"
"github.com/filecoin-project/specs-storage/storage"
"github.com/filecoin-project/go-fil-markets/piecestore" "github.com/filecoin-project/go-fil-markets/piecestore"
"github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/v2/actors/builtin/market"
"github.com/filecoin-project/specs-storage/storage"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil" "github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
"github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/lotus/extern/sector-storage/storiface"
"github.com/filecoin-project/lotus/extern/storage-sealing/sealiface" "github.com/filecoin-project/lotus/extern/storage-sealing/sealiface"
) )
@@ -91,8 +90,7 @@ type StorageMiner interface {
SectorsUpdate(context.Context, abi.SectorNumber, SectorState) error //perm:admin SectorsUpdate(context.Context, abi.SectorNumber, SectorState) error //perm:admin
// SectorRemove removes the sector from storage. It doesn't terminate it on-chain, which can // SectorRemove removes the sector from storage. It doesn't terminate it on-chain, which can
// be done with SectorTerminate. Removing and not terminating live sectors will cause additional penalties. // be done with SectorTerminate. Removing and not terminating live sectors will cause additional penalties.
SectorRemove(context.Context, abi.SectorNumber) error //perm:admin SectorRemove(context.Context, abi.SectorNumber) error //perm:admin
SectorMarkForUpgrade(ctx context.Context, id abi.SectorNumber, snap bool) error //perm:admin
// SectorTerminate terminates the sector on-chain (adding it to a termination batch first), then // SectorTerminate terminates the sector on-chain (adding it to a termination batch first), then
// automatically removes it from storage // automatically removes it from storage
SectorTerminate(context.Context, abi.SectorNumber) error //perm:admin SectorTerminate(context.Context, abi.SectorNumber) error //perm:admin
@@ -100,7 +98,8 @@ type StorageMiner interface {
// Returns null if message wasn't sent // Returns null if message wasn't sent
SectorTerminateFlush(ctx context.Context) (*cid.Cid, error) //perm:admin SectorTerminateFlush(ctx context.Context) (*cid.Cid, error) //perm:admin
// SectorTerminatePending returns a list of pending sector terminations to be sent in the next batch message // SectorTerminatePending returns a list of pending sector terminations to be sent in the next batch message
SectorTerminatePending(ctx context.Context) ([]abi.SectorID, error) //perm:admin SectorTerminatePending(ctx context.Context) ([]abi.SectorID, error) //perm:admin
SectorMarkForUpgrade(ctx context.Context, id abi.SectorNumber) error //perm:admin
// SectorPreCommitFlush immediately sends a PreCommit message with sectors batched for PreCommit. // SectorPreCommitFlush immediately sends a PreCommit message with sectors batched for PreCommit.
// Returns null if message wasn't sent // Returns null if message wasn't sent
SectorPreCommitFlush(ctx context.Context) ([]sealiface.PreCommitBatchRes, error) //perm:admin SectorPreCommitFlush(ctx context.Context) ([]sealiface.PreCommitBatchRes, error) //perm:admin
@@ -111,9 +110,6 @@ type StorageMiner interface {
SectorCommitFlush(ctx context.Context) ([]sealiface.CommitBatchRes, error) //perm:admin SectorCommitFlush(ctx context.Context) ([]sealiface.CommitBatchRes, error) //perm:admin
// SectorCommitPending returns a list of pending Commit sectors to be sent in the next aggregate message // SectorCommitPending returns a list of pending Commit sectors to be sent in the next aggregate message
SectorCommitPending(ctx context.Context) ([]abi.SectorID, error) //perm:admin SectorCommitPending(ctx context.Context) ([]abi.SectorID, error) //perm:admin
SectorMatchPendingPiecesToOpenSectors(ctx context.Context) error //perm:admin
// SectorAbortUpgrade can be called on sectors that are in the process of being upgraded to abort it
SectorAbortUpgrade(context.Context, abi.SectorNumber) error //perm:admin
// WorkerConnect tells the node to connect to workers RPC // WorkerConnect tells the node to connect to workers RPC
WorkerConnect(context.Context, string) error //perm:admin retry:true WorkerConnect(context.Context, string) error //perm:admin retry:true
@@ -121,42 +117,36 @@ type StorageMiner interface {
WorkerJobs(context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) //perm:admin WorkerJobs(context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) //perm:admin
//storiface.WorkerReturn //storiface.WorkerReturn
ReturnAddPiece(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err *storiface.CallError) error //perm:admin retry:true ReturnAddPiece(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err *storiface.CallError) error //perm:admin retry:true
ReturnSealPreCommit1(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err *storiface.CallError) error //perm:admin retry:true ReturnSealPreCommit1(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err *storiface.CallError) error //perm:admin retry:true
ReturnSealPreCommit2(ctx context.Context, callID storiface.CallID, sealed storage.SectorCids, err *storiface.CallError) error //perm:admin retry:true ReturnSealPreCommit2(ctx context.Context, callID storiface.CallID, sealed storage.SectorCids, err *storiface.CallError) error //perm:admin retry:true
ReturnSealCommit1(ctx context.Context, callID storiface.CallID, out storage.Commit1Out, err *storiface.CallError) error //perm:admin retry:true ReturnSealCommit1(ctx context.Context, callID storiface.CallID, out storage.Commit1Out, err *storiface.CallError) error //perm:admin retry:true
ReturnSealCommit2(ctx context.Context, callID storiface.CallID, proof storage.Proof, err *storiface.CallError) error //perm:admin retry:true ReturnSealCommit2(ctx context.Context, callID storiface.CallID, proof storage.Proof, err *storiface.CallError) error //perm:admin retry:true
ReturnFinalizeSector(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true ReturnFinalizeSector(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
ReturnReplicaUpdate(ctx context.Context, callID storiface.CallID, out storage.ReplicaUpdateOut, err *storiface.CallError) error //perm:admin retry:true ReturnReleaseUnsealed(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
ReturnProveReplicaUpdate1(ctx context.Context, callID storiface.CallID, vanillaProofs storage.ReplicaVanillaProofs, err *storiface.CallError) error //perm:admin retry:true ReturnMoveStorage(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
ReturnProveReplicaUpdate2(ctx context.Context, callID storiface.CallID, proof storage.ReplicaUpdateProof, err *storiface.CallError) error //perm:admin retry:true ReturnUnsealPiece(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
ReturnGenerateSectorKeyFromData(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true ReturnReadPiece(ctx context.Context, callID storiface.CallID, ok bool, err *storiface.CallError) error //perm:admin retry:true
ReturnFinalizeReplicaUpdate(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true ReturnFetch(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
ReturnReleaseUnsealed(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
ReturnMoveStorage(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
ReturnUnsealPiece(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
ReturnReadPiece(ctx context.Context, callID storiface.CallID, ok bool, err *storiface.CallError) error //perm:admin retry:true
ReturnFetch(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
// SealingSchedDiag dumps internal sealing scheduler state // SealingSchedDiag dumps internal sealing scheduler state
SealingSchedDiag(ctx context.Context, doSched bool) (interface{}, error) //perm:admin SealingSchedDiag(ctx context.Context, doSched bool) (interface{}, error) //perm:admin
SealingAbort(ctx context.Context, call storiface.CallID) error //perm:admin SealingAbort(ctx context.Context, call storiface.CallID) error //perm:admin
// SectorIndex //stores.SectorIndex
StorageAttach(context.Context, storiface.StorageInfo, fsutil.FsStat) error //perm:admin StorageAttach(context.Context, stores.StorageInfo, fsutil.FsStat) error //perm:admin
StorageInfo(context.Context, storiface.ID) (storiface.StorageInfo, error) //perm:admin StorageInfo(context.Context, stores.ID) (stores.StorageInfo, error) //perm:admin
StorageReportHealth(context.Context, storiface.ID, storiface.HealthReport) error //perm:admin StorageReportHealth(context.Context, stores.ID, stores.HealthReport) error //perm:admin
StorageDeclareSector(ctx context.Context, storageID storiface.ID, s abi.SectorID, ft storiface.SectorFileType, primary bool) error //perm:admin StorageDeclareSector(ctx context.Context, storageID stores.ID, s abi.SectorID, ft storiface.SectorFileType, primary bool) error //perm:admin
StorageDropSector(ctx context.Context, storageID storiface.ID, s abi.SectorID, ft storiface.SectorFileType) error //perm:admin StorageDropSector(ctx context.Context, storageID stores.ID, s abi.SectorID, ft storiface.SectorFileType) error //perm:admin
StorageFindSector(ctx context.Context, sector abi.SectorID, ft storiface.SectorFileType, ssize abi.SectorSize, allowFetch bool) ([]storiface.SectorStorageInfo, error) //perm:admin StorageFindSector(ctx context.Context, sector abi.SectorID, ft storiface.SectorFileType, ssize abi.SectorSize, allowFetch bool) ([]stores.SectorStorageInfo, error) //perm:admin
StorageBestAlloc(ctx context.Context, allocate storiface.SectorFileType, ssize abi.SectorSize, pathType storiface.PathType) ([]storiface.StorageInfo, error) //perm:admin StorageBestAlloc(ctx context.Context, allocate storiface.SectorFileType, ssize abi.SectorSize, pathType storiface.PathType) ([]stores.StorageInfo, error) //perm:admin
StorageLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) error //perm:admin StorageLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) error //perm:admin
StorageTryLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) //perm:admin StorageTryLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) //perm:admin
StorageList(ctx context.Context) (map[storiface.ID][]storiface.Decl, error) //perm:admin StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error) //perm:admin
StorageGetLocks(ctx context.Context) (storiface.SectorLocks, error) //perm:admin
StorageLocal(ctx context.Context) (map[storiface.ID]string, error) //perm:admin StorageLocal(ctx context.Context) (map[stores.ID]string, error) //perm:admin
StorageStat(ctx context.Context, id storiface.ID) (fsutil.FsStat, error) //perm:admin StorageStat(ctx context.Context, id stores.ID) (fsutil.FsStat, error) //perm:admin
MarketImportDealData(ctx context.Context, propcid cid.Cid, path string) error //perm:write MarketImportDealData(ctx context.Context, propcid cid.Cid, path string) error //perm:write
MarketListDeals(ctx context.Context) ([]MarketDeal, error) //perm:read MarketListDeals(ctx context.Context) ([]MarketDeal, error) //perm:read
@@ -169,67 +159,12 @@ type StorageMiner interface {
MarketGetRetrievalAsk(ctx context.Context) (*retrievalmarket.Ask, error) //perm:read MarketGetRetrievalAsk(ctx context.Context) (*retrievalmarket.Ask, error) //perm:read
MarketListDataTransfers(ctx context.Context) ([]DataTransferChannel, error) //perm:write MarketListDataTransfers(ctx context.Context) ([]DataTransferChannel, error) //perm:write
MarketDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error) //perm:write MarketDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error) //perm:write
// MarketDataTransferDiagnostics generates debugging information about current data transfers over graphsync
MarketDataTransferDiagnostics(ctx context.Context, p peer.ID) (*TransferDiagnostics, error) //perm:write
// MarketRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer // MarketRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer
MarketRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error //perm:write MarketRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error //perm:write
// MarketCancelDataTransfer cancels a data transfer with the given transfer ID and other peer // MarketCancelDataTransfer cancels a data transfer with the given transfer ID and other peer
MarketCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error //perm:write MarketCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error //perm:write
MarketPendingDeals(ctx context.Context) (PendingDealInfo, error) //perm:write MarketPendingDeals(ctx context.Context) (PendingDealInfo, error) //perm:write
MarketPublishPendingDeals(ctx context.Context) error //perm:admin 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.
DagstoreListShards(ctx context.Context) ([]DagstoreShardInfo, error) //perm:read
// DagstoreInitializeShard initializes an uninitialized shard.
//
// Initialization consists of fetching the shard's data (deal payload) from
// the storage subsystem, generating an index, and persisting the index
// to facilitate later retrievals, and/or to publish to external sources.
//
// This operation is intended to complement the initial migration. The
// migration registers a shard for every unique piece CID, with lazy
// initialization. Thus, shards are not initialized immediately to avoid
// IO activity competing with proving. Instead, shard are initialized
// when first accessed. This method forces the initialization of a shard by
// accessing it and immediately releasing it. This is useful to warm up the
// cache to facilitate subsequent retrievals, and to generate the indexes
// to publish them externally.
//
// This operation fails if the shard is not in ShardStateNew state.
// It blocks until initialization finishes.
DagstoreInitializeShard(ctx context.Context, key string) error //perm:write
// DagstoreRecoverShard attempts to recover a failed shard.
//
// This operation fails if the shard is not in ShardStateErrored state.
// It blocks until recovery finishes. If recovery failed, it returns the
// error.
DagstoreRecoverShard(ctx context.Context, key string) error //perm:write
// DagstoreInitializeAll initializes all uninitialized shards in bulk,
// according to the policy passed in the parameters.
//
// It is recommended to set a maximum concurrency to avoid extreme
// IO pressure if the storage subsystem has a large amount of deals.
//
// It returns a stream of events to report progress.
DagstoreInitializeAll(ctx context.Context, params DagstoreInitializeAllParams) (<-chan DagstoreInitializeAllEvent, error) //perm:write
// DagstoreGC runs garbage collection on the DAG store.
DagstoreGC(ctx context.Context) ([]DagstoreShardResult, error) //perm:admin
// IndexerAnnounceDeal informs indexer nodes that a new deal was received,
// so they can download its index
IndexerAnnounceDeal(ctx context.Context, proposalCid cid.Cid) error //perm:admin
// IndexerAnnounceAllDeals informs the indexer nodes aboutall active deals.
IndexerAnnounceAllDeals(ctx context.Context) error //perm:admin
// DagstoreLookupPieces returns information about shards that contain the given CID.
DagstoreLookupPieces(ctx context.Context, cid cid.Cid) ([]DagstoreShardInfo, error) //perm:admin
// RuntimeSubsystems returns the subsystems that are enabled // RuntimeSubsystems returns the subsystems that are enabled
// in this instance. // in this instance.
@@ -267,10 +202,11 @@ type StorageMiner interface {
CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef, expensive bool) (map[abi.SectorNumber]string, error) //perm:admin CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef, expensive bool) (map[abi.SectorNumber]string, error) //perm:admin
ComputeProof(ctx context.Context, ssi []builtin.ExtendedSectorInfo, rand abi.PoStRandomness, poStEpoch abi.ChainEpoch, nv abinetwork.Version) ([]builtin.PoStProof, error) //perm:read ComputeProof(ctx context.Context, ssi []builtin.SectorInfo, rand abi.PoStRandomness) ([]builtin.PoStProof, error) //perm:read
} }
var _ storiface.WorkerReturn = *new(StorageMiner) var _ storiface.WorkerReturn = *new(StorageMiner)
var _ stores.SectorIndex = *new(StorageMiner)
type SealRes struct { type SealRes struct {
Err string Err string
@@ -288,26 +224,19 @@ type SectorLog struct {
Message string Message string
} }
type SectorPiece struct {
Piece abi.PieceInfo
DealInfo *PieceDealInfo // nil for pieces which do not appear in deals (e.g. filler pieces)
}
type SectorInfo struct { type SectorInfo struct {
SectorID abi.SectorNumber SectorID abi.SectorNumber
State SectorState State SectorState
CommD *cid.Cid CommD *cid.Cid
CommR *cid.Cid CommR *cid.Cid
Proof []byte Proof []byte
Deals []abi.DealID Deals []abi.DealID
Pieces []SectorPiece Ticket SealTicket
Ticket SealTicket Seed SealSeed
Seed SealSeed PreCommitMsg *cid.Cid
PreCommitMsg *cid.Cid CommitMsg *cid.Cid
CommitMsg *cid.Cid Retries uint64
Retries uint64 ToUpgrade bool
ToUpgrade bool
ReplicaUpdateMessage *cid.Cid
LastErr string LastErr string
@@ -407,34 +336,3 @@ type DealSchedule struct {
StartEpoch abi.ChainEpoch StartEpoch abi.ChainEpoch
EndEpoch abi.ChainEpoch EndEpoch abi.ChainEpoch
} }
// DagstoreShardInfo is the serialized form of dagstore.DagstoreShardInfo that
// we expose through JSON-RPC to avoid clients having to depend on the
// dagstore lib.
type DagstoreShardInfo struct {
Key string
State string
Error string
}
// DagstoreShardResult enumerates results per shard.
type DagstoreShardResult struct {
Key string
Success bool
Error string
}
type DagstoreInitializeAllParams struct {
MaxConcurrency int
IncludeSealed bool
}
// DagstoreInitializeAllEvent represents an initialization event.
type DagstoreInitializeAllEvent struct {
Key string
Event string // "start", "end"
Success bool
Error string
Total int
Current int
}
+1 -6
View File
@@ -1,4 +1,3 @@
//stm: #unit
package api package api
import ( import (
@@ -27,7 +26,6 @@ func goCmd() string {
} }
func TestDoesntDependOnFFI(t *testing.T) { func TestDoesntDependOnFFI(t *testing.T) {
//stm: @OTHER_IMPLEMENTATION_FFI_DEPENDENCE_001
deps, err := exec.Command(goCmd(), "list", "-deps", "github.com/filecoin-project/lotus/api").Output() deps, err := exec.Command(goCmd(), "list", "-deps", "github.com/filecoin-project/lotus/api").Output()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -40,7 +38,6 @@ func TestDoesntDependOnFFI(t *testing.T) {
} }
func TestDoesntDependOnBuild(t *testing.T) { func TestDoesntDependOnBuild(t *testing.T) {
//stm: @OTHER_IMPLEMENTATION_FFI_DEPENDENCE_002
deps, err := exec.Command(goCmd(), "list", "-deps", "github.com/filecoin-project/lotus/api").Output() deps, err := exec.Command(goCmd(), "list", "-deps", "github.com/filecoin-project/lotus/api").Output()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -53,7 +50,6 @@ func TestDoesntDependOnBuild(t *testing.T) {
} }
func TestReturnTypes(t *testing.T) { func TestReturnTypes(t *testing.T) {
//stm: @OTHER_IMPLEMENTATION_001
errType := reflect.TypeOf(new(error)).Elem() errType := reflect.TypeOf(new(error)).Elem()
bareIface := reflect.TypeOf(new(interface{})).Elem() bareIface := reflect.TypeOf(new(interface{})).Elem()
jmarsh := reflect.TypeOf(new(json.Marshaler)).Elem() jmarsh := reflect.TypeOf(new(json.Marshaler)).Elem()
@@ -80,7 +76,7 @@ func TestReturnTypes(t *testing.T) {
seen[typ] = struct{}{} seen[typ] = struct{}{}
if typ.Kind() == reflect.Interface && typ != bareIface && !typ.Implements(jmarsh) { if typ.Kind() == reflect.Interface && typ != bareIface && !typ.Implements(jmarsh) {
t.Error("methods can't return interfaces or struct types not implementing json.Marshaller", m.Name) t.Error("methods can't return interfaces", m.Name)
} }
switch typ.Kind() { switch typ.Kind() {
@@ -119,7 +115,6 @@ func TestReturnTypes(t *testing.T) {
} }
func TestPermTags(t *testing.T) { func TestPermTags(t *testing.T) {
//stm: @OTHER_IMPLEMENTATION_PERM_TAGS_001
_ = PermissionedFullAPI(&FullNodeStruct{}) _ = PermissionedFullAPI(&FullNodeStruct{})
_ = PermissionedStorMinerAPI(&StorageMinerStruct{}) _ = PermissionedStorMinerAPI(&StorageMinerStruct{})
_ = PermissionedWorkerAPI(&WorkerStruct{}) _ = PermissionedWorkerAPI(&WorkerStruct{})
+2 -11
View File
@@ -7,9 +7,8 @@ import (
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/v5/actors/runtime/proof"
"github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks"
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
"github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/lotus/extern/sector-storage/storiface"
"github.com/filecoin-project/specs-storage/storage" "github.com/filecoin-project/specs-storage/storage"
) )
@@ -30,7 +29,7 @@ type Worker interface {
// TaskType -> Weight // TaskType -> Weight
TaskTypes(context.Context) (map[sealtasks.TaskType]struct{}, error) //perm:admin TaskTypes(context.Context) (map[sealtasks.TaskType]struct{}, error) //perm:admin
Paths(context.Context) ([]storiface.StoragePath, error) //perm:admin Paths(context.Context) ([]stores.StoragePath, error) //perm:admin
Info(context.Context) (storiface.WorkerInfo, error) //perm:admin Info(context.Context) (storiface.WorkerInfo, error) //perm:admin
// storiface.WorkerCalls // storiface.WorkerCalls
@@ -40,19 +39,11 @@ type Worker interface {
SealCommit1(ctx context.Context, sector storage.SectorRef, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) //perm:admin SealCommit1(ctx context.Context, sector storage.SectorRef, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) //perm:admin
SealCommit2(ctx context.Context, sector storage.SectorRef, c1o storage.Commit1Out) (storiface.CallID, error) //perm:admin SealCommit2(ctx context.Context, sector storage.SectorRef, c1o storage.Commit1Out) (storiface.CallID, error) //perm:admin
FinalizeSector(ctx context.Context, sector storage.SectorRef, keepUnsealed []storage.Range) (storiface.CallID, error) //perm:admin FinalizeSector(ctx context.Context, sector storage.SectorRef, keepUnsealed []storage.Range) (storiface.CallID, error) //perm:admin
FinalizeReplicaUpdate(ctx context.Context, sector storage.SectorRef, keepUnsealed []storage.Range) (storiface.CallID, error) //perm:admin
ReplicaUpdate(ctx context.Context, sector storage.SectorRef, pieces []abi.PieceInfo) (storiface.CallID, error) //perm:admin
ProveReplicaUpdate1(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid) (storiface.CallID, error) //perm:admin
ProveReplicaUpdate2(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid, vanillaProofs storage.ReplicaVanillaProofs) (storiface.CallID, error) //perm:admin
GenerateSectorKeyFromData(ctx context.Context, sector storage.SectorRef, commD cid.Cid) (storiface.CallID, error) //perm:admin
ReleaseUnsealed(ctx context.Context, sector storage.SectorRef, safeToFree []storage.Range) (storiface.CallID, error) //perm:admin ReleaseUnsealed(ctx context.Context, sector storage.SectorRef, safeToFree []storage.Range) (storiface.CallID, error) //perm:admin
MoveStorage(ctx context.Context, sector storage.SectorRef, types storiface.SectorFileType) (storiface.CallID, error) //perm:admin MoveStorage(ctx context.Context, sector storage.SectorRef, types storiface.SectorFileType) (storiface.CallID, error) //perm:admin
UnsealPiece(context.Context, storage.SectorRef, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (storiface.CallID, error) //perm:admin UnsealPiece(context.Context, storage.SectorRef, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (storiface.CallID, error) //perm:admin
Fetch(context.Context, storage.SectorRef, storiface.SectorFileType, storiface.PathType, storiface.AcquireMode) (storiface.CallID, error) //perm:admin Fetch(context.Context, storage.SectorRef, storiface.SectorFileType, storiface.PathType, storiface.AcquireMode) (storiface.CallID, error) //perm:admin
GenerateWinningPoSt(ctx context.Context, ppt abi.RegisteredPoStProof, mid abi.ActorID, sectors []storiface.PostSectorChallenge, randomness abi.PoStRandomness) ([]proof.PoStProof, error) //perm:admin
GenerateWindowPoSt(ctx context.Context, ppt abi.RegisteredPoStProof, mid abi.ActorID, sectors []storiface.PostSectorChallenge, partitionIdx int, randomness abi.PoStRandomness) (storiface.WindowPoStResult, error) //perm:admin
TaskDisable(ctx context.Context, tt sealtasks.TaskType) error //perm:admin TaskDisable(ctx context.Context, tt sealtasks.TaskType) error //perm:admin
TaskEnable(ctx context.Context, tt sealtasks.TaskType) error //perm:admin TaskEnable(ctx context.Context, tt sealtasks.TaskType) error //perm:admin
+17 -69
View File
@@ -1,7 +1,6 @@
package docgen package docgen
import ( import (
"encoding/json"
"fmt" "fmt"
"go/ast" "go/ast"
"go/parser" "go/parser"
@@ -14,9 +13,11 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-multistore"
"github.com/filecoin-project/lotus/node/repo/importmgr"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/ipfs/go-graphsync" "github.com/ipfs/go-filestore"
"github.com/libp2p/go-libp2p-core/metrics" "github.com/libp2p/go-libp2p-core/metrics"
"github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
@@ -25,10 +26,9 @@ import (
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
datatransfer "github.com/filecoin-project/go-data-transfer" datatransfer "github.com/filecoin-project/go-data-transfer"
filestore "github.com/filecoin-project/go-fil-markets/filestore" filestore2 "github.com/filecoin-project/go-fil-markets/filestore"
"github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-jsonrpc/auth" "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/abi"
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
@@ -40,10 +40,10 @@ import (
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks"
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
"github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/lotus/extern/sector-storage/storiface"
sealing "github.com/filecoin-project/lotus/extern/storage-sealing" sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/repo/imports"
) )
var ExampleValues = map[reflect.Type]interface{}{ var ExampleValues = map[reflect.Type]interface{}{
@@ -90,10 +90,8 @@ func init() {
addExample(pid) addExample(pid)
addExample(&pid) addExample(&pid)
storeIDExample := imports.ID(50) multistoreIDExample := multistore.StoreID(50)
textSelExample := textselector.Expression("Links/21/Hash/Links/42/Hash") storeIDExample := importmgr.ImportID(50)
apiSelExample := api.Selector("Links/21/Hash/Links/42/Hash")
clientEvent := retrievalmarket.ClientEventDealAccepted
addExample(bitfield.NewFromSet([]uint64{5})) addExample(bitfield.NewFromSet([]uint64{5}))
addExample(abi.RegisteredSealProof_StackedDrg32GiBV1_1) addExample(abi.RegisteredSealProof_StackedDrg32GiBV1_1)
@@ -112,6 +110,7 @@ func init() {
addExample(abi.UnpaddedPieceSize(1024)) addExample(abi.UnpaddedPieceSize(1024))
addExample(abi.UnpaddedPieceSize(1024).Padded()) addExample(abi.UnpaddedPieceSize(1024).Padded())
addExample(abi.DealID(5432)) addExample(abi.DealID(5432))
addExample(filestore.StatusFileChanged)
addExample(abi.SectorNumber(9)) addExample(abi.SectorNumber(9))
addExample(abi.SectorSize(32 * 1024 * 1024 * 1024)) addExample(abi.SectorSize(32 * 1024 * 1024 * 1024))
addExample(api.MpoolChange(0)) addExample(api.MpoolChange(0))
@@ -121,17 +120,14 @@ func init() {
addExample(api.FullAPIVersion1) addExample(api.FullAPIVersion1)
addExample(api.PCHInbound) addExample(api.PCHInbound)
addExample(time.Minute) addExample(time.Minute)
addExample(graphsync.NewRequestID())
addExample(datatransfer.TransferID(3)) addExample(datatransfer.TransferID(3))
addExample(datatransfer.Ongoing) addExample(datatransfer.Ongoing)
addExample(storeIDExample) addExample(storeIDExample)
addExample(&storeIDExample) addExample(&storeIDExample)
addExample(clientEvent) addExample(multistoreIDExample)
addExample(&clientEvent) addExample(&multistoreIDExample)
addExample(retrievalmarket.ClientEventDealAccepted) addExample(retrievalmarket.ClientEventDealAccepted)
addExample(retrievalmarket.DealStatusNew) addExample(retrievalmarket.DealStatusNew)
addExample(&textSelExample)
addExample(&apiSelExample)
addExample(network.ReachabilityPublic) addExample(network.ReachabilityPublic)
addExample(build.NewestNetworkVersion) addExample(build.NewestNetworkVersion)
addExample(map[string]int{"name": 42}) addExample(map[string]int{"name": 42})
@@ -183,7 +179,7 @@ func init() {
ExampleValues[reflect.TypeOf(struct{ A multiaddr.Multiaddr }{}).Field(0).Type] = maddr ExampleValues[reflect.TypeOf(struct{ A multiaddr.Multiaddr }{}).Field(0).Type] = maddr
// miner specific // miner specific
addExample(filestore.Path(".lotusminer/fstmp123")) addExample(filestore2.Path(".lotusminer/fstmp123"))
si := uint64(12) si := uint64(12)
addExample(&si) addExample(&si)
addExample(retrievalmarket.DealID(5)) addExample(retrievalmarket.DealID(5))
@@ -198,10 +194,10 @@ func init() {
}, },
}) })
addExample(api.SectorState(sealing.Proving)) addExample(api.SectorState(sealing.Proving))
addExample(storiface.ID("76f1988b-ef30-4d7e-b3ec-9a627f4ba5a8")) addExample(stores.ID("76f1988b-ef30-4d7e-b3ec-9a627f4ba5a8"))
addExample(storiface.FTUnsealed) addExample(storiface.FTUnsealed)
addExample(storiface.PathSealing) addExample(storiface.PathSealing)
addExample(map[storiface.ID][]storiface.Decl{ addExample(map[stores.ID][]stores.Decl{
"76f1988b-ef30-4d7e-b3ec-9a627f4ba5a8": { "76f1988b-ef30-4d7e-b3ec-9a627f4ba5a8": {
{ {
SectorID: abi.SectorID{Miner: 1000, Number: 100}, SectorID: abi.SectorID{Miner: 1000, Number: 100},
@@ -209,7 +205,7 @@ func init() {
}, },
}, },
}) })
addExample(map[storiface.ID]string{ addExample(map[stores.ID]string{
"76f1988b-ef30-4d7e-b3ec-9a627f4ba5a8": "/data/path", "76f1988b-ef30-4d7e-b3ec-9a627f4ba5a8": "/data/path",
}) })
addExample(map[uuid.UUID][]storiface.WorkerJob{ addExample(map[uuid.UUID][]storiface.WorkerJob{
@@ -233,18 +229,16 @@ func init() {
Hostname: "host", Hostname: "host",
Resources: storiface.WorkerResources{ Resources: storiface.WorkerResources{
MemPhysical: 256 << 30, MemPhysical: 256 << 30,
MemUsed: 2 << 30,
MemSwap: 120 << 30, MemSwap: 120 << 30,
MemSwapUsed: 2 << 30, MemReserved: 2 << 30,
CPUs: 64, CPUs: 64,
GPUs: []string{"aGPU 1337"}, GPUs: []string{"aGPU 1337"},
Resources: storiface.ResourceTable,
}, },
}, },
Enabled: true, Enabled: true,
MemUsedMin: 0, MemUsedMin: 0,
MemUsedMax: 0, MemUsedMax: 0,
GpuUsed: 0, GpuUsed: false,
CpuUse: 0, CpuUse: 0,
}, },
}) })
@@ -252,18 +246,10 @@ func init() {
addExample(map[abi.SectorNumber]string{ addExample(map[abi.SectorNumber]string{
123: "can't acquire read lock", 123: "can't acquire read lock",
}) })
addExample(json.RawMessage(`"json raw message"`))
addExample(map[api.SectorState]int{ addExample(map[api.SectorState]int{
api.SectorState(sealing.Proving): 120, api.SectorState(sealing.Proving): 120,
}) })
addExample([]abi.SectorNumber{123, 124}) addExample([]abi.SectorNumber{123, 124})
addExample([]storiface.SectorLock{
{
Sector: abi.SectorID{Number: 123, Miner: 1000},
Write: [storiface.FileTypes]uint{0, 0, 1},
Read: [storiface.FileTypes]uint{2, 3, 0},
},
})
// worker specific // worker specific
addExample(storiface.AcquireMove) addExample(storiface.AcquireMove)
@@ -289,44 +275,6 @@ func init() {
api.SubsystemSectorStorage, api.SubsystemSectorStorage,
api.SubsystemMarkets, api.SubsystemMarkets,
}) })
addExample(api.DagstoreShardResult{
Key: "baga6ea4seaqecmtz7iak33dsfshi627abz4i4665dfuzr3qfs4bmad6dx3iigdq",
Error: "<error>",
})
addExample(api.DagstoreShardInfo{
Key: "baga6ea4seaqecmtz7iak33dsfshi627abz4i4665dfuzr3qfs4bmad6dx3iigdq",
State: "ShardStateAvailable",
Error: "<error>",
})
addExample(storiface.ResourceTable)
addExample(network.ScopeStat{
Memory: 123,
NumStreamsInbound: 1,
NumStreamsOutbound: 2,
NumConnsInbound: 3,
NumConnsOutbound: 4,
NumFD: 5,
})
addExample(map[string]network.ScopeStat{
"abc": {
Memory: 123,
NumStreamsInbound: 1,
NumStreamsOutbound: 2,
NumConnsInbound: 3,
NumConnsOutbound: 4,
NumFD: 5,
}})
addExample(api.NetLimit{
Memory: 123,
StreamsInbound: 1,
StreamsOutbound: 2,
Streams: 3,
ConnsInbound: 3,
ConnsOutbound: 4,
Conns: 4,
FD: 5,
})
} }
func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) { func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) {
@@ -377,7 +325,7 @@ func ExampleValue(method string, t, parent reflect.Type) interface{} {
switch t.Kind() { switch t.Kind() {
case reflect.Slice: case reflect.Slice:
out := reflect.New(t).Elem() out := reflect.New(t).Elem()
out = reflect.Append(out, reflect.ValueOf(ExampleValue(method, t.Elem(), t))) reflect.Append(out, reflect.ValueOf(ExampleValue(method, t.Elem(), t)))
return out.Interface() return out.Interface()
case reflect.Chan: case reflect.Chan:
return ExampleValue(method, t.Elem(), nil) return ExampleValue(method, t.Elem(), nil)
+56 -249
View File
@@ -6,9 +6,7 @@ package mocks
import ( import (
context "context" context "context"
json "encoding/json"
reflect "reflect" reflect "reflect"
time "time"
address "github.com/filecoin-project/go-address" address "github.com/filecoin-project/go-address"
bitfield "github.com/filecoin-project/go-bitfield" bitfield "github.com/filecoin-project/go-bitfield"
@@ -25,9 +23,9 @@ import (
apitypes "github.com/filecoin-project/lotus/api/types" apitypes "github.com/filecoin-project/lotus/api/types"
miner "github.com/filecoin-project/lotus/chain/actors/builtin/miner" miner "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
types "github.com/filecoin-project/lotus/chain/types" types "github.com/filecoin-project/lotus/chain/types"
alerting "github.com/filecoin-project/lotus/journal/alerting" marketevents "github.com/filecoin-project/lotus/markets/loggers"
dtypes "github.com/filecoin-project/lotus/node/modules/dtypes" dtypes "github.com/filecoin-project/lotus/node/modules/dtypes"
imports "github.com/filecoin-project/lotus/node/repo/imports" importmgr "github.com/filecoin-project/lotus/node/repo/importmgr"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
paych "github.com/filecoin-project/specs-actors/actors/builtin/paych" paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
@@ -300,6 +298,36 @@ func (mr *MockFullNodeMockRecorder) ChainGetPath(arg0, arg1, arg2 interface{}) *
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetPath", reflect.TypeOf((*MockFullNode)(nil).ChainGetPath), arg0, arg1, arg2) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetPath", reflect.TypeOf((*MockFullNode)(nil).ChainGetPath), arg0, arg1, arg2)
} }
// ChainGetRandomnessFromBeacon mocks base method.
func (m *MockFullNode) ChainGetRandomnessFromBeacon(arg0 context.Context, arg1 types.TipSetKey, arg2 crypto.DomainSeparationTag, arg3 abi.ChainEpoch, arg4 []byte) (abi.Randomness, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChainGetRandomnessFromBeacon", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(abi.Randomness)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ChainGetRandomnessFromBeacon indicates an expected call of ChainGetRandomnessFromBeacon.
func (mr *MockFullNodeMockRecorder) ChainGetRandomnessFromBeacon(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetRandomnessFromBeacon", reflect.TypeOf((*MockFullNode)(nil).ChainGetRandomnessFromBeacon), arg0, arg1, arg2, arg3, arg4)
}
// ChainGetRandomnessFromTickets mocks base method.
func (m *MockFullNode) ChainGetRandomnessFromTickets(arg0 context.Context, arg1 types.TipSetKey, arg2 crypto.DomainSeparationTag, arg3 abi.ChainEpoch, arg4 []byte) (abi.Randomness, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChainGetRandomnessFromTickets", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(abi.Randomness)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ChainGetRandomnessFromTickets indicates an expected call of ChainGetRandomnessFromTickets.
func (mr *MockFullNodeMockRecorder) ChainGetRandomnessFromTickets(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetRandomnessFromTickets", reflect.TypeOf((*MockFullNode)(nil).ChainGetRandomnessFromTickets), arg0, arg1, arg2, arg3, arg4)
}
// ChainGetTipSet mocks base method. // ChainGetTipSet mocks base method.
func (m *MockFullNode) ChainGetTipSet(arg0 context.Context, arg1 types.TipSetKey) (*types.TipSet, error) { func (m *MockFullNode) ChainGetTipSet(arg0 context.Context, arg1 types.TipSetKey) (*types.TipSet, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@@ -315,21 +343,6 @@ func (mr *MockFullNodeMockRecorder) ChainGetTipSet(arg0, arg1 interface{}) *gomo
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetTipSet", reflect.TypeOf((*MockFullNode)(nil).ChainGetTipSet), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetTipSet", reflect.TypeOf((*MockFullNode)(nil).ChainGetTipSet), arg0, arg1)
} }
// ChainGetTipSetAfterHeight mocks base method.
func (m *MockFullNode) ChainGetTipSetAfterHeight(arg0 context.Context, arg1 abi.ChainEpoch, arg2 types.TipSetKey) (*types.TipSet, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChainGetTipSetAfterHeight", arg0, arg1, arg2)
ret0, _ := ret[0].(*types.TipSet)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ChainGetTipSetAfterHeight indicates an expected call of ChainGetTipSetAfterHeight.
func (mr *MockFullNodeMockRecorder) ChainGetTipSetAfterHeight(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetTipSetAfterHeight", reflect.TypeOf((*MockFullNode)(nil).ChainGetTipSetAfterHeight), arg0, arg1, arg2)
}
// ChainGetTipSetByHeight mocks base method. // ChainGetTipSetByHeight mocks base method.
func (m *MockFullNode) ChainGetTipSetByHeight(arg0 context.Context, arg1 abi.ChainEpoch, arg2 types.TipSetKey) (*types.TipSet, error) { func (m *MockFullNode) ChainGetTipSetByHeight(arg0 context.Context, arg1 abi.ChainEpoch, arg2 types.TipSetKey) (*types.TipSet, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@@ -537,20 +550,6 @@ func (mr *MockFullNodeMockRecorder) ClientDealSize(arg0, arg1 interface{}) *gomo
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientDealSize", reflect.TypeOf((*MockFullNode)(nil).ClientDealSize), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientDealSize", reflect.TypeOf((*MockFullNode)(nil).ClientDealSize), arg0, arg1)
} }
// ClientExport mocks base method.
func (m *MockFullNode) ClientExport(arg0 context.Context, arg1 api.ExportRef, arg2 api.FileRef) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ClientExport", arg0, arg1, arg2)
ret0, _ := ret[0].(error)
return ret0
}
// ClientExport indicates an expected call of ClientExport.
func (mr *MockFullNodeMockRecorder) ClientExport(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientExport", reflect.TypeOf((*MockFullNode)(nil).ClientExport), arg0, arg1, arg2)
}
// ClientFindData mocks base method. // ClientFindData mocks base method.
func (m *MockFullNode) ClientFindData(arg0 context.Context, arg1 cid.Cid, arg2 *cid.Cid) ([]api.QueryOffer, error) { func (m *MockFullNode) ClientFindData(arg0 context.Context, arg1 cid.Cid, arg2 *cid.Cid) ([]api.QueryOffer, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@@ -761,7 +760,7 @@ func (mr *MockFullNodeMockRecorder) ClientQueryAsk(arg0, arg1, arg2 interface{})
} }
// ClientRemoveImport mocks base method. // ClientRemoveImport mocks base method.
func (m *MockFullNode) ClientRemoveImport(arg0 context.Context, arg1 imports.ID) error { func (m *MockFullNode) ClientRemoveImport(arg0 context.Context, arg1 importmgr.ImportID) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ClientRemoveImport", arg0, arg1) ret := m.ctrl.Call(m, "ClientRemoveImport", arg0, arg1)
ret0, _ := ret[0].(error) ret0, _ := ret[0].(error)
@@ -789,18 +788,17 @@ func (mr *MockFullNodeMockRecorder) ClientRestartDataTransfer(arg0, arg1, arg2,
} }
// ClientRetrieve mocks base method. // ClientRetrieve mocks base method.
func (m *MockFullNode) ClientRetrieve(arg0 context.Context, arg1 api.RetrievalOrder) (*api.RestrievalRes, error) { func (m *MockFullNode) ClientRetrieve(arg0 context.Context, arg1 api.RetrievalOrder, arg2 *api.FileRef) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ClientRetrieve", arg0, arg1) ret := m.ctrl.Call(m, "ClientRetrieve", arg0, arg1, arg2)
ret0, _ := ret[0].(*api.RestrievalRes) ret0, _ := ret[0].(error)
ret1, _ := ret[1].(error) return ret0
return ret0, ret1
} }
// ClientRetrieve indicates an expected call of ClientRetrieve. // ClientRetrieve indicates an expected call of ClientRetrieve.
func (mr *MockFullNodeMockRecorder) ClientRetrieve(arg0, arg1 interface{}) *gomock.Call { func (mr *MockFullNodeMockRecorder) ClientRetrieve(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientRetrieve", reflect.TypeOf((*MockFullNode)(nil).ClientRetrieve), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientRetrieve", reflect.TypeOf((*MockFullNode)(nil).ClientRetrieve), arg0, arg1, arg2)
} }
// ClientRetrieveTryRestartInsufficientFunds mocks base method. // ClientRetrieveTryRestartInsufficientFunds mocks base method.
@@ -817,18 +815,19 @@ func (mr *MockFullNodeMockRecorder) ClientRetrieveTryRestartInsufficientFunds(ar
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientRetrieveTryRestartInsufficientFunds", reflect.TypeOf((*MockFullNode)(nil).ClientRetrieveTryRestartInsufficientFunds), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientRetrieveTryRestartInsufficientFunds", reflect.TypeOf((*MockFullNode)(nil).ClientRetrieveTryRestartInsufficientFunds), arg0, arg1)
} }
// ClientRetrieveWait mocks base method. // ClientRetrieveWithEvents mocks base method.
func (m *MockFullNode) ClientRetrieveWait(arg0 context.Context, arg1 retrievalmarket.DealID) error { func (m *MockFullNode) ClientRetrieveWithEvents(arg0 context.Context, arg1 api.RetrievalOrder, arg2 *api.FileRef) (<-chan marketevents.RetrievalEvent, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ClientRetrieveWait", arg0, arg1) ret := m.ctrl.Call(m, "ClientRetrieveWithEvents", arg0, arg1, arg2)
ret0, _ := ret[0].(error) ret0, _ := ret[0].(<-chan marketevents.RetrievalEvent)
return ret0 ret1, _ := ret[1].(error)
return ret0, ret1
} }
// ClientRetrieveWait indicates an expected call of ClientRetrieveWait. // ClientRetrieveWithEvents indicates an expected call of ClientRetrieveWithEvents.
func (mr *MockFullNodeMockRecorder) ClientRetrieveWait(arg0, arg1 interface{}) *gomock.Call { func (mr *MockFullNodeMockRecorder) ClientRetrieveWithEvents(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientRetrieveWait", reflect.TypeOf((*MockFullNode)(nil).ClientRetrieveWait), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientRetrieveWithEvents", reflect.TypeOf((*MockFullNode)(nil).ClientRetrieveWithEvents), arg0, arg1, arg2)
} }
// ClientStartDeal mocks base method. // ClientStartDeal mocks base method.
@@ -980,21 +979,6 @@ func (mr *MockFullNodeMockRecorder) ID(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockFullNode)(nil).ID), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockFullNode)(nil).ID), arg0)
} }
// LogAlerts mocks base method.
func (m *MockFullNode) LogAlerts(arg0 context.Context) ([]alerting.Alert, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "LogAlerts", arg0)
ret0, _ := ret[0].([]alerting.Alert)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// LogAlerts indicates an expected call of LogAlerts.
func (mr *MockFullNodeMockRecorder) LogAlerts(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LogAlerts", reflect.TypeOf((*MockFullNode)(nil).LogAlerts), arg0)
}
// LogList mocks base method. // LogList mocks base method.
func (m *MockFullNode) LogList(arg0 context.Context) ([]string, error) { func (m *MockFullNode) LogList(arg0 context.Context) ([]string, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@@ -1442,33 +1426,18 @@ func (mr *MockFullNodeMockRecorder) MsigApproveTxnHash(arg0, arg1, arg2, arg3, a
} }
// MsigCancel mocks base method. // MsigCancel mocks base method.
func (m *MockFullNode) MsigCancel(arg0 context.Context, arg1 address.Address, arg2 uint64, arg3 address.Address) (*api.MessagePrototype, error) { func (m *MockFullNode) MsigCancel(arg0 context.Context, arg1 address.Address, arg2 uint64, arg3 address.Address, arg4 big.Int, arg5 address.Address, arg6 uint64, arg7 []byte) (*api.MessagePrototype, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigCancel", arg0, arg1, arg2, arg3) ret := m.ctrl.Call(m, "MsigCancel", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
ret0, _ := ret[0].(*api.MessagePrototype) ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
// MsigCancel indicates an expected call of MsigCancel. // MsigCancel indicates an expected call of MsigCancel.
func (mr *MockFullNodeMockRecorder) MsigCancel(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { func (mr *MockFullNodeMockRecorder) MsigCancel(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MsigCancel", reflect.TypeOf((*MockFullNode)(nil).MsigCancel), arg0, arg1, arg2, arg3) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MsigCancel", reflect.TypeOf((*MockFullNode)(nil).MsigCancel), arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
}
// MsigCancelTxnHash mocks base method.
func (m *MockFullNode) MsigCancelTxnHash(arg0 context.Context, arg1 address.Address, arg2 uint64, arg3 address.Address, arg4 big.Int, arg5 address.Address, arg6 uint64, arg7 []byte) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigCancelTxnHash", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// MsigCancelTxnHash indicates an expected call of MsigCancelTxnHash.
func (mr *MockFullNodeMockRecorder) MsigCancelTxnHash(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MsigCancelTxnHash", reflect.TypeOf((*MockFullNode)(nil).MsigCancelTxnHash), arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
} }
// MsigCreate mocks base method. // MsigCreate mocks base method.
@@ -1812,21 +1781,6 @@ func (mr *MockFullNodeMockRecorder) NetFindPeer(arg0, arg1 interface{}) *gomock.
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetFindPeer", reflect.TypeOf((*MockFullNode)(nil).NetFindPeer), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetFindPeer", reflect.TypeOf((*MockFullNode)(nil).NetFindPeer), arg0, arg1)
} }
// NetLimit mocks base method.
func (m *MockFullNode) NetLimit(arg0 context.Context, arg1 string) (api.NetLimit, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetLimit", arg0, arg1)
ret0, _ := ret[0].(api.NetLimit)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// NetLimit indicates an expected call of NetLimit.
func (mr *MockFullNodeMockRecorder) NetLimit(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetLimit", reflect.TypeOf((*MockFullNode)(nil).NetLimit), arg0, arg1)
}
// NetPeerInfo mocks base method. // NetPeerInfo mocks base method.
func (m *MockFullNode) NetPeerInfo(arg0 context.Context, arg1 peer.ID) (*api.ExtendedPeerInfo, error) { func (m *MockFullNode) NetPeerInfo(arg0 context.Context, arg1 peer.ID) (*api.ExtendedPeerInfo, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@@ -1857,64 +1811,6 @@ func (mr *MockFullNodeMockRecorder) NetPeers(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPeers", reflect.TypeOf((*MockFullNode)(nil).NetPeers), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPeers", reflect.TypeOf((*MockFullNode)(nil).NetPeers), arg0)
} }
// NetPing mocks base method.
func (m *MockFullNode) NetPing(arg0 context.Context, arg1 peer.ID) (time.Duration, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetPing", arg0, arg1)
ret0, _ := ret[0].(time.Duration)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// NetPing indicates an expected call of NetPing.
func (mr *MockFullNodeMockRecorder) NetPing(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPing", reflect.TypeOf((*MockFullNode)(nil).NetPing), arg0, arg1)
}
// NetProtectAdd mocks base method.
func (m *MockFullNode) NetProtectAdd(arg0 context.Context, arg1 []peer.ID) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetProtectAdd", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// NetProtectAdd indicates an expected call of NetProtectAdd.
func (mr *MockFullNodeMockRecorder) NetProtectAdd(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetProtectAdd", reflect.TypeOf((*MockFullNode)(nil).NetProtectAdd), arg0, arg1)
}
// NetProtectList mocks base method.
func (m *MockFullNode) NetProtectList(arg0 context.Context) ([]peer.ID, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetProtectList", arg0)
ret0, _ := ret[0].([]peer.ID)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// NetProtectList indicates an expected call of NetProtectList.
func (mr *MockFullNodeMockRecorder) NetProtectList(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetProtectList", reflect.TypeOf((*MockFullNode)(nil).NetProtectList), arg0)
}
// NetProtectRemove mocks base method.
func (m *MockFullNode) NetProtectRemove(arg0 context.Context, arg1 []peer.ID) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetProtectRemove", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// NetProtectRemove indicates an expected call of NetProtectRemove.
func (mr *MockFullNodeMockRecorder) NetProtectRemove(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetProtectRemove", reflect.TypeOf((*MockFullNode)(nil).NetProtectRemove), arg0, arg1)
}
// NetPubsubScores mocks base method. // NetPubsubScores mocks base method.
func (m *MockFullNode) NetPubsubScores(arg0 context.Context) ([]api.PubsubScore, error) { func (m *MockFullNode) NetPubsubScores(arg0 context.Context) ([]api.PubsubScore, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@@ -1930,35 +1826,6 @@ func (mr *MockFullNodeMockRecorder) NetPubsubScores(arg0 interface{}) *gomock.Ca
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPubsubScores", reflect.TypeOf((*MockFullNode)(nil).NetPubsubScores), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPubsubScores", reflect.TypeOf((*MockFullNode)(nil).NetPubsubScores), arg0)
} }
// NetSetLimit mocks base method.
func (m *MockFullNode) NetSetLimit(arg0 context.Context, arg1 string, arg2 api.NetLimit) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetSetLimit", arg0, arg1, arg2)
ret0, _ := ret[0].(error)
return ret0
}
// NetSetLimit indicates an expected call of NetSetLimit.
func (mr *MockFullNodeMockRecorder) NetSetLimit(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetSetLimit", reflect.TypeOf((*MockFullNode)(nil).NetSetLimit), arg0, arg1, arg2)
}
// NetStat mocks base method.
func (m *MockFullNode) NetStat(arg0 context.Context, arg1 string) (api.NetStat, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetStat", arg0, arg1)
ret0, _ := ret[0].(api.NetStat)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// NetStat indicates an expected call of NetStat.
func (mr *MockFullNodeMockRecorder) NetStat(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetStat", reflect.TypeOf((*MockFullNode)(nil).NetStat), arg0, arg1)
}
// NodeStatus mocks base method. // NodeStatus mocks base method.
func (m *MockFullNode) NodeStatus(arg0 context.Context, arg1 bool) (api.NodeStatus, error) { func (m *MockFullNode) NodeStatus(arg0 context.Context, arg1 bool) (api.NodeStatus, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@@ -2034,34 +1901,19 @@ func (mr *MockFullNodeMockRecorder) PaychCollect(arg0, arg1 interface{}) *gomock
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PaychCollect", reflect.TypeOf((*MockFullNode)(nil).PaychCollect), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PaychCollect", reflect.TypeOf((*MockFullNode)(nil).PaychCollect), arg0, arg1)
} }
// PaychFund mocks base method.
func (m *MockFullNode) PaychFund(arg0 context.Context, arg1, arg2 address.Address, arg3 big.Int) (*api.ChannelInfo, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PaychFund", arg0, arg1, arg2, arg3)
ret0, _ := ret[0].(*api.ChannelInfo)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// PaychFund indicates an expected call of PaychFund.
func (mr *MockFullNodeMockRecorder) PaychFund(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PaychFund", reflect.TypeOf((*MockFullNode)(nil).PaychFund), arg0, arg1, arg2, arg3)
}
// PaychGet mocks base method. // PaychGet mocks base method.
func (m *MockFullNode) PaychGet(arg0 context.Context, arg1, arg2 address.Address, arg3 big.Int, arg4 api.PaychGetOpts) (*api.ChannelInfo, error) { func (m *MockFullNode) PaychGet(arg0 context.Context, arg1, arg2 address.Address, arg3 big.Int) (*api.ChannelInfo, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PaychGet", arg0, arg1, arg2, arg3, arg4) ret := m.ctrl.Call(m, "PaychGet", arg0, arg1, arg2, arg3)
ret0, _ := ret[0].(*api.ChannelInfo) ret0, _ := ret[0].(*api.ChannelInfo)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
// PaychGet indicates an expected call of PaychGet. // PaychGet indicates an expected call of PaychGet.
func (mr *MockFullNodeMockRecorder) PaychGet(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { func (mr *MockFullNodeMockRecorder) PaychGet(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PaychGet", reflect.TypeOf((*MockFullNode)(nil).PaychGet), arg0, arg1, arg2, arg3, arg4) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PaychGet", reflect.TypeOf((*MockFullNode)(nil).PaychGet), arg0, arg1, arg2, arg3)
} }
// PaychGetWaitReady mocks base method. // PaychGetWaitReady mocks base method.
@@ -2377,21 +2229,6 @@ func (mr *MockFullNodeMockRecorder) StateDecodeParams(arg0, arg1, arg2, arg3, ar
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateDecodeParams", reflect.TypeOf((*MockFullNode)(nil).StateDecodeParams), arg0, arg1, arg2, arg3, arg4) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateDecodeParams", reflect.TypeOf((*MockFullNode)(nil).StateDecodeParams), arg0, arg1, arg2, arg3, arg4)
} }
// StateEncodeParams mocks base method.
func (m *MockFullNode) StateEncodeParams(arg0 context.Context, arg1 cid.Cid, arg2 abi.MethodNum, arg3 json.RawMessage) ([]byte, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateEncodeParams", arg0, arg1, arg2, arg3)
ret0, _ := ret[0].([]byte)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateEncodeParams indicates an expected call of StateEncodeParams.
func (mr *MockFullNodeMockRecorder) StateEncodeParams(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateEncodeParams", reflect.TypeOf((*MockFullNode)(nil).StateEncodeParams), arg0, arg1, arg2, arg3)
}
// StateGetActor mocks base method. // StateGetActor mocks base method.
func (m *MockFullNode) StateGetActor(arg0 context.Context, arg1 address.Address, arg2 types.TipSetKey) (*types.Actor, error) { func (m *MockFullNode) StateGetActor(arg0 context.Context, arg1 address.Address, arg2 types.TipSetKey) (*types.Actor, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@@ -2407,36 +2244,6 @@ func (mr *MockFullNodeMockRecorder) StateGetActor(arg0, arg1, arg2 interface{})
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetActor", reflect.TypeOf((*MockFullNode)(nil).StateGetActor), arg0, arg1, arg2) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetActor", reflect.TypeOf((*MockFullNode)(nil).StateGetActor), arg0, arg1, arg2)
} }
// StateGetRandomnessFromBeacon mocks base method.
func (m *MockFullNode) StateGetRandomnessFromBeacon(arg0 context.Context, arg1 crypto.DomainSeparationTag, arg2 abi.ChainEpoch, arg3 []byte, arg4 types.TipSetKey) (abi.Randomness, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateGetRandomnessFromBeacon", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(abi.Randomness)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateGetRandomnessFromBeacon indicates an expected call of StateGetRandomnessFromBeacon.
func (mr *MockFullNodeMockRecorder) StateGetRandomnessFromBeacon(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetRandomnessFromBeacon", reflect.TypeOf((*MockFullNode)(nil).StateGetRandomnessFromBeacon), arg0, arg1, arg2, arg3, arg4)
}
// StateGetRandomnessFromTickets mocks base method.
func (m *MockFullNode) StateGetRandomnessFromTickets(arg0 context.Context, arg1 crypto.DomainSeparationTag, arg2 abi.ChainEpoch, arg3 []byte, arg4 types.TipSetKey) (abi.Randomness, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateGetRandomnessFromTickets", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(abi.Randomness)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateGetRandomnessFromTickets indicates an expected call of StateGetRandomnessFromTickets.
func (mr *MockFullNodeMockRecorder) StateGetRandomnessFromTickets(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetRandomnessFromTickets", reflect.TypeOf((*MockFullNode)(nil).StateGetRandomnessFromTickets), arg0, arg1, arg2, arg3, arg4)
}
// StateListActors mocks base method. // StateListActors mocks base method.
func (m *MockFullNode) StateListActors(arg0 context.Context, arg1 types.TipSetKey) ([]address.Address, error) { func (m *MockFullNode) StateListActors(arg0 context.Context, arg1 types.TipSetKey) ([]address.Address, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
+106 -680
View File
File diff suppressed because it is too large Load Diff
-3
View File
@@ -1,4 +1,3 @@
//stm: #unit
package api package api
import ( import (
@@ -30,7 +29,6 @@ type StrC struct {
} }
func TestGetInternalStructs(t *testing.T) { func TestGetInternalStructs(t *testing.T) {
//stm: @OTHER_IMPLEMENTATION_API_STRUCTS_001
var proxy StrA var proxy StrA
sts := GetInternalStructs(&proxy) sts := GetInternalStructs(&proxy)
@@ -46,7 +44,6 @@ func TestGetInternalStructs(t *testing.T) {
} }
func TestNestedInternalStructs(t *testing.T) { func TestNestedInternalStructs(t *testing.T) {
//stm: @OTHER_IMPLEMENTATION_API_STRUCTS_001
var proxy StrC var proxy StrC
// check that only the top-level internal struct gets picked up // check that only the top-level internal struct gets picked up
+2 -93
View File
@@ -5,14 +5,12 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/libp2p/go-libp2p-core/network" "github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/lotus/chain/types"
datatransfer "github.com/filecoin-project/go-data-transfer" datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/ipfs/go-graphsync"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub "github.com/libp2p/go-libp2p-pubsub"
@@ -56,30 +54,6 @@ type MessageSendSpec struct {
MaxFee abi.TokenAmount MaxFee abi.TokenAmount
} }
// GraphSyncDataTransfer provides diagnostics on a data transfer happening over graphsync
type GraphSyncDataTransfer struct {
// GraphSync request id for this transfer
RequestID *graphsync.RequestID
// Graphsync state for this transfer
RequestState string
// If a channel ID is present, indicates whether this is the current graphsync request for this channel
// (could have changed in a restart)
IsCurrentChannelRequest bool
// Data transfer channel ID for this transfer
ChannelID *datatransfer.ChannelID
// Data transfer state for this transfer
ChannelState *DataTransferChannel
// Diagnostic information about this request -- and unexpected inconsistencies in
// request state
Diagnostics []string
}
// TransferDiagnostics give current information about transfers going over graphsync that may be helpful for debugging
type TransferDiagnostics struct {
ReceivingTransfers []*GraphSyncDataTransfer
SendingTransfers []*GraphSyncDataTransfer
}
type DataTransferChannel struct { type DataTransferChannel struct {
TransferID datatransfer.TransferID TransferID datatransfer.TransferID
Status datatransfer.Status Status datatransfer.Status
@@ -125,28 +99,6 @@ func NewDataTransferChannel(hostID peer.ID, channelState datatransfer.ChannelSta
return channel return channel
} }
type NetStat struct {
System *network.ScopeStat `json:",omitempty"`
Transient *network.ScopeStat `json:",omitempty"`
Services map[string]network.ScopeStat `json:",omitempty"`
Protocols map[string]network.ScopeStat `json:",omitempty"`
Peers map[string]network.ScopeStat `json:",omitempty"`
}
type NetLimit struct {
Dynamic bool `json:",omitempty"`
// set if Dynamic is false
Memory int64 `json:",omitempty"`
// set if Dynamic is true
MemoryFraction float64 `json:",omitempty"`
MinMemory int64 `json:",omitempty"`
MaxMemory int64 `json:",omitempty"`
Streams, StreamsInbound, StreamsOutbound int
Conns, ConnsInbound, ConnsOutbound int
FD int
}
type NetBlockList struct { type NetBlockList struct {
Peers []peer.ID Peers []peer.ID
IPAddrs []string IPAddrs []string
@@ -242,47 +194,4 @@ type RetrievalInfo struct {
TransferChannelID *datatransfer.ChannelID TransferChannelID *datatransfer.ChannelID
DataTransfer *DataTransferChannel DataTransfer *DataTransferChannel
// optional event if part of ClientGetRetrievalUpdates
Event *retrievalmarket.ClientEvent
}
type RestrievalRes struct {
DealID retrievalmarket.DealID
}
// Selector specifies ipld selector string
// - if the string starts with '{', it's interpreted as json selector string
// see https://ipld.io/specs/selectors/ and https://ipld.io/specs/selectors/fixtures/selector-fixtures-1/
// - otherwise the string is interpreted as ipld-selector-text-lite (simple ipld path)
// see https://github.com/ipld/go-ipld-selector-text-lite
type Selector string
type DagSpec struct {
// DataSelector matches data to be retrieved
// - when using textselector, the path specifies subtree
// - the matched graph must have a single root
DataSelector *Selector
// ExportMerkleProof is applicable only when exporting to a CAR file via a path textselector
// When true, in addition to the selection target, the resulting CAR will contain every block along the
// path back to, and including the original root
// When false the resulting CAR contains only the blocks of the target subdag
ExportMerkleProof bool
}
type ExportRef struct {
Root cid.Cid
// DAGs array specifies a list of DAGs to export
// - If exporting into unixfs files, only one DAG is supported, DataSelector is only used to find the targeted root node
// - If exporting into a car file
// - When exactly one text-path DataSelector is specified exports the subgraph and its full merkle-path from the original root
// - Otherwise ( multiple paths and/or JSON selector specs) determines each individual subroot and exports the subtrees as a multi-root car
// - When not specified defaults to a single DAG:
// - Data - the entire DAG: `{"R":{"l":{"none":{}},":>":{"a":{">":{"@":{}}}}}}`
DAGs []DagSpec
FromLocalCAR string // if specified, get data from a local CARv2 file.
DealID retrievalmarket.DealID
} }
+4 -44
View File
@@ -11,8 +11,8 @@ import (
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/lotus/node/repo/importmgr"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
textselector "github.com/ipld/go-ipld-selector-text-lite"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
@@ -22,7 +22,6 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
marketevents "github.com/filecoin-project/lotus/markets/loggers" marketevents "github.com/filecoin-project/lotus/markets/loggers"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/repo/imports"
) )
//go:generate go run github.com/golang/mock/mockgen -destination=v0mocks/mock_full.go -package=v0mocks . FullNode //go:generate go run github.com/golang/mock/mockgen -destination=v0mocks/mock_full.go -package=v0mocks . FullNode
@@ -306,7 +305,7 @@ type FullNode interface {
// ClientImport imports file under the specified path into filestore. // ClientImport imports file under the specified path into filestore.
ClientImport(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) //perm:admin ClientImport(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) //perm:admin
// ClientRemoveImport removes file import // ClientRemoveImport removes file import
ClientRemoveImport(ctx context.Context, importID imports.ID) error //perm:admin ClientRemoveImport(ctx context.Context, importID importmgr.ImportID) error //perm:admin
// ClientStartDeal proposes a deal with a miner. // ClientStartDeal proposes a deal with a miner.
ClientStartDeal(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) //perm:admin ClientStartDeal(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) //perm:admin
// ClientStatelessDeal fire-and-forget-proposes an offline deal to a miner without subsequent tracking. // ClientStatelessDeal fire-and-forget-proposes an offline deal to a miner without subsequent tracking.
@@ -326,10 +325,10 @@ type FullNode interface {
// ClientMinerQueryOffer returns a QueryOffer for the specific miner and file. // ClientMinerQueryOffer returns a QueryOffer for the specific miner and file.
ClientMinerQueryOffer(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (api.QueryOffer, error) //perm:read ClientMinerQueryOffer(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (api.QueryOffer, error) //perm:read
// ClientRetrieve initiates the retrieval of a file, as specified in the order. // ClientRetrieve initiates the retrieval of a file, as specified in the order.
ClientRetrieve(ctx context.Context, order RetrievalOrder, ref *api.FileRef) error //perm:admin ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error //perm:admin
// ClientRetrieveWithEvents initiates the retrieval of a file, as specified in the order, and provides a channel // ClientRetrieveWithEvents initiates the retrieval of a file, as specified in the order, and provides a channel
// of status updates. // of status updates.
ClientRetrieveWithEvents(ctx context.Context, order RetrievalOrder, ref *api.FileRef) (<-chan marketevents.RetrievalEvent, error) //perm:admin ClientRetrieveWithEvents(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) (<-chan marketevents.RetrievalEvent, error) //perm:admin
// ClientQueryAsk returns a signed StorageAsk from the specified miner. // ClientQueryAsk returns a signed StorageAsk from the specified miner.
// ClientListRetrievals returns information about retrievals made by the local client // ClientListRetrievals returns information about retrievals made by the local client
ClientListRetrievals(ctx context.Context) ([]api.RetrievalInfo, error) //perm:write ClientListRetrievals(ctx context.Context) ([]api.RetrievalInfo, error) //perm:write
@@ -599,11 +598,6 @@ type FullNode interface {
// StateNetworkVersion returns the network version at the given tipset // StateNetworkVersion returns the network version at the given tipset
StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, error) //perm:read StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, error) //perm:read
// StateGetRandomnessFromTickets is used to sample the chain for randomness.
StateGetRandomnessFromTickets(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) //perm:read
// StateGetRandomnessFromBeacon is used to sample the beacon for randomness.
StateGetRandomnessFromBeacon(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) //perm:read
// MethodGroup: Msig // MethodGroup: Msig
// The Msig methods are used to interact with multisig wallets on the // The Msig methods are used to interact with multisig wallets on the
// filecoin network // filecoin network
@@ -715,37 +709,3 @@ type FullNode interface {
// the path specified when calling CreateBackup is within the base path // the path specified when calling CreateBackup is within the base path
CreateBackup(ctx context.Context, fpath string) error //perm:admin CreateBackup(ctx context.Context, fpath string) error //perm:admin
} }
func OfferOrder(o api.QueryOffer, client address.Address) RetrievalOrder {
return RetrievalOrder{
Root: o.Root,
Piece: o.Piece,
Size: o.Size,
Total: o.MinPrice,
UnsealPrice: o.UnsealPrice,
PaymentInterval: o.PaymentInterval,
PaymentIntervalIncrease: o.PaymentIntervalIncrease,
Client: client,
Miner: o.Miner,
MinerPeer: &o.MinerPeer,
}
}
type RetrievalOrder struct {
// TODO: make this less unixfs specific
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
Total types.BigInt
UnsealPrice types.BigInt
PaymentInterval uint64
PaymentIntervalIncrease uint64
Client address.Address
Miner address.Address
MinerPeer *retrievalmarket.RetrievalPeer
}
+2 -2
View File
@@ -8,7 +8,7 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/go-state-types/dline"
abinetwork "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
@@ -57,7 +57,7 @@ type Gateway interface {
StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error)
StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error)
StateNetworkVersion(context.Context, types.TipSetKey) (abinetwork.Version, error) StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
StateSearchMsg(ctx context.Context, msg cid.Cid) (*api.MsgLookup, error) StateSearchMsg(ctx context.Context, msg cid.Cid) (*api.MsgLookup, error)
StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error)
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
+16 -42
View File
@@ -13,7 +13,7 @@ import (
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/go-state-types/dline"
abinetwork "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
apitypes "github.com/filecoin-project/lotus/api/types" apitypes "github.com/filecoin-project/lotus/api/types"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
@@ -21,7 +21,7 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
marketevents "github.com/filecoin-project/lotus/markets/loggers" marketevents "github.com/filecoin-project/lotus/markets/loggers"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/repo/imports" "github.com/filecoin-project/lotus/node/repo/importmgr"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@@ -121,15 +121,15 @@ type FullNodeStruct struct {
ClientQueryAsk func(p0 context.Context, p1 peer.ID, p2 address.Address) (*storagemarket.StorageAsk, error) `perm:"read"` ClientQueryAsk func(p0 context.Context, p1 peer.ID, p2 address.Address) (*storagemarket.StorageAsk, error) `perm:"read"`
ClientRemoveImport func(p0 context.Context, p1 imports.ID) error `perm:"admin"` ClientRemoveImport func(p0 context.Context, p1 importmgr.ImportID) error `perm:"admin"`
ClientRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` ClientRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"`
ClientRetrieve func(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) error `perm:"admin"` ClientRetrieve func(p0 context.Context, p1 api.RetrievalOrder, p2 *api.FileRef) error `perm:"admin"`
ClientRetrieveTryRestartInsufficientFunds func(p0 context.Context, p1 address.Address) error `perm:"write"` ClientRetrieveTryRestartInsufficientFunds func(p0 context.Context, p1 address.Address) error `perm:"write"`
ClientRetrieveWithEvents func(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) (<-chan marketevents.RetrievalEvent, error) `perm:"admin"` ClientRetrieveWithEvents func(p0 context.Context, p1 api.RetrievalOrder, p2 *api.FileRef) (<-chan marketevents.RetrievalEvent, error) `perm:"admin"`
ClientStartDeal func(p0 context.Context, p1 *api.StartDealParams) (*cid.Cid, error) `perm:"admin"` ClientStartDeal func(p0 context.Context, p1 *api.StartDealParams) (*cid.Cid, error) `perm:"admin"`
@@ -267,10 +267,6 @@ type FullNodeStruct struct {
StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `perm:"read"` StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `perm:"read"`
StateGetRandomnessFromBeacon func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"`
StateGetRandomnessFromTickets func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"`
StateGetReceipt func(p0 context.Context, p1 cid.Cid, p2 types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"` StateGetReceipt func(p0 context.Context, p1 cid.Cid, p2 types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"`
StateListActors func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` StateListActors func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"`
@@ -451,7 +447,7 @@ type GatewayStruct struct {
StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `` StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) ``
StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (abinetwork.Version, error) `` StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (network.Version, error) ``
StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) `` StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) ``
@@ -943,14 +939,14 @@ func (s *FullNodeStub) ClientQueryAsk(p0 context.Context, p1 peer.ID, p2 address
return nil, ErrNotSupported return nil, ErrNotSupported
} }
func (s *FullNodeStruct) ClientRemoveImport(p0 context.Context, p1 imports.ID) error { func (s *FullNodeStruct) ClientRemoveImport(p0 context.Context, p1 importmgr.ImportID) error {
if s.Internal.ClientRemoveImport == nil { if s.Internal.ClientRemoveImport == nil {
return ErrNotSupported return ErrNotSupported
} }
return s.Internal.ClientRemoveImport(p0, p1) return s.Internal.ClientRemoveImport(p0, p1)
} }
func (s *FullNodeStub) ClientRemoveImport(p0 context.Context, p1 imports.ID) error { func (s *FullNodeStub) ClientRemoveImport(p0 context.Context, p1 importmgr.ImportID) error {
return ErrNotSupported return ErrNotSupported
} }
@@ -965,14 +961,14 @@ func (s *FullNodeStub) ClientRestartDataTransfer(p0 context.Context, p1 datatran
return ErrNotSupported return ErrNotSupported
} }
func (s *FullNodeStruct) ClientRetrieve(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) error { func (s *FullNodeStruct) ClientRetrieve(p0 context.Context, p1 api.RetrievalOrder, p2 *api.FileRef) error {
if s.Internal.ClientRetrieve == nil { if s.Internal.ClientRetrieve == nil {
return ErrNotSupported return ErrNotSupported
} }
return s.Internal.ClientRetrieve(p0, p1, p2) return s.Internal.ClientRetrieve(p0, p1, p2)
} }
func (s *FullNodeStub) ClientRetrieve(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) error { func (s *FullNodeStub) ClientRetrieve(p0 context.Context, p1 api.RetrievalOrder, p2 *api.FileRef) error {
return ErrNotSupported return ErrNotSupported
} }
@@ -987,14 +983,14 @@ func (s *FullNodeStub) ClientRetrieveTryRestartInsufficientFunds(p0 context.Cont
return ErrNotSupported return ErrNotSupported
} }
func (s *FullNodeStruct) ClientRetrieveWithEvents(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) (<-chan marketevents.RetrievalEvent, error) { func (s *FullNodeStruct) ClientRetrieveWithEvents(p0 context.Context, p1 api.RetrievalOrder, p2 *api.FileRef) (<-chan marketevents.RetrievalEvent, error) {
if s.Internal.ClientRetrieveWithEvents == nil { if s.Internal.ClientRetrieveWithEvents == nil {
return nil, ErrNotSupported return nil, ErrNotSupported
} }
return s.Internal.ClientRetrieveWithEvents(p0, p1, p2) return s.Internal.ClientRetrieveWithEvents(p0, p1, p2)
} }
func (s *FullNodeStub) ClientRetrieveWithEvents(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) (<-chan marketevents.RetrievalEvent, error) { func (s *FullNodeStub) ClientRetrieveWithEvents(p0 context.Context, p1 api.RetrievalOrder, p2 *api.FileRef) (<-chan marketevents.RetrievalEvent, error) {
return nil, ErrNotSupported return nil, ErrNotSupported
} }
@@ -1746,28 +1742,6 @@ func (s *FullNodeStub) StateGetActor(p0 context.Context, p1 address.Address, p2
return nil, ErrNotSupported return nil, ErrNotSupported
} }
func (s *FullNodeStruct) StateGetRandomnessFromBeacon(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) {
if s.Internal.StateGetRandomnessFromBeacon == nil {
return *new(abi.Randomness), ErrNotSupported
}
return s.Internal.StateGetRandomnessFromBeacon(p0, p1, p2, p3, p4)
}
func (s *FullNodeStub) StateGetRandomnessFromBeacon(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) {
return *new(abi.Randomness), ErrNotSupported
}
func (s *FullNodeStruct) StateGetRandomnessFromTickets(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) {
if s.Internal.StateGetRandomnessFromTickets == nil {
return *new(abi.Randomness), ErrNotSupported
}
return s.Internal.StateGetRandomnessFromTickets(p0, p1, p2, p3, p4)
}
func (s *FullNodeStub) StateGetRandomnessFromTickets(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) {
return *new(abi.Randomness), ErrNotSupported
}
func (s *FullNodeStruct) StateGetReceipt(p0 context.Context, p1 cid.Cid, p2 types.TipSetKey) (*types.MessageReceipt, error) { func (s *FullNodeStruct) StateGetReceipt(p0 context.Context, p1 cid.Cid, p2 types.TipSetKey) (*types.MessageReceipt, error) {
if s.Internal.StateGetReceipt == nil { if s.Internal.StateGetReceipt == nil {
return nil, ErrNotSupported return nil, ErrNotSupported
@@ -2703,15 +2677,15 @@ func (s *GatewayStub) StateMinerProvingDeadline(p0 context.Context, p1 address.A
return nil, ErrNotSupported return nil, ErrNotSupported
} }
func (s *GatewayStruct) StateNetworkVersion(p0 context.Context, p1 types.TipSetKey) (abinetwork.Version, error) { func (s *GatewayStruct) StateNetworkVersion(p0 context.Context, p1 types.TipSetKey) (network.Version, error) {
if s.Internal.StateNetworkVersion == nil { if s.Internal.StateNetworkVersion == nil {
return *new(abinetwork.Version), ErrNotSupported return *new(network.Version), ErrNotSupported
} }
return s.Internal.StateNetworkVersion(p0, p1) return s.Internal.StateNetworkVersion(p0, p1)
} }
func (s *GatewayStub) StateNetworkVersion(p0 context.Context, p1 types.TipSetKey) (abinetwork.Version, error) { func (s *GatewayStub) StateNetworkVersion(p0 context.Context, p1 types.TipSetKey) (network.Version, error) {
return *new(abinetwork.Version), ErrNotSupported return *new(network.Version), ErrNotSupported
} }
func (s *GatewayStruct) StateSearchMsg(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) { func (s *GatewayStruct) StateSearchMsg(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) {
+4 -154
View File
@@ -7,7 +7,6 @@ package v0mocks
import ( import (
context "context" context "context"
reflect "reflect" reflect "reflect"
time "time"
address "github.com/filecoin-project/go-address" address "github.com/filecoin-project/go-address"
bitfield "github.com/filecoin-project/go-bitfield" bitfield "github.com/filecoin-project/go-bitfield"
@@ -22,13 +21,11 @@ import (
network "github.com/filecoin-project/go-state-types/network" network "github.com/filecoin-project/go-state-types/network"
api "github.com/filecoin-project/lotus/api" api "github.com/filecoin-project/lotus/api"
apitypes "github.com/filecoin-project/lotus/api/types" apitypes "github.com/filecoin-project/lotus/api/types"
v0api "github.com/filecoin-project/lotus/api/v0api"
miner "github.com/filecoin-project/lotus/chain/actors/builtin/miner" miner "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
types "github.com/filecoin-project/lotus/chain/types" types "github.com/filecoin-project/lotus/chain/types"
alerting "github.com/filecoin-project/lotus/journal/alerting"
marketevents "github.com/filecoin-project/lotus/markets/loggers" marketevents "github.com/filecoin-project/lotus/markets/loggers"
dtypes "github.com/filecoin-project/lotus/node/modules/dtypes" dtypes "github.com/filecoin-project/lotus/node/modules/dtypes"
imports "github.com/filecoin-project/lotus/node/repo/imports" importmgr "github.com/filecoin-project/lotus/node/repo/importmgr"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
paych "github.com/filecoin-project/specs-actors/actors/builtin/paych" paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
@@ -734,7 +731,7 @@ func (mr *MockFullNodeMockRecorder) ClientQueryAsk(arg0, arg1, arg2 interface{})
} }
// ClientRemoveImport mocks base method. // ClientRemoveImport mocks base method.
func (m *MockFullNode) ClientRemoveImport(arg0 context.Context, arg1 imports.ID) error { func (m *MockFullNode) ClientRemoveImport(arg0 context.Context, arg1 importmgr.ImportID) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ClientRemoveImport", arg0, arg1) ret := m.ctrl.Call(m, "ClientRemoveImport", arg0, arg1)
ret0, _ := ret[0].(error) ret0, _ := ret[0].(error)
@@ -762,7 +759,7 @@ func (mr *MockFullNodeMockRecorder) ClientRestartDataTransfer(arg0, arg1, arg2,
} }
// ClientRetrieve mocks base method. // ClientRetrieve mocks base method.
func (m *MockFullNode) ClientRetrieve(arg0 context.Context, arg1 v0api.RetrievalOrder, arg2 *api.FileRef) error { func (m *MockFullNode) ClientRetrieve(arg0 context.Context, arg1 api.RetrievalOrder, arg2 *api.FileRef) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ClientRetrieve", arg0, arg1, arg2) ret := m.ctrl.Call(m, "ClientRetrieve", arg0, arg1, arg2)
ret0, _ := ret[0].(error) ret0, _ := ret[0].(error)
@@ -790,7 +787,7 @@ func (mr *MockFullNodeMockRecorder) ClientRetrieveTryRestartInsufficientFunds(ar
} }
// ClientRetrieveWithEvents mocks base method. // ClientRetrieveWithEvents mocks base method.
func (m *MockFullNode) ClientRetrieveWithEvents(arg0 context.Context, arg1 v0api.RetrievalOrder, arg2 *api.FileRef) (<-chan marketevents.RetrievalEvent, error) { func (m *MockFullNode) ClientRetrieveWithEvents(arg0 context.Context, arg1 api.RetrievalOrder, arg2 *api.FileRef) (<-chan marketevents.RetrievalEvent, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ClientRetrieveWithEvents", arg0, arg1, arg2) ret := m.ctrl.Call(m, "ClientRetrieveWithEvents", arg0, arg1, arg2)
ret0, _ := ret[0].(<-chan marketevents.RetrievalEvent) ret0, _ := ret[0].(<-chan marketevents.RetrievalEvent)
@@ -953,21 +950,6 @@ func (mr *MockFullNodeMockRecorder) ID(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockFullNode)(nil).ID), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockFullNode)(nil).ID), arg0)
} }
// LogAlerts mocks base method.
func (m *MockFullNode) LogAlerts(arg0 context.Context) ([]alerting.Alert, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "LogAlerts", arg0)
ret0, _ := ret[0].([]alerting.Alert)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// LogAlerts indicates an expected call of LogAlerts.
func (mr *MockFullNodeMockRecorder) LogAlerts(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LogAlerts", reflect.TypeOf((*MockFullNode)(nil).LogAlerts), arg0)
}
// LogList mocks base method. // LogList mocks base method.
func (m *MockFullNode) LogList(arg0 context.Context) ([]string, error) { func (m *MockFullNode) LogList(arg0 context.Context) ([]string, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@@ -1725,21 +1707,6 @@ func (mr *MockFullNodeMockRecorder) NetFindPeer(arg0, arg1 interface{}) *gomock.
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetFindPeer", reflect.TypeOf((*MockFullNode)(nil).NetFindPeer), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetFindPeer", reflect.TypeOf((*MockFullNode)(nil).NetFindPeer), arg0, arg1)
} }
// NetLimit mocks base method.
func (m *MockFullNode) NetLimit(arg0 context.Context, arg1 string) (api.NetLimit, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetLimit", arg0, arg1)
ret0, _ := ret[0].(api.NetLimit)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// NetLimit indicates an expected call of NetLimit.
func (mr *MockFullNodeMockRecorder) NetLimit(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetLimit", reflect.TypeOf((*MockFullNode)(nil).NetLimit), arg0, arg1)
}
// NetPeerInfo mocks base method. // NetPeerInfo mocks base method.
func (m *MockFullNode) NetPeerInfo(arg0 context.Context, arg1 peer.ID) (*api.ExtendedPeerInfo, error) { func (m *MockFullNode) NetPeerInfo(arg0 context.Context, arg1 peer.ID) (*api.ExtendedPeerInfo, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@@ -1770,64 +1737,6 @@ func (mr *MockFullNodeMockRecorder) NetPeers(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPeers", reflect.TypeOf((*MockFullNode)(nil).NetPeers), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPeers", reflect.TypeOf((*MockFullNode)(nil).NetPeers), arg0)
} }
// NetPing mocks base method.
func (m *MockFullNode) NetPing(arg0 context.Context, arg1 peer.ID) (time.Duration, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetPing", arg0, arg1)
ret0, _ := ret[0].(time.Duration)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// NetPing indicates an expected call of NetPing.
func (mr *MockFullNodeMockRecorder) NetPing(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPing", reflect.TypeOf((*MockFullNode)(nil).NetPing), arg0, arg1)
}
// NetProtectAdd mocks base method.
func (m *MockFullNode) NetProtectAdd(arg0 context.Context, arg1 []peer.ID) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetProtectAdd", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// NetProtectAdd indicates an expected call of NetProtectAdd.
func (mr *MockFullNodeMockRecorder) NetProtectAdd(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetProtectAdd", reflect.TypeOf((*MockFullNode)(nil).NetProtectAdd), arg0, arg1)
}
// NetProtectList mocks base method.
func (m *MockFullNode) NetProtectList(arg0 context.Context) ([]peer.ID, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetProtectList", arg0)
ret0, _ := ret[0].([]peer.ID)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// NetProtectList indicates an expected call of NetProtectList.
func (mr *MockFullNodeMockRecorder) NetProtectList(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetProtectList", reflect.TypeOf((*MockFullNode)(nil).NetProtectList), arg0)
}
// NetProtectRemove mocks base method.
func (m *MockFullNode) NetProtectRemove(arg0 context.Context, arg1 []peer.ID) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetProtectRemove", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// NetProtectRemove indicates an expected call of NetProtectRemove.
func (mr *MockFullNodeMockRecorder) NetProtectRemove(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetProtectRemove", reflect.TypeOf((*MockFullNode)(nil).NetProtectRemove), arg0, arg1)
}
// NetPubsubScores mocks base method. // NetPubsubScores mocks base method.
func (m *MockFullNode) NetPubsubScores(arg0 context.Context) ([]api.PubsubScore, error) { func (m *MockFullNode) NetPubsubScores(arg0 context.Context) ([]api.PubsubScore, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@@ -1843,35 +1752,6 @@ func (mr *MockFullNodeMockRecorder) NetPubsubScores(arg0 interface{}) *gomock.Ca
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPubsubScores", reflect.TypeOf((*MockFullNode)(nil).NetPubsubScores), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPubsubScores", reflect.TypeOf((*MockFullNode)(nil).NetPubsubScores), arg0)
} }
// NetSetLimit mocks base method.
func (m *MockFullNode) NetSetLimit(arg0 context.Context, arg1 string, arg2 api.NetLimit) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetSetLimit", arg0, arg1, arg2)
ret0, _ := ret[0].(error)
return ret0
}
// NetSetLimit indicates an expected call of NetSetLimit.
func (mr *MockFullNodeMockRecorder) NetSetLimit(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetSetLimit", reflect.TypeOf((*MockFullNode)(nil).NetSetLimit), arg0, arg1, arg2)
}
// NetStat mocks base method.
func (m *MockFullNode) NetStat(arg0 context.Context, arg1 string) (api.NetStat, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetStat", arg0, arg1)
ret0, _ := ret[0].(api.NetStat)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// NetStat indicates an expected call of NetStat.
func (mr *MockFullNodeMockRecorder) NetStat(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetStat", reflect.TypeOf((*MockFullNode)(nil).NetStat), arg0, arg1)
}
// PaychAllocateLane mocks base method. // PaychAllocateLane mocks base method.
func (m *MockFullNode) PaychAllocateLane(arg0 context.Context, arg1 address.Address) (uint64, error) { func (m *MockFullNode) PaychAllocateLane(arg0 context.Context, arg1 address.Address) (uint64, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@@ -2275,36 +2155,6 @@ func (mr *MockFullNodeMockRecorder) StateGetActor(arg0, arg1, arg2 interface{})
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetActor", reflect.TypeOf((*MockFullNode)(nil).StateGetActor), arg0, arg1, arg2) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetActor", reflect.TypeOf((*MockFullNode)(nil).StateGetActor), arg0, arg1, arg2)
} }
// StateGetRandomnessFromBeacon mocks base method.
func (m *MockFullNode) StateGetRandomnessFromBeacon(arg0 context.Context, arg1 crypto.DomainSeparationTag, arg2 abi.ChainEpoch, arg3 []byte, arg4 types.TipSetKey) (abi.Randomness, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateGetRandomnessFromBeacon", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(abi.Randomness)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateGetRandomnessFromBeacon indicates an expected call of StateGetRandomnessFromBeacon.
func (mr *MockFullNodeMockRecorder) StateGetRandomnessFromBeacon(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetRandomnessFromBeacon", reflect.TypeOf((*MockFullNode)(nil).StateGetRandomnessFromBeacon), arg0, arg1, arg2, arg3, arg4)
}
// StateGetRandomnessFromTickets mocks base method.
func (m *MockFullNode) StateGetRandomnessFromTickets(arg0 context.Context, arg1 crypto.DomainSeparationTag, arg2 abi.ChainEpoch, arg3 []byte, arg4 types.TipSetKey) (abi.Randomness, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateGetRandomnessFromTickets", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(abi.Randomness)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateGetRandomnessFromTickets indicates an expected call of StateGetRandomnessFromTickets.
func (mr *MockFullNodeMockRecorder) StateGetRandomnessFromTickets(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetRandomnessFromTickets", reflect.TypeOf((*MockFullNode)(nil).StateGetRandomnessFromTickets), arg0, arg1, arg2, arg3, arg4)
}
// StateGetReceipt mocks base method. // StateGetReceipt mocks base method.
func (m *MockFullNode) StateGetReceipt(arg0 context.Context, arg1 cid.Cid, arg2 types.TipSetKey) (*types.MessageReceipt, error) { func (m *MockFullNode) StateGetReceipt(arg0 context.Context, arg1 cid.Cid, arg2 types.TipSetKey) (*types.MessageReceipt, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
+1 -158
View File
@@ -3,11 +3,6 @@ package v0api
import ( import (
"context" "context"
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
marketevents "github.com/filecoin-project/lotus/markets/loggers"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@@ -111,7 +106,7 @@ func (w *WrapperV1Full) MsigApproveTxnHash(ctx context.Context, msig address.Add
} }
func (w *WrapperV1Full) MsigCancel(ctx context.Context, msig address.Address, txID uint64, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) { func (w *WrapperV1Full) MsigCancel(ctx context.Context, msig address.Address, txID uint64, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
p, err := w.FullNode.MsigCancelTxnHash(ctx, msig, txID, to, amt, src, method, params) p, err := w.FullNode.MsigCancel(ctx, msig, txID, to, amt, src, method, params)
if err != nil { if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err) return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
} }
@@ -189,156 +184,4 @@ func (w *WrapperV1Full) MsigRemoveSigner(ctx context.Context, msig address.Addre
return w.executePrototype(ctx, p) return w.executePrototype(ctx, p)
} }
func (w *WrapperV1Full) ChainGetRandomnessFromTickets(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) {
return w.StateGetRandomnessFromTickets(ctx, personalization, randEpoch, entropy, tsk)
}
func (w *WrapperV1Full) ChainGetRandomnessFromBeacon(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) {
return w.StateGetRandomnessFromBeacon(ctx, personalization, randEpoch, entropy, tsk)
}
func (w *WrapperV1Full) ClientRetrieve(ctx context.Context, order RetrievalOrder, ref *api.FileRef) error {
events := make(chan marketevents.RetrievalEvent)
go w.clientRetrieve(ctx, order, ref, events)
for {
select {
case evt, ok := <-events:
if !ok { // done successfully
return nil
}
if evt.Err != "" {
return xerrors.Errorf("retrieval failed: %s", evt.Err)
}
case <-ctx.Done():
return xerrors.Errorf("retrieval timed out")
}
}
}
func (w *WrapperV1Full) ClientRetrieveWithEvents(ctx context.Context, order RetrievalOrder, ref *api.FileRef) (<-chan marketevents.RetrievalEvent, error) {
events := make(chan marketevents.RetrievalEvent)
go w.clientRetrieve(ctx, order, ref, events)
return events, nil
}
func readSubscribeEvents(ctx context.Context, dealID retrievalmarket.DealID, subscribeEvents <-chan api.RetrievalInfo, events chan marketevents.RetrievalEvent) error {
for {
var subscribeEvent api.RetrievalInfo
var evt retrievalmarket.ClientEvent
select {
case <-ctx.Done():
return xerrors.New("Retrieval Timed Out")
case subscribeEvent = <-subscribeEvents:
if subscribeEvent.ID != dealID {
// we can't check the deal ID ahead of time because:
// 1. We need to subscribe before retrieving.
// 2. We won't know the deal ID until after retrieving.
continue
}
if subscribeEvent.Event != nil {
evt = *subscribeEvent.Event
}
}
select {
case <-ctx.Done():
return xerrors.New("Retrieval Timed Out")
case events <- marketevents.RetrievalEvent{
Event: evt,
Status: subscribeEvent.Status,
BytesReceived: subscribeEvent.BytesReceived,
FundsSpent: subscribeEvent.TotalPaid,
}:
}
switch subscribeEvent.Status {
case retrievalmarket.DealStatusCompleted:
return nil
case retrievalmarket.DealStatusRejected:
return xerrors.Errorf("Retrieval Proposal Rejected: %s", subscribeEvent.Message)
case
retrievalmarket.DealStatusDealNotFound,
retrievalmarket.DealStatusErrored:
return xerrors.Errorf("Retrieval Error: %s", subscribeEvent.Message)
}
}
}
func (w *WrapperV1Full) clientRetrieve(ctx context.Context, order RetrievalOrder, ref *api.FileRef, events chan marketevents.RetrievalEvent) {
defer close(events)
finish := func(e error) {
if e != nil {
events <- marketevents.RetrievalEvent{Err: e.Error(), FundsSpent: big.Zero()}
}
}
var dealID retrievalmarket.DealID
if order.FromLocalCAR == "" {
// Subscribe to events before retrieving to avoid losing events.
subscribeCtx, cancel := context.WithCancel(ctx)
defer cancel()
retrievalEvents, err := w.ClientGetRetrievalUpdates(subscribeCtx)
if err != nil {
finish(xerrors.Errorf("GetRetrievalUpdates failed: %w", err))
return
}
retrievalRes, err := w.FullNode.ClientRetrieve(ctx, api.RetrievalOrder{
Root: order.Root,
Piece: order.Piece,
Size: order.Size,
Total: order.Total,
UnsealPrice: order.UnsealPrice,
PaymentInterval: order.PaymentInterval,
PaymentIntervalIncrease: order.PaymentIntervalIncrease,
Client: order.Client,
Miner: order.Miner,
MinerPeer: order.MinerPeer,
})
if err != nil {
finish(xerrors.Errorf("Retrieve failed: %w", err))
return
}
dealID = retrievalRes.DealID
err = readSubscribeEvents(ctx, retrievalRes.DealID, retrievalEvents, events)
if err != nil {
finish(xerrors.Errorf("Retrieve: %w", err))
return
}
}
// If ref is nil, it only fetches the data into the configured blockstore.
if ref == nil {
finish(nil)
return
}
eref := api.ExportRef{
Root: order.Root,
FromLocalCAR: order.FromLocalCAR,
DealID: dealID,
}
if order.DatamodelPathSelector != nil {
s := api.Selector(*order.DatamodelPathSelector)
eref.DAGs = append(eref.DAGs, api.DagSpec{
DataSelector: &s,
ExportMerkleProof: true,
})
}
finish(w.ClientExport(ctx, eref, *ref))
}
func (w *WrapperV1Full) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) {
return w.FullNode.PaychFund(ctx, from, to, amt)
}
var _ FullNode = &WrapperV1Full{} var _ FullNode = &WrapperV1Full{}
+4 -4
View File
@@ -54,11 +54,11 @@ func VersionForType(nodeType NodeType) (Version, error) {
// semver versions of the rpc api exposed // semver versions of the rpc api exposed
var ( var (
FullAPIVersion0 = newVer(1, 5, 0) FullAPIVersion0 = newVer(1, 3, 1)
FullAPIVersion1 = newVer(2, 2, 0) FullAPIVersion1 = newVer(2, 1, 1)
MinerAPIVersion0 = newVer(1, 5, 0) MinerAPIVersion0 = newVer(1, 2, 0)
WorkerAPIVersion0 = newVer(1, 6, 0) WorkerAPIVersion0 = newVer(1, 1, 0)
) )
//nolint:varcheck,deadcode //nolint:varcheck,deadcode
+9 -9
View File
@@ -25,35 +25,35 @@ func NewAPIBlockstore(cio ChainIO) Blockstore {
return Adapt(bs) // return an adapted blockstore. return Adapt(bs) // return an adapted blockstore.
} }
func (a *apiBlockstore) DeleteBlock(context.Context, cid.Cid) error { func (a *apiBlockstore) DeleteBlock(cid.Cid) error {
return xerrors.New("not supported") return xerrors.New("not supported")
} }
func (a *apiBlockstore) Has(ctx context.Context, c cid.Cid) (bool, error) { func (a *apiBlockstore) Has(c cid.Cid) (bool, error) {
return a.api.ChainHasObj(ctx, c) return a.api.ChainHasObj(context.TODO(), c)
} }
func (a *apiBlockstore) Get(ctx context.Context, c cid.Cid) (blocks.Block, error) { func (a *apiBlockstore) Get(c cid.Cid) (blocks.Block, error) {
bb, err := a.api.ChainReadObj(ctx, c) bb, err := a.api.ChainReadObj(context.TODO(), c)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return blocks.NewBlockWithCid(bb, c) return blocks.NewBlockWithCid(bb, c)
} }
func (a *apiBlockstore) GetSize(ctx context.Context, c cid.Cid) (int, error) { func (a *apiBlockstore) GetSize(c cid.Cid) (int, error) {
bb, err := a.api.ChainReadObj(ctx, c) bb, err := a.api.ChainReadObj(context.TODO(), c)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return len(bb), nil return len(bb), nil
} }
func (a *apiBlockstore) Put(context.Context, blocks.Block) error { func (a *apiBlockstore) Put(blocks.Block) error {
return xerrors.New("not supported") return xerrors.New("not supported")
} }
func (a *apiBlockstore) PutMany(context.Context, []blocks.Block) error { func (a *apiBlockstore) PutMany([]blocks.Block) error {
return xerrors.New("not supported") return xerrors.New("not supported")
} }
-262
View File
@@ -1,262 +0,0 @@
package blockstore
import (
"context"
"sync"
"time"
"golang.org/x/xerrors"
block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
)
// autolog is a logger for the autobatching blockstore. It is subscoped from the
// blockstore logger.
var autolog = log.Named("auto")
// contains the same set of blocks twice, once as an ordered list for flushing, and as a map for fast access
type blockBatch struct {
blockList []block.Block
blockMap map[cid.Cid]block.Block
}
type AutobatchBlockstore struct {
// TODO: drop if memory consumption is too high
addedCids map[cid.Cid]struct{}
stateLock sync.Mutex
bufferedBatch blockBatch
flushingBatch blockBatch
flushErr error
flushCh chan struct{}
doFlushLock sync.Mutex
flushRetryDelay time.Duration
doneCh chan struct{}
shutdown context.CancelFunc
backingBs Blockstore
bufferCapacity int
bufferSize int
}
func NewAutobatch(ctx context.Context, backingBs Blockstore, bufferCapacity int) *AutobatchBlockstore {
ctx, cancel := context.WithCancel(ctx)
bs := &AutobatchBlockstore{
addedCids: make(map[cid.Cid]struct{}),
backingBs: backingBs,
bufferCapacity: bufferCapacity,
flushCh: make(chan struct{}, 1),
doneCh: make(chan struct{}),
// could be made configable
flushRetryDelay: time.Millisecond * 100,
shutdown: cancel,
}
bs.bufferedBatch.blockMap = make(map[cid.Cid]block.Block)
go bs.flushWorker(ctx)
return bs
}
func (bs *AutobatchBlockstore) Put(ctx context.Context, blk block.Block) error {
bs.stateLock.Lock()
defer bs.stateLock.Unlock()
_, ok := bs.addedCids[blk.Cid()]
if !ok {
bs.addedCids[blk.Cid()] = struct{}{}
bs.bufferedBatch.blockList = append(bs.bufferedBatch.blockList, blk)
bs.bufferedBatch.blockMap[blk.Cid()] = blk
bs.bufferSize += len(blk.RawData())
if bs.bufferSize >= bs.bufferCapacity {
// signal that a flush is appropriate, may be ignored
select {
case bs.flushCh <- struct{}{}:
default:
// do nothing
}
}
}
return nil
}
func (bs *AutobatchBlockstore) flushWorker(ctx context.Context) {
defer close(bs.doneCh)
for {
select {
case <-bs.flushCh:
// TODO: check if we _should_ actually flush. We could get a spurious wakeup
// here.
putErr := bs.doFlush(ctx, false)
for putErr != nil {
select {
case <-ctx.Done():
return
case <-time.After(bs.flushRetryDelay):
autolog.Errorf("FLUSH ERRORED: %w, retrying after %v", putErr, bs.flushRetryDelay)
putErr = bs.doFlush(ctx, true)
}
}
case <-ctx.Done():
// Do one last flush.
_ = bs.doFlush(ctx, false)
return
}
}
}
// caller must NOT hold stateLock
// set retryOnly to true to only retry a failed flush and not flush anything new.
func (bs *AutobatchBlockstore) doFlush(ctx context.Context, retryOnly bool) error {
bs.doFlushLock.Lock()
defer bs.doFlushLock.Unlock()
// If we failed to flush last time, try flushing again.
if bs.flushErr != nil {
bs.flushErr = bs.backingBs.PutMany(ctx, bs.flushingBatch.blockList)
}
// If we failed, or we're _only_ retrying, bail.
if retryOnly || bs.flushErr != nil {
return bs.flushErr
}
// Then take the current batch...
bs.stateLock.Lock()
// We do NOT clear addedCids here, because its purpose is to expedite Puts
bs.flushingBatch = bs.bufferedBatch
bs.bufferedBatch.blockList = make([]block.Block, 0, len(bs.flushingBatch.blockList))
bs.bufferedBatch.blockMap = make(map[cid.Cid]block.Block, len(bs.flushingBatch.blockMap))
bs.stateLock.Unlock()
// And try to flush it.
bs.flushErr = bs.backingBs.PutMany(ctx, bs.flushingBatch.blockList)
// If we succeeded, reset the batch. Otherwise, we'll try again next time.
if bs.flushErr == nil {
bs.stateLock.Lock()
bs.flushingBatch = blockBatch{}
bs.stateLock.Unlock()
}
return bs.flushErr
}
// caller must NOT hold stateLock
func (bs *AutobatchBlockstore) Flush(ctx context.Context) error {
return bs.doFlush(ctx, false)
}
func (bs *AutobatchBlockstore) Shutdown(ctx context.Context) error {
// TODO: Prevent puts after we call this to avoid losing data.
bs.shutdown()
select {
case <-bs.doneCh:
case <-ctx.Done():
return ctx.Err()
}
bs.doFlushLock.Lock()
defer bs.doFlushLock.Unlock()
return bs.flushErr
}
func (bs *AutobatchBlockstore) Get(ctx context.Context, c cid.Cid) (block.Block, error) {
// may seem backward to check the backingBs first, but that is the likeliest case
blk, err := bs.backingBs.Get(ctx, c)
if err == nil {
return blk, nil
}
if err != ErrNotFound {
return blk, err
}
bs.stateLock.Lock()
defer bs.stateLock.Unlock()
v, ok := bs.flushingBatch.blockMap[c]
if ok {
return v, nil
}
v, ok = bs.bufferedBatch.blockMap[c]
if ok {
return v, nil
}
return bs.Get(ctx, c)
}
func (bs *AutobatchBlockstore) DeleteBlock(context.Context, cid.Cid) error {
// if we wanted to support this, we would have to:
// - flush
// - delete from the backingBs (if present)
// - remove from addedCids (if present)
// - if present in addedCids, also walk the ordered lists and remove if present
return xerrors.New("deletion is unsupported")
}
func (bs *AutobatchBlockstore) DeleteMany(ctx context.Context, cids []cid.Cid) error {
// see note in DeleteBlock()
return xerrors.New("deletion is unsupported")
}
func (bs *AutobatchBlockstore) Has(ctx context.Context, c cid.Cid) (bool, error) {
_, err := bs.Get(ctx, c)
if err == nil {
return true, nil
}
if err == ErrNotFound {
return false, nil
}
return false, err
}
func (bs *AutobatchBlockstore) GetSize(ctx context.Context, c cid.Cid) (int, error) {
blk, err := bs.Get(ctx, c)
if err != nil {
return 0, err
}
return len(blk.RawData()), nil
}
func (bs *AutobatchBlockstore) PutMany(ctx context.Context, blks []block.Block) error {
for _, blk := range blks {
if err := bs.Put(ctx, blk); err != nil {
return err
}
}
return nil
}
func (bs *AutobatchBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
if err := bs.Flush(ctx); err != nil {
return nil, err
}
return bs.backingBs.AllKeysChan(ctx)
}
func (bs *AutobatchBlockstore) HashOnRead(enabled bool) {
bs.backingBs.HashOnRead(enabled)
}
func (bs *AutobatchBlockstore) View(ctx context.Context, cid cid.Cid, callback func([]byte) error) error {
blk, err := bs.Get(ctx, cid)
if err != nil {
return err
}
return callback(blk.RawData())
}
-34
View File
@@ -1,34 +0,0 @@
package blockstore
import (
"context"
"testing"
"github.com/stretchr/testify/require"
)
func TestAutobatchBlockstore(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ab := NewAutobatch(ctx, NewMemory(), len(b0.RawData())+len(b1.RawData())-1)
require.NoError(t, ab.Put(ctx, b0))
require.NoError(t, ab.Put(ctx, b1))
require.NoError(t, ab.Put(ctx, b2))
v0, err := ab.Get(ctx, b0.Cid())
require.NoError(t, err)
require.Equal(t, b0.RawData(), v0.RawData())
v1, err := ab.Get(ctx, b1.Cid())
require.NoError(t, err)
require.Equal(t, b1.RawData(), v1.RawData())
v2, err := ab.Get(ctx, b2.Cid())
require.NoError(t, err)
require.Equal(t, b2.RawData(), v2.RawData())
require.NoError(t, ab.Flush(ctx))
require.NoError(t, ab.Shutdown(ctx))
}
+8 -8
View File
@@ -525,7 +525,7 @@ func (b *Blockstore) Size() (int64, error) {
// View implements blockstore.Viewer, which leverages zero-copy read-only // View implements blockstore.Viewer, which leverages zero-copy read-only
// access to values. // access to values.
func (b *Blockstore) View(ctx context.Context, cid cid.Cid, fn func([]byte) error) error { func (b *Blockstore) View(cid cid.Cid, fn func([]byte) error) error {
if err := b.access(); err != nil { if err := b.access(); err != nil {
return err return err
} }
@@ -552,7 +552,7 @@ func (b *Blockstore) View(ctx context.Context, cid cid.Cid, fn func([]byte) erro
} }
// Has implements Blockstore.Has. // Has implements Blockstore.Has.
func (b *Blockstore) Has(ctx context.Context, cid cid.Cid) (bool, error) { func (b *Blockstore) Has(cid cid.Cid) (bool, error) {
if err := b.access(); err != nil { if err := b.access(); err != nil {
return false, err return false, err
} }
@@ -582,7 +582,7 @@ func (b *Blockstore) Has(ctx context.Context, cid cid.Cid) (bool, error) {
} }
// Get implements Blockstore.Get. // Get implements Blockstore.Get.
func (b *Blockstore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) { func (b *Blockstore) Get(cid cid.Cid) (blocks.Block, error) {
if !cid.Defined() { if !cid.Defined() {
return nil, blockstore.ErrNotFound return nil, blockstore.ErrNotFound
} }
@@ -619,7 +619,7 @@ func (b *Blockstore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error)
} }
// GetSize implements Blockstore.GetSize. // GetSize implements Blockstore.GetSize.
func (b *Blockstore) GetSize(ctx context.Context, cid cid.Cid) (int, error) { func (b *Blockstore) GetSize(cid cid.Cid) (int, error) {
if err := b.access(); err != nil { if err := b.access(); err != nil {
return 0, err return 0, err
} }
@@ -652,7 +652,7 @@ func (b *Blockstore) GetSize(ctx context.Context, cid cid.Cid) (int, error) {
} }
// Put implements Blockstore.Put. // Put implements Blockstore.Put.
func (b *Blockstore) Put(ctx context.Context, block blocks.Block) error { func (b *Blockstore) Put(block blocks.Block) error {
if err := b.access(); err != nil { if err := b.access(); err != nil {
return err return err
} }
@@ -691,7 +691,7 @@ func (b *Blockstore) Put(ctx context.Context, block blocks.Block) error {
} }
// PutMany implements Blockstore.PutMany. // PutMany implements Blockstore.PutMany.
func (b *Blockstore) PutMany(ctx context.Context, blocks []blocks.Block) error { func (b *Blockstore) PutMany(blocks []blocks.Block) error {
if err := b.access(); err != nil { if err := b.access(); err != nil {
return err return err
} }
@@ -755,7 +755,7 @@ func (b *Blockstore) PutMany(ctx context.Context, blocks []blocks.Block) error {
} }
// DeleteBlock implements Blockstore.DeleteBlock. // DeleteBlock implements Blockstore.DeleteBlock.
func (b *Blockstore) DeleteBlock(ctx context.Context, cid cid.Cid) error { func (b *Blockstore) DeleteBlock(cid cid.Cid) error {
if err := b.access(); err != nil { if err := b.access(); err != nil {
return err return err
} }
@@ -774,7 +774,7 @@ func (b *Blockstore) DeleteBlock(ctx context.Context, cid cid.Cid) error {
}) })
} }
func (b *Blockstore) DeleteMany(ctx context.Context, cids []cid.Cid) error { func (b *Blockstore) DeleteMany(cids []cid.Cid) error {
if err := b.access(); err != nil { if err := b.access(); err != nil {
return err return err
} }
+23 -21
View File
@@ -1,10 +1,9 @@
//stm: #unit
package badgerbs package badgerbs
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@@ -20,8 +19,6 @@ import (
) )
func TestBadgerBlockstore(t *testing.T) { func TestBadgerBlockstore(t *testing.T) {
//stm: @SPLITSTORE_BADGER_PUT_001, @SPLITSTORE_BADGER_POOLED_STORAGE_KEY_001
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
(&Suite{ (&Suite{
NewBlockstore: newBlockstore(DefaultOptions), NewBlockstore: newBlockstore(DefaultOptions),
OpenBlockstore: openBlockstore(DefaultOptions), OpenBlockstore: openBlockstore(DefaultOptions),
@@ -40,8 +37,6 @@ func TestBadgerBlockstore(t *testing.T) {
} }
func TestStorageKey(t *testing.T) { func TestStorageKey(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
//stm: @SPLITSTORE_BADGER_STORAGE_KEY_001
bs, _ := newBlockstore(DefaultOptions)(t) bs, _ := newBlockstore(DefaultOptions)(t)
bbs := bs.(*Blockstore) bbs := bs.(*Blockstore)
defer bbs.Close() //nolint:errcheck defer bbs.Close() //nolint:errcheck
@@ -77,13 +72,20 @@ func newBlockstore(optsSupplier func(path string) Options) func(tb testing.TB) (
return func(tb testing.TB) (bs blockstore.BasicBlockstore, path string) { return func(tb testing.TB) (bs blockstore.BasicBlockstore, path string) {
tb.Helper() tb.Helper()
path = tb.TempDir() path, err := ioutil.TempDir("", "")
if err != nil {
tb.Fatal(err)
}
db, err := Open(optsSupplier(path)) db, err := Open(optsSupplier(path))
if err != nil { if err != nil {
tb.Fatal(err) tb.Fatal(err)
} }
tb.Cleanup(func() {
_ = os.RemoveAll(path)
})
return db, path return db, path
} }
} }
@@ -96,11 +98,17 @@ func openBlockstore(optsSupplier func(path string) Options) func(tb testing.TB,
} }
func testMove(t *testing.T, optsF func(string) Options) { func testMove(t *testing.T, optsF func(string) Options) {
ctx := context.Background() basePath, err := ioutil.TempDir("", "")
basePath := t.TempDir() if err != nil {
t.Fatal(err)
}
dbPath := filepath.Join(basePath, "db") dbPath := filepath.Join(basePath, "db")
t.Cleanup(func() {
_ = os.RemoveAll(basePath)
})
db, err := Open(optsF(dbPath)) db, err := Open(optsF(dbPath))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -114,7 +122,7 @@ func testMove(t *testing.T, optsF func(string) Options) {
// add some blocks // add some blocks
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
blk := blocks.NewBlock([]byte(fmt.Sprintf("some data %d", i))) blk := blocks.NewBlock([]byte(fmt.Sprintf("some data %d", i)))
err := db.Put(ctx, blk) err := db.Put(blk)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -124,7 +132,7 @@ func testMove(t *testing.T, optsF func(string) Options) {
// delete some of them // delete some of them
for i := 5; i < 10; i++ { for i := 5; i < 10; i++ {
c := have[i].Cid() c := have[i].Cid()
err := db.DeleteBlock(ctx, c) err := db.DeleteBlock(c)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -137,7 +145,7 @@ func testMove(t *testing.T, optsF func(string) Options) {
g.Go(func() error { g.Go(func() error {
for i := 10; i < 1000; i++ { for i := 10; i < 1000; i++ {
blk := blocks.NewBlock([]byte(fmt.Sprintf("some data %d", i))) blk := blocks.NewBlock([]byte(fmt.Sprintf("some data %d", i)))
err := db.Put(ctx, blk) err := db.Put(blk)
if err != nil { if err != nil {
return err return err
} }
@@ -157,7 +165,7 @@ func testMove(t *testing.T, optsF func(string) Options) {
// now check that we have all the blocks in have and none in the deleted lists // now check that we have all the blocks in have and none in the deleted lists
checkBlocks := func() { checkBlocks := func() {
for _, blk := range have { for _, blk := range have {
has, err := db.Has(ctx, blk.Cid()) has, err := db.Has(blk.Cid())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -166,7 +174,7 @@ func testMove(t *testing.T, optsF func(string) Options) {
t.Fatal("missing block") t.Fatal("missing block")
} }
blk2, err := db.Get(ctx, blk.Cid()) blk2, err := db.Get(blk.Cid())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -177,7 +185,7 @@ func testMove(t *testing.T, optsF func(string) Options) {
} }
for _, c := range deleted { for _, c := range deleted {
has, err := db.Has(ctx, c) has, err := db.Has(c)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -255,16 +263,10 @@ func testMove(t *testing.T, optsF func(string) Options) {
} }
func TestMoveNoPrefix(t *testing.T) { func TestMoveNoPrefix(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
//stm: @SPLITSTORE_BADGER_PUT_001, @SPLITSTORE_BADGER_POOLED_STORAGE_KEY_001
//stm: @SPLITSTORE_BADGER_DELETE_001, @SPLITSTORE_BADGER_COLLECT_GARBAGE_001
testMove(t, DefaultOptions) testMove(t, DefaultOptions)
} }
func TestMoveWithPrefix(t *testing.T) { func TestMoveWithPrefix(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
//stm: @SPLITSTORE_BADGER_PUT_001, @SPLITSTORE_BADGER_POOLED_STORAGE_KEY_001
//stm: @SPLITSTORE_BADGER_DELETE_001, @SPLITSTORE_BADGER_COLLECT_GARBAGE_001
testMove(t, func(path string) Options { testMove(t, func(path string) Options {
opts := DefaultOptions(path) opts := DefaultOptions(path)
opts.Prefix = "/prefixed/" opts.Prefix = "/prefixed/"
+24 -68
View File
@@ -1,4 +1,3 @@
//stm: #unit
package badgerbs package badgerbs
import ( import (
@@ -45,38 +44,28 @@ func (s *Suite) RunTests(t *testing.T, prefix string) {
} }
func (s *Suite) TestGetWhenKeyNotPresent(t *testing.T) { func (s *Suite) TestGetWhenKeyNotPresent(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
//stm: @SPLITSTORE_BADGER_GET_001, @SPLITSTORE_BADGER_POOLED_STORAGE_KEY_001
ctx := context.Background()
bs, _ := s.NewBlockstore(t) bs, _ := s.NewBlockstore(t)
if c, ok := bs.(io.Closer); ok { if c, ok := bs.(io.Closer); ok {
defer func() { require.NoError(t, c.Close()) }() defer func() { require.NoError(t, c.Close()) }()
} }
c := cid.NewCidV0(u.Hash([]byte("stuff"))) c := cid.NewCidV0(u.Hash([]byte("stuff")))
bl, err := bs.Get(ctx, c) bl, err := bs.Get(c)
require.Nil(t, bl) require.Nil(t, bl)
require.Equal(t, blockstore.ErrNotFound, err) require.Equal(t, blockstore.ErrNotFound, err)
} }
func (s *Suite) TestGetWhenKeyIsNil(t *testing.T) { func (s *Suite) TestGetWhenKeyIsNil(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
//stm: @SPLITSTORE_BADGER_GET_001
ctx := context.Background()
bs, _ := s.NewBlockstore(t) bs, _ := s.NewBlockstore(t)
if c, ok := bs.(io.Closer); ok { if c, ok := bs.(io.Closer); ok {
defer func() { require.NoError(t, c.Close()) }() defer func() { require.NoError(t, c.Close()) }()
} }
_, err := bs.Get(ctx, cid.Undef) _, err := bs.Get(cid.Undef)
require.Equal(t, blockstore.ErrNotFound, err) require.Equal(t, blockstore.ErrNotFound, err)
} }
func (s *Suite) TestPutThenGetBlock(t *testing.T) { func (s *Suite) TestPutThenGetBlock(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
//stm: @SPLITSTORE_BADGER_PUT_001, @SPLITSTORE_BADGER_POOLED_STORAGE_KEY_001
//stm: @SPLITSTORE_BADGER_GET_001
ctx := context.Background()
bs, _ := s.NewBlockstore(t) bs, _ := s.NewBlockstore(t)
if c, ok := bs.(io.Closer); ok { if c, ok := bs.(io.Closer); ok {
defer func() { require.NoError(t, c.Close()) }() defer func() { require.NoError(t, c.Close()) }()
@@ -84,18 +73,15 @@ func (s *Suite) TestPutThenGetBlock(t *testing.T) {
orig := blocks.NewBlock([]byte("some data")) orig := blocks.NewBlock([]byte("some data"))
err := bs.Put(ctx, orig) err := bs.Put(orig)
require.NoError(t, err) require.NoError(t, err)
fetched, err := bs.Get(ctx, orig.Cid()) fetched, err := bs.Get(orig.Cid())
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, orig.RawData(), fetched.RawData()) require.Equal(t, orig.RawData(), fetched.RawData())
} }
func (s *Suite) TestHas(t *testing.T) { func (s *Suite) TestHas(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
//stm: @SPLITSTORE_BADGER_HAS_001, @SPLITSTORE_BADGER_POOLED_STORAGE_KEY_001
ctx := context.Background()
bs, _ := s.NewBlockstore(t) bs, _ := s.NewBlockstore(t)
if c, ok := bs.(io.Closer); ok { if c, ok := bs.(io.Closer); ok {
defer func() { require.NoError(t, c.Close()) }() defer func() { require.NoError(t, c.Close()) }()
@@ -103,23 +89,19 @@ func (s *Suite) TestHas(t *testing.T) {
orig := blocks.NewBlock([]byte("some data")) orig := blocks.NewBlock([]byte("some data"))
err := bs.Put(ctx, orig) err := bs.Put(orig)
require.NoError(t, err) require.NoError(t, err)
ok, err := bs.Has(ctx, orig.Cid()) ok, err := bs.Has(orig.Cid())
require.NoError(t, err) require.NoError(t, err)
require.True(t, ok) require.True(t, ok)
ok, err = bs.Has(ctx, blocks.NewBlock([]byte("another thing")).Cid()) ok, err = bs.Has(blocks.NewBlock([]byte("another thing")).Cid())
require.NoError(t, err) require.NoError(t, err)
require.False(t, ok) require.False(t, ok)
} }
func (s *Suite) TestCidv0v1(t *testing.T) { func (s *Suite) TestCidv0v1(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
//stm: @SPLITSTORE_BADGER_PUT_001, @SPLITSTORE_BADGER_POOLED_STORAGE_KEY_001
//stm: @SPLITSTORE_BADGER_GET_001
ctx := context.Background()
bs, _ := s.NewBlockstore(t) bs, _ := s.NewBlockstore(t)
if c, ok := bs.(io.Closer); ok { if c, ok := bs.(io.Closer); ok {
defer func() { require.NoError(t, c.Close()) }() defer func() { require.NoError(t, c.Close()) }()
@@ -127,20 +109,15 @@ func (s *Suite) TestCidv0v1(t *testing.T) {
orig := blocks.NewBlock([]byte("some data")) orig := blocks.NewBlock([]byte("some data"))
err := bs.Put(ctx, orig) err := bs.Put(orig)
require.NoError(t, err) require.NoError(t, err)
fetched, err := bs.Get(ctx, cid.NewCidV1(cid.DagProtobuf, orig.Cid().Hash())) fetched, err := bs.Get(cid.NewCidV1(cid.DagProtobuf, orig.Cid().Hash()))
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, orig.RawData(), fetched.RawData()) require.Equal(t, orig.RawData(), fetched.RawData())
} }
func (s *Suite) TestPutThenGetSizeBlock(t *testing.T) { func (s *Suite) TestPutThenGetSizeBlock(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
//stm: @SPLITSTORE_BADGER_PUT_001, @SPLITSTORE_BADGER_POOLED_STORAGE_KEY_001
//stm: @SPLITSTORE_BADGER_GET_SIZE_001
ctx := context.Background()
bs, _ := s.NewBlockstore(t) bs, _ := s.NewBlockstore(t)
if c, ok := bs.(io.Closer); ok { if c, ok := bs.(io.Closer); ok {
defer func() { require.NoError(t, c.Close()) }() defer func() { require.NoError(t, c.Close()) }()
@@ -150,28 +127,26 @@ func (s *Suite) TestPutThenGetSizeBlock(t *testing.T) {
missingBlock := blocks.NewBlock([]byte("missingBlock")) missingBlock := blocks.NewBlock([]byte("missingBlock"))
emptyBlock := blocks.NewBlock([]byte{}) emptyBlock := blocks.NewBlock([]byte{})
err := bs.Put(ctx, block) err := bs.Put(block)
require.NoError(t, err) require.NoError(t, err)
blockSize, err := bs.GetSize(ctx, block.Cid()) blockSize, err := bs.GetSize(block.Cid())
require.NoError(t, err) require.NoError(t, err)
require.Len(t, block.RawData(), blockSize) require.Len(t, block.RawData(), blockSize)
err = bs.Put(ctx, emptyBlock) err = bs.Put(emptyBlock)
require.NoError(t, err) require.NoError(t, err)
emptySize, err := bs.GetSize(ctx, emptyBlock.Cid()) emptySize, err := bs.GetSize(emptyBlock.Cid())
require.NoError(t, err) require.NoError(t, err)
require.Zero(t, emptySize) require.Zero(t, emptySize)
missingSize, err := bs.GetSize(ctx, missingBlock.Cid()) missingSize, err := bs.GetSize(missingBlock.Cid())
require.Equal(t, blockstore.ErrNotFound, err) require.Equal(t, blockstore.ErrNotFound, err)
require.Equal(t, -1, missingSize) require.Equal(t, -1, missingSize)
} }
func (s *Suite) TestAllKeysSimple(t *testing.T) { func (s *Suite) TestAllKeysSimple(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
//stm: @SPLITSTORE_BADGER_PUT_001, @SPLITSTORE_BADGER_POOLED_STORAGE_KEY_001
bs, _ := s.NewBlockstore(t) bs, _ := s.NewBlockstore(t)
if c, ok := bs.(io.Closer); ok { if c, ok := bs.(io.Closer); ok {
defer func() { require.NoError(t, c.Close()) }() defer func() { require.NoError(t, c.Close()) }()
@@ -188,9 +163,6 @@ func (s *Suite) TestAllKeysSimple(t *testing.T) {
} }
func (s *Suite) TestAllKeysRespectsContext(t *testing.T) { func (s *Suite) TestAllKeysRespectsContext(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
//stm: @SPLITSTORE_BADGER_PUT_001, @SPLITSTORE_BADGER_POOLED_STORAGE_KEY_001
//stm: @SPLITSTORE_BADGER_ALL_KEYS_CHAN_001
bs, _ := s.NewBlockstore(t) bs, _ := s.NewBlockstore(t)
if c, ok := bs.(io.Closer); ok { if c, ok := bs.(io.Closer); ok {
defer func() { require.NoError(t, c.Close()) }() defer func() { require.NoError(t, c.Close()) }()
@@ -221,7 +193,6 @@ func (s *Suite) TestAllKeysRespectsContext(t *testing.T) {
} }
func (s *Suite) TestDoubleClose(t *testing.T) { func (s *Suite) TestDoubleClose(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
bs, _ := s.NewBlockstore(t) bs, _ := s.NewBlockstore(t)
c, ok := bs.(io.Closer) c, ok := bs.(io.Closer)
if !ok { if !ok {
@@ -232,10 +203,6 @@ func (s *Suite) TestDoubleClose(t *testing.T) {
} }
func (s *Suite) TestReopenPutGet(t *testing.T) { func (s *Suite) TestReopenPutGet(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
//stm: @SPLITSTORE_BADGER_PUT_001, @SPLITSTORE_BADGER_POOLED_STORAGE_KEY_001
//stm: @SPLITSTORE_BADGER_GET_001
ctx := context.Background()
bs, path := s.NewBlockstore(t) bs, path := s.NewBlockstore(t)
c, ok := bs.(io.Closer) c, ok := bs.(io.Closer)
if !ok { if !ok {
@@ -243,7 +210,7 @@ func (s *Suite) TestReopenPutGet(t *testing.T) {
} }
orig := blocks.NewBlock([]byte("some data")) orig := blocks.NewBlock([]byte("some data"))
err := bs.Put(ctx, orig) err := bs.Put(orig)
require.NoError(t, err) require.NoError(t, err)
err = c.Close() err = c.Close()
@@ -252,7 +219,7 @@ func (s *Suite) TestReopenPutGet(t *testing.T) {
bs, err = s.OpenBlockstore(t, path) bs, err = s.OpenBlockstore(t, path)
require.NoError(t, err) require.NoError(t, err)
fetched, err := bs.Get(ctx, orig.Cid()) fetched, err := bs.Get(orig.Cid())
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, orig.RawData(), fetched.RawData()) require.Equal(t, orig.RawData(), fetched.RawData())
@@ -261,11 +228,6 @@ func (s *Suite) TestReopenPutGet(t *testing.T) {
} }
func (s *Suite) TestPutMany(t *testing.T) { func (s *Suite) TestPutMany(t *testing.T) {
//stm: @SPLITSTORE_BADGER_OPEN_001, @SPLITSTORE_BADGER_CLOSE_001
//stm: @SPLITSTORE_BADGER_HAS_001, @SPLITSTORE_BADGER_POOLED_STORAGE_KEY_001
//stm: @SPLITSTORE_BADGER_GET_001, @SPLITSTORE_BADGER_PUT_MANY_001
//stm: @SPLITSTORE_BADGER_ALL_KEYS_CHAN_001
ctx := context.Background()
bs, _ := s.NewBlockstore(t) bs, _ := s.NewBlockstore(t)
if c, ok := bs.(io.Closer); ok { if c, ok := bs.(io.Closer); ok {
defer func() { require.NoError(t, c.Close()) }() defer func() { require.NoError(t, c.Close()) }()
@@ -276,15 +238,15 @@ func (s *Suite) TestPutMany(t *testing.T) {
blocks.NewBlock([]byte("foo2")), blocks.NewBlock([]byte("foo2")),
blocks.NewBlock([]byte("foo3")), blocks.NewBlock([]byte("foo3")),
} }
err := bs.PutMany(ctx, blks) err := bs.PutMany(blks)
require.NoError(t, err) require.NoError(t, err)
for _, blk := range blks { for _, blk := range blks {
fetched, err := bs.Get(ctx, blk.Cid()) fetched, err := bs.Get(blk.Cid())
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, blk.RawData(), fetched.RawData()) require.Equal(t, blk.RawData(), fetched.RawData())
ok, err := bs.Has(ctx, blk.Cid()) ok, err := bs.Has(blk.Cid())
require.NoError(t, err) require.NoError(t, err)
require.True(t, ok) require.True(t, ok)
} }
@@ -297,12 +259,6 @@ func (s *Suite) TestPutMany(t *testing.T) {
} }
func (s *Suite) TestDelete(t *testing.T) { func (s *Suite) TestDelete(t *testing.T) {
//stm: @SPLITSTORE_BADGER_PUT_001, @SPLITSTORE_BADGER_POOLED_STORAGE_KEY_001
//stm: @SPLITSTORE_BADGER_DELETE_001, @SPLITSTORE_BADGER_POOLED_STORAGE_HAS_001
//stm: @SPLITSTORE_BADGER_ALL_KEYS_CHAN_001, @SPLITSTORE_BADGER_HAS_001
//stm: @SPLITSTORE_BADGER_PUT_MANY_001
ctx := context.Background()
bs, _ := s.NewBlockstore(t) bs, _ := s.NewBlockstore(t)
if c, ok := bs.(io.Closer); ok { if c, ok := bs.(io.Closer); ok {
defer func() { require.NoError(t, c.Close()) }() defer func() { require.NoError(t, c.Close()) }()
@@ -313,10 +269,10 @@ func (s *Suite) TestDelete(t *testing.T) {
blocks.NewBlock([]byte("foo2")), blocks.NewBlock([]byte("foo2")),
blocks.NewBlock([]byte("foo3")), blocks.NewBlock([]byte("foo3")),
} }
err := bs.PutMany(ctx, blks) err := bs.PutMany(blks)
require.NoError(t, err) require.NoError(t, err)
err = bs.DeleteBlock(ctx, blks[1].Cid()) err = bs.DeleteBlock(blks[1].Cid())
require.NoError(t, err) require.NoError(t, err)
ch, err := bs.AllKeysChan(context.Background()) ch, err := bs.AllKeysChan(context.Background())
@@ -329,17 +285,17 @@ func (s *Suite) TestDelete(t *testing.T) {
cid.NewCidV1(cid.Raw, blks[2].Cid().Hash()), cid.NewCidV1(cid.Raw, blks[2].Cid().Hash()),
}) })
has, err := bs.Has(ctx, blks[1].Cid()) has, err := bs.Has(blks[1].Cid())
require.NoError(t, err) require.NoError(t, err)
require.False(t, has) require.False(t, has)
} }
func insertBlocks(t *testing.T, bs blockstore.BasicBlockstore, count int) []cid.Cid { func insertBlocks(t *testing.T, bs blockstore.BasicBlockstore, count int) []cid.Cid {
ctx := context.Background()
keys := make([]cid.Cid, count) keys := make([]cid.Cid, count)
for i := 0; i < count; i++ { for i := 0; i < count; i++ {
block := blocks.NewBlock([]byte(fmt.Sprintf("some data %d", i))) block := blocks.NewBlock([]byte(fmt.Sprintf("some data %d", i)))
err := bs.Put(ctx, block) err := bs.Put(block)
require.NoError(t, err) require.NoError(t, err)
// NewBlock assigns a CIDv0; we convert it to CIDv1 because that's what // NewBlock assigns a CIDv0; we convert it to CIDv1 because that's what
// the store returns. // the store returns.
+5 -7
View File
@@ -1,8 +1,6 @@
package blockstore package blockstore
import ( import (
"context"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
ds "github.com/ipfs/go-datastore" ds "github.com/ipfs/go-datastore"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
@@ -29,7 +27,7 @@ type BasicBlockstore = blockstore.Blockstore
type Viewer = blockstore.Viewer type Viewer = blockstore.Viewer
type BatchDeleter interface { type BatchDeleter interface {
DeleteMany(ctx context.Context, cids []cid.Cid) error DeleteMany(cids []cid.Cid) error
} }
// BlockstoreIterator is a trait for efficient iteration // BlockstoreIterator is a trait for efficient iteration
@@ -95,17 +93,17 @@ type adaptedBlockstore struct {
var _ Blockstore = (*adaptedBlockstore)(nil) var _ Blockstore = (*adaptedBlockstore)(nil)
func (a *adaptedBlockstore) View(ctx context.Context, cid cid.Cid, callback func([]byte) error) error { func (a *adaptedBlockstore) View(cid cid.Cid, callback func([]byte) error) error {
blk, err := a.Get(ctx, cid) blk, err := a.Get(cid)
if err != nil { if err != nil {
return err return err
} }
return callback(blk.RawData()) return callback(blk.RawData())
} }
func (a *adaptedBlockstore) DeleteMany(ctx context.Context, cids []cid.Cid) error { func (a *adaptedBlockstore) DeleteMany(cids []cid.Cid) error {
for _, cid := range cids { for _, cid := range cids {
err := a.DeleteBlock(ctx, cid) err := a.DeleteBlock(cid)
if err != nil { if err != nil {
return err return err
} }
+23 -23
View File
@@ -88,34 +88,34 @@ func (bs *BufferedBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid,
return out, nil return out, nil
} }
func (bs *BufferedBlockstore) DeleteBlock(ctx context.Context, c cid.Cid) error { func (bs *BufferedBlockstore) DeleteBlock(c cid.Cid) error {
if err := bs.read.DeleteBlock(ctx, c); err != nil { if err := bs.read.DeleteBlock(c); err != nil {
return err return err
} }
return bs.write.DeleteBlock(ctx, c) return bs.write.DeleteBlock(c)
} }
func (bs *BufferedBlockstore) DeleteMany(ctx context.Context, cids []cid.Cid) error { func (bs *BufferedBlockstore) DeleteMany(cids []cid.Cid) error {
if err := bs.read.DeleteMany(ctx, cids); err != nil { if err := bs.read.DeleteMany(cids); err != nil {
return err return err
} }
return bs.write.DeleteMany(ctx, cids) return bs.write.DeleteMany(cids)
} }
func (bs *BufferedBlockstore) View(ctx context.Context, c cid.Cid, callback func([]byte) error) error { func (bs *BufferedBlockstore) View(c cid.Cid, callback func([]byte) error) error {
// both stores are viewable. // both stores are viewable.
if err := bs.write.View(ctx, c, callback); err == ErrNotFound { if err := bs.write.View(c, callback); err == ErrNotFound {
// not found in write blockstore; fall through. // not found in write blockstore; fall through.
} else { } else {
return err // propagate errors, or nil, i.e. found. return err // propagate errors, or nil, i.e. found.
} }
return bs.read.View(ctx, c, callback) return bs.read.View(c, callback)
} }
func (bs *BufferedBlockstore) Get(ctx context.Context, c cid.Cid) (block.Block, error) { func (bs *BufferedBlockstore) Get(c cid.Cid) (block.Block, error) {
if out, err := bs.write.Get(ctx, c); err != nil { if out, err := bs.write.Get(c); err != nil {
if err != ErrNotFound { if err != ErrNotFound {
return nil, err return nil, err
} }
@@ -123,20 +123,20 @@ func (bs *BufferedBlockstore) Get(ctx context.Context, c cid.Cid) (block.Block,
return out, nil return out, nil
} }
return bs.read.Get(ctx, c) return bs.read.Get(c)
} }
func (bs *BufferedBlockstore) GetSize(ctx context.Context, c cid.Cid) (int, error) { func (bs *BufferedBlockstore) GetSize(c cid.Cid) (int, error) {
s, err := bs.read.GetSize(ctx, c) s, err := bs.read.GetSize(c)
if err == ErrNotFound || s == 0 { if err == ErrNotFound || s == 0 {
return bs.write.GetSize(ctx, c) return bs.write.GetSize(c)
} }
return s, err return s, err
} }
func (bs *BufferedBlockstore) Put(ctx context.Context, blk block.Block) error { func (bs *BufferedBlockstore) Put(blk block.Block) error {
has, err := bs.read.Has(ctx, blk.Cid()) // TODO: consider dropping this check has, err := bs.read.Has(blk.Cid()) // TODO: consider dropping this check
if err != nil { if err != nil {
return err return err
} }
@@ -145,11 +145,11 @@ func (bs *BufferedBlockstore) Put(ctx context.Context, blk block.Block) error {
return nil return nil
} }
return bs.write.Put(ctx, blk) return bs.write.Put(blk)
} }
func (bs *BufferedBlockstore) Has(ctx context.Context, c cid.Cid) (bool, error) { func (bs *BufferedBlockstore) Has(c cid.Cid) (bool, error) {
has, err := bs.write.Has(ctx, c) has, err := bs.write.Has(c)
if err != nil { if err != nil {
return false, err return false, err
} }
@@ -157,7 +157,7 @@ func (bs *BufferedBlockstore) Has(ctx context.Context, c cid.Cid) (bool, error)
return true, nil return true, nil
} }
return bs.read.Has(ctx, c) return bs.read.Has(c)
} }
func (bs *BufferedBlockstore) HashOnRead(hor bool) { func (bs *BufferedBlockstore) HashOnRead(hor bool) {
@@ -165,8 +165,8 @@ func (bs *BufferedBlockstore) HashOnRead(hor bool) {
bs.write.HashOnRead(hor) bs.write.HashOnRead(hor)
} }
func (bs *BufferedBlockstore) PutMany(ctx context.Context, blks []block.Block) error { func (bs *BufferedBlockstore) PutMany(blks []block.Block) error {
return bs.write.PutMany(ctx, blks) return bs.write.PutMany(blks)
} }
func (bs *BufferedBlockstore) Read() Blockstore { func (bs *BufferedBlockstore) Read() Blockstore {
-21
View File
@@ -1,21 +0,0 @@
package blockstore
import (
"context"
)
type hotViewKey struct{}
var hotView = hotViewKey{}
// WithHotView constructs a new context with an option that provides a hint to the blockstore
// (e.g. the splitstore) that the object (and its ipld references) should be kept hot.
func WithHotView(ctx context.Context) context.Context {
return context.WithValue(ctx, hotView, struct{}{})
}
// IsHotView returns true if the hot view option is set in the context
func IsHotView(ctx context.Context) bool {
v := ctx.Value(hotView)
return v != nil
}
+12 -12
View File
@@ -18,39 +18,39 @@ func NewDiscardStore(bs Blockstore) Blockstore {
return &discardstore{bs: bs} return &discardstore{bs: bs}
} }
func (b *discardstore) Has(ctx context.Context, cid cid.Cid) (bool, error) { func (b *discardstore) Has(cid cid.Cid) (bool, error) {
return b.bs.Has(ctx, cid) return b.bs.Has(cid)
} }
func (b *discardstore) HashOnRead(hor bool) { func (b *discardstore) HashOnRead(hor bool) {
b.bs.HashOnRead(hor) b.bs.HashOnRead(hor)
} }
func (b *discardstore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) { func (b *discardstore) Get(cid cid.Cid) (blocks.Block, error) {
return b.bs.Get(ctx, cid) return b.bs.Get(cid)
} }
func (b *discardstore) GetSize(ctx context.Context, cid cid.Cid) (int, error) { func (b *discardstore) GetSize(cid cid.Cid) (int, error) {
return b.bs.GetSize(ctx, cid) return b.bs.GetSize(cid)
} }
func (b *discardstore) View(ctx context.Context, cid cid.Cid, f func([]byte) error) error { func (b *discardstore) View(cid cid.Cid, f func([]byte) error) error {
return b.bs.View(ctx, cid, f) return b.bs.View(cid, f)
} }
func (b *discardstore) Put(ctx context.Context, blk blocks.Block) error { func (b *discardstore) Put(blk blocks.Block) error {
return nil return nil
} }
func (b *discardstore) PutMany(ctx context.Context, blks []blocks.Block) error { func (b *discardstore) PutMany(blks []blocks.Block) error {
return nil return nil
} }
func (b *discardstore) DeleteBlock(ctx context.Context, cid cid.Cid) error { func (b *discardstore) DeleteBlock(cid cid.Cid) error {
return nil return nil
} }
func (b *discardstore) DeleteMany(ctx context.Context, cids []cid.Cid) error { func (b *discardstore) DeleteMany(cids []cid.Cid) error {
return nil return nil
} }
+5 -5
View File
@@ -71,14 +71,14 @@ func (fbs *FallbackStore) getFallback(c cid.Cid) (blocks.Block, error) {
// chain bitswap puts blocks in temp blockstore which is cleaned up // chain bitswap puts blocks in temp blockstore which is cleaned up
// every few min (to drop any messages we fetched but don't want) // every few min (to drop any messages we fetched but don't want)
// in this case we want to keep this block around // in this case we want to keep this block around
if err := fbs.Put(ctx, b); err != nil { if err := fbs.Put(b); err != nil {
return nil, xerrors.Errorf("persisting fallback-fetched block: %w", err) return nil, xerrors.Errorf("persisting fallback-fetched block: %w", err)
} }
return b, nil return b, nil
} }
func (fbs *FallbackStore) Get(ctx context.Context, c cid.Cid) (blocks.Block, error) { func (fbs *FallbackStore) Get(c cid.Cid) (blocks.Block, error) {
b, err := fbs.Blockstore.Get(ctx, c) b, err := fbs.Blockstore.Get(c)
switch err { switch err {
case nil: case nil:
return b, nil return b, nil
@@ -89,8 +89,8 @@ func (fbs *FallbackStore) Get(ctx context.Context, c cid.Cid) (blocks.Block, err
} }
} }
func (fbs *FallbackStore) GetSize(ctx context.Context, c cid.Cid) (int, error) { func (fbs *FallbackStore) GetSize(c cid.Cid) (int, error) {
sz, err := fbs.Blockstore.GetSize(ctx, c) sz, err := fbs.Blockstore.GetSize(c)
switch err { switch err {
case nil: case nil:
return sz, nil return sz, nil
+16 -16
View File
@@ -38,7 +38,7 @@ func decodeCid(cid cid.Cid) (inline bool, data []byte, err error) {
return false, nil, err return false, nil, err
} }
func (b *idstore) Has(ctx context.Context, cid cid.Cid) (bool, error) { func (b *idstore) Has(cid cid.Cid) (bool, error) {
inline, _, err := decodeCid(cid) inline, _, err := decodeCid(cid)
if err != nil { if err != nil {
return false, xerrors.Errorf("error decoding Cid: %w", err) return false, xerrors.Errorf("error decoding Cid: %w", err)
@@ -48,10 +48,10 @@ func (b *idstore) Has(ctx context.Context, cid cid.Cid) (bool, error) {
return true, nil return true, nil
} }
return b.bs.Has(ctx, cid) return b.bs.Has(cid)
} }
func (b *idstore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) { func (b *idstore) Get(cid cid.Cid) (blocks.Block, error) {
inline, data, err := decodeCid(cid) inline, data, err := decodeCid(cid)
if err != nil { if err != nil {
return nil, xerrors.Errorf("error decoding Cid: %w", err) return nil, xerrors.Errorf("error decoding Cid: %w", err)
@@ -61,10 +61,10 @@ func (b *idstore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) {
return blocks.NewBlockWithCid(data, cid) return blocks.NewBlockWithCid(data, cid)
} }
return b.bs.Get(ctx, cid) return b.bs.Get(cid)
} }
func (b *idstore) GetSize(ctx context.Context, cid cid.Cid) (int, error) { func (b *idstore) GetSize(cid cid.Cid) (int, error) {
inline, data, err := decodeCid(cid) inline, data, err := decodeCid(cid)
if err != nil { if err != nil {
return 0, xerrors.Errorf("error decoding Cid: %w", err) return 0, xerrors.Errorf("error decoding Cid: %w", err)
@@ -74,10 +74,10 @@ func (b *idstore) GetSize(ctx context.Context, cid cid.Cid) (int, error) {
return len(data), err return len(data), err
} }
return b.bs.GetSize(ctx, cid) return b.bs.GetSize(cid)
} }
func (b *idstore) View(ctx context.Context, cid cid.Cid, cb func([]byte) error) error { func (b *idstore) View(cid cid.Cid, cb func([]byte) error) error {
inline, data, err := decodeCid(cid) inline, data, err := decodeCid(cid)
if err != nil { if err != nil {
return xerrors.Errorf("error decoding Cid: %w", err) return xerrors.Errorf("error decoding Cid: %w", err)
@@ -87,10 +87,10 @@ func (b *idstore) View(ctx context.Context, cid cid.Cid, cb func([]byte) error)
return cb(data) return cb(data)
} }
return b.bs.View(ctx, cid, cb) return b.bs.View(cid, cb)
} }
func (b *idstore) Put(ctx context.Context, blk blocks.Block) error { func (b *idstore) Put(blk blocks.Block) error {
inline, _, err := decodeCid(blk.Cid()) inline, _, err := decodeCid(blk.Cid())
if err != nil { if err != nil {
return xerrors.Errorf("error decoding Cid: %w", err) return xerrors.Errorf("error decoding Cid: %w", err)
@@ -100,10 +100,10 @@ func (b *idstore) Put(ctx context.Context, blk blocks.Block) error {
return nil return nil
} }
return b.bs.Put(ctx, blk) return b.bs.Put(blk)
} }
func (b *idstore) PutMany(ctx context.Context, blks []blocks.Block) error { func (b *idstore) PutMany(blks []blocks.Block) error {
toPut := make([]blocks.Block, 0, len(blks)) toPut := make([]blocks.Block, 0, len(blks))
for _, blk := range blks { for _, blk := range blks {
inline, _, err := decodeCid(blk.Cid()) inline, _, err := decodeCid(blk.Cid())
@@ -118,13 +118,13 @@ func (b *idstore) PutMany(ctx context.Context, blks []blocks.Block) error {
} }
if len(toPut) > 0 { if len(toPut) > 0 {
return b.bs.PutMany(ctx, toPut) return b.bs.PutMany(toPut)
} }
return nil return nil
} }
func (b *idstore) DeleteBlock(ctx context.Context, cid cid.Cid) error { func (b *idstore) DeleteBlock(cid cid.Cid) error {
inline, _, err := decodeCid(cid) inline, _, err := decodeCid(cid)
if err != nil { if err != nil {
return xerrors.Errorf("error decoding Cid: %w", err) return xerrors.Errorf("error decoding Cid: %w", err)
@@ -134,10 +134,10 @@ func (b *idstore) DeleteBlock(ctx context.Context, cid cid.Cid) error {
return nil return nil
} }
return b.bs.DeleteBlock(ctx, cid) return b.bs.DeleteBlock(cid)
} }
func (b *idstore) DeleteMany(ctx context.Context, cids []cid.Cid) error { func (b *idstore) DeleteMany(cids []cid.Cid) error {
toDelete := make([]cid.Cid, 0, len(cids)) toDelete := make([]cid.Cid, 0, len(cids))
for _, cid := range cids { for _, cid := range cids {
inline, _, err := decodeCid(cid) inline, _, err := decodeCid(cid)
@@ -152,7 +152,7 @@ func (b *idstore) DeleteMany(ctx context.Context, cids []cid.Cid) error {
} }
if len(toDelete) > 0 { if len(toDelete) > 0 {
return b.bs.DeleteMany(ctx, toDelete) return b.bs.DeleteMany(toDelete)
} }
return nil return nil
+11 -11
View File
@@ -79,12 +79,12 @@ func NewRemoteIPFSBlockstore(ctx context.Context, maddr multiaddr.Multiaddr, onl
return Adapt(bs), nil return Adapt(bs), nil
} }
func (i *IPFSBlockstore) DeleteBlock(ctx context.Context, cid cid.Cid) error { func (i *IPFSBlockstore) DeleteBlock(cid cid.Cid) error {
return xerrors.Errorf("not supported") return xerrors.Errorf("not supported")
} }
func (i *IPFSBlockstore) Has(ctx context.Context, cid cid.Cid) (bool, error) { func (i *IPFSBlockstore) Has(cid cid.Cid) (bool, error) {
_, err := i.offlineAPI.Block().Stat(ctx, path.IpldPath(cid)) _, err := i.offlineAPI.Block().Stat(i.ctx, path.IpldPath(cid))
if err != nil { if err != nil {
// The underlying client is running in Offline mode. // The underlying client is running in Offline mode.
// Stat() will fail with an err if the block isn't in the // Stat() will fail with an err if the block isn't in the
@@ -99,8 +99,8 @@ func (i *IPFSBlockstore) Has(ctx context.Context, cid cid.Cid) (bool, error) {
return true, nil return true, nil
} }
func (i *IPFSBlockstore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) { func (i *IPFSBlockstore) Get(cid cid.Cid) (blocks.Block, error) {
rd, err := i.api.Block().Get(ctx, path.IpldPath(cid)) rd, err := i.api.Block().Get(i.ctx, path.IpldPath(cid))
if err != nil { if err != nil {
return nil, xerrors.Errorf("getting ipfs block: %w", err) return nil, xerrors.Errorf("getting ipfs block: %w", err)
} }
@@ -113,8 +113,8 @@ func (i *IPFSBlockstore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, er
return blocks.NewBlockWithCid(data, cid) return blocks.NewBlockWithCid(data, cid)
} }
func (i *IPFSBlockstore) GetSize(ctx context.Context, cid cid.Cid) (int, error) { func (i *IPFSBlockstore) GetSize(cid cid.Cid) (int, error) {
st, err := i.api.Block().Stat(ctx, path.IpldPath(cid)) st, err := i.api.Block().Stat(i.ctx, path.IpldPath(cid))
if err != nil { if err != nil {
return 0, xerrors.Errorf("getting ipfs block: %w", err) return 0, xerrors.Errorf("getting ipfs block: %w", err)
} }
@@ -122,23 +122,23 @@ func (i *IPFSBlockstore) GetSize(ctx context.Context, cid cid.Cid) (int, error)
return st.Size(), nil return st.Size(), nil
} }
func (i *IPFSBlockstore) Put(ctx context.Context, block blocks.Block) error { func (i *IPFSBlockstore) Put(block blocks.Block) error {
mhd, err := multihash.Decode(block.Cid().Hash()) mhd, err := multihash.Decode(block.Cid().Hash())
if err != nil { if err != nil {
return err return err
} }
_, err = i.api.Block().Put(ctx, bytes.NewReader(block.RawData()), _, err = i.api.Block().Put(i.ctx, bytes.NewReader(block.RawData()),
options.Block.Hash(mhd.Code, mhd.Length), options.Block.Hash(mhd.Code, mhd.Length),
options.Block.Format(cid.CodecToStr[block.Cid().Type()])) options.Block.Format(cid.CodecToStr[block.Cid().Type()]))
return err return err
} }
func (i *IPFSBlockstore) PutMany(ctx context.Context, blocks []blocks.Block) error { func (i *IPFSBlockstore) PutMany(blocks []blocks.Block) error {
// TODO: could be done in parallel // TODO: could be done in parallel
for _, block := range blocks { for _, block := range blocks {
if err := i.Put(ctx, block); err != nil { if err := i.Put(block); err != nil {
return err return err
} }
} }
+9 -9
View File
@@ -15,24 +15,24 @@ func NewMemory() MemBlockstore {
// MemBlockstore is a terminal blockstore that keeps blocks in memory. // MemBlockstore is a terminal blockstore that keeps blocks in memory.
type MemBlockstore map[cid.Cid]blocks.Block type MemBlockstore map[cid.Cid]blocks.Block
func (m MemBlockstore) DeleteBlock(ctx context.Context, k cid.Cid) error { func (m MemBlockstore) DeleteBlock(k cid.Cid) error {
delete(m, k) delete(m, k)
return nil return nil
} }
func (m MemBlockstore) DeleteMany(ctx context.Context, ks []cid.Cid) error { func (m MemBlockstore) DeleteMany(ks []cid.Cid) error {
for _, k := range ks { for _, k := range ks {
delete(m, k) delete(m, k)
} }
return nil return nil
} }
func (m MemBlockstore) Has(ctx context.Context, k cid.Cid) (bool, error) { func (m MemBlockstore) Has(k cid.Cid) (bool, error) {
_, ok := m[k] _, ok := m[k]
return ok, nil return ok, nil
} }
func (m MemBlockstore) View(ctx context.Context, k cid.Cid, callback func([]byte) error) error { func (m MemBlockstore) View(k cid.Cid, callback func([]byte) error) error {
b, ok := m[k] b, ok := m[k]
if !ok { if !ok {
return ErrNotFound return ErrNotFound
@@ -40,7 +40,7 @@ func (m MemBlockstore) View(ctx context.Context, k cid.Cid, callback func([]byte
return callback(b.RawData()) return callback(b.RawData())
} }
func (m MemBlockstore) Get(ctx context.Context, k cid.Cid) (blocks.Block, error) { func (m MemBlockstore) Get(k cid.Cid) (blocks.Block, error) {
b, ok := m[k] b, ok := m[k]
if !ok { if !ok {
return nil, ErrNotFound return nil, ErrNotFound
@@ -49,7 +49,7 @@ func (m MemBlockstore) Get(ctx context.Context, k cid.Cid) (blocks.Block, error)
} }
// GetSize returns the CIDs mapped BlockSize // GetSize returns the CIDs mapped BlockSize
func (m MemBlockstore) GetSize(ctx context.Context, k cid.Cid) (int, error) { func (m MemBlockstore) GetSize(k cid.Cid) (int, error) {
b, ok := m[k] b, ok := m[k]
if !ok { if !ok {
return 0, ErrNotFound return 0, ErrNotFound
@@ -58,7 +58,7 @@ func (m MemBlockstore) GetSize(ctx context.Context, k cid.Cid) (int, error) {
} }
// Put puts a given block to the underlying datastore // Put puts a given block to the underlying datastore
func (m MemBlockstore) Put(ctx context.Context, b blocks.Block) error { func (m MemBlockstore) Put(b blocks.Block) error {
// Convert to a basic block for safety, but try to reuse the existing // Convert to a basic block for safety, but try to reuse the existing
// block if it's already a basic block. // block if it's already a basic block.
k := b.Cid() k := b.Cid()
@@ -76,9 +76,9 @@ func (m MemBlockstore) Put(ctx context.Context, b blocks.Block) error {
// PutMany puts a slice of blocks at the same time using batching // PutMany puts a slice of blocks at the same time using batching
// capabilities of the underlying datastore whenever possible. // capabilities of the underlying datastore whenever possible.
func (m MemBlockstore) PutMany(ctx context.Context, bs []blocks.Block) error { func (m MemBlockstore) PutMany(bs []blocks.Block) error {
for _, b := range bs { for _, b := range bs {
_ = m.Put(ctx, b) // can't fail _ = m.Put(b) // can't fail
} }
return nil return nil
} }
+4 -12
View File
@@ -49,11 +49,10 @@ These are options in the `[Chainstore.Splitstore]` section of the configuration:
blockstore and discards writes; this is necessary to support syncing from a snapshot. blockstore and discards writes; this is necessary to support syncing from a snapshot.
- `MarkSetType` -- specifies the type of markset to use during compaction. - `MarkSetType` -- specifies the type of markset to use during compaction.
The markset is the data structure used by compaction/gc to track live objects. The markset is the data structure used by compaction/gc to track live objects.
The default value is "badger", which will use a disk backed markset using badger. The default value is `"map"`, which will use an in-memory map; if you are limited
If you have a lot of memory (48G or more) you can also use "map", which will use in memory (or indeed see compaction run out of memory), you can also specify
an in memory markset, speeding up compaction at the cost of higher memory usage. `"badger"` which will use an disk backed markset, using badger. This will use
Note: If you are using a VPS with a network volume, you need to provision at least much less memory, but will also make compaction slower.
3000 IOPs with the badger markset.
- `HotStoreMessageRetention` -- specifies how many finalities, beyond the 4 - `HotStoreMessageRetention` -- specifies how many finalities, beyond the 4
finalities maintained by default, to maintain messages and message receipts in the finalities maintained by default, to maintain messages and message receipts in the
hotstore. This is useful for assistive nodes that want to support syncing for other hotstore. This is useful for assistive nodes that want to support syncing for other
@@ -106,12 +105,6 @@ Compaction works transactionally with the following algorithm:
- We delete in small batches taking a lock; each batch is checked again for marks, from the concurrent transactional mark, so as to never delete anything live - We delete in small batches taking a lock; each batch is checked again for marks, from the concurrent transactional mark, so as to never delete anything live
- We then end the transaction and compact/gc the hotstore. - We then end the transaction and compact/gc the hotstore.
As of [#8008](https://github.com/filecoin-project/lotus/pull/8008) the compaction algorithm has been
modified to eliminate sorting and maintain the cold object set on disk. This drastically reduces
memory usage; in fact, when using badger as the markset compaction uses very little memory, and
it should be now possible to run splitstore with 32GB of RAM or less without danger of running out of
memory during compaction.
## Garbage Collection ## Garbage Collection
TBD -- see [#6577](https://github.com/filecoin-project/lotus/issues/6577) TBD -- see [#6577](https://github.com/filecoin-project/lotus/issues/6577)
@@ -126,7 +119,6 @@ TBD -- see [#6577](https://github.com/filecoin-project/lotus/issues/6577)
It can also optionally compact/gc the coldstore after the copy (with the `--gc-coldstore` flag) It can also optionally compact/gc the coldstore after the copy (with the `--gc-coldstore` flag)
and automatically rewrite the lotus config to disable splitstore (with the `--rewrite-config` flag). and automatically rewrite the lotus config to disable splitstore (with the `--rewrite-config` flag).
Note: the node *must be stopped* before running this command. Note: the node *must be stopped* before running this command.
- `clear` -- clears a splitstore installation for restart from snapshot.
- `check` -- asynchronously runs a basic healthcheck on the splitstore. - `check` -- asynchronously runs a basic healthcheck on the splitstore.
The results are appended to `<lotus-repo>/datastore/splitstore/check.txt`. The results are appended to `<lotus-repo>/datastore/splitstore/check.txt`.
- `info` -- prints some basic information about the splitstore. - `info` -- prints some basic information about the splitstore.
-118
View File
@@ -1,118 +0,0 @@
package splitstore
import (
"bufio"
"io"
"os"
"golang.org/x/xerrors"
cid "github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"
)
type Checkpoint struct {
file *os.File
buf *bufio.Writer
}
func NewCheckpoint(path string) (*Checkpoint, error) {
file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_SYNC, 0644)
if err != nil {
return nil, xerrors.Errorf("error creating checkpoint: %w", err)
}
buf := bufio.NewWriter(file)
return &Checkpoint{
file: file,
buf: buf,
}, nil
}
func OpenCheckpoint(path string) (*Checkpoint, cid.Cid, error) {
filein, err := os.Open(path)
if err != nil {
return nil, cid.Undef, xerrors.Errorf("error opening checkpoint for reading: %w", err)
}
defer filein.Close() //nolint:errcheck
bufin := bufio.NewReader(filein)
start, err := readRawCid(bufin, nil)
if err != nil && err != io.EOF {
return nil, cid.Undef, xerrors.Errorf("error reading cid from checkpoint: %w", err)
}
fileout, err := os.OpenFile(path, os.O_WRONLY|os.O_SYNC, 0644)
if err != nil {
return nil, cid.Undef, xerrors.Errorf("error opening checkpoint for writing: %w", err)
}
bufout := bufio.NewWriter(fileout)
return &Checkpoint{
file: fileout,
buf: bufout,
}, start, nil
}
func (cp *Checkpoint) Set(c cid.Cid) error {
if _, err := cp.file.Seek(0, io.SeekStart); err != nil {
return xerrors.Errorf("error seeking beginning of checkpoint: %w", err)
}
if err := writeRawCid(cp.buf, c, true); err != nil {
return xerrors.Errorf("error writing cid to checkpoint: %w", err)
}
return nil
}
func (cp *Checkpoint) Close() error {
if cp.file == nil {
return nil
}
err := cp.file.Close()
cp.file = nil
cp.buf = nil
return err
}
func readRawCid(buf *bufio.Reader, hbuf []byte) (cid.Cid, error) {
sz, err := buf.ReadByte()
if err != nil {
return cid.Undef, err // don't wrap EOF as it is not an error here
}
if hbuf == nil {
hbuf = make([]byte, int(sz))
} else {
hbuf = hbuf[:int(sz)]
}
if _, err := io.ReadFull(buf, hbuf); err != nil {
return cid.Undef, xerrors.Errorf("error reading hash: %w", err) // wrap EOF, it's corrupt
}
hash, err := mh.Cast(hbuf)
if err != nil {
return cid.Undef, xerrors.Errorf("error casting multihash: %w", err)
}
return cid.NewCidV1(cid.Raw, hash), nil
}
func writeRawCid(buf *bufio.Writer, c cid.Cid, flush bool) error {
hash := c.Hash()
if err := buf.WriteByte(byte(len(hash))); err != nil {
return err
}
if _, err := buf.Write(hash); err != nil {
return err
}
if flush {
return buf.Flush()
}
return nil
}
-138
View File
@@ -1,138 +0,0 @@
package splitstore
import (
"path/filepath"
"testing"
"github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash"
)
func TestCheckpoint(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "checkpoint")
makeCid := func(key string) cid.Cid {
h, err := multihash.Sum([]byte(key), multihash.SHA2_256, -1)
if err != nil {
t.Fatal(err)
}
return cid.NewCidV1(cid.Raw, h)
}
k1 := makeCid("a")
k2 := makeCid("b")
k3 := makeCid("c")
k4 := makeCid("d")
cp, err := NewCheckpoint(path)
if err != nil {
t.Fatal(err)
}
if err := cp.Set(k1); err != nil {
t.Fatal(err)
}
if err := cp.Set(k2); err != nil {
t.Fatal(err)
}
if err := cp.Close(); err != nil {
t.Fatal(err)
}
cp, start, err := OpenCheckpoint(path)
if err != nil {
t.Fatal(err)
}
if !start.Equals(k2) {
t.Fatalf("expected start to be %s; got %s", k2, start)
}
if err := cp.Set(k3); err != nil {
t.Fatal(err)
}
if err := cp.Set(k4); err != nil {
t.Fatal(err)
}
if err := cp.Close(); err != nil {
t.Fatal(err)
}
cp, start, err = OpenCheckpoint(path)
if err != nil {
t.Fatal(err)
}
if !start.Equals(k4) {
t.Fatalf("expected start to be %s; got %s", k4, start)
}
if err := cp.Close(); err != nil {
t.Fatal(err)
}
// also test correct operation with an empty checkpoint
cp, err = NewCheckpoint(path)
if err != nil {
t.Fatal(err)
}
if err := cp.Close(); err != nil {
t.Fatal(err)
}
cp, start, err = OpenCheckpoint(path)
if err != nil {
t.Fatal(err)
}
if start.Defined() {
t.Fatal("expected start to be undefined")
}
if err := cp.Set(k1); err != nil {
t.Fatal(err)
}
if err := cp.Set(k2); err != nil {
t.Fatal(err)
}
if err := cp.Close(); err != nil {
t.Fatal(err)
}
cp, start, err = OpenCheckpoint(path)
if err != nil {
t.Fatal(err)
}
if !start.Equals(k2) {
t.Fatalf("expected start to be %s; got %s", k2, start)
}
if err := cp.Set(k3); err != nil {
t.Fatal(err)
}
if err := cp.Set(k4); err != nil {
t.Fatal(err)
}
if err := cp.Close(); err != nil {
t.Fatal(err)
}
cp, start, err = OpenCheckpoint(path)
if err != nil {
t.Fatal(err)
}
if !start.Equals(k4) {
t.Fatalf("expected start to be %s; got %s", k4, start)
}
if err := cp.Close(); err != nil {
t.Fatal(err)
}
}
-102
View File
@@ -1,102 +0,0 @@
package splitstore
import (
"bufio"
"io"
"os"
"golang.org/x/xerrors"
cid "github.com/ipfs/go-cid"
)
type ColdSetWriter struct {
file *os.File
buf *bufio.Writer
}
type ColdSetReader struct {
file *os.File
buf *bufio.Reader
}
func NewColdSetWriter(path string) (*ColdSetWriter, error) {
file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
return nil, xerrors.Errorf("error creating coldset: %w", err)
}
buf := bufio.NewWriter(file)
return &ColdSetWriter{
file: file,
buf: buf,
}, nil
}
func NewColdSetReader(path string) (*ColdSetReader, error) {
file, err := os.Open(path)
if err != nil {
return nil, xerrors.Errorf("error opening coldset: %w", err)
}
buf := bufio.NewReader(file)
return &ColdSetReader{
file: file,
buf: buf,
}, nil
}
func (s *ColdSetWriter) Write(c cid.Cid) error {
return writeRawCid(s.buf, c, false)
}
func (s *ColdSetWriter) Close() error {
if s.file == nil {
return nil
}
err1 := s.buf.Flush()
err2 := s.file.Close()
s.buf = nil
s.file = nil
if err1 != nil {
return err1
}
return err2
}
func (s *ColdSetReader) ForEach(f func(cid.Cid) error) error {
hbuf := make([]byte, 256)
for {
next, err := readRawCid(s.buf, hbuf)
if err != nil {
if err == io.EOF {
return nil
}
return xerrors.Errorf("error reading coldset: %w", err)
}
if err := f(next); err != nil {
return err
}
}
}
func (s *ColdSetReader) Reset() error {
_, err := s.file.Seek(0, io.SeekStart)
return err
}
func (s *ColdSetReader) Close() error {
if s.file == nil {
return nil
}
err := s.file.Close()
s.file = nil
s.buf = nil
return err
}
-90
View File
@@ -1,90 +0,0 @@
package splitstore
import (
"fmt"
"path/filepath"
"testing"
"github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash"
)
func TestColdSet(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "coldset")
makeCid := func(i int) cid.Cid {
h, err := multihash.Sum([]byte(fmt.Sprintf("cid.%d", i)), multihash.SHA2_256, -1)
if err != nil {
t.Fatal(err)
}
return cid.NewCidV1(cid.Raw, h)
}
const count = 1000
cids := make([]cid.Cid, 0, count)
for i := 0; i < count; i++ {
cids = append(cids, makeCid(i))
}
cw, err := NewColdSetWriter(path)
if err != nil {
t.Fatal(err)
}
for _, c := range cids {
if err := cw.Write(c); err != nil {
t.Fatal(err)
}
}
if err := cw.Close(); err != nil {
t.Fatal(err)
}
cr, err := NewColdSetReader(path)
if err != nil {
t.Fatal(err)
}
index := 0
err = cr.ForEach(func(c cid.Cid) error {
if index >= count {
t.Fatal("too many cids")
}
if !c.Equals(cids[index]) {
t.Fatalf("wrong cid %d; expected %s but got %s", index, cids[index], c)
}
index++
return nil
})
if err != nil {
t.Fatal(err)
}
if err := cr.Reset(); err != nil {
t.Fatal(err)
}
index = 0
err = cr.ForEach(func(c cid.Cid) error {
if index >= count {
t.Fatal("too many cids")
}
if !c.Equals(cids[index]) {
t.Fatalf("wrong cid; expected %s but got %s", cids[index], c)
}
index++
return nil
})
if err != nil {
t.Fatal(err)
}
}
+9 -17
View File
@@ -10,36 +10,28 @@ import (
var errMarkSetClosed = errors.New("markset closed") var errMarkSetClosed = errors.New("markset closed")
// MarkSet is an interface for tracking CIDs during chain and object walks // MarkSet is a utility to keep track of seen CID, and later query for them.
//
// * If the expected dataset is large, it can be backed by a datastore (e.g. bbolt).
// * If a probabilistic result is acceptable, it can be backed by a bloom filter
type MarkSet interface { type MarkSet interface {
ObjectVisitor
Mark(cid.Cid) error Mark(cid.Cid) error
MarkMany([]cid.Cid) error
Has(cid.Cid) (bool, error) Has(cid.Cid) (bool, error)
Close() error Close() error
SetConcurrent()
// BeginCriticalSection ensures that the markset is persisted to disk for recovery in case
// of abnormal termination during the critical section span.
BeginCriticalSection() error
// EndCriticalSection ends the critical section span.
EndCriticalSection()
} }
type MarkSetEnv interface { type MarkSetEnv interface {
// New creates a new markset within the environment. Create(name string, sizeHint int64) (MarkSet, error)
// name is a unique name for this markset, mapped to the filesystem for on-disk persistence.
// sizeHint is a hint about the expected size of the markset
New(name string, sizeHint int64) (MarkSet, error)
// Recover recovers an existing markset persisted on-disk.
Recover(name string) (MarkSet, error)
// Close closes the markset
Close() error Close() error
} }
func OpenMarkSetEnv(path string, mtype string) (MarkSetEnv, error) { func OpenMarkSetEnv(path string, mtype string) (MarkSetEnv, error) {
switch mtype { switch mtype {
case "bloom":
return NewBloomMarkSetEnv()
case "map": case "map":
return NewMapMarkSetEnv(path) return NewMapMarkSetEnv()
case "badger": case "badger":
return NewBadgerMarkSetEnv(path) return NewBadgerMarkSetEnv(path)
default: default:
+81 -302
View File
@@ -3,7 +3,6 @@ package splitstore
import ( import (
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"sync" "sync"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@@ -28,8 +27,6 @@ type BadgerMarkSet struct {
writing map[int]map[string]struct{} writing map[int]map[string]struct{}
writers int writers int
seqno int seqno int
version int
persist bool
db *badger.DB db *badger.DB
path string path string
@@ -49,12 +46,39 @@ func NewBadgerMarkSetEnv(path string) (MarkSetEnv, error) {
return &BadgerMarkSetEnv{path: msPath}, nil return &BadgerMarkSetEnv{path: msPath}, nil
} }
func (e *BadgerMarkSetEnv) New(name string, sizeHint int64) (MarkSet, error) { func (e *BadgerMarkSetEnv) Create(name string, sizeHint int64) (MarkSet, error) {
path := filepath.Join(e.path, name) path := filepath.Join(e.path, name)
db, err := openBadgerDB(path, false) // clean up first
err := os.RemoveAll(path)
if err != nil { if err != nil {
return nil, xerrors.Errorf("error creating badger db: %w", err) return nil, xerrors.Errorf("error clearing markset directory: %w", err)
}
err = os.MkdirAll(path, 0755) //nolint:gosec
if err != nil {
return nil, xerrors.Errorf("error creating markset directory: %w", err)
}
opts := badger.DefaultOptions(path)
opts.SyncWrites = false
opts.CompactL0OnClose = false
opts.Compression = options.None
// Note: We use FileIO for loading modes to avoid memory thrashing and interference
// between the system blockstore and the markset.
// It was observed that using the default memory mapped option resulted in
// significant interference and unacceptably high block validation times once the markset
// exceeded 1GB in size.
opts.TableLoadingMode = options.FileIO
opts.ValueLogLoadingMode = options.FileIO
opts.Logger = &badgerLogger{
SugaredLogger: log.Desugar().WithOptions(zap.AddCallerSkip(1)).Sugar(),
skip2: log.Desugar().WithOptions(zap.AddCallerSkip(2)).Sugar(),
}
db, err := badger.Open(opts)
if err != nil {
return nil, xerrors.Errorf("error creating badger markset: %w", err)
} }
ms := &BadgerMarkSet{ ms := &BadgerMarkSet{
@@ -68,251 +92,30 @@ func (e *BadgerMarkSetEnv) New(name string, sizeHint int64) (MarkSet, error) {
return ms, nil return ms, nil
} }
func (e *BadgerMarkSetEnv) Recover(name string) (MarkSet, error) {
path := filepath.Join(e.path, name)
if _, err := os.Stat(path); err != nil {
return nil, xerrors.Errorf("error stating badger db path: %w", err)
}
db, err := openBadgerDB(path, true)
if err != nil {
return nil, xerrors.Errorf("error creating badger db: %w", err)
}
ms := &BadgerMarkSet{
pend: make(map[string]struct{}),
writing: make(map[int]map[string]struct{}),
db: db,
path: path,
persist: true,
}
ms.cond.L = &ms.mx
return ms, nil
}
func (e *BadgerMarkSetEnv) Close() error { func (e *BadgerMarkSetEnv) Close() error {
return nil return os.RemoveAll(e.path)
}
func (s *BadgerMarkSet) BeginCriticalSection() error {
s.mx.Lock()
if s.persist {
s.mx.Unlock()
return nil
}
var write bool
var seqno int
if len(s.pend) > 0 {
write = true
seqno = s.nextBatch()
}
s.persist = true
s.mx.Unlock()
if write {
// all writes sync once perist is true
return s.write(seqno)
}
// wait for any pending writes and sync
s.mx.Lock()
for s.writers > 0 {
s.cond.Wait()
}
s.mx.Unlock()
return s.db.Sync()
}
func (s *BadgerMarkSet) EndCriticalSection() {
s.mx.Lock()
defer s.mx.Unlock()
s.persist = false
} }
func (s *BadgerMarkSet) Mark(c cid.Cid) error { func (s *BadgerMarkSet) Mark(c cid.Cid) error {
s.mx.Lock() s.mx.Lock()
if s.pend == nil { if s.pend == nil {
s.mx.Unlock() s.mx.Unlock()
return errMarkSetClosed return errMarkSetClosed
} }
write, seqno := s.put(string(c.Hash())) s.pend[string(c.Hash())] = struct{}{}
s.mx.Unlock()
if write { if len(s.pend) < badgerMarkSetBatchSize {
return s.write(seqno)
}
return nil
}
func (s *BadgerMarkSet) MarkMany(batch []cid.Cid) error {
s.mx.Lock()
if s.pend == nil {
s.mx.Unlock() s.mx.Unlock()
return errMarkSetClosed return nil
} }
write, seqno := s.putMany(batch) pend := s.pend
s.mx.Unlock()
if write {
return s.write(seqno)
}
return nil
}
func (s *BadgerMarkSet) Has(c cid.Cid) (bool, error) {
s.mx.RLock()
defer s.mx.RUnlock()
key := c.Hash()
pendKey := string(key)
has, err := s.tryPending(pendKey)
if has || err != nil {
return has, err
}
return s.tryDB(key)
}
func (s *BadgerMarkSet) Visit(c cid.Cid) (bool, error) {
key := c.Hash()
pendKey := string(key)
s.mx.RLock()
has, err := s.tryPending(pendKey)
if has || err != nil {
s.mx.RUnlock()
return false, err
}
has, err = s.tryDB(key)
if has || err != nil {
s.mx.RUnlock()
return false, err
}
// we need to upgrade the lock to exclusive in order to write; take the version count to see
// if there was another write while we were upgrading
version := s.version
s.mx.RUnlock()
s.mx.Lock()
// we have to do the check dance again
has, err = s.tryPending(pendKey)
if has || err != nil {
s.mx.Unlock()
return false, err
}
if version != s.version {
// something was written to the db, we need to check it
has, err = s.tryDB(key)
if has || err != nil {
s.mx.Unlock()
return false, err
}
}
write, seqno := s.put(pendKey)
s.mx.Unlock()
if write {
err = s.write(seqno)
}
return true, err
}
// reader holds the (r)lock
func (s *BadgerMarkSet) tryPending(key string) (has bool, err error) {
if s.pend == nil {
return false, errMarkSetClosed
}
if _, ok := s.pend[key]; ok {
return true, nil
}
for _, wr := range s.writing {
if _, ok := wr[key]; ok {
return true, nil
}
}
return false, nil
}
func (s *BadgerMarkSet) tryDB(key []byte) (has bool, err error) {
err = s.db.View(func(txn *badger.Txn) error {
_, err := txn.Get(key)
return err
})
switch err {
case nil:
return true, nil
case badger.ErrKeyNotFound:
return false, nil
default:
return false, err
}
}
// writer holds the exclusive lock
func (s *BadgerMarkSet) put(key string) (write bool, seqno int) {
s.pend[key] = struct{}{}
if !s.persist && len(s.pend) < badgerMarkSetBatchSize {
return false, 0
}
seqno = s.nextBatch()
return true, seqno
}
func (s *BadgerMarkSet) putMany(batch []cid.Cid) (write bool, seqno int) {
for _, c := range batch {
key := string(c.Hash())
s.pend[key] = struct{}{}
}
if !s.persist && len(s.pend) < badgerMarkSetBatchSize {
return false, 0
}
seqno = s.nextBatch()
return true, seqno
}
func (s *BadgerMarkSet) nextBatch() int {
seqno := s.seqno seqno := s.seqno
s.seqno++ s.seqno++
s.writing[seqno] = s.pend s.writing[seqno] = pend
s.pend = make(map[string]struct{}) s.pend = make(map[string]struct{})
return seqno
}
func (s *BadgerMarkSet) write(seqno int) (err error) {
s.mx.Lock()
if s.pend == nil {
s.mx.Unlock()
return errMarkSetClosed
}
pend := s.writing[seqno]
s.writers++ s.writers++
s.mx.Unlock() s.mx.Unlock()
@@ -320,11 +123,7 @@ func (s *BadgerMarkSet) write(seqno int) (err error) {
s.mx.Lock() s.mx.Lock()
defer s.mx.Unlock() defer s.mx.Unlock()
if err == nil { delete(s.writing, seqno)
delete(s.writing, seqno)
s.version++
}
s.writers-- s.writers--
if s.writers == 0 { if s.writers == 0 {
s.cond.Broadcast() s.cond.Broadcast()
@@ -337,25 +136,56 @@ func (s *BadgerMarkSet) write(seqno int) (err error) {
defer batch.Cancel() defer batch.Cancel()
for k := range pend { for k := range pend {
if err = batch.Set([]byte(k), empty); err != nil { if err := batch.Set([]byte(k), empty); err != nil {
return xerrors.Errorf("error setting batch: %w", err) return err
} }
} }
err = batch.Flush() err := batch.Flush()
if err != nil { if err != nil {
return xerrors.Errorf("error flushing batch to badger markset: %w", err) return xerrors.Errorf("error flushing batch to badger markset: %w", err)
} }
s.mx.RLock() return nil
persist := s.persist }
s.mx.RUnlock()
if persist { func (s *BadgerMarkSet) Has(c cid.Cid) (bool, error) {
return s.db.Sync() s.mx.RLock()
defer s.mx.RUnlock()
if s.pend == nil {
return false, errMarkSetClosed
} }
return nil key := c.Hash()
pendKey := string(key)
_, ok := s.pend[pendKey]
if ok {
return true, nil
}
for _, wr := range s.writing {
_, ok := wr[pendKey]
if ok {
return true, nil
}
}
err := s.db.View(func(txn *badger.Txn) error {
_, err := txn.Get(key)
return err
})
switch err {
case nil:
return true, nil
case badger.ErrKeyNotFound:
return false, nil
default:
return false, xerrors.Errorf("error checking badger markset: %w", err)
}
} }
func (s *BadgerMarkSet) Close() error { func (s *BadgerMarkSet) Close() error {
@@ -374,65 +204,12 @@ func (s *BadgerMarkSet) Close() error {
db := s.db db := s.db
s.db = nil s.db = nil
return closeBadgerDB(db, s.path, s.persist)
}
func openBadgerDB(path string, recover bool) (*badger.DB, error) {
// if it is not a recovery, clean up first
if !recover {
err := os.RemoveAll(path)
if err != nil {
return nil, xerrors.Errorf("error clearing markset directory: %w", err)
}
err = os.MkdirAll(path, 0755) //nolint:gosec
if err != nil {
return nil, xerrors.Errorf("error creating markset directory: %w", err)
}
}
opts := badger.DefaultOptions(path)
// we manually sync when we are in critical section
opts.SyncWrites = false
// no need to do that
opts.CompactL0OnClose = false
// we store hashes, not much to gain by compression
opts.Compression = options.None
// Note: We use FileIO for loading modes to avoid memory thrashing and interference
// between the system blockstore and the markset.
// It was observed that using the default memory mapped option resulted in
// significant interference and unacceptably high block validation times once the markset
// exceeded 1GB in size.
opts.TableLoadingMode = options.FileIO
opts.ValueLogLoadingMode = options.FileIO
// We increase the number of L0 tables before compaction to make it unlikely to
// be necessary.
opts.NumLevelZeroTables = 20 // default is 5
opts.NumLevelZeroTablesStall = 30 // default is 10
// increase the number of compactors from default 2 so that if we ever have to
// compact, it is fast
if runtime.NumCPU()/2 > opts.NumCompactors {
opts.NumCompactors = runtime.NumCPU() / 2
}
opts.Logger = &badgerLogger{
SugaredLogger: log.Desugar().WithOptions(zap.AddCallerSkip(1)).Sugar(),
skip2: log.Desugar().WithOptions(zap.AddCallerSkip(2)).Sugar(),
}
return badger.Open(opts)
}
func closeBadgerDB(db *badger.DB, path string, persist bool) error {
err := db.Close() err := db.Close()
if err != nil { if err != nil {
return xerrors.Errorf("error closing badger markset: %w", err) return xerrors.Errorf("error closing badger markset: %w", err)
} }
if persist { err = os.RemoveAll(s.path)
return nil
}
err = os.RemoveAll(path)
if err != nil { if err != nil {
return xerrors.Errorf("error deleting badger markset: %w", err) return xerrors.Errorf("error deleting badger markset: %w", err)
} }
@@ -440,6 +217,8 @@ func closeBadgerDB(db *badger.DB, path string, persist bool) error {
return nil return nil
} }
func (s *BadgerMarkSet) SetConcurrent() {}
// badger logging through go-log // badger logging through go-log
type badgerLogger struct { type badgerLogger struct {
*zap.SugaredLogger *zap.SugaredLogger
+107
View File
@@ -0,0 +1,107 @@
package splitstore
import (
"crypto/rand"
"crypto/sha256"
"sync"
"golang.org/x/xerrors"
bbloom "github.com/ipfs/bbloom"
cid "github.com/ipfs/go-cid"
)
const (
BloomFilterMinSize = 10_000_000
BloomFilterProbability = 0.01
)
type BloomMarkSetEnv struct{}
var _ MarkSetEnv = (*BloomMarkSetEnv)(nil)
type BloomMarkSet struct {
salt []byte
mx sync.RWMutex
bf *bbloom.Bloom
ts bool
}
var _ MarkSet = (*BloomMarkSet)(nil)
func NewBloomMarkSetEnv() (*BloomMarkSetEnv, error) {
return &BloomMarkSetEnv{}, nil
}
func (e *BloomMarkSetEnv) Create(name string, sizeHint int64) (MarkSet, error) {
size := int64(BloomFilterMinSize)
for size < sizeHint {
size += BloomFilterMinSize
}
salt := make([]byte, 4)
_, err := rand.Read(salt)
if err != nil {
return nil, xerrors.Errorf("error reading salt: %w", err)
}
bf, err := bbloom.New(float64(size), BloomFilterProbability)
if err != nil {
return nil, xerrors.Errorf("error creating bloom filter: %w", err)
}
return &BloomMarkSet{salt: salt, bf: bf}, nil
}
func (e *BloomMarkSetEnv) Close() error {
return nil
}
func (s *BloomMarkSet) saltedKey(cid cid.Cid) []byte {
hash := cid.Hash()
key := make([]byte, len(s.salt)+len(hash))
n := copy(key, s.salt)
copy(key[n:], hash)
rehash := sha256.Sum256(key)
return rehash[:]
}
func (s *BloomMarkSet) Mark(cid cid.Cid) error {
if s.ts {
s.mx.Lock()
defer s.mx.Unlock()
}
if s.bf == nil {
return errMarkSetClosed
}
s.bf.Add(s.saltedKey(cid))
return nil
}
func (s *BloomMarkSet) Has(cid cid.Cid) (bool, error) {
if s.ts {
s.mx.RLock()
defer s.mx.RUnlock()
}
if s.bf == nil {
return false, errMarkSetClosed
}
return s.bf.Has(s.saltedKey(cid)), nil
}
func (s *BloomMarkSet) Close() error {
if s.ts {
s.mx.Lock()
defer s.mx.Unlock()
}
s.bf = nil
return nil
}
func (s *BloomMarkSet) SetConcurrent() {
s.ts = true
}
+21 -235
View File
@@ -1,20 +1,12 @@
package splitstore package splitstore
import ( import (
"bufio"
"io"
"os"
"path/filepath"
"sync" "sync"
"golang.org/x/xerrors"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
) )
type MapMarkSetEnv struct { type MapMarkSetEnv struct{}
path string
}
var _ MarkSetEnv = (*MapMarkSetEnv)(nil) var _ MarkSetEnv = (*MapMarkSetEnv)(nil)
@@ -22,194 +14,44 @@ type MapMarkSet struct {
mx sync.RWMutex mx sync.RWMutex
set map[string]struct{} set map[string]struct{}
persist bool ts bool
file *os.File
buf *bufio.Writer
path string
} }
var _ MarkSet = (*MapMarkSet)(nil) var _ MarkSet = (*MapMarkSet)(nil)
func NewMapMarkSetEnv(path string) (*MapMarkSetEnv, error) { func NewMapMarkSetEnv() (*MapMarkSetEnv, error) {
msPath := filepath.Join(path, "markset.map") return &MapMarkSetEnv{}, nil
err := os.MkdirAll(msPath, 0755) //nolint:gosec
if err != nil {
return nil, xerrors.Errorf("error creating markset directory: %w", err)
}
return &MapMarkSetEnv{path: msPath}, nil
} }
func (e *MapMarkSetEnv) New(name string, sizeHint int64) (MarkSet, error) { func (e *MapMarkSetEnv) Create(name string, sizeHint int64) (MarkSet, error) {
path := filepath.Join(e.path, name)
return &MapMarkSet{ return &MapMarkSet{
set: make(map[string]struct{}, sizeHint), set: make(map[string]struct{}, sizeHint),
path: path,
}, nil }, nil
} }
func (e *MapMarkSetEnv) Recover(name string) (MarkSet, error) {
path := filepath.Join(e.path, name)
s := &MapMarkSet{
set: make(map[string]struct{}),
path: path,
}
in, err := os.Open(path)
if err != nil {
return nil, xerrors.Errorf("error opening markset file for read: %w", err)
}
defer in.Close() //nolint:errcheck
// wrap a buffered reader to make this faster
buf := bufio.NewReader(in)
for {
var sz byte
if sz, err = buf.ReadByte(); err != nil {
break
}
key := make([]byte, int(sz))
if _, err = io.ReadFull(buf, key); err != nil {
break
}
s.set[string(key)] = struct{}{}
}
if err != io.EOF {
return nil, xerrors.Errorf("error reading markset file: %w", err)
}
file, err := os.OpenFile(s.path, os.O_WRONLY|os.O_APPEND, 0)
if err != nil {
return nil, xerrors.Errorf("error opening markset file for write: %w", err)
}
s.persist = true
s.file = file
s.buf = bufio.NewWriter(file)
return s, nil
}
func (e *MapMarkSetEnv) Close() error { func (e *MapMarkSetEnv) Close() error {
return nil return nil
} }
func (s *MapMarkSet) BeginCriticalSection() error { func (s *MapMarkSet) Mark(cid cid.Cid) error {
s.mx.Lock() if s.ts {
defer s.mx.Unlock() s.mx.Lock()
defer s.mx.Unlock()
}
if s.set == nil { if s.set == nil {
return errMarkSetClosed return errMarkSetClosed
} }
if s.persist { s.set[string(cid.Hash())] = struct{}{}
return nil
}
file, err := os.OpenFile(s.path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
return xerrors.Errorf("error opening markset file: %w", err)
}
// wrap a buffered writer to make this faster
s.buf = bufio.NewWriter(file)
for key := range s.set {
if err := s.writeKey([]byte(key), false); err != nil {
_ = file.Close()
s.buf = nil
return err
}
}
if err := s.buf.Flush(); err != nil {
_ = file.Close()
s.buf = nil
return xerrors.Errorf("error flushing markset file buffer: %w", err)
}
s.file = file
s.persist = true
return nil
}
func (s *MapMarkSet) EndCriticalSection() {
s.mx.Lock()
defer s.mx.Unlock()
if !s.persist {
return
}
_ = s.file.Close()
_ = os.Remove(s.path)
s.file = nil
s.buf = nil
s.persist = false
}
func (s *MapMarkSet) Mark(c cid.Cid) error {
s.mx.Lock()
defer s.mx.Unlock()
if s.set == nil {
return errMarkSetClosed
}
hash := c.Hash()
s.set[string(hash)] = struct{}{}
if s.persist {
if err := s.writeKey(hash, true); err != nil {
return err
}
if err := s.file.Sync(); err != nil {
return xerrors.Errorf("error syncing markset: %w", err)
}
}
return nil
}
func (s *MapMarkSet) MarkMany(batch []cid.Cid) error {
s.mx.Lock()
defer s.mx.Unlock()
if s.set == nil {
return errMarkSetClosed
}
for _, c := range batch {
hash := c.Hash()
s.set[string(hash)] = struct{}{}
if s.persist {
if err := s.writeKey(hash, false); err != nil {
return err
}
}
}
if s.persist {
if err := s.buf.Flush(); err != nil {
return xerrors.Errorf("error flushing markset buffer to disk: %w", err)
}
if err := s.file.Sync(); err != nil {
return xerrors.Errorf("error syncing markset: %w", err)
}
}
return nil return nil
} }
func (s *MapMarkSet) Has(cid cid.Cid) (bool, error) { func (s *MapMarkSet) Has(cid cid.Cid) (bool, error) {
s.mx.RLock() if s.ts {
defer s.mx.RUnlock() s.mx.RLock()
defer s.mx.RUnlock()
}
if s.set == nil { if s.set == nil {
return false, errMarkSetClosed return false, errMarkSetClosed
@@ -219,71 +61,15 @@ func (s *MapMarkSet) Has(cid cid.Cid) (bool, error) {
return ok, nil return ok, nil
} }
func (s *MapMarkSet) Visit(c cid.Cid) (bool, error) {
s.mx.Lock()
defer s.mx.Unlock()
if s.set == nil {
return false, errMarkSetClosed
}
hash := c.Hash()
key := string(hash)
if _, ok := s.set[key]; ok {
return false, nil
}
s.set[key] = struct{}{}
if s.persist {
if err := s.writeKey(hash, true); err != nil {
return false, err
}
if err := s.file.Sync(); err != nil {
return false, xerrors.Errorf("error syncing markset: %w", err)
}
}
return true, nil
}
func (s *MapMarkSet) Close() error { func (s *MapMarkSet) Close() error {
s.mx.Lock() if s.ts {
defer s.mx.Unlock() s.mx.Lock()
defer s.mx.Unlock()
if s.set == nil {
return nil
} }
s.set = nil s.set = nil
if s.file != nil {
if err := s.file.Close(); err != nil {
log.Warnf("error closing markset file: %s", err)
}
if !s.persist {
if err := os.Remove(s.path); err != nil {
log.Warnf("error removing markset file: %s", err)
}
}
}
return nil return nil
} }
func (s *MapMarkSet) writeKey(k []byte, flush bool) error { func (s *MapMarkSet) SetConcurrent() {
if err := s.buf.WriteByte(byte(len(k))); err != nil { s.ts = true
return xerrors.Errorf("error writing markset key length to disk: %w", err)
}
if _, err := s.buf.Write(k); err != nil {
return xerrors.Errorf("error writing markset key to disk: %w", err)
}
if flush {
if err := s.buf.Flush(); err != nil {
return xerrors.Errorf("error flushing markset buffer to disk: %w", err)
}
}
return nil
} }
+15 -385
View File
@@ -1,7 +1,7 @@
//stm: #unit
package splitstore package splitstore
import ( import (
"io/ioutil"
"testing" "testing"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
@@ -9,32 +9,29 @@ import (
) )
func TestMapMarkSet(t *testing.T) { func TestMapMarkSet(t *testing.T) {
//stm: @SPLITSTORE_MARKSET_CREATE_001, @SPLITSTORE_MARKSET_HAS_001, @@SPLITSTORE_MARKSET_MARK_001
//stm: @SPLITSTORE_MARKSET_CLOSE_001, @SPLITSTORE_MARKSET_CREATE_VISITOR_001
testMarkSet(t, "map") testMarkSet(t, "map")
testMarkSetRecovery(t, "map") }
testMarkSetMarkMany(t, "map")
testMarkSetVisitor(t, "map") func TestBloomMarkSet(t *testing.T) {
testMarkSetVisitorRecovery(t, "map") testMarkSet(t, "bloom")
} }
func TestBadgerMarkSet(t *testing.T) { func TestBadgerMarkSet(t *testing.T) {
//stm: @SPLITSTORE_MARKSET_CREATE_001, @SPLITSTORE_MARKSET_HAS_001, @@SPLITSTORE_MARKSET_MARK_001
//stm: @SPLITSTORE_MARKSET_CLOSE_001, @SPLITSTORE_MARKSET_CREATE_VISITOR_001
bs := badgerMarkSetBatchSize bs := badgerMarkSetBatchSize
badgerMarkSetBatchSize = 1 badgerMarkSetBatchSize = 1
t.Cleanup(func() { t.Cleanup(func() {
badgerMarkSetBatchSize = bs badgerMarkSetBatchSize = bs
}) })
testMarkSet(t, "badger") testMarkSet(t, "badger")
testMarkSetRecovery(t, "badger")
testMarkSetMarkMany(t, "badger")
testMarkSetVisitor(t, "badger")
testMarkSetVisitorRecovery(t, "badger")
} }
func testMarkSet(t *testing.T, lsType string) { func testMarkSet(t *testing.T, lsType string) {
path := t.TempDir() t.Helper()
path, err := ioutil.TempDir("", "sweep-test.*")
if err != nil {
t.Fatal(err)
}
env, err := OpenMarkSetEnv(path, lsType) env, err := OpenMarkSetEnv(path, lsType)
if err != nil { if err != nil {
@@ -42,13 +39,12 @@ func testMarkSet(t *testing.T, lsType string) {
} }
defer env.Close() //nolint:errcheck defer env.Close() //nolint:errcheck
// stm: @SPLITSTORE_MARKSET_CREATE_001 hotSet, err := env.Create("hot", 0)
hotSet, err := env.New("hot", 0)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
coldSet, err := env.New("cold", 0) coldSet, err := env.Create("cold", 0)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -62,9 +58,7 @@ func testMarkSet(t *testing.T, lsType string) {
return cid.NewCidV1(cid.Raw, h) return cid.NewCidV1(cid.Raw, h)
} }
// stm: @SPLITSTORE_MARKSET_HAS_001
mustHave := func(s MarkSet, cid cid.Cid) { mustHave := func(s MarkSet, cid cid.Cid) {
t.Helper()
has, err := s.Has(cid) has, err := s.Has(cid)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -76,7 +70,6 @@ func testMarkSet(t *testing.T, lsType string) {
} }
mustNotHave := func(s MarkSet, cid cid.Cid) { mustNotHave := func(s MarkSet, cid cid.Cid) {
t.Helper()
has, err := s.Has(cid) has, err := s.Has(cid)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -92,7 +85,6 @@ func testMarkSet(t *testing.T, lsType string) {
k3 := makeCid("c") k3 := makeCid("c")
k4 := makeCid("d") k4 := makeCid("d")
// stm: @SPLITSTORE_MARKSET_MARK_001
hotSet.Mark(k1) //nolint hotSet.Mark(k1) //nolint
hotSet.Mark(k2) //nolint hotSet.Mark(k2) //nolint
coldSet.Mark(k3) //nolint coldSet.Mark(k3) //nolint
@@ -119,12 +111,12 @@ func testMarkSet(t *testing.T, lsType string) {
t.Fatal(err) t.Fatal(err)
} }
hotSet, err = env.New("hot", 0) hotSet, err = env.Create("hot", 0)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
coldSet, err = env.New("cold", 0) coldSet, err = env.Create("cold", 0)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -143,7 +135,6 @@ func testMarkSet(t *testing.T, lsType string) {
mustNotHave(coldSet, k3) mustNotHave(coldSet, k3)
mustNotHave(coldSet, k4) mustNotHave(coldSet, k4)
//stm: @SPLITSTORE_MARKSET_CLOSE_001
err = hotSet.Close() err = hotSet.Close()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -154,364 +145,3 @@ func testMarkSet(t *testing.T, lsType string) {
t.Fatal(err) t.Fatal(err)
} }
} }
func testMarkSetVisitor(t *testing.T, lsType string) {
path := t.TempDir()
env, err := OpenMarkSetEnv(path, lsType)
if err != nil {
t.Fatal(err)
}
defer env.Close() //nolint:errcheck
//stm: @SPLITSTORE_MARKSET_CREATE_VISITOR_001
visitor, err := env.New("test", 0)
if err != nil {
t.Fatal(err)
}
defer visitor.Close() //nolint:errcheck
makeCid := func(key string) cid.Cid {
h, err := multihash.Sum([]byte(key), multihash.SHA2_256, -1)
if err != nil {
t.Fatal(err)
}
return cid.NewCidV1(cid.Raw, h)
}
mustVisit := func(v ObjectVisitor, cid cid.Cid) {
visit, err := v.Visit(cid)
if err != nil {
t.Fatal(err)
}
if !visit {
t.Fatal("object should be visited")
}
}
mustNotVisit := func(v ObjectVisitor, cid cid.Cid) {
visit, err := v.Visit(cid)
if err != nil {
t.Fatal(err)
}
if visit {
t.Fatal("unexpected visit")
}
}
k1 := makeCid("a")
k2 := makeCid("b")
k3 := makeCid("c")
k4 := makeCid("d")
mustVisit(visitor, k1)
mustVisit(visitor, k2)
mustVisit(visitor, k3)
mustVisit(visitor, k4)
mustNotVisit(visitor, k1)
mustNotVisit(visitor, k2)
mustNotVisit(visitor, k3)
mustNotVisit(visitor, k4)
}
func testMarkSetVisitorRecovery(t *testing.T, lsType string) {
path := t.TempDir()
env, err := OpenMarkSetEnv(path, lsType)
if err != nil {
t.Fatal(err)
}
defer env.Close() //nolint:errcheck
visitor, err := env.New("test", 0)
if err != nil {
t.Fatal(err)
}
defer visitor.Close() //nolint:errcheck
makeCid := func(key string) cid.Cid {
h, err := multihash.Sum([]byte(key), multihash.SHA2_256, -1)
if err != nil {
t.Fatal(err)
}
return cid.NewCidV1(cid.Raw, h)
}
mustVisit := func(v ObjectVisitor, cid cid.Cid) {
visit, err := v.Visit(cid)
if err != nil {
t.Fatal(err)
}
if !visit {
t.Fatal("object should be visited")
}
}
mustNotVisit := func(v ObjectVisitor, cid cid.Cid) {
visit, err := v.Visit(cid)
if err != nil {
t.Fatal(err)
}
if visit {
t.Fatal("unexpected visit")
}
}
k1 := makeCid("a")
k2 := makeCid("b")
k3 := makeCid("c")
k4 := makeCid("d")
mustVisit(visitor, k1)
mustVisit(visitor, k2)
if err := visitor.BeginCriticalSection(); err != nil {
t.Fatal(err)
}
mustVisit(visitor, k3)
mustVisit(visitor, k4)
mustNotVisit(visitor, k1)
mustNotVisit(visitor, k2)
mustNotVisit(visitor, k3)
mustNotVisit(visitor, k4)
if err := visitor.Close(); err != nil {
t.Fatal(err)
}
visitor, err = env.Recover("test")
if err != nil {
t.Fatal(err)
}
mustNotVisit(visitor, k1)
mustNotVisit(visitor, k2)
mustNotVisit(visitor, k3)
mustNotVisit(visitor, k4)
visitor.EndCriticalSection()
if err := visitor.Close(); err != nil {
t.Fatal(err)
}
_, err = env.Recover("test")
if err == nil {
t.Fatal("expected recovery to fail")
}
}
func testMarkSetRecovery(t *testing.T, lsType string) {
path := t.TempDir()
env, err := OpenMarkSetEnv(path, lsType)
if err != nil {
t.Fatal(err)
}
defer env.Close() //nolint:errcheck
markSet, err := env.New("test", 0)
if err != nil {
t.Fatal(err)
}
makeCid := func(key string) cid.Cid {
h, err := multihash.Sum([]byte(key), multihash.SHA2_256, -1)
if err != nil {
t.Fatal(err)
}
return cid.NewCidV1(cid.Raw, h)
}
mustHave := func(s MarkSet, cid cid.Cid) {
t.Helper()
has, err := s.Has(cid)
if err != nil {
t.Fatal(err)
}
if !has {
t.Fatal("mark not found")
}
}
mustNotHave := func(s MarkSet, cid cid.Cid) {
t.Helper()
has, err := s.Has(cid)
if err != nil {
t.Fatal(err)
}
if has {
t.Fatal("unexpected mark")
}
}
k1 := makeCid("a")
k2 := makeCid("b")
k3 := makeCid("c")
k4 := makeCid("d")
if err := markSet.Mark(k1); err != nil {
t.Fatal(err)
}
if err := markSet.Mark(k2); err != nil {
t.Fatal(err)
}
mustHave(markSet, k1)
mustHave(markSet, k2)
mustNotHave(markSet, k3)
mustNotHave(markSet, k4)
if err := markSet.BeginCriticalSection(); err != nil {
t.Fatal(err)
}
if err := markSet.Mark(k3); err != nil {
t.Fatal(err)
}
if err := markSet.Mark(k4); err != nil {
t.Fatal(err)
}
mustHave(markSet, k1)
mustHave(markSet, k2)
mustHave(markSet, k3)
mustHave(markSet, k4)
if err := markSet.Close(); err != nil {
t.Fatal(err)
}
markSet, err = env.Recover("test")
if err != nil {
t.Fatal(err)
}
mustHave(markSet, k1)
mustHave(markSet, k2)
mustHave(markSet, k3)
mustHave(markSet, k4)
markSet.EndCriticalSection()
if err := markSet.Close(); err != nil {
t.Fatal(err)
}
_, err = env.Recover("test")
if err == nil {
t.Fatal("expected recovery to fail")
}
}
func testMarkSetMarkMany(t *testing.T, lsType string) {
path := t.TempDir()
env, err := OpenMarkSetEnv(path, lsType)
if err != nil {
t.Fatal(err)
}
defer env.Close() //nolint:errcheck
markSet, err := env.New("test", 0)
if err != nil {
t.Fatal(err)
}
makeCid := func(key string) cid.Cid {
h, err := multihash.Sum([]byte(key), multihash.SHA2_256, -1)
if err != nil {
t.Fatal(err)
}
return cid.NewCidV1(cid.Raw, h)
}
mustHave := func(s MarkSet, cid cid.Cid) {
t.Helper()
has, err := s.Has(cid)
if err != nil {
t.Fatal(err)
}
if !has {
t.Fatal("mark not found")
}
}
mustNotHave := func(s MarkSet, cid cid.Cid) {
t.Helper()
has, err := s.Has(cid)
if err != nil {
t.Fatal(err)
}
if has {
t.Fatal("unexpected mark")
}
}
k1 := makeCid("a")
k2 := makeCid("b")
k3 := makeCid("c")
k4 := makeCid("d")
if err := markSet.MarkMany([]cid.Cid{k1, k2}); err != nil {
t.Fatal(err)
}
mustHave(markSet, k1)
mustHave(markSet, k2)
mustNotHave(markSet, k3)
mustNotHave(markSet, k4)
if err := markSet.BeginCriticalSection(); err != nil {
t.Fatal(err)
}
if err := markSet.MarkMany([]cid.Cid{k3, k4}); err != nil {
t.Fatal(err)
}
mustHave(markSet, k1)
mustHave(markSet, k2)
mustHave(markSet, k3)
mustHave(markSet, k4)
if err := markSet.Close(); err != nil {
t.Fatal(err)
}
markSet, err = env.Recover("test")
if err != nil {
t.Fatal(err)
}
mustHave(markSet, k1)
mustHave(markSet, k2)
mustHave(markSet, k3)
mustHave(markSet, k4)
markSet.EndCriticalSection()
if err := markSet.Close(); err != nil {
t.Fatal(err)
}
_, err = env.Recover("test")
if err == nil {
t.Fatal("expected recovery to fail")
}
}
+30 -177
View File
@@ -18,8 +18,6 @@ import (
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
bstore "github.com/filecoin-project/lotus/blockstore" bstore "github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/metrics"
@@ -49,9 +47,6 @@ var (
enableDebugLog = false enableDebugLog = false
// set this to true if you want to track origin stack traces in the write log // set this to true if you want to track origin stack traces in the write log
enableDebugLogWriteTraces = false enableDebugLogWriteTraces = false
// upgradeBoundary is the boundary before and after an upgrade where we suppress compaction
upgradeBoundary = build.Finality
) )
func init() { func init() {
@@ -103,12 +98,6 @@ type ChainAccessor interface {
SubscribeHeadChanges(change func(revert []*types.TipSet, apply []*types.TipSet) error) SubscribeHeadChanges(change func(revert []*types.TipSet, apply []*types.TipSet) error)
} }
// upgradeRange is a precomputed epoch range during which we shouldn't compact so as to not
// interfere with an upgrade
type upgradeRange struct {
start, end abi.ChainEpoch
}
// hotstore is the interface that must be satisfied by the hot blockstore; it is an extension // hotstore is the interface that must be satisfied by the hot blockstore; it is an extension
// of the Blockstore interface with the traits we need for compaction. // of the Blockstore interface with the traits we need for compaction.
type hotstore interface { type hotstore interface {
@@ -129,13 +118,13 @@ type SplitStore struct {
headChangeMx sync.Mutex headChangeMx sync.Mutex
coldPurgeSize int
chain ChainAccessor chain ChainAccessor
ds dstore.Datastore ds dstore.Datastore
cold bstore.Blockstore cold bstore.Blockstore
hot hotstore hot hotstore
upgrades []upgradeRange
markSetEnv MarkSetEnv markSetEnv MarkSetEnv
markSetSize int64 markSetSize int64
@@ -153,20 +142,10 @@ type SplitStore struct {
txnViews int txnViews int
txnViewsWaiting bool txnViewsWaiting bool
txnActive bool txnActive bool
txnProtect MarkSet
txnRefsMx sync.Mutex txnRefsMx sync.Mutex
txnRefs map[cid.Cid]struct{} txnRefs map[cid.Cid]struct{}
txnMissing map[cid.Cid]struct{} txnMissing map[cid.Cid]struct{}
txnMarkSet MarkSet
txnSyncMx sync.Mutex
txnSyncCond sync.Cond
txnSync bool
// background cold object reification
reifyWorkers sync.WaitGroup
reifyMx sync.Mutex
reifyCond sync.Cond
reifyPend map[cid.Cid]struct{}
reifyInProgress map[cid.Cid]struct{}
// registered protectors // registered protectors
protectors []func(func(cid.Cid) error) error protectors []func(func(cid.Cid) error) error
@@ -203,16 +182,13 @@ func Open(path string, ds dstore.Datastore, hot, cold bstore.Blockstore, cfg *Co
cold: cold, cold: cold,
hot: hots, hot: hots,
markSetEnv: markSetEnv, markSetEnv: markSetEnv,
coldPurgeSize: defaultColdPurgeSize,
} }
ss.txnViewsCond.L = &ss.txnViewsMx ss.txnViewsCond.L = &ss.txnViewsMx
ss.txnSyncCond.L = &ss.txnSyncMx
ss.ctx, ss.cancel = context.WithCancel(context.Background()) ss.ctx, ss.cancel = context.WithCancel(context.Background())
ss.reifyCond.L = &ss.reifyMx
ss.reifyPend = make(map[cid.Cid]struct{})
ss.reifyInProgress = make(map[cid.Cid]struct{})
if enableDebugLog { if enableDebugLog {
ss.debug, err = openDebugLog(path) ss.debug, err = openDebugLog(path)
if err != nil { if err != nil {
@@ -220,29 +196,21 @@ func Open(path string, ds dstore.Datastore, hot, cold bstore.Blockstore, cfg *Co
} }
} }
if ss.checkpointExists() {
log.Info("found compaction checkpoint; resuming compaction")
if err := ss.completeCompaction(); err != nil {
markSetEnv.Close() //nolint:errcheck
return nil, xerrors.Errorf("error resuming compaction: %w", err)
}
}
return ss, nil return ss, nil
} }
// Blockstore interface // Blockstore interface
func (s *SplitStore) DeleteBlock(_ context.Context, _ cid.Cid) error { func (s *SplitStore) DeleteBlock(_ cid.Cid) error {
// afaict we don't seem to be using this method, so it's not implemented // afaict we don't seem to be using this method, so it's not implemented
return errors.New("DeleteBlock not implemented on SplitStore; don't do this Luke!") //nolint return errors.New("DeleteBlock not implemented on SplitStore; don't do this Luke!") //nolint
} }
func (s *SplitStore) DeleteMany(_ context.Context, _ []cid.Cid) error { func (s *SplitStore) DeleteMany(_ []cid.Cid) error {
// afaict we don't seem to be using this method, so it's not implemented // afaict we don't seem to be using this method, so it's not implemented
return errors.New("DeleteMany not implemented on SplitStore; don't do this Luke!") //nolint return errors.New("DeleteMany not implemented on SplitStore; don't do this Luke!") //nolint
} }
func (s *SplitStore) Has(ctx context.Context, cid cid.Cid) (bool, error) { func (s *SplitStore) Has(cid cid.Cid) (bool, error) {
if isIdentiyCid(cid) { if isIdentiyCid(cid) {
return true, nil return true, nil
} }
@@ -250,21 +218,7 @@ func (s *SplitStore) Has(ctx context.Context, cid cid.Cid) (bool, error) {
s.txnLk.RLock() s.txnLk.RLock()
defer s.txnLk.RUnlock() defer s.txnLk.RUnlock()
// critical section has, err := s.hot.Has(cid)
if s.txnMarkSet != nil {
has, err := s.txnMarkSet.Has(cid)
if err != nil {
return false, err
}
if has {
return s.has(cid)
}
return s.cold.Has(ctx, cid)
}
has, err := s.hot.Has(ctx, cid)
if err != nil { if err != nil {
return has, err return has, err
@@ -275,16 +229,10 @@ func (s *SplitStore) Has(ctx context.Context, cid cid.Cid) (bool, error) {
return true, nil return true, nil
} }
has, err = s.cold.Has(ctx, cid) return s.cold.Has(cid)
if has && bstore.IsHotView(ctx) {
s.reifyColdObject(cid)
}
return has, err
} }
func (s *SplitStore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) { func (s *SplitStore) Get(cid cid.Cid) (blocks.Block, error) {
if isIdentiyCid(cid) { if isIdentiyCid(cid) {
data, err := decodeIdentityCid(cid) data, err := decodeIdentityCid(cid)
if err != nil { if err != nil {
@@ -297,21 +245,7 @@ func (s *SplitStore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error)
s.txnLk.RLock() s.txnLk.RLock()
defer s.txnLk.RUnlock() defer s.txnLk.RUnlock()
// critical section blk, err := s.hot.Get(cid)
if s.txnMarkSet != nil {
has, err := s.txnMarkSet.Has(cid)
if err != nil {
return nil, err
}
if has {
return s.get(cid)
}
return s.cold.Get(ctx, cid)
}
blk, err := s.hot.Get(ctx, cid)
switch err { switch err {
case nil: case nil:
@@ -323,13 +257,10 @@ func (s *SplitStore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error)
s.debug.LogReadMiss(cid) s.debug.LogReadMiss(cid)
} }
blk, err = s.cold.Get(ctx, cid) blk, err = s.cold.Get(cid)
if err == nil { if err == nil {
if bstore.IsHotView(ctx) {
s.reifyColdObject(cid)
}
stats.Record(s.ctx, metrics.SplitstoreMiss.M(1)) stats.Record(s.ctx, metrics.SplitstoreMiss.M(1))
} }
return blk, err return blk, err
@@ -338,7 +269,7 @@ func (s *SplitStore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error)
} }
} }
func (s *SplitStore) GetSize(ctx context.Context, cid cid.Cid) (int, error) { func (s *SplitStore) GetSize(cid cid.Cid) (int, error) {
if isIdentiyCid(cid) { if isIdentiyCid(cid) {
data, err := decodeIdentityCid(cid) data, err := decodeIdentityCid(cid)
if err != nil { if err != nil {
@@ -351,21 +282,7 @@ func (s *SplitStore) GetSize(ctx context.Context, cid cid.Cid) (int, error) {
s.txnLk.RLock() s.txnLk.RLock()
defer s.txnLk.RUnlock() defer s.txnLk.RUnlock()
// critical section size, err := s.hot.GetSize(cid)
if s.txnMarkSet != nil {
has, err := s.txnMarkSet.Has(cid)
if err != nil {
return 0, err
}
if has {
return s.getSize(cid)
}
return s.cold.GetSize(ctx, cid)
}
size, err := s.hot.GetSize(ctx, cid)
switch err { switch err {
case nil: case nil:
@@ -377,12 +294,8 @@ func (s *SplitStore) GetSize(ctx context.Context, cid cid.Cid) (int, error) {
s.debug.LogReadMiss(cid) s.debug.LogReadMiss(cid)
} }
size, err = s.cold.GetSize(ctx, cid) size, err = s.cold.GetSize(cid)
if err == nil { if err == nil {
if bstore.IsHotView(ctx) {
s.reifyColdObject(cid)
}
stats.Record(s.ctx, metrics.SplitstoreMiss.M(1)) stats.Record(s.ctx, metrics.SplitstoreMiss.M(1))
} }
return size, err return size, err
@@ -392,7 +305,7 @@ func (s *SplitStore) GetSize(ctx context.Context, cid cid.Cid) (int, error) {
} }
} }
func (s *SplitStore) Put(ctx context.Context, blk blocks.Block) error { func (s *SplitStore) Put(blk blocks.Block) error {
if isIdentiyCid(blk.Cid()) { if isIdentiyCid(blk.Cid()) {
return nil return nil
} }
@@ -400,24 +313,18 @@ func (s *SplitStore) Put(ctx context.Context, blk blocks.Block) error {
s.txnLk.RLock() s.txnLk.RLock()
defer s.txnLk.RUnlock() defer s.txnLk.RUnlock()
err := s.hot.Put(ctx, blk) err := s.hot.Put(blk)
if err != nil { if err != nil {
return err return err
} }
s.debug.LogWrite(blk) s.debug.LogWrite(blk)
// critical section
if s.txnMarkSet != nil {
s.markLiveRefs([]cid.Cid{blk.Cid()})
return nil
}
s.trackTxnRef(blk.Cid()) s.trackTxnRef(blk.Cid())
return nil return nil
} }
func (s *SplitStore) PutMany(ctx context.Context, blks []blocks.Block) error { func (s *SplitStore) PutMany(blks []blocks.Block) error {
// filter identites // filter identites
idcids := 0 idcids := 0
for _, blk := range blks { for _, blk := range blks {
@@ -451,19 +358,13 @@ func (s *SplitStore) PutMany(ctx context.Context, blks []blocks.Block) error {
s.txnLk.RLock() s.txnLk.RLock()
defer s.txnLk.RUnlock() defer s.txnLk.RUnlock()
err := s.hot.PutMany(ctx, blks) err := s.hot.PutMany(blks)
if err != nil { if err != nil {
return err return err
} }
s.debug.LogWriteMany(blks) s.debug.LogWriteMany(blks)
// critical section
if s.txnMarkSet != nil {
s.markLiveRefs(batch)
return nil
}
s.trackTxnRefMany(batch) s.trackTxnRefMany(batch)
return nil return nil
} }
@@ -513,7 +414,7 @@ func (s *SplitStore) HashOnRead(enabled bool) {
s.cold.HashOnRead(enabled) s.cold.HashOnRead(enabled)
} }
func (s *SplitStore) View(ctx context.Context, cid cid.Cid, cb func([]byte) error) error { func (s *SplitStore) View(cid cid.Cid, cb func([]byte) error) error {
if isIdentiyCid(cid) { if isIdentiyCid(cid) {
data, err := decodeIdentityCid(cid) data, err := decodeIdentityCid(cid)
if err != nil { if err != nil {
@@ -523,23 +424,6 @@ func (s *SplitStore) View(ctx context.Context, cid cid.Cid, cb func([]byte) erro
return cb(data) return cb(data)
} }
// critical section
s.txnLk.RLock() // the lock is released in protectView if we are not in critical section
if s.txnMarkSet != nil {
has, err := s.txnMarkSet.Has(cid)
s.txnLk.RUnlock()
if err != nil {
return err
}
if has {
return s.view(cid, cb)
}
return s.cold.View(ctx, cid, cb)
}
// views are (optimistically) protected two-fold: // views are (optimistically) protected two-fold:
// - if there is an active transaction, then the reference is protected. // - if there is an active transaction, then the reference is protected.
// - if there is no active transaction, active views are tracked in a // - if there is no active transaction, active views are tracked in a
@@ -551,19 +435,15 @@ func (s *SplitStore) View(ctx context.Context, cid cid.Cid, cb func([]byte) erro
s.protectView(cid) s.protectView(cid)
defer s.viewDone() defer s.viewDone()
err := s.hot.View(ctx, cid, cb) err := s.hot.View(cid, cb)
switch err { switch err {
case bstore.ErrNotFound: case bstore.ErrNotFound:
if s.isWarm() { if s.isWarm() {
s.debug.LogReadMiss(cid) s.debug.LogReadMiss(cid)
} }
err = s.cold.View(ctx, cid, cb) err = s.cold.View(cid, cb)
if err == nil { if err == nil {
if bstore.IsHotView(ctx) {
s.reifyColdObject(cid)
}
stats.Record(s.ctx, metrics.SplitstoreMiss.M(1)) stats.Record(s.ctx, metrics.SplitstoreMiss.M(1))
} }
return err return err
@@ -580,33 +460,16 @@ func (s *SplitStore) isWarm() bool {
} }
// State tracking // State tracking
func (s *SplitStore) Start(chain ChainAccessor, us stmgr.UpgradeSchedule) error { func (s *SplitStore) Start(chain ChainAccessor) error {
s.chain = chain s.chain = chain
curTs := chain.GetHeaviestTipSet() curTs := chain.GetHeaviestTipSet()
// precompute the upgrade boundaries
s.upgrades = make([]upgradeRange, 0, len(us))
for _, upgrade := range us {
boundary := upgrade.Height
for _, pre := range upgrade.PreMigrations {
preMigrationBoundary := upgrade.Height - pre.StartWithin
if preMigrationBoundary < boundary {
boundary = preMigrationBoundary
}
}
upgradeStart := boundary - upgradeBoundary
upgradeEnd := upgrade.Height + upgradeBoundary
s.upgrades = append(s.upgrades, upgradeRange{start: upgradeStart, end: upgradeEnd})
}
// should we warmup // should we warmup
warmup := false warmup := false
// load base epoch from metadata ds // load base epoch from metadata ds
// if none, then use current epoch because it's a fresh start // if none, then use current epoch because it's a fresh start
bs, err := s.ds.Get(s.ctx, baseEpochKey) bs, err := s.ds.Get(baseEpochKey)
switch err { switch err {
case nil: case nil:
s.baseEpoch = bytesToEpoch(bs) s.baseEpoch = bytesToEpoch(bs)
@@ -627,7 +490,7 @@ func (s *SplitStore) Start(chain ChainAccessor, us stmgr.UpgradeSchedule) error
} }
// load warmup epoch from metadata ds // load warmup epoch from metadata ds
bs, err = s.ds.Get(s.ctx, warmupEpochKey) bs, err = s.ds.Get(warmupEpochKey)
switch err { switch err {
case nil: case nil:
s.warmupEpoch = bytesToEpoch(bs) s.warmupEpoch = bytesToEpoch(bs)
@@ -640,7 +503,7 @@ func (s *SplitStore) Start(chain ChainAccessor, us stmgr.UpgradeSchedule) error
} }
// load markSetSize from metadata ds to provide a size hint for marksets // load markSetSize from metadata ds to provide a size hint for marksets
bs, err = s.ds.Get(s.ctx, markSetSizeKey) bs, err = s.ds.Get(markSetSizeKey)
switch err { switch err {
case nil: case nil:
s.markSetSize = bytesToInt64(bs) s.markSetSize = bytesToInt64(bs)
@@ -651,7 +514,7 @@ func (s *SplitStore) Start(chain ChainAccessor, us stmgr.UpgradeSchedule) error
} }
// load compactionIndex from metadata ds to provide a hint as to when to perform moving gc // load compactionIndex from metadata ds to provide a hint as to when to perform moving gc
bs, err = s.ds.Get(s.ctx, compactionIndexKey) bs, err = s.ds.Get(compactionIndexKey)
switch err { switch err {
case nil: case nil:
s.compactionIndex = bytesToInt64(bs) s.compactionIndex = bytesToInt64(bs)
@@ -673,9 +536,6 @@ func (s *SplitStore) Start(chain ChainAccessor, us stmgr.UpgradeSchedule) error
} }
} }
// spawn the reifier
go s.reifyOrchestrator()
// watch the chain // watch the chain
chain.SubscribeHeadChanges(s.HeadChange) chain.SubscribeHeadChanges(s.HeadChange)
@@ -696,19 +556,12 @@ func (s *SplitStore) Close() error {
} }
if atomic.LoadInt32(&s.compacting) == 1 { if atomic.LoadInt32(&s.compacting) == 1 {
s.txnSyncMx.Lock()
s.txnSync = true
s.txnSyncCond.Broadcast()
s.txnSyncMx.Unlock()
log.Warn("close with ongoing compaction in progress; waiting for it to finish...") log.Warn("close with ongoing compaction in progress; waiting for it to finish...")
for atomic.LoadInt32(&s.compacting) == 1 { for atomic.LoadInt32(&s.compacting) == 1 {
time.Sleep(time.Second) time.Sleep(time.Second)
} }
} }
s.reifyCond.Broadcast()
s.reifyWorkers.Wait()
s.cancel() s.cancel()
return multierr.Combine(s.markSetEnv.Close(), s.debug.Close()) return multierr.Combine(s.markSetEnv.Close(), s.debug.Close())
} }
@@ -723,5 +576,5 @@ func (s *SplitStore) checkClosing() error {
func (s *SplitStore) setBaseEpoch(epoch abi.ChainEpoch) error { func (s *SplitStore) setBaseEpoch(epoch abi.ChainEpoch) error {
s.baseEpoch = epoch s.baseEpoch = epoch
return s.ds.Put(s.ctx, baseEpochKey, epochToBytes(epoch)) return s.ds.Put(baseEpochKey, epochToBytes(epoch))
} }
+8 -20
View File
@@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"sync"
"sync/atomic" "sync/atomic"
"time" "time"
@@ -68,10 +67,7 @@ func (s *SplitStore) doCheck(curTs *types.TipSet) error {
} }
defer output.Close() //nolint:errcheck defer output.Close() //nolint:errcheck
var mx sync.Mutex
write := func(format string, args ...interface{}) { write := func(format string, args ...interface{}) {
mx.Lock()
defer mx.Unlock()
_, err := fmt.Fprintf(output, format+"\n", args...) _, err := fmt.Fprintf(output, format+"\n", args...)
if err != nil { if err != nil {
log.Warnf("error writing check output: %s", err) log.Warnf("error writing check output: %s", err)
@@ -86,22 +82,14 @@ func (s *SplitStore) doCheck(curTs *types.TipSet) error {
write("compaction index: %d", s.compactionIndex) write("compaction index: %d", s.compactionIndex)
write("--") write("--")
coldCnt := new(int64) var coldCnt, missingCnt int64
missingCnt := new(int64) err = s.walkChain(curTs, boundaryEpoch, boundaryEpoch,
visitor, err := s.markSetEnv.New("check", 0)
if err != nil {
return xerrors.Errorf("error creating visitor: %w", err)
}
defer visitor.Close() //nolint
err = s.walkChain(curTs, boundaryEpoch, boundaryEpoch, visitor,
func(c cid.Cid) error { func(c cid.Cid) error {
if isUnitaryObject(c) { if isUnitaryObject(c) {
return errStopWalk return errStopWalk
} }
has, err := s.hot.Has(s.ctx, c) has, err := s.hot.Has(c)
if err != nil { if err != nil {
return xerrors.Errorf("error checking hotstore: %w", err) return xerrors.Errorf("error checking hotstore: %w", err)
} }
@@ -110,16 +98,16 @@ func (s *SplitStore) doCheck(curTs *types.TipSet) error {
return nil return nil
} }
has, err = s.cold.Has(s.ctx, c) has, err = s.cold.Has(c)
if err != nil { if err != nil {
return xerrors.Errorf("error checking coldstore: %w", err) return xerrors.Errorf("error checking coldstore: %w", err)
} }
if has { if has {
atomic.AddInt64(coldCnt, 1) coldCnt++
write("cold object reference: %s", c) write("cold object reference: %s", c)
} else { } else {
atomic.AddInt64(missingCnt, 1) missingCnt++
write("missing object reference: %s", c) write("missing object reference: %s", c)
return errStopWalk return errStopWalk
} }
@@ -133,9 +121,9 @@ func (s *SplitStore) doCheck(curTs *types.TipSet) error {
return err return err
} }
log.Infow("check done", "cold", *coldCnt, "missing", *missingCnt) log.Infow("check done", "cold", coldCnt, "missing", missingCnt)
write("--") write("--")
write("cold: %d missing: %d", *coldCnt, *missingCnt) write("cold: %d missing: %d", coldCnt, missingCnt)
write("DONE") write("DONE")
return nil return nil
File diff suppressed because it is too large Load Diff
+18 -18
View File
@@ -20,28 +20,28 @@ func (s *SplitStore) Expose() bstore.Blockstore {
return &exposedSplitStore{s: s} return &exposedSplitStore{s: s}
} }
func (es *exposedSplitStore) DeleteBlock(_ context.Context, _ cid.Cid) error { func (es *exposedSplitStore) DeleteBlock(_ cid.Cid) error {
return errors.New("DeleteBlock: operation not supported") return errors.New("DeleteBlock: operation not supported")
} }
func (es *exposedSplitStore) DeleteMany(_ context.Context, _ []cid.Cid) error { func (es *exposedSplitStore) DeleteMany(_ []cid.Cid) error {
return errors.New("DeleteMany: operation not supported") return errors.New("DeleteMany: operation not supported")
} }
func (es *exposedSplitStore) Has(ctx context.Context, c cid.Cid) (bool, error) { func (es *exposedSplitStore) Has(c cid.Cid) (bool, error) {
if isIdentiyCid(c) { if isIdentiyCid(c) {
return true, nil return true, nil
} }
has, err := es.s.hot.Has(ctx, c) has, err := es.s.hot.Has(c)
if has || err != nil { if has || err != nil {
return has, err return has, err
} }
return es.s.cold.Has(ctx, c) return es.s.cold.Has(c)
} }
func (es *exposedSplitStore) Get(ctx context.Context, c cid.Cid) (blocks.Block, error) { func (es *exposedSplitStore) Get(c cid.Cid) (blocks.Block, error) {
if isIdentiyCid(c) { if isIdentiyCid(c) {
data, err := decodeIdentityCid(c) data, err := decodeIdentityCid(c)
if err != nil { if err != nil {
@@ -51,16 +51,16 @@ func (es *exposedSplitStore) Get(ctx context.Context, c cid.Cid) (blocks.Block,
return blocks.NewBlockWithCid(data, c) return blocks.NewBlockWithCid(data, c)
} }
blk, err := es.s.hot.Get(ctx, c) blk, err := es.s.hot.Get(c)
switch err { switch err {
case bstore.ErrNotFound: case bstore.ErrNotFound:
return es.s.cold.Get(ctx, c) return es.s.cold.Get(c)
default: default:
return blk, err return blk, err
} }
} }
func (es *exposedSplitStore) GetSize(ctx context.Context, c cid.Cid) (int, error) { func (es *exposedSplitStore) GetSize(c cid.Cid) (int, error) {
if isIdentiyCid(c) { if isIdentiyCid(c) {
data, err := decodeIdentityCid(c) data, err := decodeIdentityCid(c)
if err != nil { if err != nil {
@@ -70,21 +70,21 @@ func (es *exposedSplitStore) GetSize(ctx context.Context, c cid.Cid) (int, error
return len(data), nil return len(data), nil
} }
size, err := es.s.hot.GetSize(ctx, c) size, err := es.s.hot.GetSize(c)
switch err { switch err {
case bstore.ErrNotFound: case bstore.ErrNotFound:
return es.s.cold.GetSize(ctx, c) return es.s.cold.GetSize(c)
default: default:
return size, err return size, err
} }
} }
func (es *exposedSplitStore) Put(ctx context.Context, blk blocks.Block) error { func (es *exposedSplitStore) Put(blk blocks.Block) error {
return es.s.Put(ctx, blk) return es.s.Put(blk)
} }
func (es *exposedSplitStore) PutMany(ctx context.Context, blks []blocks.Block) error { func (es *exposedSplitStore) PutMany(blks []blocks.Block) error {
return es.s.PutMany(ctx, blks) return es.s.PutMany(blks)
} }
func (es *exposedSplitStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) { func (es *exposedSplitStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
@@ -93,7 +93,7 @@ func (es *exposedSplitStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, e
func (es *exposedSplitStore) HashOnRead(enabled bool) {} func (es *exposedSplitStore) HashOnRead(enabled bool) {}
func (es *exposedSplitStore) View(ctx context.Context, c cid.Cid, f func([]byte) error) error { func (es *exposedSplitStore) View(c cid.Cid, f func([]byte) error) error {
if isIdentiyCid(c) { if isIdentiyCid(c) {
data, err := decodeIdentityCid(c) data, err := decodeIdentityCid(c)
if err != nil { if err != nil {
@@ -103,10 +103,10 @@ func (es *exposedSplitStore) View(ctx context.Context, c cid.Cid, f func([]byte)
return f(data) return f(data)
} }
err := es.s.hot.View(ctx, c, f) err := es.s.hot.View(c, f)
switch err { switch err {
case bstore.ErrNotFound: case bstore.ErrNotFound:
return es.s.cold.View(ctx, c, f) return es.s.cold.View(c, f)
default: default:
return err return err
-214
View File
@@ -1,214 +0,0 @@
package splitstore
import (
"errors"
"runtime"
"sync/atomic"
"golang.org/x/xerrors"
blocks "github.com/ipfs/go-block-format"
cid "github.com/ipfs/go-cid"
)
var (
errReifyLimit = errors.New("reification limit reached")
ReifyLimit = 16384
)
func (s *SplitStore) reifyColdObject(c cid.Cid) {
if !s.isWarm() {
return
}
if isUnitaryObject(c) {
return
}
s.reifyMx.Lock()
defer s.reifyMx.Unlock()
_, ok := s.reifyInProgress[c]
if ok {
return
}
s.reifyPend[c] = struct{}{}
s.reifyCond.Broadcast()
}
func (s *SplitStore) reifyOrchestrator() {
workers := runtime.NumCPU() / 4
if workers < 2 {
workers = 2
}
workch := make(chan cid.Cid, workers)
defer close(workch)
for i := 0; i < workers; i++ {
s.reifyWorkers.Add(1)
go s.reifyWorker(workch)
}
for {
s.reifyMx.Lock()
for len(s.reifyPend) == 0 && atomic.LoadInt32(&s.closing) == 0 {
s.reifyCond.Wait()
}
if atomic.LoadInt32(&s.closing) != 0 {
s.reifyMx.Unlock()
return
}
reifyPend := s.reifyPend
s.reifyPend = make(map[cid.Cid]struct{})
s.reifyMx.Unlock()
for c := range reifyPend {
select {
case workch <- c:
case <-s.ctx.Done():
return
}
}
}
}
func (s *SplitStore) reifyWorker(workch chan cid.Cid) {
defer s.reifyWorkers.Done()
for c := range workch {
s.doReify(c)
}
}
func (s *SplitStore) doReify(c cid.Cid) {
var toreify, totrack, toforget []cid.Cid
defer func() {
s.reifyMx.Lock()
defer s.reifyMx.Unlock()
for _, c := range toreify {
delete(s.reifyInProgress, c)
}
for _, c := range totrack {
delete(s.reifyInProgress, c)
}
for _, c := range toforget {
delete(s.reifyInProgress, c)
}
}()
s.txnLk.RLock()
defer s.txnLk.RUnlock()
count := 0
err := s.walkObjectIncomplete(c, newTmpVisitor(),
func(c cid.Cid) error {
if isUnitaryObject(c) {
return errStopWalk
}
count++
if count > ReifyLimit {
return errReifyLimit
}
s.reifyMx.Lock()
_, inProgress := s.reifyInProgress[c]
if !inProgress {
s.reifyInProgress[c] = struct{}{}
}
s.reifyMx.Unlock()
if inProgress {
return errStopWalk
}
has, err := s.hot.Has(s.ctx, c)
if err != nil {
return xerrors.Errorf("error checking hotstore: %w", err)
}
if has {
if s.txnMarkSet != nil {
hasMark, err := s.txnMarkSet.Has(c)
if err != nil {
log.Warnf("error checking markset: %s", err)
} else if hasMark {
toforget = append(toforget, c)
return errStopWalk
}
} else {
totrack = append(totrack, c)
return errStopWalk
}
}
toreify = append(toreify, c)
return nil
},
func(missing cid.Cid) error {
log.Warnf("missing reference while reifying %s: %s", c, missing)
return errStopWalk
})
if err != nil {
if xerrors.Is(err, errReifyLimit) {
log.Debug("reification aborted; reify limit reached")
return
}
log.Warnf("error walking cold object for reification (cid: %s): %s", c, err)
return
}
log.Debugf("reifying %d objects rooted at %s", len(toreify), c)
// this should not get too big, maybe some 100s of objects.
batch := make([]blocks.Block, 0, len(toreify))
for _, c := range toreify {
blk, err := s.cold.Get(s.ctx, c)
if err != nil {
log.Warnf("error retrieving cold object for reification (cid: %s): %s", c, err)
continue
}
if err := s.checkClosing(); err != nil {
return
}
batch = append(batch, blk)
}
if len(batch) > 0 {
err = s.hot.PutMany(s.ctx, batch)
if err != nil {
log.Warnf("error reifying cold object (cid: %s): %s", c, err)
return
}
}
if s.txnMarkSet != nil {
if len(toreify) > 0 {
if err := s.txnMarkSet.MarkMany(toreify); err != nil {
log.Warnf("error marking reified objects: %s", err)
}
}
if len(totrack) > 0 {
if err := s.txnMarkSet.MarkMany(totrack); err != nil {
log.Warnf("error marking tracked objects: %s", err)
}
}
} else {
// if txnActive is false these are noops
if len(toreify) > 0 {
s.trackTxnRefMany(toreify)
}
if len(totrack) > 0 {
s.trackTxnRefMany(totrack)
}
}
}
+30 -415
View File
@@ -1,11 +1,9 @@
//stm: #unit
package splitstore package splitstore
import ( import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"math/rand"
"sync" "sync"
"sync/atomic" "sync/atomic"
"testing" "testing"
@@ -13,7 +11,6 @@ import (
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/mock" "github.com/filecoin-project/lotus/chain/types/mock"
@@ -22,19 +19,16 @@ import (
datastore "github.com/ipfs/go-datastore" datastore "github.com/ipfs/go-datastore"
dssync "github.com/ipfs/go-datastore/sync" dssync "github.com/ipfs/go-datastore/sync"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
mh "github.com/multiformats/go-multihash"
) )
func init() { func init() {
CompactionThreshold = 5 CompactionThreshold = 5
CompactionBoundary = 2 CompactionBoundary = 2
WarmupBoundary = 0 WarmupBoundary = 0
SyncWaitTime = time.Millisecond
logging.SetLogLevel("splitstore", "DEBUG") logging.SetLogLevel("splitstore", "DEBUG")
} }
func testSplitStore(t *testing.T, cfg *Config) { func testSplitStore(t *testing.T, cfg *Config) {
ctx := context.Background()
chain := &mockChain{t: t} chain := &mockChain{t: t}
// the myriads of stores // the myriads of stores
@@ -44,7 +38,7 @@ func testSplitStore(t *testing.T, cfg *Config) {
// this is necessary to avoid the garbage mock puts in the blocks // this is necessary to avoid the garbage mock puts in the blocks
garbage := blocks.NewBlock([]byte{1, 2, 3}) garbage := blocks.NewBlock([]byte{1, 2, 3})
err := cold.Put(ctx, garbage) err := cold.Put(garbage)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -65,29 +59,27 @@ func testSplitStore(t *testing.T, cfg *Config) {
t.Fatal(err) t.Fatal(err)
} }
err = cold.Put(ctx, blk) err = cold.Put(blk)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
// create a garbage block that is protected with a rgistered protector // create a garbage block that is protected with a rgistered protector
protected := blocks.NewBlock([]byte("protected!")) protected := blocks.NewBlock([]byte("protected!"))
err = hot.Put(ctx, protected) err = hot.Put(protected)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
// and another one that is not protected // and another one that is not protected
unprotected := blocks.NewBlock([]byte("unprotected!")) unprotected := blocks.NewBlock([]byte("unprotected!"))
err = hot.Put(ctx, unprotected) err = hot.Put(unprotected)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
path := t.TempDir()
// open the splitstore // open the splitstore
ss, err := Open(path, ds, hot, cold, cfg) ss, err := Open("", ds, hot, cold, cfg)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -98,7 +90,7 @@ func testSplitStore(t *testing.T, cfg *Config) {
return protect(protected.Cid()) return protect(protected.Cid())
}) })
err = ss.Start(chain, nil) err = ss.Start(chain)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -116,11 +108,11 @@ func testSplitStore(t *testing.T, cfg *Config) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = ss.Put(ctx, stateRoot) err = ss.Put(stateRoot)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = ss.Put(ctx, sblk) err = ss.Put(sblk)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -131,10 +123,6 @@ func testSplitStore(t *testing.T, cfg *Config) {
} }
waitForCompaction := func() { waitForCompaction := func() {
ss.txnSyncMx.Lock()
ss.txnSync = true
ss.txnSyncCond.Broadcast()
ss.txnSyncMx.Unlock()
for atomic.LoadInt32(&ss.compacting) == 1 { for atomic.LoadInt32(&ss.compacting) == 1 {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
@@ -187,7 +175,7 @@ func testSplitStore(t *testing.T, cfg *Config) {
} }
// ensure our protected block is still there // ensure our protected block is still there
has, err := hot.Has(ctx, protected.Cid()) has, err := hot.Has(protected.Cid())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -197,7 +185,7 @@ func testSplitStore(t *testing.T, cfg *Config) {
} }
// ensure our unprotected block is in the coldstore now // ensure our unprotected block is in the coldstore now
has, err = hot.Has(ctx, unprotected.Cid()) has, err = hot.Has(unprotected.Cid())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -206,7 +194,7 @@ func testSplitStore(t *testing.T, cfg *Config) {
t.Fatal("unprotected block is still in hotstore") t.Fatal("unprotected block is still in hotstore")
} }
has, err = cold.Has(ctx, unprotected.Cid()) has, err = cold.Has(unprotected.Cid())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -220,16 +208,10 @@ func testSplitStore(t *testing.T, cfg *Config) {
} }
func TestSplitStoreCompaction(t *testing.T) { func TestSplitStoreCompaction(t *testing.T) {
//stm: @SPLITSTORE_SPLITSTORE_OPEN_001, @SPLITSTORE_SPLITSTORE_CLOSE_001
//stm: @SPLITSTORE_SPLITSTORE_PUT_001, @SPLITSTORE_SPLITSTORE_ADD_PROTECTOR_001
//stm: @SPLITSTORE_SPLITSTORE_CLOSE_001
testSplitStore(t, &Config{MarkSetType: "map"}) testSplitStore(t, &Config{MarkSetType: "map"})
} }
func TestSplitStoreCompactionWithBadger(t *testing.T) { func TestSplitStoreCompactionWithBadger(t *testing.T) {
//stm: @SPLITSTORE_SPLITSTORE_OPEN_001, @SPLITSTORE_SPLITSTORE_CLOSE_001
//stm: @SPLITSTORE_SPLITSTORE_PUT_001, @SPLITSTORE_SPLITSTORE_ADD_PROTECTOR_001
//stm: @SPLITSTORE_SPLITSTORE_CLOSE_001
bs := badgerMarkSetBatchSize bs := badgerMarkSetBatchSize
badgerMarkSetBatchSize = 1 badgerMarkSetBatchSize = 1
t.Cleanup(func() { t.Cleanup(func() {
@@ -238,365 +220,6 @@ func TestSplitStoreCompactionWithBadger(t *testing.T) {
testSplitStore(t, &Config{MarkSetType: "badger"}) testSplitStore(t, &Config{MarkSetType: "badger"})
} }
func TestSplitStoreSuppressCompactionNearUpgrade(t *testing.T) {
//stm: @SPLITSTORE_SPLITSTORE_OPEN_001, @SPLITSTORE_SPLITSTORE_CLOSE_001
//stm: @SPLITSTORE_SPLITSTORE_PUT_001, @SPLITSTORE_SPLITSTORE_ADD_PROTECTOR_001
//stm: @SPLITSTORE_SPLITSTORE_CLOSE_001
ctx := context.Background()
chain := &mockChain{t: t}
// the myriads of stores
ds := dssync.MutexWrap(datastore.NewMapDatastore())
hot := newMockStore()
cold := newMockStore()
// this is necessary to avoid the garbage mock puts in the blocks
garbage := blocks.NewBlock([]byte{1, 2, 3})
err := cold.Put(ctx, garbage)
if err != nil {
t.Fatal(err)
}
// genesis
genBlock := mock.MkBlock(nil, 0, 0)
genBlock.Messages = garbage.Cid()
genBlock.ParentMessageReceipts = garbage.Cid()
genBlock.ParentStateRoot = garbage.Cid()
genBlock.Timestamp = uint64(time.Now().Unix())
genTs := mock.TipSet(genBlock)
chain.push(genTs)
// put the genesis block to cold store
blk, err := genBlock.ToStorageBlock()
if err != nil {
t.Fatal(err)
}
err = cold.Put(ctx, blk)
if err != nil {
t.Fatal(err)
}
path := t.TempDir()
// open the splitstore
ss, err := Open(path, ds, hot, cold, &Config{MarkSetType: "map"})
if err != nil {
t.Fatal(err)
}
defer ss.Close() //nolint
// create an upgrade schedule that will suppress compaction during the test
upgradeBoundary = 0
upgrade := stmgr.Upgrade{
Height: 10,
PreMigrations: []stmgr.PreMigration{{StartWithin: 10}},
}
err = ss.Start(chain, []stmgr.Upgrade{upgrade})
if err != nil {
t.Fatal(err)
}
mkBlock := func(curTs *types.TipSet, i int, stateRoot blocks.Block) *types.TipSet {
blk := mock.MkBlock(curTs, uint64(i), uint64(i))
blk.Messages = garbage.Cid()
blk.ParentMessageReceipts = garbage.Cid()
blk.ParentStateRoot = stateRoot.Cid()
blk.Timestamp = uint64(time.Now().Unix())
sblk, err := blk.ToStorageBlock()
if err != nil {
t.Fatal(err)
}
err = ss.Put(ctx, stateRoot)
if err != nil {
t.Fatal(err)
}
err = ss.Put(ctx, sblk)
if err != nil {
t.Fatal(err)
}
ts := mock.TipSet(blk)
chain.push(ts)
return ts
}
waitForCompaction := func() {
ss.txnSyncMx.Lock()
ss.txnSync = true
ss.txnSyncCond.Broadcast()
ss.txnSyncMx.Unlock()
for atomic.LoadInt32(&ss.compacting) == 1 {
time.Sleep(100 * time.Millisecond)
}
}
curTs := genTs
for i := 1; i < 10; i++ {
stateRoot := blocks.NewBlock([]byte{byte(i), 3, 3, 7})
curTs = mkBlock(curTs, i, stateRoot)
waitForCompaction()
}
countBlocks := func(bs blockstore.Blockstore) int {
count := 0
_ = bs.(blockstore.BlockstoreIterator).ForEachKey(func(_ cid.Cid) error {
count++
return nil
})
return count
}
// we should not have compacted due to suppression and everything should still be hot
hotCnt := countBlocks(hot)
coldCnt := countBlocks(cold)
if hotCnt != 20 {
t.Errorf("expected %d blocks, but got %d", 20, hotCnt)
}
if coldCnt != 2 {
t.Errorf("expected %d blocks, but got %d", 2, coldCnt)
}
// put some more blocks, now we should compact
for i := 10; i < 20; i++ {
stateRoot := blocks.NewBlock([]byte{byte(i), 3, 3, 7})
curTs = mkBlock(curTs, i, stateRoot)
waitForCompaction()
}
hotCnt = countBlocks(hot)
coldCnt = countBlocks(cold)
if hotCnt != 24 {
t.Errorf("expected %d blocks, but got %d", 24, hotCnt)
}
if coldCnt != 18 {
t.Errorf("expected %d blocks, but got %d", 18, coldCnt)
}
}
func testSplitStoreReification(t *testing.T, f func(context.Context, blockstore.Blockstore, cid.Cid) error) {
ds := dssync.MutexWrap(datastore.NewMapDatastore())
hot := newMockStore()
cold := newMockStore()
mkRandomBlock := func() blocks.Block {
data := make([]byte, 128)
_, err := rand.Read(data)
if err != nil {
t.Fatal(err)
}
return blocks.NewBlock(data)
}
block1 := mkRandomBlock()
block2 := mkRandomBlock()
block3 := mkRandomBlock()
hdr := mock.MkBlock(nil, 0, 0)
hdr.Messages = block1.Cid()
hdr.ParentMessageReceipts = block2.Cid()
hdr.ParentStateRoot = block3.Cid()
block4, err := hdr.ToStorageBlock()
if err != nil {
t.Fatal(err)
}
allBlocks := []blocks.Block{block1, block2, block3, block4}
for _, blk := range allBlocks {
err := cold.Put(context.Background(), blk)
if err != nil {
t.Fatal(err)
}
}
path := t.TempDir()
ss, err := Open(path, ds, hot, cold, &Config{MarkSetType: "map"})
if err != nil {
t.Fatal(err)
}
defer ss.Close() //nolint
ss.warmupEpoch = 1
go ss.reifyOrchestrator()
waitForReification := func() {
for {
ss.reifyMx.Lock()
ready := len(ss.reifyPend) == 0 && len(ss.reifyInProgress) == 0
ss.reifyMx.Unlock()
if ready {
return
}
time.Sleep(time.Millisecond)
}
}
// first access using the standard view
err = f(context.Background(), ss, block4.Cid())
if err != nil {
t.Fatal(err)
}
// nothing should be reified
waitForReification()
for _, blk := range allBlocks {
has, err := hot.Has(context.Background(), blk.Cid())
if err != nil {
t.Fatal(err)
}
if has {
t.Fatal("block unexpectedly reified")
}
}
// now make the hot/reifying view and ensure access reifies
err = f(blockstore.WithHotView(context.Background()), ss, block4.Cid())
if err != nil {
t.Fatal(err)
}
// everything should be reified
waitForReification()
for i, blk := range allBlocks {
has, err := hot.Has(context.Background(), blk.Cid())
if err != nil {
t.Fatal(err)
}
if !has {
t.Fatalf("block%d was not reified", i+1)
}
}
}
func testSplitStoreReificationLimit(t *testing.T, f func(context.Context, blockstore.Blockstore, cid.Cid) error) {
ds := dssync.MutexWrap(datastore.NewMapDatastore())
hot := newMockStore()
cold := newMockStore()
mkRandomBlock := func() blocks.Block {
data := make([]byte, 128)
_, err := rand.Read(data)
if err != nil {
t.Fatal(err)
}
return blocks.NewBlock(data)
}
block1 := mkRandomBlock()
block2 := mkRandomBlock()
block3 := mkRandomBlock()
hdr := mock.MkBlock(nil, 0, 0)
hdr.Messages = block1.Cid()
hdr.ParentMessageReceipts = block2.Cid()
hdr.ParentStateRoot = block3.Cid()
block4, err := hdr.ToStorageBlock()
if err != nil {
t.Fatal(err)
}
allBlocks := []blocks.Block{block1, block2, block3, block4}
for _, blk := range allBlocks {
err := cold.Put(context.Background(), blk)
if err != nil {
t.Fatal(err)
}
}
path := t.TempDir()
ss, err := Open(path, ds, hot, cold, &Config{MarkSetType: "map"})
if err != nil {
t.Fatal(err)
}
defer ss.Close() //nolint
ss.warmupEpoch = 1
go ss.reifyOrchestrator()
waitForReification := func() {
for {
ss.reifyMx.Lock()
ready := len(ss.reifyPend) == 0 && len(ss.reifyInProgress) == 0
ss.reifyMx.Unlock()
if ready {
return
}
time.Sleep(time.Millisecond)
}
}
// do a hot access -- nothing should be reified as the limit should be exceeded
oldReifyLimit := ReifyLimit
ReifyLimit = 2
t.Cleanup(func() {
ReifyLimit = oldReifyLimit
})
err = f(blockstore.WithHotView(context.Background()), ss, block4.Cid())
if err != nil {
t.Fatal(err)
}
waitForReification()
for _, blk := range allBlocks {
has, err := hot.Has(context.Background(), blk.Cid())
if err != nil {
t.Fatal(err)
}
if has {
t.Fatal("block unexpectedly reified")
}
}
}
func TestSplitStoreReification(t *testing.T) {
t.Log("test reification with Has")
testSplitStoreReification(t, func(ctx context.Context, s blockstore.Blockstore, c cid.Cid) error {
_, err := s.Has(ctx, c)
return err
})
t.Log("test reification with Get")
testSplitStoreReification(t, func(ctx context.Context, s blockstore.Blockstore, c cid.Cid) error {
_, err := s.Get(ctx, c)
return err
})
t.Log("test reification with GetSize")
testSplitStoreReification(t, func(ctx context.Context, s blockstore.Blockstore, c cid.Cid) error {
_, err := s.GetSize(ctx, c)
return err
})
t.Log("test reification with View")
testSplitStoreReification(t, func(ctx context.Context, s blockstore.Blockstore, c cid.Cid) error {
return s.View(ctx, c, func(_ []byte) error { return nil })
})
t.Log("test reification limit")
testSplitStoreReificationLimit(t, func(ctx context.Context, s blockstore.Blockstore, c cid.Cid) error {
_, err := s.Has(ctx, c)
return err
})
}
type mockChain struct { type mockChain struct {
t testing.TB t testing.TB
@@ -666,43 +289,35 @@ func (c *mockChain) SubscribeHeadChanges(change func(revert []*types.TipSet, app
type mockStore struct { type mockStore struct {
mx sync.Mutex mx sync.Mutex
set map[string]blocks.Block set map[cid.Cid]blocks.Block
} }
func newMockStore() *mockStore { func newMockStore() *mockStore {
return &mockStore{set: make(map[string]blocks.Block)} return &mockStore{set: make(map[cid.Cid]blocks.Block)}
} }
func (b *mockStore) keyOf(c cid.Cid) string { func (b *mockStore) Has(cid cid.Cid) (bool, error) {
return string(c.Hash())
}
func (b *mockStore) cidOf(k string) cid.Cid {
return cid.NewCidV1(cid.Raw, mh.Multihash([]byte(k)))
}
func (b *mockStore) Has(_ context.Context, cid cid.Cid) (bool, error) {
b.mx.Lock() b.mx.Lock()
defer b.mx.Unlock() defer b.mx.Unlock()
_, ok := b.set[b.keyOf(cid)] _, ok := b.set[cid]
return ok, nil return ok, nil
} }
func (b *mockStore) HashOnRead(hor bool) {} func (b *mockStore) HashOnRead(hor bool) {}
func (b *mockStore) Get(_ context.Context, cid cid.Cid) (blocks.Block, error) { func (b *mockStore) Get(cid cid.Cid) (blocks.Block, error) {
b.mx.Lock() b.mx.Lock()
defer b.mx.Unlock() defer b.mx.Unlock()
blk, ok := b.set[b.keyOf(cid)] blk, ok := b.set[cid]
if !ok { if !ok {
return nil, blockstore.ErrNotFound return nil, blockstore.ErrNotFound
} }
return blk, nil return blk, nil
} }
func (b *mockStore) GetSize(ctx context.Context, cid cid.Cid) (int, error) { func (b *mockStore) GetSize(cid cid.Cid) (int, error) {
blk, err := b.Get(ctx, cid) blk, err := b.Get(cid)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@@ -710,46 +325,46 @@ func (b *mockStore) GetSize(ctx context.Context, cid cid.Cid) (int, error) {
return len(blk.RawData()), nil return len(blk.RawData()), nil
} }
func (b *mockStore) View(ctx context.Context, cid cid.Cid, f func([]byte) error) error { func (b *mockStore) View(cid cid.Cid, f func([]byte) error) error {
blk, err := b.Get(ctx, cid) blk, err := b.Get(cid)
if err != nil { if err != nil {
return err return err
} }
return f(blk.RawData()) return f(blk.RawData())
} }
func (b *mockStore) Put(_ context.Context, blk blocks.Block) error { func (b *mockStore) Put(blk blocks.Block) error {
b.mx.Lock() b.mx.Lock()
defer b.mx.Unlock() defer b.mx.Unlock()
b.set[b.keyOf(blk.Cid())] = blk b.set[blk.Cid()] = blk
return nil return nil
} }
func (b *mockStore) PutMany(_ context.Context, blks []blocks.Block) error { func (b *mockStore) PutMany(blks []blocks.Block) error {
b.mx.Lock() b.mx.Lock()
defer b.mx.Unlock() defer b.mx.Unlock()
for _, blk := range blks { for _, blk := range blks {
b.set[b.keyOf(blk.Cid())] = blk b.set[blk.Cid()] = blk
} }
return nil return nil
} }
func (b *mockStore) DeleteBlock(_ context.Context, cid cid.Cid) error { func (b *mockStore) DeleteBlock(cid cid.Cid) error {
b.mx.Lock() b.mx.Lock()
defer b.mx.Unlock() defer b.mx.Unlock()
delete(b.set, b.keyOf(cid)) delete(b.set, cid)
return nil return nil
} }
func (b *mockStore) DeleteMany(_ context.Context, cids []cid.Cid) error { func (b *mockStore) DeleteMany(cids []cid.Cid) error {
b.mx.Lock() b.mx.Lock()
defer b.mx.Unlock() defer b.mx.Unlock()
for _, c := range cids { for _, c := range cids {
delete(b.set, b.keyOf(c)) delete(b.set, c)
} }
return nil return nil
} }
@@ -763,7 +378,7 @@ func (b *mockStore) ForEachKey(f func(cid.Cid) error) error {
defer b.mx.Unlock() defer b.mx.Unlock()
for c := range b.set { for c := range b.set {
err := f(b.cidOf(c)) err := f(c)
if err != nil { if err != nil {
return err return err
} }
+16 -29
View File
@@ -1,7 +1,6 @@
package splitstore package splitstore
import ( import (
"sync"
"sync/atomic" "sync/atomic"
"time" "time"
@@ -56,28 +55,19 @@ func (s *SplitStore) doWarmup(curTs *types.TipSet) error {
if WarmupBoundary < epoch { if WarmupBoundary < epoch {
boundaryEpoch = epoch - WarmupBoundary boundaryEpoch = epoch - WarmupBoundary
} }
var mx sync.Mutex
batchHot := make([]blocks.Block, 0, batchSize) batchHot := make([]blocks.Block, 0, batchSize)
count := new(int64) count := int64(0)
xcount := new(int64) xcount := int64(0)
missing := new(int64) missing := int64(0)
err := s.walkChain(curTs, boundaryEpoch, epoch+1, // we don't load messages/receipts in warmup
visitor, err := s.markSetEnv.New("warmup", 0)
if err != nil {
return xerrors.Errorf("error creating visitor: %w", err)
}
defer visitor.Close() //nolint
err = s.walkChain(curTs, boundaryEpoch, epoch+1, // we don't load messages/receipts in warmup
visitor,
func(c cid.Cid) error { func(c cid.Cid) error {
if isUnitaryObject(c) { if isUnitaryObject(c) {
return errStopWalk return errStopWalk
} }
atomic.AddInt64(count, 1) count++
has, err := s.hot.Has(s.ctx, c) has, err := s.hot.Has(c)
if err != nil { if err != nil {
return err return err
} }
@@ -86,28 +76,25 @@ func (s *SplitStore) doWarmup(curTs *types.TipSet) error {
return nil return nil
} }
blk, err := s.cold.Get(s.ctx, c) blk, err := s.cold.Get(c)
if err != nil { if err != nil {
if err == bstore.ErrNotFound { if err == bstore.ErrNotFound {
atomic.AddInt64(missing, 1) missing++
return errStopWalk return errStopWalk
} }
return err return err
} }
atomic.AddInt64(xcount, 1) xcount++
mx.Lock()
batchHot = append(batchHot, blk) batchHot = append(batchHot, blk)
if len(batchHot) == batchSize { if len(batchHot) == batchSize {
err = s.hot.PutMany(s.ctx, batchHot) err = s.hot.PutMany(batchHot)
if err != nil { if err != nil {
mx.Unlock()
return err return err
} }
batchHot = batchHot[:0] batchHot = batchHot[:0]
} }
mx.Unlock()
return nil return nil
}) })
@@ -117,22 +104,22 @@ func (s *SplitStore) doWarmup(curTs *types.TipSet) error {
} }
if len(batchHot) > 0 { if len(batchHot) > 0 {
err = s.hot.PutMany(s.ctx, batchHot) err = s.hot.PutMany(batchHot)
if err != nil { if err != nil {
return err return err
} }
} }
log.Infow("warmup stats", "visited", *count, "warm", *xcount, "missing", *missing) log.Infow("warmup stats", "visited", count, "warm", xcount, "missing", missing)
s.markSetSize = *count + *count>>2 // overestimate a bit s.markSetSize = count + count>>2 // overestimate a bit
err = s.ds.Put(s.ctx, markSetSizeKey, int64ToBytes(s.markSetSize)) err = s.ds.Put(markSetSizeKey, int64ToBytes(s.markSetSize))
if err != nil { if err != nil {
log.Warnf("error saving mark set size: %s", err) log.Warnf("error saving mark set size: %s", err)
} }
// save the warmup epoch // save the warmup epoch
err = s.ds.Put(s.ctx, warmupEpochKey, epochToBytes(epoch)) err = s.ds.Put(warmupEpochKey, epochToBytes(epoch))
if err != nil { if err != nil {
return xerrors.Errorf("error saving warm up epoch: %w", err) return xerrors.Errorf("error saving warm up epoch: %w", err)
} }
@@ -141,7 +128,7 @@ func (s *SplitStore) doWarmup(curTs *types.TipSet) error {
s.mx.Unlock() s.mx.Unlock()
// also save the compactionIndex, as this is used as an indicator of warmup for upgraded nodes // also save the compactionIndex, as this is used as an indicator of warmup for upgraded nodes
err = s.ds.Put(s.ctx, compactionIndexKey, int64ToBytes(s.compactionIndex)) err = s.ds.Put(compactionIndexKey, int64ToBytes(s.compactionIndex))
if err != nil { if err != nil {
return xerrors.Errorf("error saving compaction index: %w", err) return xerrors.Errorf("error saving compaction index: %w", err)
} }
-60
View File
@@ -1,60 +0,0 @@
package splitstore
import (
"sync"
cid "github.com/ipfs/go-cid"
)
// ObjectVisitor is an interface for deduplicating objects during walks
type ObjectVisitor interface {
Visit(cid.Cid) (bool, error)
}
type noopVisitor struct{}
var _ ObjectVisitor = (*noopVisitor)(nil)
func (v *noopVisitor) Visit(_ cid.Cid) (bool, error) {
return true, nil
}
type tmpVisitor struct {
set *cid.Set
}
var _ ObjectVisitor = (*tmpVisitor)(nil)
func (v *tmpVisitor) Visit(c cid.Cid) (bool, error) {
if isUnitaryObject(c) {
return false, nil
}
return v.set.Visit(c), nil
}
func newTmpVisitor() ObjectVisitor {
return &tmpVisitor{set: cid.NewSet()}
}
type concurrentVisitor struct {
mx sync.Mutex
set *cid.Set
}
var _ ObjectVisitor = (*concurrentVisitor)(nil)
func newConcurrentVisitor() *concurrentVisitor {
return &concurrentVisitor{set: cid.NewSet()}
}
func (v *concurrentVisitor) Visit(c cid.Cid) (bool, error) {
if isUnitaryObject(c) {
return false, nil
}
v.mx.Lock()
defer v.mx.Unlock()
return v.set.Visit(c), nil
}
+16 -16
View File
@@ -20,53 +20,53 @@ type SyncBlockstore struct {
bs MemBlockstore // specifically use a memStore to save indirection overhead. bs MemBlockstore // specifically use a memStore to save indirection overhead.
} }
func (m *SyncBlockstore) DeleteBlock(ctx context.Context, k cid.Cid) error { func (m *SyncBlockstore) DeleteBlock(k cid.Cid) error {
m.mu.Lock() m.mu.Lock()
defer m.mu.Unlock() defer m.mu.Unlock()
return m.bs.DeleteBlock(ctx, k) return m.bs.DeleteBlock(k)
} }
func (m *SyncBlockstore) DeleteMany(ctx context.Context, ks []cid.Cid) error { func (m *SyncBlockstore) DeleteMany(ks []cid.Cid) error {
m.mu.Lock() m.mu.Lock()
defer m.mu.Unlock() defer m.mu.Unlock()
return m.bs.DeleteMany(ctx, ks) return m.bs.DeleteMany(ks)
} }
func (m *SyncBlockstore) Has(ctx context.Context, k cid.Cid) (bool, error) { func (m *SyncBlockstore) Has(k cid.Cid) (bool, error) {
m.mu.RLock() m.mu.RLock()
defer m.mu.RUnlock() defer m.mu.RUnlock()
return m.bs.Has(ctx, k) return m.bs.Has(k)
} }
func (m *SyncBlockstore) View(ctx context.Context, k cid.Cid, callback func([]byte) error) error { func (m *SyncBlockstore) View(k cid.Cid, callback func([]byte) error) error {
m.mu.RLock() m.mu.RLock()
defer m.mu.RUnlock() defer m.mu.RUnlock()
return m.bs.View(ctx, k, callback) return m.bs.View(k, callback)
} }
func (m *SyncBlockstore) Get(ctx context.Context, k cid.Cid) (blocks.Block, error) { func (m *SyncBlockstore) Get(k cid.Cid) (blocks.Block, error) {
m.mu.RLock() m.mu.RLock()
defer m.mu.RUnlock() defer m.mu.RUnlock()
return m.bs.Get(ctx, k) return m.bs.Get(k)
} }
func (m *SyncBlockstore) GetSize(ctx context.Context, k cid.Cid) (int, error) { func (m *SyncBlockstore) GetSize(k cid.Cid) (int, error) {
m.mu.RLock() m.mu.RLock()
defer m.mu.RUnlock() defer m.mu.RUnlock()
return m.bs.GetSize(ctx, k) return m.bs.GetSize(k)
} }
func (m *SyncBlockstore) Put(ctx context.Context, b blocks.Block) error { func (m *SyncBlockstore) Put(b blocks.Block) error {
m.mu.Lock() m.mu.Lock()
defer m.mu.Unlock() defer m.mu.Unlock()
return m.bs.Put(ctx, b) return m.bs.Put(b)
} }
func (m *SyncBlockstore) PutMany(ctx context.Context, bs []blocks.Block) error { func (m *SyncBlockstore) PutMany(bs []blocks.Block) error {
m.mu.Lock() m.mu.Lock()
defer m.mu.Unlock() defer m.mu.Unlock()
return m.bs.PutMany(ctx, bs) return m.bs.PutMany(bs)
} }
func (m *SyncBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) { func (m *SyncBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
+21 -25
View File
@@ -47,12 +47,8 @@ func (t *TimedCacheBlockstore) Start(_ context.Context) error {
return fmt.Errorf("already started") return fmt.Errorf("already started")
} }
t.closeCh = make(chan struct{}) t.closeCh = make(chan struct{})
// Create this timer before starting the goroutine. Otherwise, creating the timer will race
// with adding time to the mock clock, and we could add time _first_, then stall waiting for
// a timer that'll never fire.
ticker := t.clock.Ticker(t.interval)
go func() { go func() {
ticker := t.clock.Ticker(t.interval)
defer ticker.Stop() defer ticker.Stop()
for { for {
select { select {
@@ -92,28 +88,28 @@ func (t *TimedCacheBlockstore) rotate() {
t.mu.Unlock() t.mu.Unlock()
} }
func (t *TimedCacheBlockstore) Put(ctx context.Context, b blocks.Block) error { func (t *TimedCacheBlockstore) Put(b blocks.Block) error {
// Don't check the inactive set here. We want to keep this block for at // Don't check the inactive set here. We want to keep this block for at
// least one interval. // least one interval.
t.mu.Lock() t.mu.Lock()
defer t.mu.Unlock() defer t.mu.Unlock()
return t.active.Put(ctx, b) return t.active.Put(b)
} }
func (t *TimedCacheBlockstore) PutMany(ctx context.Context, bs []blocks.Block) error { func (t *TimedCacheBlockstore) PutMany(bs []blocks.Block) error {
t.mu.Lock() t.mu.Lock()
defer t.mu.Unlock() defer t.mu.Unlock()
return t.active.PutMany(ctx, bs) return t.active.PutMany(bs)
} }
func (t *TimedCacheBlockstore) View(ctx context.Context, k cid.Cid, callback func([]byte) error) error { func (t *TimedCacheBlockstore) View(k cid.Cid, callback func([]byte) error) error {
// The underlying blockstore is always a "mem" blockstore so there's no difference, // The underlying blockstore is always a "mem" blockstore so there's no difference,
// from a performance perspective, between view & get. So we call Get to avoid // from a performance perspective, between view & get. So we call Get to avoid
// calling an arbitrary callback while holding a lock. // calling an arbitrary callback while holding a lock.
t.mu.RLock() t.mu.RLock()
block, err := t.active.Get(ctx, k) block, err := t.active.Get(k)
if err == ErrNotFound { if err == ErrNotFound {
block, err = t.inactive.Get(ctx, k) block, err = t.inactive.Get(k)
} }
t.mu.RUnlock() t.mu.RUnlock()
@@ -123,51 +119,51 @@ func (t *TimedCacheBlockstore) View(ctx context.Context, k cid.Cid, callback fun
return callback(block.RawData()) return callback(block.RawData())
} }
func (t *TimedCacheBlockstore) Get(ctx context.Context, k cid.Cid) (blocks.Block, error) { func (t *TimedCacheBlockstore) Get(k cid.Cid) (blocks.Block, error) {
t.mu.RLock() t.mu.RLock()
defer t.mu.RUnlock() defer t.mu.RUnlock()
b, err := t.active.Get(ctx, k) b, err := t.active.Get(k)
if err == ErrNotFound { if err == ErrNotFound {
b, err = t.inactive.Get(ctx, k) b, err = t.inactive.Get(k)
} }
return b, err return b, err
} }
func (t *TimedCacheBlockstore) GetSize(ctx context.Context, k cid.Cid) (int, error) { func (t *TimedCacheBlockstore) GetSize(k cid.Cid) (int, error) {
t.mu.RLock() t.mu.RLock()
defer t.mu.RUnlock() defer t.mu.RUnlock()
size, err := t.active.GetSize(ctx, k) size, err := t.active.GetSize(k)
if err == ErrNotFound { if err == ErrNotFound {
size, err = t.inactive.GetSize(ctx, k) size, err = t.inactive.GetSize(k)
} }
return size, err return size, err
} }
func (t *TimedCacheBlockstore) Has(ctx context.Context, k cid.Cid) (bool, error) { func (t *TimedCacheBlockstore) Has(k cid.Cid) (bool, error) {
t.mu.RLock() t.mu.RLock()
defer t.mu.RUnlock() defer t.mu.RUnlock()
if has, err := t.active.Has(ctx, k); err != nil { if has, err := t.active.Has(k); err != nil {
return false, err return false, err
} else if has { } else if has {
return true, nil return true, nil
} }
return t.inactive.Has(ctx, k) return t.inactive.Has(k)
} }
func (t *TimedCacheBlockstore) HashOnRead(_ bool) { func (t *TimedCacheBlockstore) HashOnRead(_ bool) {
// no-op // no-op
} }
func (t *TimedCacheBlockstore) DeleteBlock(ctx context.Context, k cid.Cid) error { func (t *TimedCacheBlockstore) DeleteBlock(k cid.Cid) error {
t.mu.Lock() t.mu.Lock()
defer t.mu.Unlock() defer t.mu.Unlock()
return multierr.Combine(t.active.DeleteBlock(ctx, k), t.inactive.DeleteBlock(ctx, k)) return multierr.Combine(t.active.DeleteBlock(k), t.inactive.DeleteBlock(k))
} }
func (t *TimedCacheBlockstore) DeleteMany(ctx context.Context, ks []cid.Cid) error { func (t *TimedCacheBlockstore) DeleteMany(ks []cid.Cid) error {
t.mu.Lock() t.mu.Lock()
defer t.mu.Unlock() defer t.mu.Unlock()
return multierr.Combine(t.active.DeleteMany(ctx, ks), t.inactive.DeleteMany(ctx, ks)) return multierr.Combine(t.active.DeleteMany(ks), t.inactive.DeleteMany(ks))
} }
func (t *TimedCacheBlockstore) AllKeysChan(_ context.Context) (<-chan cid.Cid, error) { func (t *TimedCacheBlockstore) AllKeysChan(_ context.Context) (<-chan cid.Cid, error) {
+11 -17
View File
@@ -1,4 +1,3 @@
//stm: #unit
package blockstore package blockstore
import ( import (
@@ -14,17 +13,12 @@ import (
) )
func TestTimedCacheBlockstoreSimple(t *testing.T) { func TestTimedCacheBlockstoreSimple(t *testing.T) {
//stm: @SPLITSTORE_TIMED_BLOCKSTORE_START_001
//stm: @SPLITSTORE_TIMED_BLOCKSTORE_PUT_001, @SPLITSTORE_TIMED_BLOCKSTORE_HAS_001, @SPLITSTORE_TIMED_BLOCKSTORE_GET_001
//stm: @SPLITSTORE_TIMED_BLOCKSTORE_ALL_KEYS_CHAN_001
tc := NewTimedCacheBlockstore(10 * time.Millisecond) tc := NewTimedCacheBlockstore(10 * time.Millisecond)
mClock := clock.NewMock() mClock := clock.NewMock()
mClock.Set(time.Now()) mClock.Set(time.Now())
tc.clock = mClock tc.clock = mClock
tc.doneRotatingCh = make(chan struct{}) tc.doneRotatingCh = make(chan struct{})
ctx := context.Background()
_ = tc.Start(context.Background()) _ = tc.Start(context.Background())
mClock.Add(1) // IDK why it is needed but it makes it work mClock.Add(1) // IDK why it is needed but it makes it work
@@ -33,18 +27,18 @@ func TestTimedCacheBlockstoreSimple(t *testing.T) {
}() }()
b1 := blocks.NewBlock([]byte("foo")) b1 := blocks.NewBlock([]byte("foo"))
require.NoError(t, tc.Put(ctx, b1)) require.NoError(t, tc.Put(b1))
b2 := blocks.NewBlock([]byte("bar")) b2 := blocks.NewBlock([]byte("bar"))
require.NoError(t, tc.Put(ctx, b2)) require.NoError(t, tc.Put(b2))
b3 := blocks.NewBlock([]byte("baz")) b3 := blocks.NewBlock([]byte("baz"))
b1out, err := tc.Get(ctx, b1.Cid()) b1out, err := tc.Get(b1.Cid())
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, b1.RawData(), b1out.RawData()) require.Equal(t, b1.RawData(), b1out.RawData())
has, err := tc.Has(ctx, b1.Cid()) has, err := tc.Has(b1.Cid())
require.NoError(t, err) require.NoError(t, err)
require.True(t, has) require.True(t, has)
@@ -52,17 +46,17 @@ func TestTimedCacheBlockstoreSimple(t *testing.T) {
<-tc.doneRotatingCh <-tc.doneRotatingCh
// We should still have everything. // We should still have everything.
has, err = tc.Has(ctx, b1.Cid()) has, err = tc.Has(b1.Cid())
require.NoError(t, err) require.NoError(t, err)
require.True(t, has) require.True(t, has)
has, err = tc.Has(ctx, b2.Cid()) has, err = tc.Has(b2.Cid())
require.NoError(t, err) require.NoError(t, err)
require.True(t, has) require.True(t, has)
// extend b2, add b3. // extend b2, add b3.
require.NoError(t, tc.Put(ctx, b2)) require.NoError(t, tc.Put(b2))
require.NoError(t, tc.Put(ctx, b3)) require.NoError(t, tc.Put(b3))
// all keys once. // all keys once.
allKeys, err := tc.AllKeysChan(context.Background()) allKeys, err := tc.AllKeysChan(context.Background())
@@ -77,15 +71,15 @@ func TestTimedCacheBlockstoreSimple(t *testing.T) {
<-tc.doneRotatingCh <-tc.doneRotatingCh
// should still have b2, and b3, but not b1 // should still have b2, and b3, but not b1
has, err = tc.Has(ctx, b1.Cid()) has, err = tc.Has(b1.Cid())
require.NoError(t, err) require.NoError(t, err)
require.False(t, has) require.False(t, has)
has, err = tc.Has(ctx, b2.Cid()) has, err = tc.Has(b2.Cid())
require.NoError(t, err) require.NoError(t, err)
require.True(t, has) require.True(t, has)
has, err = tc.Has(ctx, b3.Cid()) has, err = tc.Has(b3.Cid())
require.NoError(t, err) require.NoError(t, err)
require.True(t, has) require.True(t, has)
} }
+16 -16
View File
@@ -19,72 +19,72 @@ func Union(stores ...Blockstore) Blockstore {
return unionBlockstore(stores) return unionBlockstore(stores)
} }
func (m unionBlockstore) Has(ctx context.Context, cid cid.Cid) (has bool, err error) { func (m unionBlockstore) Has(cid cid.Cid) (has bool, err error) {
for _, bs := range m { for _, bs := range m {
if has, err = bs.Has(ctx, cid); has || err != nil { if has, err = bs.Has(cid); has || err != nil {
break break
} }
} }
return has, err return has, err
} }
func (m unionBlockstore) Get(ctx context.Context, cid cid.Cid) (blk blocks.Block, err error) { func (m unionBlockstore) Get(cid cid.Cid) (blk blocks.Block, err error) {
for _, bs := range m { for _, bs := range m {
if blk, err = bs.Get(ctx, cid); err == nil || err != ErrNotFound { if blk, err = bs.Get(cid); err == nil || err != ErrNotFound {
break break
} }
} }
return blk, err return blk, err
} }
func (m unionBlockstore) View(ctx context.Context, cid cid.Cid, callback func([]byte) error) (err error) { func (m unionBlockstore) View(cid cid.Cid, callback func([]byte) error) (err error) {
for _, bs := range m { for _, bs := range m {
if err = bs.View(ctx, cid, callback); err == nil || err != ErrNotFound { if err = bs.View(cid, callback); err == nil || err != ErrNotFound {
break break
} }
} }
return err return err
} }
func (m unionBlockstore) GetSize(ctx context.Context, cid cid.Cid) (size int, err error) { func (m unionBlockstore) GetSize(cid cid.Cid) (size int, err error) {
for _, bs := range m { for _, bs := range m {
if size, err = bs.GetSize(ctx, cid); err == nil || err != ErrNotFound { if size, err = bs.GetSize(cid); err == nil || err != ErrNotFound {
break break
} }
} }
return size, err return size, err
} }
func (m unionBlockstore) Put(ctx context.Context, block blocks.Block) (err error) { func (m unionBlockstore) Put(block blocks.Block) (err error) {
for _, bs := range m { for _, bs := range m {
if err = bs.Put(ctx, block); err != nil { if err = bs.Put(block); err != nil {
break break
} }
} }
return err return err
} }
func (m unionBlockstore) PutMany(ctx context.Context, blks []blocks.Block) (err error) { func (m unionBlockstore) PutMany(blks []blocks.Block) (err error) {
for _, bs := range m { for _, bs := range m {
if err = bs.PutMany(ctx, blks); err != nil { if err = bs.PutMany(blks); err != nil {
break break
} }
} }
return err return err
} }
func (m unionBlockstore) DeleteBlock(ctx context.Context, cid cid.Cid) (err error) { func (m unionBlockstore) DeleteBlock(cid cid.Cid) (err error) {
for _, bs := range m { for _, bs := range m {
if err = bs.DeleteBlock(ctx, cid); err != nil { if err = bs.DeleteBlock(cid); err != nil {
break break
} }
} }
return err return err
} }
func (m unionBlockstore) DeleteMany(ctx context.Context, cids []cid.Cid) (err error) { func (m unionBlockstore) DeleteMany(cids []cid.Cid) (err error) {
for _, bs := range m { for _, bs := range m {
if err = bs.DeleteMany(ctx, cids); err != nil { if err = bs.DeleteMany(cids); err != nil {
break break
} }
} }
+19 -26
View File
@@ -1,4 +1,3 @@
//stm: #unit
package blockstore package blockstore
import ( import (
@@ -16,85 +15,79 @@ var (
) )
func TestUnionBlockstore_Get(t *testing.T) { func TestUnionBlockstore_Get(t *testing.T) {
//stm: @SPLITSTORE_UNION_BLOCKSTORE_GET_001
ctx := context.Background()
m1 := NewMemory() m1 := NewMemory()
m2 := NewMemory() m2 := NewMemory()
_ = m1.Put(ctx, b1) _ = m1.Put(b1)
_ = m2.Put(ctx, b2) _ = m2.Put(b2)
u := Union(m1, m2) u := Union(m1, m2)
v1, err := u.Get(ctx, b1.Cid()) v1, err := u.Get(b1.Cid())
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, b1.RawData(), v1.RawData()) require.Equal(t, b1.RawData(), v1.RawData())
v2, err := u.Get(ctx, b2.Cid()) v2, err := u.Get(b2.Cid())
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, b2.RawData(), v2.RawData()) require.Equal(t, b2.RawData(), v2.RawData())
} }
func TestUnionBlockstore_Put_PutMany_Delete_AllKeysChan(t *testing.T) { func TestUnionBlockstore_Put_PutMany_Delete_AllKeysChan(t *testing.T) {
//stm: @SPLITSTORE_UNION_BLOCKSTORE_PUT_001, @SPLITSTORE_UNION_BLOCKSTORE_HAS_001
//stm: @SPLITSTORE_UNION_BLOCKSTORE_PUT_MANY_001, @SPLITSTORE_UNION_BLOCKSTORE_DELETE_001
//stm: @SPLITSTORE_UNION_BLOCKSTORE_ALL_KEYS_CHAN_001
ctx := context.Background()
m1 := NewMemory() m1 := NewMemory()
m2 := NewMemory() m2 := NewMemory()
u := Union(m1, m2) u := Union(m1, m2)
err := u.Put(ctx, b0) err := u.Put(b0)
require.NoError(t, err) require.NoError(t, err)
var has bool var has bool
// write was broadcasted to all stores. // write was broadcasted to all stores.
has, _ = m1.Has(ctx, b0.Cid()) has, _ = m1.Has(b0.Cid())
require.True(t, has) require.True(t, has)
has, _ = m2.Has(ctx, b0.Cid()) has, _ = m2.Has(b0.Cid())
require.True(t, has) require.True(t, has)
has, _ = u.Has(ctx, b0.Cid()) has, _ = u.Has(b0.Cid())
require.True(t, has) require.True(t, has)
// put many. // put many.
err = u.PutMany(ctx, []blocks.Block{b1, b2}) err = u.PutMany([]blocks.Block{b1, b2})
require.NoError(t, err) require.NoError(t, err)
// write was broadcasted to all stores. // write was broadcasted to all stores.
has, _ = m1.Has(ctx, b1.Cid()) has, _ = m1.Has(b1.Cid())
require.True(t, has) require.True(t, has)
has, _ = m1.Has(ctx, b2.Cid()) has, _ = m1.Has(b2.Cid())
require.True(t, has) require.True(t, has)
has, _ = m2.Has(ctx, b1.Cid()) has, _ = m2.Has(b1.Cid())
require.True(t, has) require.True(t, has)
has, _ = m2.Has(ctx, b2.Cid()) has, _ = m2.Has(b2.Cid())
require.True(t, has) require.True(t, has)
// also in the union store. // also in the union store.
has, _ = u.Has(ctx, b1.Cid()) has, _ = u.Has(b1.Cid())
require.True(t, has) require.True(t, has)
has, _ = u.Has(ctx, b2.Cid()) has, _ = u.Has(b2.Cid())
require.True(t, has) require.True(t, has)
// deleted from all stores. // deleted from all stores.
err = u.DeleteBlock(ctx, b1.Cid()) err = u.DeleteBlock(b1.Cid())
require.NoError(t, err) require.NoError(t, err)
has, _ = u.Has(ctx, b1.Cid()) has, _ = u.Has(b1.Cid())
require.False(t, has) require.False(t, has)
has, _ = m1.Has(ctx, b1.Cid()) has, _ = m1.Has(b1.Cid())
require.False(t, has) require.False(t, has)
has, _ = m2.Has(ctx, b1.Cid()) has, _ = m2.Has(b1.Cid())
require.False(t, has) require.False(t, has)
// check that AllKeysChan returns b0 and b2, twice (once per backing store) // check that AllKeysChan returns b0 and b2, twice (once per backing store)
+2 -2
View File
@@ -1,2 +1,2 @@
/dns4/bootstrap-0.butterfly.fildev.network/tcp/1347/p2p/12D3KooWFHDtFx7CVTy4xoCDutVo1cScvSnQjDeaM8UzwVS1qwkh /dns4/bootstrap-0.butterfly.fildev.network/tcp/1347/p2p/12D3KooWBbZd7Su9XfLUQ12RynGQ3ZmGY1nGqFntmqop9pLNJE6g
/dns4/bootstrap-1.butterfly.fildev.network/tcp/1347/p2p/12D3KooWKt8cwpkiumkT8x32c3YFxsPRwhV5J8hCYPn9mhUmcAXt /dns4/bootstrap-1.butterfly.fildev.network/tcp/1347/p2p/12D3KooWGKRzEY4tJFTmAmrYUpa1CVVohmV9YjJbC9v5XWY2gUji
+2 -2
View File
@@ -1,2 +1,2 @@
/dns4/bootstrap-0.interop.fildev.network/tcp/1347/p2p/12D3KooWPfaWdJjpPTQp5kSqsqvauJaM4cFz5NWja7qyjx7vVfjL /dns4/bootstrap-0.interop.fildev.network/tcp/1347/p2p/12D3KooWLGPq9JL1xwL6gHok7HSNxtK1Q5kyfg4Hk69ifRPghn4i
/dns4/bootstrap-1.interop.fildev.network/tcp/1347/p2p/12D3KooWS5tjcL6s4hHZ1HVRTgGKaXpKkiHfbBSJdjbzgejgJpEh /dns4/bootstrap-1.interop.fildev.network/tcp/1347/p2p/12D3KooWFYS1f31zafv8mqqYu8U3hEqYvaZ6avWzYU3BmZdpyH3h
+4
View File
@@ -0,0 +1,4 @@
/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.
-6
View File
@@ -1,6 +0,0 @@
package build
var (
DefaultFDLimit uint64 = 16 << 10
MinerFDLimit uint64 = 100_000
)
Binary file not shown.
Binary file not shown.
Binary file not shown.
-2
View File
@@ -1,4 +1,3 @@
//stm: #unit
package build package build
import ( import (
@@ -8,7 +7,6 @@ import (
) )
func TestOpenRPCDiscoverJSON_Version(t *testing.T) { func TestOpenRPCDiscoverJSON_Version(t *testing.T) {
//stm: @OTHER_IMPLEMENTATION_OPENRPC_VERSION_001
// openRPCDocVersion is the current OpenRPC version of the API docs. // openRPCDocVersion is the current OpenRPC version of the API docs.
openRPCDocVersion := "1.2.6" openRPCDocVersion := "1.2.6"
-183
View File
@@ -1,183 +0,0 @@
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"))
}
+1 -11
View File
@@ -1,4 +1,3 @@
//go:build debug || 2k
// +build debug 2k // +build debug 2k
package build package build
@@ -10,15 +9,12 @@ import (
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/actors/policy"
) )
const BootstrappersFile = "" const BootstrappersFile = ""
const GenesisFile = "" const GenesisFile = ""
const GenesisNetworkVersion = network.Version15
var UpgradeBreezeHeight = abi.ChainEpoch(-1) var UpgradeBreezeHeight = abi.ChainEpoch(-1)
const BreezeGasTampingDuration = 0 const BreezeGasTampingDuration = 0
@@ -32,6 +28,7 @@ var UpgradeAssemblyHeight = abi.ChainEpoch(-5)
var UpgradeLiftoffHeight = abi.ChainEpoch(-6) var UpgradeLiftoffHeight = abi.ChainEpoch(-6)
var UpgradeKumquatHeight = abi.ChainEpoch(-7) var UpgradeKumquatHeight = abi.ChainEpoch(-7)
var UpgradePricelistOopsHeight = abi.ChainEpoch(-8)
var UpgradeCalicoHeight = abi.ChainEpoch(-9) var UpgradeCalicoHeight = abi.ChainEpoch(-9)
var UpgradePersianHeight = abi.ChainEpoch(-10) var UpgradePersianHeight = abi.ChainEpoch(-10)
var UpgradeOrangeHeight = abi.ChainEpoch(-11) var UpgradeOrangeHeight = abi.ChainEpoch(-11)
@@ -45,10 +42,6 @@ var UpgradeTurboHeight = abi.ChainEpoch(-15)
var UpgradeHyperdriveHeight = abi.ChainEpoch(-16) var UpgradeHyperdriveHeight = abi.ChainEpoch(-16)
var UpgradeChocolateHeight = abi.ChainEpoch(-17)
var UpgradeOhSnapHeight = abi.ChainEpoch(-18)
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet, 0: DrandMainnet,
} }
@@ -89,11 +82,8 @@ func init() {
UpgradeNorwegianHeight = getUpgradeHeight("LOTUS_NORWEGIAN_HEIGHT", UpgradeNorwegianHeight) UpgradeNorwegianHeight = getUpgradeHeight("LOTUS_NORWEGIAN_HEIGHT", UpgradeNorwegianHeight)
UpgradeTurboHeight = getUpgradeHeight("LOTUS_ACTORSV4_HEIGHT", UpgradeTurboHeight) UpgradeTurboHeight = getUpgradeHeight("LOTUS_ACTORSV4_HEIGHT", UpgradeTurboHeight)
UpgradeHyperdriveHeight = getUpgradeHeight("LOTUS_HYPERDRIVE_HEIGHT", UpgradeHyperdriveHeight) UpgradeHyperdriveHeight = getUpgradeHeight("LOTUS_HYPERDRIVE_HEIGHT", UpgradeHyperdriveHeight)
UpgradeChocolateHeight = getUpgradeHeight("LOTUS_CHOCOLATE_HEIGHT", UpgradeChocolateHeight)
UpgradeOhSnapHeight = getUpgradeHeight("LOTUS_OHSNAP_HEIGHT", UpgradeOhSnapHeight)
BuildType |= Build2k BuildType |= Build2k
} }
const BlockDelaySecs = uint64(4) const BlockDelaySecs = uint64(4)
+13 -23
View File
@@ -1,4 +1,3 @@
//go:build butterflynet
// +build butterflynet // +build butterflynet
package build package build
@@ -6,7 +5,6 @@ package build
import ( import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/actors/policy"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@@ -16,8 +14,6 @@ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet, 0: DrandMainnet,
} }
const GenesisNetworkVersion = network.Version14
const BootstrappersFile = "butterflynet.pi" const BootstrappersFile = "butterflynet.pi"
const GenesisFile = "butterflynet.car" const GenesisFile = "butterflynet.car"
@@ -27,36 +23,30 @@ const UpgradeSmokeHeight = -2
const UpgradeIgnitionHeight = -3 const UpgradeIgnitionHeight = -3
const UpgradeRefuelHeight = -4 const UpgradeRefuelHeight = -4
var UpgradeAssemblyHeight = abi.ChainEpoch(-5) var UpgradeAssemblyHeight = abi.ChainEpoch(30)
const UpgradeTapeHeight = -6 const UpgradeTapeHeight = 60
const UpgradeLiftoffHeight = -7 const UpgradeLiftoffHeight = -5
const UpgradeKumquatHeight = -8 const UpgradeKumquatHeight = 90
const UpgradeCalicoHeight = -9 const UpgradePricelistOopsHeight = 119
const UpgradePersianHeight = -10 const UpgradeCalicoHeight = 120
const UpgradeClausHeight = -11 const UpgradePersianHeight = 150
const UpgradeOrangeHeight = -12 const UpgradeClausHeight = 180
const UpgradeTrustHeight = -13 const UpgradeOrangeHeight = 210
const UpgradeNorwegianHeight = -14 const UpgradeTrustHeight = 240
const UpgradeTurboHeight = -15 const UpgradeNorwegianHeight = UpgradeTrustHeight + (builtin2.EpochsInHour * 12)
const UpgradeHyperdriveHeight = -16 const UpgradeTurboHeight = 8922
const UpgradeChocolateHeight = -17 const UpgradeHyperdriveHeight = 9999999
const UpgradeOhSnapHeight = 240
func init() { func init() {
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2 << 30)) policy.SetConsensusMinerMinPower(abi.NewStoragePower(2 << 30))
policy.SetSupportedProofTypes( policy.SetSupportedProofTypes(
abi.RegisteredSealProof_StackedDrg512MiBV1, abi.RegisteredSealProof_StackedDrg512MiBV1,
abi.RegisteredSealProof_StackedDrg32GiBV1,
abi.RegisteredSealProof_StackedDrg64GiBV1,
) )
SetAddressNetwork(address.Testnet) SetAddressNetwork(address.Testnet)
Devnet = true Devnet = true
BuildType = BuildButterflynet
} }
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds) const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
+2 -10
View File
@@ -1,4 +1,3 @@
//go:build calibnet
// +build calibnet // +build calibnet
package build package build
@@ -6,7 +5,6 @@ package build
import ( import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/actors/policy"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@@ -16,8 +14,6 @@ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet, 0: DrandMainnet,
} }
const GenesisNetworkVersion = network.Version0
const BootstrappersFile = "calibnet.pi" const BootstrappersFile = "calibnet.pi"
const GenesisFile = "calibnet.car" const GenesisFile = "calibnet.car"
@@ -37,6 +33,8 @@ const UpgradeLiftoffHeight = -5
const UpgradeKumquatHeight = 90 const UpgradeKumquatHeight = 90
const UpgradePricelistOopsHeight = 119
const UpgradeCalicoHeight = 120 const UpgradeCalicoHeight = 120
const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 1) const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 1)
@@ -52,11 +50,6 @@ const UpgradeTurboHeight = 390
const UpgradeHyperdriveHeight = 420 const UpgradeHyperdriveHeight = 420
const UpgradeChocolateHeight = 312746
// 2022-02-10T19:23:00Z
const UpgradeOhSnapHeight = 682006
func init() { func init() {
policy.SetConsensusMinerMinPower(abi.NewStoragePower(32 << 30)) policy.SetConsensusMinerMinPower(abi.NewStoragePower(32 << 30))
policy.SetSupportedProofTypes( policy.SetSupportedProofTypes(
@@ -69,7 +62,6 @@ func init() {
Devnet = true Devnet = true
BuildType = BuildCalibnet BuildType = BuildCalibnet
} }
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds) const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
-1
View File
@@ -1,4 +1,3 @@
//go:build debug
// +build debug // +build debug
package build package build
+11 -20
View File
@@ -1,4 +1,3 @@
//go:build interopnet
// +build interopnet // +build interopnet
package build package build
@@ -11,15 +10,14 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/actors/policy"
) )
const BootstrappersFile = "interopnet.pi" const BootstrappersFile = "interopnet.pi"
const GenesisFile = "interopnet.car" const GenesisFile = "interopnet.car"
const GenesisNetworkVersion = network.Version15
var UpgradeBreezeHeight = abi.ChainEpoch(-1) var UpgradeBreezeHeight = abi.ChainEpoch(-1)
const BreezeGasTampingDuration = 0 const BreezeGasTampingDuration = 0
@@ -33,6 +31,7 @@ var UpgradeAssemblyHeight = abi.ChainEpoch(-5)
var UpgradeLiftoffHeight = abi.ChainEpoch(-6) var UpgradeLiftoffHeight = abi.ChainEpoch(-6)
var UpgradeKumquatHeight = abi.ChainEpoch(-7) var UpgradeKumquatHeight = abi.ChainEpoch(-7)
var UpgradePricelistOopsHeight = abi.ChainEpoch(-8)
var UpgradeCalicoHeight = abi.ChainEpoch(-9) var UpgradeCalicoHeight = abi.ChainEpoch(-9)
var UpgradePersianHeight = abi.ChainEpoch(-10) var UpgradePersianHeight = abi.ChainEpoch(-10)
var UpgradeOrangeHeight = abi.ChainEpoch(-11) var UpgradeOrangeHeight = abi.ChainEpoch(-11)
@@ -45,26 +44,21 @@ var UpgradeNorwegianHeight = abi.ChainEpoch(-14)
var UpgradeTurboHeight = abi.ChainEpoch(-15) var UpgradeTurboHeight = abi.ChainEpoch(-15)
var UpgradeHyperdriveHeight = abi.ChainEpoch(-16) var UpgradeHyperdriveHeight = abi.ChainEpoch(-16)
var UpgradeChocolateHeight = abi.ChainEpoch(-17)
var UpgradeOhSnapHeight = abi.ChainEpoch(-18)
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet, 0: DrandMainnet,
} }
func init() { func init() {
policy.SetSupportedProofTypes(
abi.RegisteredSealProof_StackedDrg2KiBV1,
abi.RegisteredSealProof_StackedDrg8MiBV1,
abi.RegisteredSealProof_StackedDrg512MiBV1,
)
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256)) policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
policy.SetPreCommitChallengeDelay(abi.ChainEpoch(10)) policy.SetPreCommitChallengeDelay(abi.ChainEpoch(10))
InsecurePoStValidation = true
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2 << 30))
policy.SetSupportedProofTypes(
abi.RegisteredSealProof_StackedDrg512MiBV1,
abi.RegisteredSealProof_StackedDrg32GiBV1,
abi.RegisteredSealProof_StackedDrg64GiBV1,
)
getUpgradeHeight := func(ev string, def abi.ChainEpoch) abi.ChainEpoch { getUpgradeHeight := func(ev string, def abi.ChainEpoch) abi.ChainEpoch {
hs, found := os.LookupEnv(ev) hs, found := os.LookupEnv(ev)
if found { if found {
@@ -95,18 +89,15 @@ func init() {
UpgradeNorwegianHeight = getUpgradeHeight("LOTUS_NORWEGIAN_HEIGHT", UpgradeNorwegianHeight) UpgradeNorwegianHeight = getUpgradeHeight("LOTUS_NORWEGIAN_HEIGHT", UpgradeNorwegianHeight)
UpgradeTurboHeight = getUpgradeHeight("LOTUS_ACTORSV4_HEIGHT", UpgradeTurboHeight) UpgradeTurboHeight = getUpgradeHeight("LOTUS_ACTORSV4_HEIGHT", UpgradeTurboHeight)
UpgradeHyperdriveHeight = getUpgradeHeight("LOTUS_HYPERDRIVE_HEIGHT", UpgradeHyperdriveHeight) UpgradeHyperdriveHeight = getUpgradeHeight("LOTUS_HYPERDRIVE_HEIGHT", UpgradeHyperdriveHeight)
UpgradeChocolateHeight = getUpgradeHeight("LOTUS_CHOCOLATE_HEIGHT", UpgradeChocolateHeight)
UpgradeOhSnapHeight = getUpgradeHeight("LOTUS_OHSNAP_HEIGHT", UpgradeOhSnapHeight)
BuildType |= BuildInteropnet BuildType |= BuildInteropnet
SetAddressNetwork(address.Testnet) SetAddressNetwork(address.Testnet)
Devnet = true Devnet = true
} }
const BlockDelaySecs = uint64(5) const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
const PropagationDelaySecs = uint64(1) const PropagationDelaySecs = uint64(6)
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start // BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
const BootstrapPeerThreshold = 2 const BootstrapPeerThreshold = 2
+11 -15
View File
@@ -1,5 +1,10 @@
//go:build !debug && !2k && !testground && !calibnet && !nerpanet && !butterflynet && !interopnet // +build !debug
// +build !debug,!2k,!testground,!calibnet,!nerpanet,!butterflynet,!interopnet // +build !2k
// +build !testground
// +build !calibnet
// +build !nerpanet
// +build !butterflynet
// +build !interopnet
package build package build
@@ -7,8 +12,6 @@ import (
"math" "math"
"os" "os"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
@@ -19,8 +22,6 @@ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
UpgradeSmokeHeight: DrandMainnet, UpgradeSmokeHeight: DrandMainnet,
} }
const GenesisNetworkVersion = network.Version0
const BootstrappersFile = "mainnet.pi" const BootstrappersFile = "mainnet.pi"
const GenesisFile = "mainnet.car" const GenesisFile = "mainnet.car"
@@ -44,6 +45,7 @@ const UpgradeLiftoffHeight = 148888
const UpgradeKumquatHeight = 170000 const UpgradeKumquatHeight = 170000
const UpgradePricelistOopsHeight = 265199
const UpgradeCalicoHeight = 265200 const UpgradeCalicoHeight = 265200
const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 60) const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 60)
@@ -62,21 +64,15 @@ const UpgradeNorwegianHeight = 665280
const UpgradeTurboHeight = 712320 const UpgradeTurboHeight = 712320
// 2021-06-30T22:00:00Z // 2021-06-30T22:00:00Z
const UpgradeHyperdriveHeight = 892800 var UpgradeHyperdriveHeight = abi.ChainEpoch(892800)
// 2021-10-26T13:30:00Z
const UpgradeChocolateHeight = 1231620
// 2022-03-01T15:00:00Z
var UpgradeOhSnapHeight = abi.ChainEpoch(1594680)
func init() { func init() {
if os.Getenv("LOTUS_USE_TEST_ADDRESSES") != "1" { if os.Getenv("LOTUS_USE_TEST_ADDRESSES") != "1" {
SetAddressNetwork(address.Mainnet) SetAddressNetwork(address.Mainnet)
} }
if os.Getenv("LOTUS_DISABLE_SNAPDEALS") == "1" { if os.Getenv("LOTUS_DISABLE_HYPERDRIVE") == "1" {
UpgradeOhSnapHeight = math.MaxInt64 UpgradeHyperdriveHeight = math.MaxInt64
} }
Devnet = false Devnet = false
+1 -9
View File
@@ -1,11 +1,9 @@
//go:build nerpanet
// +build nerpanet // +build nerpanet
package build package build
import ( import (
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@@ -16,8 +14,6 @@ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet, 0: DrandMainnet,
} }
const GenesisNetworkVersion = network.Version0
const BootstrappersFile = "nerpanet.pi" const BootstrappersFile = "nerpanet.pi"
const GenesisFile = "nerpanet.car" const GenesisFile = "nerpanet.car"
@@ -36,6 +32,7 @@ const UpgradeTapeHeight = 60
const UpgradeKumquatHeight = 90 const UpgradeKumquatHeight = 90
const UpgradePricelistOopsHeight = 99
const UpgradeCalicoHeight = 100 const UpgradeCalicoHeight = 100
const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 1) const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 1)
@@ -48,8 +45,6 @@ const UpgradeNorwegianHeight = 201000
const UpgradeTurboHeight = 203000 const UpgradeTurboHeight = 203000
const UpgradeHyperdriveHeight = 379178 const UpgradeHyperdriveHeight = 379178
const UpgradeChocolateHeight = 999999999
func init() { func init() {
// Minimum block production power is set to 4 TiB // Minimum block production power is set to 4 TiB
// Rationale is to discourage small-scale miners from trying to take over the network // Rationale is to discourage small-scale miners from trying to take over the network
@@ -72,9 +67,6 @@ func init() {
//miner.WPoStChallengeLookback = abi.ChainEpoch(2) //miner.WPoStChallengeLookback = abi.ChainEpoch(2)
Devnet = false Devnet = false
BuildType = BuildNerpanet
} }
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds) const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
-11
View File
@@ -13,17 +13,6 @@ import (
func BlocksTopic(netName dtypes.NetworkName) string { return "/fil/blocks/" + string(netName) } func BlocksTopic(netName dtypes.NetworkName) string { return "/fil/blocks/" + string(netName) }
func MessagesTopic(netName dtypes.NetworkName) string { return "/fil/msgs/" + string(netName) } func MessagesTopic(netName dtypes.NetworkName) string { return "/fil/msgs/" + string(netName) }
func IndexerIngestTopic(netName dtypes.NetworkName) string {
nn := string(netName)
// The network name testnetnet is here for historical reasons.
// Going forward we aim to use the name `mainnet` where possible.
if nn == "testnetnet" {
nn = "mainnet"
}
return "/indexer/ingest/" + nn
}
func DhtProtocolName(netName dtypes.NetworkName) protocol.ID { func DhtProtocolName(netName dtypes.NetworkName) protocol.ID {
return protocol.ID("/fil/kad/" + string(netName)) return protocol.ID("/fil/kad/" + string(netName))
} }
+2 -12
View File
@@ -1,4 +1,3 @@
//go:build !testground
// +build !testground // +build !testground
package build package build
@@ -26,17 +25,8 @@ const UnixfsLinksPerLevel = 1024
// Consensus / Network // Consensus / Network
const AllowableClockDriftSecs = uint64(1) const AllowableClockDriftSecs = uint64(1)
const NewestNetworkVersion = network.Version13
// TODO: This is still terrible...What's the impact of updating this before mainnet actually upgrades const ActorUpgradeNetworkVersion = network.Version4
/* inline-gen template
const NewestNetworkVersion = network.Version{{.latestNetworkVersion}}
/* inline-gen start */
const NewestNetworkVersion = network.Version15
/* inline-gen end */
// Epochs // Epochs
const ForkLengthThreshold = Finality const ForkLengthThreshold = Finality
+18 -22
View File
@@ -1,4 +1,3 @@
//go:build testground
// +build testground // +build testground
// This file makes hardcoded parameters (const) configurable as vars. // This file makes hardcoded parameters (const) configurable as vars.
@@ -83,32 +82,29 @@ var (
UpgradeBreezeHeight abi.ChainEpoch = -1 UpgradeBreezeHeight abi.ChainEpoch = -1
BreezeGasTampingDuration abi.ChainEpoch = 0 BreezeGasTampingDuration abi.ChainEpoch = 0
UpgradeSmokeHeight abi.ChainEpoch = -1 UpgradeSmokeHeight abi.ChainEpoch = -1
UpgradeIgnitionHeight abi.ChainEpoch = -2 UpgradeIgnitionHeight abi.ChainEpoch = -2
UpgradeRefuelHeight abi.ChainEpoch = -3 UpgradeRefuelHeight abi.ChainEpoch = -3
UpgradeTapeHeight abi.ChainEpoch = -4 UpgradeTapeHeight abi.ChainEpoch = -4
UpgradeAssemblyHeight abi.ChainEpoch = 10 UpgradeAssemblyHeight abi.ChainEpoch = 10
UpgradeLiftoffHeight abi.ChainEpoch = -5 UpgradeLiftoffHeight abi.ChainEpoch = -5
UpgradeKumquatHeight abi.ChainEpoch = -6 UpgradeKumquatHeight abi.ChainEpoch = -6
UpgradeCalicoHeight abi.ChainEpoch = -8 UpgradePricelistOopsHeight abi.ChainEpoch = -7
UpgradePersianHeight abi.ChainEpoch = -9 UpgradeCalicoHeight abi.ChainEpoch = -8
UpgradeOrangeHeight abi.ChainEpoch = -10 UpgradePersianHeight abi.ChainEpoch = -9
UpgradeClausHeight abi.ChainEpoch = -11 UpgradeOrangeHeight abi.ChainEpoch = -10
UpgradeTrustHeight abi.ChainEpoch = -12 UpgradeClausHeight abi.ChainEpoch = -11
UpgradeNorwegianHeight abi.ChainEpoch = -13 UpgradeTrustHeight abi.ChainEpoch = -12
UpgradeTurboHeight abi.ChainEpoch = -14 UpgradeNorwegianHeight abi.ChainEpoch = -13
UpgradeHyperdriveHeight abi.ChainEpoch = -15 UpgradeTurboHeight abi.ChainEpoch = -14
UpgradeChocolateHeight abi.ChainEpoch = -16 UpgradeHyperdriveHeight abi.ChainEpoch = -15
UpgradeOhSnapHeight abi.ChainEpoch = -17
DrandSchedule = map[abi.ChainEpoch]DrandEnum{ DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet, 0: DrandMainnet,
} }
GenesisNetworkVersion = network.Version0 NewestNetworkVersion = network.Version11
ActorUpgradeNetworkVersion = network.Version4
NewestNetworkVersion = network.Version15
ActorUpgradeNetworkVersion = network.Version15
Devnet = true Devnet = true
ZeroAddress = MustParseAddress("f3yaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaby2smx7a") ZeroAddress = MustParseAddress("f3yaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaby2smx7a")
-50
View File
@@ -1,54 +1,4 @@
{ {
"v28-empty-sector-update-merkletree-poseidon_hasher-8-0-0-61fa69f38b9cc771ba27b670124714b4ea77fbeae05e377fb859c4a43b73a30c.params": {
"cid": "Qma5WL6abSqYg9uUQAZ3EHS286bsNsha7oAGsJBD48Bq2q",
"digest": "c3ad7bb549470b82ad52ed070aebb4f4",
"sector_size": 536870912
},
"v28-empty-sector-update-merkletree-poseidon_hasher-8-0-0-61fa69f38b9cc771ba27b670124714b4ea77fbeae05e377fb859c4a43b73a30c.vk": {
"cid": "QmUa7f9JtJMsqJJ3s3ZXk6WyF4xJLE8FiqYskZGgk8GCDv",
"digest": "994c5b7d450ca9da348c910689f2dc7f",
"sector_size": 536870912
},
"v28-empty-sector-update-merkletree-poseidon_hasher-8-0-0-92180959e1918d26350b8e6cfe217bbdd0a2d8de51ebec269078b364b715ad63.params": {
"cid": "QmQiT4qBGodrVNEgVTDXxBNDdPbaD8Ag7Sx3ZTq1zHX79S",
"digest": "5aedd2cf3e5c0a15623d56a1b43110ad",
"sector_size": 8388608
},
"v28-empty-sector-update-merkletree-poseidon_hasher-8-0-0-92180959e1918d26350b8e6cfe217bbdd0a2d8de51ebec269078b364b715ad63.vk": {
"cid": "QmdcpKUQvHM8RFRVKbk1yHfEqMcBzhtFWKRp9SNEmWq37i",
"digest": "abd80269054d391a734febdac0d2e687",
"sector_size": 8388608
},
"v28-empty-sector-update-merkletree-poseidon_hasher-8-0-0-fb9e095bebdd77511c0269b967b4d87ba8b8a525edaa0e165de23ba454510194.params": {
"cid": "QmYM6Hg7mjmvA3ZHTsqkss1fkdyDju5dDmLiBZGJ5pz9y9",
"digest": "311f92a3e75036ced01b1c0025f1fa0c",
"sector_size": 2048
},
"v28-empty-sector-update-merkletree-poseidon_hasher-8-0-0-fb9e095bebdd77511c0269b967b4d87ba8b8a525edaa0e165de23ba454510194.vk": {
"cid": "QmaQsTLL3nc5dw6wAvaioJSBfd1jhQrA2o6ucFf7XeV74P",
"digest": "eadad9784969890d30f2749708c79771",
"sector_size": 2048
},
"v28-empty-sector-update-merkletree-poseidon_hasher-8-8-0-3b7f44a9362e3985369454947bc94022e118211e49fd672d52bec1cbfd599d18.params": {
"cid": "QmNPc75iEfcahCwNKdqnWLtxnjspUGGR4iscjiz3wP3RtS",
"digest": "1b3cfd761a961543f9eb273e435a06a2",
"sector_size": 34359738368
},
"v28-empty-sector-update-merkletree-poseidon_hasher-8-8-0-3b7f44a9362e3985369454947bc94022e118211e49fd672d52bec1cbfd599d18.vk": {
"cid": "QmdFFUe1gcz9MMHc6YW8aoV48w4ckvcERjt7PkydQAMfCN",
"digest": "3a6941983754737fde880d29c7094905",
"sector_size": 34359738368
},
"v28-empty-sector-update-merkletree-poseidon_hasher-8-8-2-102e1444a7e9a97ebf1e3d6855dcc77e66c011ea66f936d9b2c508f87f2f83a7.params": {
"cid": "QmUB6xTVjzBQGuDNeyJMrrJ1byk58vhPm8eY2Lv9pgwanp",
"digest": "1a392e7b759fb18e036c7559b5ece816",
"sector_size": 68719476736
},
"v28-empty-sector-update-merkletree-poseidon_hasher-8-8-2-102e1444a7e9a97ebf1e3d6855dcc77e66c011ea66f936d9b2c508f87f2f83a7.vk": {
"cid": "Qmd794Jty7k26XJ8Eg4NDEks65Qk8G4GVfGkwqvymv8HAg",
"digest": "80e366df2f1011953c2d01c7b7c9ee8e",
"sector_size": 68719476736
},
"v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-0170db1f394b35d995252228ee359194b13199d259380541dc529fb0099096b0.params": { "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-0170db1f394b35d995252228ee359194b13199d259380541dc529fb0099096b0.params": {
"cid": "QmVxjFRyhmyQaZEtCh7nk2abc7LhFkzhnRX4rcHqCCpikR", "cid": "QmVxjFRyhmyQaZEtCh7nk2abc7LhFkzhnRX4rcHqCCpikR",
"digest": "7610b9f82bfc88405b7a832b651ce2f6", "digest": "7610b9f82bfc88405b7a832b651ce2f6",
+1 -2
View File
@@ -1,5 +1,4 @@
//go:build tools //+build tools
// +build tools
package build package build
+10 -13
View File
@@ -6,16 +6,15 @@ var CurrentCommit string
var BuildType int var BuildType int
const ( const (
BuildDefault = 0 BuildDefault = 0
BuildMainnet = 0x1 BuildMainnet = 0x1
Build2k = 0x2 Build2k = 0x2
BuildDebug = 0x3 BuildDebug = 0x3
BuildCalibnet = 0x4 BuildCalibnet = 0x4
BuildInteropnet = 0x5 BuildInteropnet = 0x5
BuildButterflynet = 0x7
) )
func BuildTypeString() string { func buildType() string {
switch BuildType { switch BuildType {
case BuildDefault: case BuildDefault:
return "" return ""
@@ -29,20 +28,18 @@ func BuildTypeString() string {
return "+calibnet" return "+calibnet"
case BuildInteropnet: case BuildInteropnet:
return "+interopnet" return "+interopnet"
case BuildButterflynet:
return "+butterflynet"
default: default:
return "+huh?" return "+huh?"
} }
} }
// BuildVersion is the local build version // BuildVersion is the local build version, set by build system
const BuildVersion = "1.15.2-dev" const BuildVersion = "1.11.1-rc1"
func UserVersion() string { func UserVersion() string {
if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" {
return BuildVersion return BuildVersion
} }
return BuildVersion + BuildTypeString() + CurrentCommit return BuildVersion + buildType() + CurrentCommit
} }
-3
View File
@@ -1,4 +1,3 @@
//stm: #unit
package adt package adt
import ( import (
@@ -45,7 +44,6 @@ func TestDiffAdtArray(t *testing.T) {
changes := new(TestDiffArray) changes := new(TestDiffArray)
//stm: @CHAIN_ADT_ARRAY_DIFF_001
assert.NoError(t, DiffAdtArray(arrA, arrB, changes)) assert.NoError(t, DiffAdtArray(arrA, arrB, changes))
assert.NotNil(t, changes) assert.NotNil(t, changes)
@@ -100,7 +98,6 @@ func TestDiffAdtMap(t *testing.T) {
changes := new(TestDiffMap) changes := new(TestDiffMap)
//stm: @CHAIN_ADT_MAP_DIFF_001
assert.NoError(t, DiffAdtMap(mapA, mapB, changes)) assert.NoError(t, DiffAdtMap(mapA, mapB, changes))
assert.NotNil(t, changes) assert.NotNil(t, changes)
-3
View File
@@ -1,4 +1,3 @@
//stm: #unit
package aerrors_test package aerrors_test
import ( import (
@@ -12,7 +11,6 @@ import (
) )
func TestFatalError(t *testing.T) { func TestFatalError(t *testing.T) {
//stm: @OTHER_IMPLEMENTATION_ACTOR_ERRORS_001
e1 := xerrors.New("out of disk space") e1 := xerrors.New("out of disk space")
e2 := xerrors.Errorf("could not put node: %w", e1) e2 := xerrors.Errorf("could not put node: %w", e1)
e3 := xerrors.Errorf("could not save head: %w", e2) e3 := xerrors.Errorf("could not save head: %w", e2)
@@ -26,7 +24,6 @@ func TestFatalError(t *testing.T) {
assert.True(t, IsFatal(aw4), "should be fatal") assert.True(t, IsFatal(aw4), "should be fatal")
} }
func TestAbsorbeError(t *testing.T) { func TestAbsorbeError(t *testing.T) {
//stm: @OTHER_IMPLEMENTATION_ACTOR_ERRORS_001
e1 := xerrors.New("EOF") e1 := xerrors.New("EOF")
e2 := xerrors.Errorf("could not decode: %w", e1) e2 := xerrors.Errorf("could not decode: %w", e1)
ae := Absorb(e2, 35, "failed to decode CBOR") ae := Absorb(e2, 35, "failed to decode CBOR")

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