diff --git a/.circleci/config.yml b/.circleci/config.yml index e674b2289..3f676c7b3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -23,11 +23,6 @@ executors: commands: - install-deps: - steps: - - run: | - sudo apt update - sudo apt install python-is-python3 prepare: parameters: linux: @@ -41,9 +36,8 @@ commands: steps: - checkout - git_fetch_all_tags - - checkout - when: - condition: << parameters.linux >> + condition: <> steps: - run: name: Check Go Version @@ -56,6 +50,8 @@ commands: fi - run: sudo apt-get update - run: sudo apt-get install ocl-icd-opencl-dev libhwloc-dev + - run: sudo apt-get install python-is-python3 + - when: condition: <> steps: @@ -70,21 +66,12 @@ commands: echo 'export GOPATH="${HOME}/go"' >> $BASH_ENV - run: go version - run: - name: Install pkg-config, goreleaser, and sha512sum - command: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config goreleaser/tap/goreleaser coreutils + name: Install dependencies with Homebrew + command: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config coreutils jq hwloc - run: name: Install Rust command: | curl https://sh.rustup.rs -sSf | sh -s -- -y - - run: - name: Install hwloc - command: | - mkdir ~/hwloc - curl --location https://download.open-mpi.org/release/hwloc/v2.4/hwloc-2.4.1.tar.gz --output ~/hwloc/hwloc-2.4.1.tar.gz - cd ~/hwloc - tar -xvzpf hwloc-2.4.1.tar.gz - cd hwloc-2.4.1 - ./configure && make && sudo make install - run: git submodule sync - run: git submodule update --init download-params: @@ -104,28 +91,13 @@ commands: install_ipfs: steps: - run: | - apt update - apt install -y wget - wget https://github.com/ipfs/go-ipfs/releases/download/v0.12.2/go-ipfs_v0.12.2_linux-amd64.tar.gz - wget https://github.com/ipfs/go-ipfs/releases/download/v0.12.2/go-ipfs_v0.12.2_linux-amd64.tar.gz.sha512 - if [ "$(sha512sum go-ipfs_v0.12.2_linux-amd64.tar.gz)" != "$(cat go-ipfs_v0.12.2_linux-amd64.tar.gz.sha512)" ] - then - echo "ipfs failed checksum check" - exit 1 - fi - tar -xf go-ipfs_v0.12.2_linux-amd64.tar.gz - mv go-ipfs/ipfs /usr/local/bin/ipfs - chmod +x /usr/local/bin/ipfs - install_ipfs_macos: - steps: - - run: | - curl -O https://dist.ipfs.io/kubo/v0.14.0/kubo_v0.14.0_darwin-amd64.tar.gz - tar -xvzf kubo_v0.14.0_darwin-amd64.tar.gz + curl -O https://dist.ipfs.tech/kubo/v0.16.0/kubo_v0.16.0_linux-amd64.tar.gz + tar -xvzf kubo_v0.16.0_linux-amd64.tar.gz pushd kubo sudo bash install.sh popd - rm -rf kubo/ - rm kubo_v0.14.0_darwin-amd64.tar.gz + rm -rf kubo + rm kubo_v0.16.0_linux-amd64.tar.gz git_fetch_all_tags: steps: - run: @@ -150,13 +122,12 @@ commands: - run: name: "Run a packer build" command: packer build << parameters.args >> << parameters.template >> - no_output_timeout: 30m + no_output_timeout: 1h jobs: mod-tidy-check: executor: golang steps: - - install-deps - prepare - run: go mod tidy -v - run: @@ -164,37 +135,6 @@ jobs: command: | git --no-pager diff go.mod go.sum git --no-pager diff --quiet go.mod go.sum - build-linux: - executor: golang - steps: - - install-deps - - prepare - - run: sudo apt-get update - - run: sudo apt-get install npm - - run: - command: make buildall - - run: - name: check tag and version output match - command: ./scripts/version-check.sh ./lotus - - store_artifacts: - path: lotus - - store_artifacts: - path: lotus-miner - - store_artifacts: - path: lotus-worker - - run: mkdir linux && mv lotus lotus-miner lotus-worker linux/ - - persist_to_workspace: - root: "." - paths: - - linux - - build-debug: - executor: golang - steps: - - install-deps - - prepare - - run: - command: make debug test: description: | @@ -224,7 +164,6 @@ jobs: description: gotestsum format. https://github.com/gotestyourself/gotestsum#format executor: << parameters.executor >> steps: - - install-deps - prepare - run: command: make deps lotus @@ -268,7 +207,6 @@ jobs: submodule is used. executor: << parameters.executor >> steps: - - install-deps - prepare - run: command: make deps lotus @@ -311,121 +249,104 @@ jobs: path: /tmp/test-reports - store_artifacts: path: /tmp/test-artifacts/conformance-coverage.html - build-ntwk-calibration: - description: | - Compile lotus binaries for the calibration network - parameters: - <<: *test-params - executor: << parameters.executor >> + + build-linux-amd64: + executor: golang steps: - - install-deps - prepare - - run: make calibnet - - run: mkdir linux-calibrationnet && mv lotus lotus-miner lotus-worker linux-calibrationnet + - run: make lotus lotus-miner lotus-worker + - run: + name: check tag and version output match + command: ./scripts/version-check.sh ./lotus + - run: | + mkdir -p /tmp/workspace/linux_amd64_v1 && \ + mv lotus lotus-miner lotus-worker /tmp/workspace/linux_amd64_v1/ - persist_to_workspace: - root: "." + root: /tmp/workspace paths: - - linux-calibrationnet - build-ntwk-butterfly: - description: | - Compile lotus binaries for the butterfly network - parameters: - <<: *test-params - executor: << parameters.executor >> - steps: - - install-deps - - prepare - - run: make butterflynet - - run: mkdir linux-butterflynet && mv lotus lotus-miner lotus-worker linux-butterflynet - - persist_to_workspace: - root: "." - paths: - - linux-butterflynet - build-lotus-soup: - description: | - Compile `lotus-soup` Testground test plan - parameters: - <<: *test-params - executor: << parameters.executor >> - steps: - - install-deps - - prepare - - run: cd extern/filecoin-ffi && make - - run: - name: "go get lotus@master" - command: cd testplans/lotus-soup && go mod edit -replace=github.com/filecoin-project/lotus=../.. && go mod tidy - - run: - name: "build lotus-soup testplan" - command: pushd testplans/lotus-soup && go build -tags=testground . - trigger-testplans: - description: | - Trigger `lotus-soup` test cases on TaaS - parameters: - <<: *test-params - executor: << parameters.executor >> - steps: - - install-deps - - prepare - - run: - name: "download testground" - command: wget https://gist.github.com/nonsense/5fbf3167cac79945f658771aed32fc44/raw/2e17eb0debf7ec6bdf027c1bdafc2c92dd97273b/testground-d3e9603 -O ~/testground-cli && chmod +x ~/testground-cli - - run: - name: "prepare .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: - 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 - - run: - name: "go get lotus@master" - command: cd testplans/lotus-soup && go get github.com/filecoin-project/lotus@master - - run: - name: "trigger deals baseline testplan on taas" - command: ~/testground-cli run composition -f $HOME/testground/plans/lotus-soup/_compositions/baseline-k8s-3-1.toml --metadata-commit=$CIRCLE_SHA1 --metadata-repo=filecoin-project/lotus --metadata-branch=$CIRCLE_BRANCH - - run: - name: "trigger payment channel stress testplan on taas" - command: ~/testground-cli run composition -f $HOME/testground/plans/lotus-soup/_compositions/paych-stress-k8s.toml --metadata-commit=$CIRCLE_SHA1 --metadata-repo=filecoin-project/lotus --metadata-branch=$CIRCLE_BRANCH - build-macos: + - linux_amd64_v1 + + build-darwin-amd64: description: build darwin lotus binary - parameters: - publish: - default: false - description: publish github release and homebrew? - type: boolean + working_directory: ~/go/src/github.com/filecoin-project/lotus macos: xcode: "13.4.1" - working_directory: ~/go/src/github.com/filecoin-project/lotus steps: - prepare: linux: false darwin: true - - install_ipfs_macos - - restore_cache: - name: restore cargo cache - key: v3-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.sum" }} + - run: make lotus lotus-miner lotus-worker + - run: + name: check tag and version output match + command: ./scripts/version-check.sh ./lotus + - run: | + mkdir -p /tmp/workspace/darwin_amd64_v1 && \ + mv lotus lotus-miner lotus-worker /tmp/workspace/darwin_amd64_v1/ + - persist_to_workspace: + root: /tmp/workspace + paths: + - darwin_amd64_v1 + + build-darwin-arm64: + description: self-hosted m1 runner + working_directory: ~/go/src/github.com/filecoin-project/lotus + machine: true + resource_class: filecoin-project/self-hosted-m1 + steps: + - run: echo 'export PATH=/opt/homebrew/bin:"$PATH"' >> "$BASH_ENV" + - prepare: + linux: false + darwin: true + - run: | + export CPATH=$(brew --prefix)/include + export LIBRARY_PATH=$(brew --prefix)/lib + make lotus lotus-miner lotus-worker + - run: + name: check tag and version output match + command: ./scripts/version-check.sh ./lotus + - run: | + mkdir -p /tmp/workspace/darwin_arm64 && \ + mv lotus lotus-miner lotus-worker /tmp/workspace/darwin_arm64/ + - persist_to_workspace: + root: /tmp/workspace + paths: + - darwin_arm64 + - run: + command: make clean + when: always + - run: + name: cleanup homebrew + command: HOMEBREW_NO_AUTO_UPDATE=1 brew uninstall pkg-config coreutils jq hwloc + when: always + + release: + executor: golang + parameters: + dry-run: + default: false + description: should this release actually publish it's artifacts? + type: boolean + steps: + - checkout + - run: | + echo 'deb [trusted=yes] https://repo.goreleaser.com/apt/ /' | sudo tee /etc/apt/sources.list.d/goreleaser.list + sudo apt update + sudo apt install goreleaser-pro + - install_ipfs + - attach_workspace: + at: /tmp/workspace - when: - condition: << parameters.publish >> + condition: << parameters.dry-run >> steps: - - run: goreleaser release --rm-dist + - run: goreleaser release --rm-dist --snapshot --debug - run: ./scripts/generate-checksums.sh - - run: ./scripts/publish-checksums.sh - when: condition: - not: << parameters.publish >> + not: << parameters.dry-run >> steps: - - run: goreleaser release --rm-dist --snapshot + - run: goreleaser release --rm-dist --debug - run: ./scripts/generate-checksums.sh - - store_artifacts: - path: dist - - persist_to_workspace: - root: "." - paths: - - dist - - save_cache: - name: save cargo cache - key: v3-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.sum" }} - paths: - - "~/.rustup" - - "~/.cargo" + - run: ./scripts/publish-checksums.sh build-appimage: machine: @@ -433,7 +354,7 @@ jobs: steps: - checkout - attach_workspace: - at: "." + at: /tmp/workspace - run: name: Update Go command: | @@ -468,13 +389,11 @@ jobs: command: | sed -i "s/version: latest/version: ${CIRCLE_TAG:-latest}/" AppImageBuilder.yml make appimage - - run: - name: prepare workspace - command: | - mkdir appimage - mv Lotus-*.AppImage appimage + - run: | + mkdir -p /tmp/workspace/appimage && \ + mv Lotus-*.AppImage /tmp/workspace/appimage/ - persist_to_workspace: - root: "." + root: /tmp/workspace paths: - appimage @@ -482,7 +401,6 @@ jobs: gofmt: executor: golang steps: - - install-deps - prepare - run: command: "! go fmt ./... 2>&1 | read" @@ -490,7 +408,6 @@ jobs: gen-check: executor: golang steps: - - install-deps - prepare - run: make deps - run: go install golang.org/x/tools/cmd/goimports @@ -505,7 +422,6 @@ jobs: docs-check: executor: golang steps: - - install-deps - prepare - run: go install golang.org/x/tools/cmd/goimports - run: zcat build/openrpc/full.json.gz | jq > ../pre-openrpc-full @@ -542,7 +458,6 @@ jobs: Arguments to pass to golangci-lint executor: << parameters.executor >> steps: - - install-deps - prepare - run: command: make deps @@ -570,13 +485,13 @@ jobs: steps: - run: name: Install git jq curl - command: apt update && apt install -y git jq curl + command: apt update && apt install -y git jq curl sudo - checkout - git_fetch_all_tags - checkout - install_ipfs - attach_workspace: - at: "." + at: /tmp/workspace - when: condition: << parameters.linux >> steps: @@ -751,8 +666,6 @@ jobs: name: packer steps: - checkout - - attach_workspace: - at: "." - packer_build: template: tools/packer/lotus-snap.pkr.hcl publish-dockerhub: @@ -896,6 +809,11 @@ workflows: suite: itest-deals_publish target: "./itests/deals_publish_test.go" + - test: + name: test-itest-deals_remote_retrieval + suite: itest-deals_remote_retrieval + target: "./itests/deals_remote_retrieval_test.go" + - test: name: test-itest-deals_retry_deal_no_funds suite: itest-deals_retry_deal_no_funds @@ -951,6 +869,11 @@ workflows: suite: itest-mpool_msg_uuid target: "./itests/mpool_msg_uuid_test.go" + - test: + name: test-itest-mpool_push_with_uuid + suite: itest-mpool_push_with_uuid + target: "./itests/mpool_push_with_uuid_test.go" + - test: name: test-itest-multisig suite: itest-multisig @@ -991,6 +914,11 @@ workflows: suite: itest-pending_deal_allocation target: "./itests/pending_deal_allocation_test.go" + - test: + name: test-itest-raft_messagesigner + suite: itest-raft_messagesigner + target: "./itests/raft_messagesigner_test.go" + - test: name: test-itest-remove_verifreg_datacap suite: itest-remove_verifreg_datacap @@ -1130,47 +1058,11 @@ workflows: suite: conformance-bleeding-edge target: "./conformance" vectors-branch: specs-actors-v7 - - trigger-testplans: - filters: - branches: - only: - - master - - build-debug - - build-linux: - filters: - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - build-ntwk-calibration: - filters: - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - build-ntwk-butterfly: - filters: - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - build-lotus-soup - - build-macos: - name: publish-macos - publish: true - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+$/ - - build-macos: - filters: - branches: - only: - - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ - tags: - only: - - /^v\d+\.\d+\.\d+-rc\d+$/ - - build-appimage: + + release: + jobs: + - build-linux-amd64: + name: "Build ( linux / amd64 )" filters: branches: only: @@ -1178,11 +1070,30 @@ workflows: tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - publish: - name: publish-linux - linux: true + - build-darwin-amd64: + name: "Build ( darwin / amd64 )" + filters: + branches: + only: + - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + - build-darwin-arm64: + name: "Build ( darwin / arm64 )" + filters: + branches: + only: + - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + - release: + name: "Release" requires: - - build-linux + - "Build ( darwin / amd64 )" + - "Build ( linux / amd64 )" + - "Build ( darwin / arm64 )" filters: branches: ignore: @@ -1190,11 +1101,31 @@ workflows: tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + - release: + name: "Release (dry-run)" + dry-run: true + requires: + - "Build ( darwin / amd64 )" + - "Build ( linux / amd64 )" + - "Build ( darwin / arm64 )" + filters: + branches: + only: + - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + - build-appimage: + name: "Build AppImage" + filters: + branches: + only: + - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish: - name: publish-appimage + name: "Publish AppImage" appimage: true requires: - - build-appimage + - "Build AppImage" filters: branches: ignore: @@ -1203,14 +1134,14 @@ workflows: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - build-and-push-image: - name: build-and-push/lotus-all-in-one + name: "Publish ECR (lotus-all-in-one)" dockerfile: Dockerfile.lotus path: . repo: lotus-dev tag: '${CIRCLE_SHA1:0:8}' target: lotus-all-in-one - build-and-push-image: - name: build-and-push/lotus-test + name: "Publish ECR (lotus-test)" dockerfile: Dockerfile.lotus path: . repo: lotus-test @@ -1261,7 +1192,7 @@ workflows: only: - /^v\d+\.\d+\.\d+-rc\d+$/ - publish-dockerhub: - name: publish-dockerhub + name: "Publish Dockerhub (stable)" tag: stable filters: branches: @@ -1269,7 +1200,17 @@ workflows: - /.*/ tags: only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + - /^v\d+\.\d+\.\d+$/ + - publish-dockerhub: + name: "Publish Dockerhub (candidate)" + tag: candidate + filters: + branches: + ignore: + - /.*/ + tags: + only: + - /^v\d+\.\d+\.\d+-rc\d+$/ nightly: triggers: @@ -1291,10 +1232,10 @@ workflows: - publish-dockerhub: name: publish-dockerhub-nightly tag: nightly - monthly: + biweekly: triggers: - schedule: - cron: "0 0 1 * *" + cron: "0 0 1,15 * *" filters: branches: only: diff --git a/.circleci/template.yml b/.circleci/template.yml index a632df6b9..5a2ef1b32 100644 --- a/.circleci/template.yml +++ b/.circleci/template.yml @@ -23,11 +23,6 @@ executors: commands: - install-deps: - steps: - - run: | - sudo apt update - sudo apt install python-is-python3 prepare: parameters: linux: @@ -41,9 +36,8 @@ commands: steps: - checkout - git_fetch_all_tags - - checkout - when: - condition: << parameters.linux >> + condition: <> steps: - run: name: Check Go Version @@ -56,6 +50,8 @@ commands: fi - run: sudo apt-get update - run: sudo apt-get install ocl-icd-opencl-dev libhwloc-dev + - run: sudo apt-get install python-is-python3 + - when: condition: <> steps: @@ -70,21 +66,12 @@ commands: echo 'export GOPATH="${HOME}/go"' >> $BASH_ENV - run: go version - run: - name: Install pkg-config, goreleaser, and sha512sum - command: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config goreleaser/tap/goreleaser coreutils + name: Install dependencies with Homebrew + command: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config coreutils jq hwloc - run: name: Install Rust command: | curl https://sh.rustup.rs -sSf | sh -s -- -y - - run: - name: Install hwloc - command: | - mkdir ~/hwloc - curl --location https://download.open-mpi.org/release/hwloc/v2.4/hwloc-2.4.1.tar.gz --output ~/hwloc/hwloc-2.4.1.tar.gz - cd ~/hwloc - tar -xvzpf hwloc-2.4.1.tar.gz - cd hwloc-2.4.1 - ./configure && make && sudo make install - run: git submodule sync - run: git submodule update --init download-params: @@ -104,28 +91,13 @@ commands: install_ipfs: steps: - run: | - apt update - apt install -y wget - wget https://github.com/ipfs/go-ipfs/releases/download/v0.12.2/go-ipfs_v0.12.2_linux-amd64.tar.gz - wget https://github.com/ipfs/go-ipfs/releases/download/v0.12.2/go-ipfs_v0.12.2_linux-amd64.tar.gz.sha512 - if [ "$(sha512sum go-ipfs_v0.12.2_linux-amd64.tar.gz)" != "$(cat go-ipfs_v0.12.2_linux-amd64.tar.gz.sha512)" ] - then - echo "ipfs failed checksum check" - exit 1 - fi - tar -xf go-ipfs_v0.12.2_linux-amd64.tar.gz - mv go-ipfs/ipfs /usr/local/bin/ipfs - chmod +x /usr/local/bin/ipfs - install_ipfs_macos: - steps: - - run: | - curl -O https://dist.ipfs.io/kubo/v0.14.0/kubo_v0.14.0_darwin-amd64.tar.gz - tar -xvzf kubo_v0.14.0_darwin-amd64.tar.gz + curl -O https://dist.ipfs.tech/kubo/v0.16.0/kubo_v0.16.0_linux-amd64.tar.gz + tar -xvzf kubo_v0.16.0_linux-amd64.tar.gz pushd kubo sudo bash install.sh popd - rm -rf kubo/ - rm kubo_v0.14.0_darwin-amd64.tar.gz + rm -rf kubo + rm kubo_v0.16.0_linux-amd64.tar.gz git_fetch_all_tags: steps: - run: @@ -150,13 +122,12 @@ commands: - run: name: "Run a packer build" command: packer build << parameters.args >> << parameters.template >> - no_output_timeout: 30m + no_output_timeout: 1h jobs: mod-tidy-check: executor: golang steps: - - install-deps - prepare - run: go mod tidy -v - run: @@ -164,37 +135,6 @@ jobs: command: | git --no-pager diff go.mod go.sum git --no-pager diff --quiet go.mod go.sum - build-linux: - executor: golang - steps: - - install-deps - - prepare - - run: sudo apt-get update - - run: sudo apt-get install npm - - run: - command: make buildall - - run: - name: check tag and version output match - command: ./scripts/version-check.sh ./lotus - - store_artifacts: - path: lotus - - store_artifacts: - path: lotus-miner - - store_artifacts: - path: lotus-worker - - run: mkdir linux && mv lotus lotus-miner lotus-worker linux/ - - persist_to_workspace: - root: "." - paths: - - linux - - build-debug: - executor: golang - steps: - - install-deps - - prepare - - run: - command: make debug test: description: | @@ -224,7 +164,6 @@ jobs: description: gotestsum format. https://github.com/gotestyourself/gotestsum#format executor: << parameters.executor >> steps: - - install-deps - prepare - run: command: make deps lotus @@ -268,7 +207,6 @@ jobs: submodule is used. executor: << parameters.executor >> steps: - - install-deps - prepare - run: command: make deps lotus @@ -311,121 +249,104 @@ jobs: path: /tmp/test-reports - store_artifacts: path: /tmp/test-artifacts/conformance-coverage.html - build-ntwk-calibration: - description: | - Compile lotus binaries for the calibration network - parameters: - <<: *test-params - executor: << parameters.executor >> + + build-linux-amd64: + executor: golang steps: - - install-deps - prepare - - run: make calibnet - - run: mkdir linux-calibrationnet && mv lotus lotus-miner lotus-worker linux-calibrationnet + - run: make lotus lotus-miner lotus-worker + - run: + name: check tag and version output match + command: ./scripts/version-check.sh ./lotus + - run: | + mkdir -p /tmp/workspace/linux_amd64_v1 && \ + mv lotus lotus-miner lotus-worker /tmp/workspace/linux_amd64_v1/ - persist_to_workspace: - root: "." + root: /tmp/workspace paths: - - linux-calibrationnet - build-ntwk-butterfly: - description: | - Compile lotus binaries for the butterfly network - parameters: - <<: *test-params - executor: << parameters.executor >> - steps: - - install-deps - - prepare - - run: make butterflynet - - run: mkdir linux-butterflynet && mv lotus lotus-miner lotus-worker linux-butterflynet - - persist_to_workspace: - root: "." - paths: - - linux-butterflynet - build-lotus-soup: - description: | - Compile `lotus-soup` Testground test plan - parameters: - <<: *test-params - executor: << parameters.executor >> - steps: - - install-deps - - prepare - - run: cd extern/filecoin-ffi && make - - run: - name: "go get lotus@master" - command: cd testplans/lotus-soup && go mod edit -replace=github.com/filecoin-project/lotus=../.. && go mod tidy - - run: - name: "build lotus-soup testplan" - command: pushd testplans/lotus-soup && go build -tags=testground . - trigger-testplans: - description: | - Trigger `lotus-soup` test cases on TaaS - parameters: - <<: *test-params - executor: << parameters.executor >> - steps: - - install-deps - - prepare - - run: - name: "download testground" - command: wget https://gist.github.com/nonsense/5fbf3167cac79945f658771aed32fc44/raw/2e17eb0debf7ec6bdf027c1bdafc2c92dd97273b/testground-d3e9603 -O ~/testground-cli && chmod +x ~/testground-cli - - run: - name: "prepare .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: - 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 - - run: - name: "go get lotus@master" - command: cd testplans/lotus-soup && go get github.com/filecoin-project/lotus@master - - run: - name: "trigger deals baseline testplan on taas" - command: ~/testground-cli run composition -f $HOME/testground/plans/lotus-soup/_compositions/baseline-k8s-3-1.toml --metadata-commit=$CIRCLE_SHA1 --metadata-repo=filecoin-project/lotus --metadata-branch=$CIRCLE_BRANCH - - run: - name: "trigger payment channel stress testplan on taas" - command: ~/testground-cli run composition -f $HOME/testground/plans/lotus-soup/_compositions/paych-stress-k8s.toml --metadata-commit=$CIRCLE_SHA1 --metadata-repo=filecoin-project/lotus --metadata-branch=$CIRCLE_BRANCH - build-macos: + - linux_amd64_v1 + + build-darwin-amd64: description: build darwin lotus binary - parameters: - publish: - default: false - description: publish github release and homebrew? - type: boolean + working_directory: ~/go/src/github.com/filecoin-project/lotus macos: xcode: "13.4.1" - working_directory: ~/go/src/github.com/filecoin-project/lotus steps: - prepare: linux: false darwin: true - - install_ipfs_macos - - restore_cache: - name: restore cargo cache - key: v3-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.sum" }} + - run: make lotus lotus-miner lotus-worker + - run: + name: check tag and version output match + command: ./scripts/version-check.sh ./lotus + - run: | + mkdir -p /tmp/workspace/darwin_amd64_v1 && \ + mv lotus lotus-miner lotus-worker /tmp/workspace/darwin_amd64_v1/ + - persist_to_workspace: + root: /tmp/workspace + paths: + - darwin_amd64_v1 + + build-darwin-arm64: + description: self-hosted m1 runner + working_directory: ~/go/src/github.com/filecoin-project/lotus + machine: true + resource_class: filecoin-project/self-hosted-m1 + steps: + - run: echo 'export PATH=/opt/homebrew/bin:"$PATH"' >> "$BASH_ENV" + - prepare: + linux: false + darwin: true + - run: | + export CPATH=$(brew --prefix)/include + export LIBRARY_PATH=$(brew --prefix)/lib + make lotus lotus-miner lotus-worker + - run: + name: check tag and version output match + command: ./scripts/version-check.sh ./lotus + - run: | + mkdir -p /tmp/workspace/darwin_arm64 && \ + mv lotus lotus-miner lotus-worker /tmp/workspace/darwin_arm64/ + - persist_to_workspace: + root: /tmp/workspace + paths: + - darwin_arm64 + - run: + command: make clean + when: always + - run: + name: cleanup homebrew + command: HOMEBREW_NO_AUTO_UPDATE=1 brew uninstall pkg-config coreutils jq hwloc + when: always + + release: + executor: golang + parameters: + dry-run: + default: false + description: should this release actually publish it's artifacts? + type: boolean + steps: + - checkout + - run: | + echo 'deb [trusted=yes] https://repo.goreleaser.com/apt/ /' | sudo tee /etc/apt/sources.list.d/goreleaser.list + sudo apt update + sudo apt install goreleaser-pro + - install_ipfs + - attach_workspace: + at: /tmp/workspace - when: - condition: << parameters.publish >> + condition: << parameters.dry-run >> steps: - - run: goreleaser release --rm-dist + - run: goreleaser release --rm-dist --snapshot --debug - run: ./scripts/generate-checksums.sh - - run: ./scripts/publish-checksums.sh - when: condition: - not: << parameters.publish >> + not: << parameters.dry-run >> steps: - - run: goreleaser release --rm-dist --snapshot + - run: goreleaser release --rm-dist --debug - run: ./scripts/generate-checksums.sh - - store_artifacts: - path: dist - - persist_to_workspace: - root: "." - paths: - - dist - - save_cache: - name: save cargo cache - key: v3-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.sum" }} - paths: - - "~/.rustup" - - "~/.cargo" + - run: ./scripts/publish-checksums.sh build-appimage: machine: @@ -433,7 +354,7 @@ jobs: steps: - checkout - attach_workspace: - at: "." + at: /tmp/workspace - run: name: Update Go command: | @@ -468,13 +389,11 @@ jobs: command: | sed -i "s/version: latest/version: ${CIRCLE_TAG:-latest}/" AppImageBuilder.yml make appimage - - run: - name: prepare workspace - command: | - mkdir appimage - mv Lotus-*.AppImage appimage + - run: | + mkdir -p /tmp/workspace/appimage && \ + mv Lotus-*.AppImage /tmp/workspace/appimage/ - persist_to_workspace: - root: "." + root: /tmp/workspace paths: - appimage @@ -482,7 +401,6 @@ jobs: gofmt: executor: golang steps: - - install-deps - prepare - run: command: "! go fmt ./... 2>&1 | read" @@ -490,7 +408,6 @@ jobs: gen-check: executor: golang steps: - - install-deps - prepare - run: make deps - run: go install golang.org/x/tools/cmd/goimports @@ -505,7 +422,6 @@ jobs: docs-check: executor: golang steps: - - install-deps - prepare - run: go install golang.org/x/tools/cmd/goimports - run: zcat build/openrpc/full.json.gz | jq > ../pre-openrpc-full @@ -542,7 +458,6 @@ jobs: Arguments to pass to golangci-lint executor: << parameters.executor >> steps: - - install-deps - prepare - run: command: make deps @@ -570,13 +485,13 @@ jobs: steps: - run: name: Install git jq curl - command: apt update && apt install -y git jq curl + command: apt update && apt install -y git jq curl sudo - checkout - git_fetch_all_tags - checkout - install_ipfs - attach_workspace: - at: "." + at: /tmp/workspace - when: condition: << parameters.linux >> steps: @@ -751,8 +666,6 @@ jobs: name: packer steps: - checkout - - attach_workspace: - at: "." - packer_build: template: tools/packer/lotus-snap.pkr.hcl publish-dockerhub: @@ -840,47 +753,11 @@ workflows: suite: conformance-bleeding-edge target: "./conformance" vectors-branch: specs-actors-v7 - - trigger-testplans: - filters: - branches: - only: - - master - - build-debug - - build-linux: - filters: - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - build-ntwk-calibration: - filters: - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - build-ntwk-butterfly: - filters: - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - build-lotus-soup - - build-macos: - name: publish-macos - publish: true - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+$/ - - build-macos: - filters: - branches: - only: - - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ - tags: - only: - - /^v\d+\.\d+\.\d+-rc\d+$/ - - build-appimage: + + release: + jobs: + - build-linux-amd64: + name: "Build ( linux / amd64 )" filters: branches: only: @@ -888,11 +765,30 @@ workflows: tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - publish: - name: publish-linux - linux: true + - build-darwin-amd64: + name: "Build ( darwin / amd64 )" + filters: + branches: + only: + - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + - build-darwin-arm64: + name: "Build ( darwin / arm64 )" + filters: + branches: + only: + - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + - release: + name: "Release" requires: - - build-linux + - "Build ( darwin / amd64 )" + - "Build ( linux / amd64 )" + - "Build ( darwin / arm64 )" filters: branches: ignore: @@ -900,11 +796,31 @@ workflows: tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + - release: + name: "Release (dry-run)" + dry-run: true + requires: + - "Build ( darwin / amd64 )" + - "Build ( linux / amd64 )" + - "Build ( darwin / arm64 )" + filters: + branches: + only: + - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + - build-appimage: + name: "Build AppImage" + filters: + branches: + only: + - /^release\/v\d+\.\d+\.\d+(-rc\d+)?$/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish: - name: publish-appimage + name: "Publish AppImage" appimage: true requires: - - build-appimage + - "Build AppImage" filters: branches: ignore: @@ -913,14 +829,14 @@ workflows: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - build-and-push-image: - name: build-and-push/lotus-all-in-one + name: "Publish ECR (lotus-all-in-one)" dockerfile: Dockerfile.lotus path: . repo: lotus-dev tag: '${CIRCLE_SHA1:0:8}' target: lotus-all-in-one - build-and-push-image: - name: build-and-push/lotus-test + name: "Publish ECR (lotus-test)" dockerfile: Dockerfile.lotus path: . repo: lotus-test @@ -971,7 +887,7 @@ workflows: only: - /^v\d+\.\d+\.\d+-rc\d+$/ - publish-dockerhub: - name: publish-dockerhub + name: "Publish Dockerhub (stable)" tag: stable filters: branches: @@ -979,7 +895,17 @@ workflows: - /.*/ tags: only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + - /^v\d+\.\d+\.\d+$/ + - publish-dockerhub: + name: "Publish Dockerhub (candidate)" + tag: candidate + filters: + branches: + ignore: + - /.*/ + tags: + only: + - /^v\d+\.\d+\.\d+-rc\d+$/ nightly: triggers: @@ -1001,10 +927,10 @@ workflows: - publish-dockerhub: name: publish-dockerhub-nightly tag: nightly - monthly: + biweekly: triggers: - schedule: - cron: "0 0 1 * *" + cron: "0 0 1,15 * *" filters: branches: only: diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index c806120b1..b6ef5fa3c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,21 +1,23 @@ ## Related Issues - + ## Proposed Changes - - + ## Additional Info - + ## 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 `: : ` - - 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) + +- [ ] Commits have a clear commit message. +- [ ] PR title is in the form of of `: : ` + - example: ` fix: mempool: Introduce a cache for valid signatures` + - `PR type`: fix, feat, build, chore, ci, docs, perf, refactor, revert, style, test + - `area`, e.g. api, chain, state, market, mempool, multisig, networking, paych, proving, sealing, wallet, deps +- [ ] New features have usage guidelines and / or documentation updates in + - [ ] [Lotus Documentation](https://lotus.filecoin.io) + - [ ] [Discussion Tutorials](https://github.com/filecoin-project/lotus/discussions/categories/tutorials) +- [ ] Tests exist for new functionality or change in behavior - [ ] CI is green diff --git a/.goreleaser.yaml b/.goreleaser.yaml index f8839cc13..7e96e3ce8 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,119 +1,65 @@ project_name: lotus -before: - hooks: - - go mod tidy - - make deps universal_binaries: - id: lotus replace: true name_template: lotus - ids: - - lotus_darwin_amd64 - - lotus_darwin_arm64 - id: lotus-miner replace: true name_template: lotus-miner - ids: - - lotus-miner_darwin_amd64 - - lotus-miner_darwin_arm64 - id: lotus-worker replace: true name_template: lotus-worker - ids: - - lotus-worker_darwin_amd64 - - lotus-worker_darwin_arm64 builds: - - id: lotus_darwin_amd64 - main: ./cmd/lotus + - id: lotus binary: lotus + builder: prebuilt goos: - darwin + - linux goarch: - amd64 - env: - - CGO_ENABLED=1 - - FFI_BUILD_FROM_SOURCE=1 - ldflags: - - -X=github.com/filecoin-project/lotus/build.CurrentCommit=+git.{{.ShortCommit}} - - id: lotus-miner_darwin_amd64 - main: ./cmd/lotus-miner + - arm64 + goamd64: + - v1 + ignore: + - goos: linux + goarch: arm64 + prebuilt: + path: /tmp/workspace/{{ .Os }}_{{ .Arch }}{{ with .Amd64 }}_{{ . }}{{ end }}/lotus + - id: lotus-miner binary: lotus-miner + builder: prebuilt goos: - darwin + - linux goarch: - amd64 - env: - - CGO_ENABLED=1 - - FFI_BUILD_FROM_SOURCE=1 - ldflags: - - -X=github.com/filecoin-project/lotus/build.CurrentCommit=+git.{{.ShortCommit}} - - id: lotus-worker_darwin_amd64 - main: ./cmd/lotus-worker + - arm64 + goamd64: + - v1 + ignore: + - goos: linux + goarch: arm64 + prebuilt: + path: /tmp/workspace/{{ .Os }}_{{ .Arch }}{{ with .Amd64 }}_{{ . }}{{ end }}/lotus-miner + - id: lotus-worker binary: lotus-worker + builder: prebuilt goos: - darwin + - linux goarch: - amd64 - env: - - CGO_ENABLED=1 - - FFI_BUILD_FROM_SOURCE=1 - ldflags: - - -X=github.com/filecoin-project/lotus/build.CurrentCommit=+git.{{.ShortCommit}} - - id: lotus_darwin_arm64 - main: ./cmd/lotus - binary: lotus - goos: - - darwin - goarch: - arm64 - env: - - CGO_ENABLED=1 - - FFI_BUILD_FROM_SOURCE=1 - - CPATH=/opt/homebrew/include - - LIBRARY_PATH=/opt/homebrew/lib - ldflags: - - -X=github.com/filecoin-project/lotus/build.CurrentCommit=+git.{{.ShortCommit}} - - id: lotus-miner_darwin_arm64 - main: ./cmd/lotus-miner - binary: lotus-miner - goos: - - darwin - goarch: - - arm64 - env: - - CGO_ENABLED=1 - - FFI_BUILD_FROM_SOURCE=1 - - CPATH=/opt/homebrew/include - - LIBRARY_PATH=/opt/homebrew/lib - ldflags: - - -X=github.com/filecoin-project/lotus/build.CurrentCommit=+git.{{.ShortCommit}} - - id: lotus-worker_darwin_arm64 - main: ./cmd/lotus-worker - binary: lotus-worker - goos: - - darwin - goarch: - - arm64 - env: - - CGO_ENABLED=1 - - FFI_BUILD_FROM_SOURCE=1 - - CPATH=/opt/homebrew/include - - LIBRARY_PATH=/opt/homebrew/lib - ldflags: - - -X=github.com/filecoin-project/lotus/build.CurrentCommit=+git.{{.ShortCommit}} -# - id: linux -# main: ./cmd/lotus -# binary: lotus -# goos: -# - linux -# goarch: -# - amd64 -# env: -# - CGO_ENABLED=1 -# ldflags: -# - -X=github.com/filecoin-project/lotus/build.CurrentCommit=+git.{{.ShortCommit}} + goamd64: + - v1 + ignore: + - goos: linux + goarch: arm64 + prebuilt: + path: /tmp/workspace/{{ .Os }}_{{ .Arch }}{{ with .Amd64 }}_{{ . }}{{ end }}/lotus-worker archives: - id: primary @@ -129,8 +75,7 @@ release: owner: filecoin-project name: lotus prerelease: auto - name_template: "Release v{{.Version}}" - + name_template: "v{{.Version}}" brews: - tap: @@ -151,10 +96,8 @@ brews: homepage: "https://filecoin.io" description: "A homebrew cask for installing filecoin-project/lotus on MacOS" license: MIT + skip_upload: auto dependencies: - - name: pkg-config - - name: jq - - name: bzr - name: hwloc # produced manually so we can include cid checksums diff --git a/CHANGELOG.md b/CHANGELOG.md index a03fca1c0..cd450afd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,171 @@ # Lotus changelog +# 1.19.0 / 2022-12-07 + +This is an optional feature release of Lotus. This feature release includes the SplitStore beta, the experimental Lotus node cluster feature, as well as numerous enhancments and bugfixes. + +## Highlights +### 🟢 SplitStore v2(Beta) 🟢 + +Splitstore aims to reduce the node performance impact that's caused by the Filecoin's very large, and continuously growing chain datastore by having a hot and cold blockstore. You can find more about the Splitstore implementation [here](https://github.com/filecoin-project/lotus/blob/master/blockstore/splitstore/README.md). +Splitstore has three basic modes for node operators to configure according to your needs: +- `discard`: hotstore only, automatically archive out-of-scope objects that are beyond 4 finalities(3600 epochs). +- `universal`: stores all chain data that's beyond 4 finalities into coldstore. +- `messages`: only stores on-chain messages into coldstore. + +The `EnableColdStoreAutoPrune=` configuration is being deprecated in this release, as there is only ever one compaction running. We welcome all node operators to try the new feature and let us know [here](https://github.com/filecoin-project/lotus/discussions/9179) if you have any feedback! +There are more configuration one may set, you can read the full documentation about the SplitStoreV2 here: https://lotus.filecoin.io/lotus/configure/splitstore/. + +### 🧪 Node Cluster (*EXPERIMENTAL.*) 🧪 +The Lotus HA node cluster feature allows you to run multiple Lotus daemons for the same lotus-miner increasing resiliency. We welcome all Lotus users to join the early testing for this feature and provide your feedback. Please note that this feature is targeted towards more enterprise users of Lotus and requires at least 3 lotus nodes to be set up in a cluster. +Check out the documentation here: https://lotus.filecoin.io/lotus/configure/clusters/ + +### ⭐️ SnapDeals Enhancements ⭐️ +Numerous SnapDeals related improvements and fixes made it into this release before the code freeze. Some the highlights of the issues that has been fixed in this feature release are: + +- *Unable to snap-up a sector again if something went wrong.* - This has now been fixed ✅ +- *Error messages on loop during an open deadline.* - This has now been fixed ✅ + +## New features +- feat:splitstore:single compaction that can handle prune aka two marksets one compaction (#9571) ([filecoin-project/lotus#9571](https://github.com/filecoin-project/lotus/pull/9571)) + - Introduces a new SplitStore-mode, `messages`, which will only store on-chain messages. Fixes previously issues with regards to `AutoPrune` not compacting the coldstore. [Link to documentation](https://lotus.filecoin.io/lotus/configure/splitstore/) +- feat: Raft consensus for lotus nodes in a cluster ([filecoin-project/lotus#9294](https://github.com/filecoin-project/lotus/pull/9294)) + - Adds the experimental node cluster feature. +- feat: storage: Force exit GenerateSingleVanillaProof on cancelled context ([filecoin-project/lotus#9613](https://github.com/filecoin-project/lotus/pull/9613)) + - `GenerateSingleVanillaProof` now respects context, which means that it will skip slow to read sectors :snail: and return a context error. Instead of being blocked forever if storage reads where blocked (e.g disconnected NFS). +- feat: wdpost: Configurable pre-check timeouts ([filecoin-project/lotus#9680](https://github.com/filecoin-project/lotus/pull/9680)) + - Adds configuration knobs for setting custom amount of time a proving pre-check can take before a sector and partition will be skipped. [Link to documentation](https://lotus.filecoin.io/storage-providers/advanced-configurations/proving/#pre-check-sector-timeout) +- feat: chain: future proof the from & to address protocols ([filecoin-project/lotus#9515](https://github.com/filecoin-project/lotus/pull/9515)) + - This lets us add new address protocols to go-address without implicitly accepting them in messages on the network. +- feat: Retrieval into remote blockstores ([filecoin-project/lotus#9565](https://github.com/filecoin-project/lotus/pull/9565)) + - Makes it possible to point retrievals at a network-backed blockstore. +- feat: Add node uptime rpc / output in info command ([filecoin-project/lotus#9436](https://github.com/filecoin-project/lotus/pull/9436)) + - Adds node uptime stats to the `lotus-miner info` and `lotus info` commands +- feat: wdpost: Add ability to only have single partition per msg for partitions with… ([filecoin-project/lotus#9413](https://github.com/filecoin-project/lotus/pull/9413)) + - Adds a configuration option to have a single partition per PoSt Message for partitions containing recovering sectors. +- feat: miner paramfetch: Don't fetch param files when not needed ([filecoin-project/lotus#9391](https://github.com/filecoin-project/lotus/pull/9391)) + - A Lotus-Miner processes that has disabled local PoSt / C2 / PR2 does not need the param-files. This makes node startup much faster, reducing downtime by a lot when restarts are needed. +- feat: client: Add retrieval deal ID and bytes transferred to retrieval output ([filecoin-project/lotus#9398](https://github.com/filecoin-project/lotus/pull/9398)) + - Appends retrieval deal ID and bytes transferred to the retrieval output. +- feat: dealpublisher: check for duplicate deals before adding ([filecoin-project/lotus#9365](https://github.com/filecoin-project/lotus/pull/9365)) +- feat: Drop active retrieval check (#764) ([filecoin-project/go-fil-markets#764](https://github.com/filecoin-project/go-fil-markets/pull/764)) +- feat(retrievalmarkets): expose GetDynamicAsk (#748) ([filecoin-project/go-fil-markets#748](https://github.com/filecoin-project/go-fil-markets/pull/748)) +- feat: handle retrieval queries for unindexed identity payload CIDs (#747) ([filecoin-project/go-fil-markets#747](https://github.com/filecoin-project/go-fil-markets/pull/747)) +- feat: add a method for validating an address for a network version (#115) ([filecoin-project/go-state-types#115](https://github.com/filecoin-project/go-state-types/pull/115)) + +## Improvements +- fix: miner-cli: Fix lotus-miner proving check ([filecoin-project/lotus#9643](https://github.com/filecoin-project/lotus/pull/9643)) + - Fixes the issue where the `lotus-miner proving check` command always outputted `Error: rg is nil` +- fix: sealing pipeline: Clear CreationTime when starting sector upgrade ([filecoin-project/lotus#9642](https://github.com/filecoin-project/lotus/pull/9642)) + - Fixes the issue where an aborted SnapDeal upgrade could no longer be retried with SnapDeals. +- fix:sealing-fsm:wait mutable fsm state for immutable sector upgrade error ([filecoin-project/lotus#9598](https://github.com/filecoin-project/lotus/pull/9598)) + - Creating a new WaitMutable state - now if the deadline is open and the sectors are trying finalize they will wait on the worker until the deadline has closed. Important to note that they will not finalize as soon as the deadline closes, they will wait 1h before continuing. Fixes the previous issue where upgraded Snap-sectors for an open deadline cause a lot of `error-messages` and `p_aux` issues +- fix: cli: add beneficiary info to lotus-miner actor control list ([filecoin-project/lotus#9632](https://github.com/filecoin-project/lotus/pull/9632)) + - Adds the beneficiary address to the `lotus-miner actor control list` output. +- fix: sealing pipeine: Release assigned deals on snapdeals abort ([filecoin-project/lotus#9601](https://github.com/filecoin-project/lotus/pull/9601)) +- fix: docker: make compatible with arm platform ([filecoin-project/lotus#9363](https://github.com/filecoin-project/lotus/pull/9363)) + - Makes the `Dockerfile.lotus` compatible with ARM-platforms (e.g Mac M1). +- fix: post worker sched: Don't check worker session in a busy loop ([filecoin-project/lotus#9495](https://github.com/filecoin-project/lotus/pull/9495)) + - Fixes a looping pattern which could result in a flood of requests between `lotus-miner`<->`lotus-worker`, potentially exhausting resources needed to make http requests, that lead to all sorts of random RPC-related issues. +- fix: miner: init miner's with 32GiB sectors by default ([filecoin-project/lotus#9364](https://github.com/filecoin-project/lotus/pull/9364)) + - Makes the `lotus-miner init` defualt to 32GiB sectors. +- fix: store identity CIDs in CARs for online deals (#749) ([filecoin-project/go-fil-markets#749](https://github.com/filecoin-project/go-fil-markets/pull/749)) +- fix: cliutil: Fix URL-based API endpoint parsing + +## Dependencies +- deps: upgrade go-merkledag to 0.8.1 (#9717) +- deps: Update go-fil-markets to v1.25.0 ([filecoin-project/lotus#9633](https://github.com/filecoin-project/lotus/pull/9633)) +- deps: upgrade go-merkledag to 0.8.0 ([filecoin-project/lotus#9455](https://github.com/filecoin-project/lotus/pull/9455)) + +## Others +- fix/build: Update Zondax/hid to 0.9.1 +- refactor: sealing: minor refactor of FinalizeReplicaUpdate ([filecoin-project/lotus#9614](https://github.com/filecoin-project/lotus/pull/9614)) +- update ffi to 280c4f8b94fd46dc (#9608) ([filecoin-project/lotus#9608](https://github.com/filecoin-project/lotus/pull/9608)) +- fix: tvx: make it work with the FVM ([filecoin-project/lotus#9604](https://github.com/filecoin-project/lotus/pull/9604)) +- fix: autobatch: remove potential deadlock when a block is missing ([filecoin-project/lotus#9602](https://github.com/filecoin-project/lotus/pull/9602)) +- feat: shed: set control address: add dump bytes option ([filecoin-project/lotus#9572](https://github.com/filecoin-project/lotus/pull/9572)) +- feat: shed: Online export-car ([filecoin-project/lotus#9590](https://github.com/filecoin-project/lotus/pull/9590)) +- fix: chain: Update chain.go ([filecoin-project/lotus#9373](https://github.com/filecoin-project/lotus/pull/9373)) +- fix: fvm: Allow setting local bundles for Debug FVM for av 9+ ([filecoin-project/lotus#9509](https://github.com/filecoin-project/lotus/pull/9509)) +- fix: ux: Add outputs to wallet commands ([filecoin-project/lotus#9416](https://github.com/filecoin-project/lotus/pull/9416)) +- fix: ux: specify arg in `net ping` cmd ([filecoin-project/lotus#9459](https://github.com/filecoin-project/lotus/pull/9459)) +- fix: cli: renew --only-cc with sectorfile ([filecoin-project/lotus#9402](https://github.com/filecoin-project/lotus/pull/9402)) +- fix: bstore: Handle codecs correctly in membstore Get ([filecoin-project/lotus#9471](https://github.com/filecoin-project/lotus/pull/9471)) +- fix: not multiplied by the number of seconds ([filecoin-project/lotus#9460](https://github.com/filecoin-project/lotus/pull/9460)) +- Makefile: Drop rarely used binaries from build-devnets (#9513) ([filecoin-project/lotus#9513](https://github.com/filecoin-project/lotus/pull/9513)) +- _ci_ Remove unneeded homebrew deps ([filecoin-project/lotus#9559](https://github.com/filecoin-project/lotus/pull/9559)) +- _ci_: Have apt-get wait until it can get a lock in packer builds ([filecoin-project/lotus#9534](https://github.com/filecoin-project/lotus/pull/9534)) +- _ci_ Appimage go1.18.1 fix ([filecoin-project/lotus#9496](https://github.com/filecoin-project/lotus/pull/9496)) +- _ci_: Fix failing Digital Ocean and Amazon Machine Image release process ([filecoin-project/lotus#9425](https://github.com/filecoin-project/lotus/pull/9425)) +- _ci_: Don't publish new homebrew releases for RC builds ([filecoin-project/lotus#9350](https://github.com/filecoin-project/lotus/pull/9350)) +- _ci_: Use golang 1.18.1 to build appimage ([filecoin-project/lotus#9386](https://github.com/filecoin-project/lotus/pull/9386)) +- _ci_ Refactor release pipeline to better support m1 builds ([filecoin-project/lotus#9600](https://github.com/filecoin-project/lotus/pull/9600)) +- _ci_: Rely on local env varibale instead of context ([filecoin-project/lotus#9740](https://github.com/filecoin-project/lotus/pull/9740)) +- feat: shed: FIP0036 post poll result processing ([filecoin-project/lotus#9387](https://github.com/filecoin-project/lotus/pull/9387)) +- misc: github: Cleanup PR template ([filecoin-project/lotus#9472](https://github.com/filecoin-project/lotus/pull/9472)) +- docs: release template: Mention codegen in release prep ([filecoin-project/lotus#9430](https://github.com/filecoin-project/lotus/pull/9430)) +- chore: merge releases (v1.17.2) into master ([filecoin-project/lotus#9433](https://github.com/filecoin-project/lotus/pull/9433)) +- chore: merge release/v1.18.0 into master ([filecoin-project/lotus#9597](https://github.com/filecoin-project/lotus/pull/9597)) +- chore:shed: Teach shed/sim to understand --tipset=@nnn notation ([filecoin-project/lotus#9434](https://github.com/filecoin-project/lotus/pull/9434)) +- _chore_: Upgrade `hid` ([filecoin-project/lotus#9406](https://github.com/filecoin-project/lotus/pull/9406)) +- chore: release: Update `release_issue_template` ([filecoin-project/lotus#9150](https://github.com/filecoin-project/lotus/pull/9150)) +- chore: update lotus version to 1.19.0-rc1 +- chore: merge release into master ([filecoin-project/lotus#9657](https://github.com/filecoin-project/lotus/pull/9657)) +- Backport: #9061 rpc errors ([filecoin-project/lotus#9384](https://github.com/filecoin-project/lotus/pull/9384)) +- shed: util: get all msig ([filecoin-project/lotus#9322](https://github.com/filecoin-project/lotus/pull/9322)) +- fix: test: simplify TestDeadlineToggling ([filecoin-project/lotus#9356](https://github.com/filecoin-project/lotus/pull/9356)) +- fix: build: set PropagationDelaySecs correctly ([filecoin-project/lotus#9358](https://github.com/filecoin-project/lotus/pull/9358)) +- fix: test: flaky TestDeadlineToggling around nulls (#9354) ([filecoin-project/lotus#9354](https://github.com/filecoin-project/lotus/pull/9354)) +- fix: retrievals: price-per-byte calculation fix ([filecoin-project/lotus#9353](https://github.com/filecoin-project/lotus/pull/9353)) +- fix: docs: update Go-badge in readme ([filecoin-project/lotus#9347](https://github.com/filecoin-project/lotus/pull/9347)) +- docs: release template: clarify location of version.go ([filecoin-project/lotus#9338](https://github.com/filecoin-project/lotus/pull/9338)) +- build: Bump version to v1.17.3-dev ([filecoin-project/lotus#9337](https://github.com/filecoin-project/lotus/pull/9337)) +- github.com/filecoin-project/go-fil-markets (v1.24.0-v17 -> v1.25.0): +- Merge branch 'release/v1.24.3' +- Update ffi and update markets to v9 (#751) (#761) ([filecoin-project/go-fil-markets#761](https://github.com/filecoin-project/go-fil-markets/pull/761)) +- chore: extract Provider piece logic to separate file (#750) ([filecoin-project/go-fil-markets#750](https://github.com/filecoin-project/go-fil-markets/pull/750)) +- Merge branch 'release/v1.24.2' +- Feat/support custom metadata (#759) ([filecoin-project/go-fil-markets#759](https://github.com/filecoin-project/go-fil-markets/pull/759)) +- Revert "Update ffi and update markets to v9 (#751)" (#755) ([filecoin-project/go-fil-markets#755](https://github.com/filecoin-project/go-fil-markets/pull/755)) +- Update ffi and update markets to v9 (#751) ([filecoin-project/go-fil-markets#751](https://github.com/filecoin-project/go-fil-markets/pull/751)) +- release: v1.24.0 ([filecoin-project/go-fil-markets#745](https://github.com/filecoin-project/go-fil-markets/pull/745)) +- github.com/filecoin-project/go-state-types (v0.9.8 -> v0.9.9): + +## lotus-market EOL notice + +As mentioned in [lotus v1.17.0 release notes](https://github.com/filecoin-project/lotus/releases/tag/v1.17.0), markets related features, enhancements and fixes is now lower priority for Lotus. We recommend our users to migrate to other deal making focused software, like [boost](https://boost.filecoin.io/) as soon as possible. That being said, the lotus maintainers will be: +- Lotus maintainers will stop supporting lotus-market subcomponent/**storage** deal making related issues or enhancements on Jan 31, 2023. +- In Q2 2023, we will be deprecating/removing lotus-market related code from this repository. + +If you have any questions or concerns, please raise them in [Lotus discussion](https://github.com/filecoin-project/lotus/discussions/categories/market)! + +## Contributors + +| Contributor | Commits | Lines ± | Files Changed | +|-------------|---------|---------|---------------| +| Geoff Stuart | 69 | +4745/-19478 | 405 | +| Shrenuj Bansal | 39 | +5257/-2183 | 243 | +| Łukasz Magiera | 32 | +2763/-730 | 169 | +| Aayush | 47 | +1439/-1138 | 157 | +| Ian Davis | 21 | +556/-1065 | 41 | +| Rod Vagg | 5 | +657/-320 | 18 | +| jennijuju | 4 | +632/-317 | 6 | +| Aayush Rajasekaran | 13 | +700/-135 | 18 | +| Jennifer Wang | 14 | +740/-54 | 25 | +| ZenGround0 | 1 | +193/-195 | 14 | +| Hannah Howard | 4 | +138/-122 | 52 | +| Steven Allen | 4 | +105/-24 | 11 | +| zenground0 | 9 | +109/-16 | 14 | +| Peter Rabbitson | 1 | +27/-23 | 3 | +| hannahhoward | 2 | +49/-0 | 2 | +| Airenas Vaičiūnas | 2 | +31/-16 | 2 | +| simlecode | 6 | +19/-10 | 12 | +| Phi | 5 | +16/-10 | 7 | +| sectrgt | 2 | +18/-0 | 2 | +| Jiaying Wang | 2 | +4/-4 | 3 | +| Rob Quist | 1 | +3/-1 | 1 | +| Jakub Sztandera | 1 | +1/-1 | 1 | + # 1.18.2 / 2022-12-10 This is an OPTIONAL patch release that fixes a recently reported bug, where the miner process crashes due to a panic during an AddPiece process. More details can be found [here](https://github.com/filecoin-project/lotus/pull/9822). @@ -150,8 +316,6 @@ If you have any questions or concerns, please raise them in [Lotus discussion](h | Peter Rabbitson | 1 | +3/-0 | 1 | | Jakub Sztandera | 1 | +1/-1 | 1 | - - # v1.17.2 / 2022-10-05 This is an OPTIONAL release of Lotus. This feature release introduces new sector number management APIs in Lotus that enables all the Sealing-as-a-Service and Lotus interactions needed to function. The default propagation delay setting for storage providers has also been changed, as well as numerous other features and enhancements. Check out the sub-bullet points in the feature and enhancement section to get a short description about each feature and enhancements. diff --git a/Dockerfile.lotus b/Dockerfile.lotus index 2f139a3c4..7037a5813 100644 --- a/Dockerfile.lotus +++ b/Dockerfile.lotus @@ -3,28 +3,43 @@ MAINTAINER Lotus Development Team RUN apt-get update && apt-get install -y ca-certificates build-essential clang ocl-icd-opencl-dev ocl-icd-libopencl1 jq libhwloc-dev -ARG RUST_VERSION=nightly ENV XDG_CACHE_HOME="/tmp" +### taken from https://github.com/rust-lang/docker-rust/blob/master/1.63.0/buster/Dockerfile ENV RUSTUP_HOME=/usr/local/rustup \ CARGO_HOME=/usr/local/cargo \ - PATH=/usr/local/cargo/bin:$PATH + PATH=/usr/local/cargo/bin:$PATH \ + RUST_VERSION=1.63.0 -RUN wget "https://static.rust-lang.org/rustup/dist/x86_64-unknown-linux-gnu/rustup-init"; \ +RUN set -eux; \ + dpkgArch="$(dpkg --print-architecture)"; \ + case "${dpkgArch##*-}" in \ + amd64) rustArch='x86_64-unknown-linux-gnu'; rustupSha256='5cc9ffd1026e82e7fb2eec2121ad71f4b0f044e88bca39207b3f6b769aaa799c' ;; \ + arm64) rustArch='aarch64-unknown-linux-gnu'; rustupSha256='e189948e396d47254103a49c987e7fb0e5dd8e34b200aa4481ecc4b8e41fb929' ;; \ + *) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \ + esac; \ + url="https://static.rust-lang.org/rustup/archive/1.25.1/${rustArch}/rustup-init"; \ + wget "$url"; \ + echo "${rustupSha256} *rustup-init" | sha256sum -c -; \ chmod +x rustup-init; \ - ./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION; \ + ./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION --default-host ${rustArch}; \ rm rustup-init; \ chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \ rustup --version; \ cargo --version; \ rustc --version; - +### end rust FROM builder-deps AS builder-local MAINTAINER Lotus Development Team COPY ./ /opt/filecoin WORKDIR /opt/filecoin + +### make configurable filecoin-ffi build +ARG FFI_BUILD_FROM_SOURCE=0 +ENV FFI_BUILD_FROM_SOURCE=${FFI_BUILD_FROM_SOURCE} + RUN make clean deps @@ -52,14 +67,14 @@ MAINTAINER Lotus Development Team # Base resources COPY --from=builder /etc/ssl/certs /etc/ssl/certs -COPY --from=builder /lib/x86_64-linux-gnu/libdl.so.2 /lib/ -COPY --from=builder /lib/x86_64-linux-gnu/librt.so.1 /lib/ -COPY --from=builder /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/ -COPY --from=builder /lib/x86_64-linux-gnu/libutil.so.1 /lib/ -COPY --from=builder /usr/lib/x86_64-linux-gnu/libltdl.so.7 /lib/ -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/libOpenCL.so.1 /lib/ +COPY --from=builder /lib/*/libdl.so.2 /lib/ +COPY --from=builder /lib/*/librt.so.1 /lib/ +COPY --from=builder /lib/*/libgcc_s.so.1 /lib/ +COPY --from=builder /lib/*/libutil.so.1 /lib/ +COPY --from=builder /usr/lib/*/libltdl.so.7 /lib/ +COPY --from=builder /usr/lib/*/libnuma.so.1 /lib/ +COPY --from=builder /usr/lib/*/libhwloc.so.5 /lib/ +COPY --from=builder /usr/lib/*/libOpenCL.so.1 /lib/ RUN useradd -r -u 532 -U fc \ && mkdir -p /etc/OpenCL/vendors \ diff --git a/Makefile b/Makefile index fd755055d..8f780a900 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ CLEAN+=build/.update-modules deps: $(BUILD_DEPS) .PHONY: deps -build-devnets: build lotus-seed lotus-shed lotus-wallet lotus-gateway lotus-fountain lotus-stats +build-devnets: build lotus-seed lotus-shed .PHONY: build-devnets debug: GOFLAGS+=-tags=debug diff --git a/README.md b/README.md index bab033e72..23f3eb2d9 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ - +

diff --git a/api/api_common.go b/api/api_common.go index 73a0c984c..2a887a26a 100644 --- a/api/api_common.go +++ b/api/api_common.go @@ -3,6 +3,7 @@ package api import ( "context" "fmt" + "time" "github.com/google/uuid" @@ -49,6 +50,9 @@ type Common interface { // trigger graceful shutdown Shutdown(context.Context) error //perm:admin + // StartTime returns node start time + StartTime(context.Context) (time.Time, error) //perm:read + // Session returns a random UUID of api provider session Session(context.Context) (uuid.UUID, error) //perm:read diff --git a/api/api_full.go b/api/api_full.go index 320a20687..0c281c12d 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -6,6 +6,7 @@ import ( "fmt" "time" + "github.com/google/uuid" blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p/core/peer" @@ -763,6 +764,9 @@ type FullNode interface { // LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that // the path specified when calling CreateBackup is within the base path CreateBackup(ctx context.Context, fpath string) error //perm:admin + + RaftState(ctx context.Context) (*RaftStateData, error) //perm:read + RaftLeader(ctx context.Context) (peer.ID, error) //perm:read } type StorageAsk struct { @@ -1012,8 +1016,12 @@ type RetrievalOrder struct { Client address.Address Miner address.Address MinerPeer *retrievalmarket.RetrievalPeer + + RemoteStore *RemoteStoreID `json:"RemoteStore,omitempty"` } +type RemoteStoreID = uuid.UUID + type InvocResult struct { MsgCid cid.Cid Msg *types.Message diff --git a/api/api_storage.go b/api/api_storage.go index 100be5cca..9a6eeb230 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -320,7 +320,7 @@ type StorageMiner interface { // the path specified when calling CreateBackup is within the base path CreateBackup(ctx context.Context, fpath string) error //perm:admin - CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storiface.SectorRef, expensive bool) (map[abi.SectorNumber]string, error) //perm:admin + CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storiface.SectorRef) (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 diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 5bddef2ec..96fc068cc 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -349,6 +349,10 @@ func init() { addExample(map[string]bitfield.BitField{ "": bitfield.NewFromSet([]uint64{5, 6, 7, 10}), }) + addExample(&api.RaftStateData{ + NonceMap: make(map[address.Address]uint64), + MsgUuids: make(map[uuid.UUID]*types.SignedMessage), + }) addExample(http.Header{ "Authorization": []string{"Bearer ey.."}, @@ -361,6 +365,7 @@ func init() { Headers: nil, }, }) + addExample(&uuid.UUID{}) } func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) { diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 18c260061..4a7cbe54a 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -2244,6 +2244,36 @@ func (mr *MockFullNodeMockRecorder) PaychVoucherSubmit(arg0, arg1, arg2, arg3, a return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PaychVoucherSubmit", reflect.TypeOf((*MockFullNode)(nil).PaychVoucherSubmit), arg0, arg1, arg2, arg3, arg4) } +// RaftLeader mocks base method. +func (m *MockFullNode) RaftLeader(arg0 context.Context) (peer.ID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RaftLeader", arg0) + ret0, _ := ret[0].(peer.ID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RaftLeader indicates an expected call of RaftLeader. +func (mr *MockFullNodeMockRecorder) RaftLeader(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RaftLeader", reflect.TypeOf((*MockFullNode)(nil).RaftLeader), arg0) +} + +// RaftState mocks base method. +func (m *MockFullNode) RaftState(arg0 context.Context) (*api.RaftStateData, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RaftState", arg0) + ret0, _ := ret[0].(*api.RaftStateData) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RaftState indicates an expected call of RaftState. +func (mr *MockFullNodeMockRecorder) RaftState(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RaftState", reflect.TypeOf((*MockFullNode)(nil).RaftState), arg0) +} + // Session mocks base method. func (m *MockFullNode) Session(arg0 context.Context) (uuid.UUID, error) { m.ctrl.T.Helper() @@ -2273,6 +2303,21 @@ func (mr *MockFullNodeMockRecorder) Shutdown(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Shutdown", reflect.TypeOf((*MockFullNode)(nil).Shutdown), arg0) } +// StartTime mocks base method. +func (m *MockFullNode) StartTime(arg0 context.Context) (time.Time, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StartTime", arg0) + ret0, _ := ret[0].(time.Time) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// StartTime indicates an expected call of StartTime. +func (mr *MockFullNodeMockRecorder) StartTime(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartTime", reflect.TypeOf((*MockFullNode)(nil).StartTime), arg0) +} + // StateAccountKey mocks base method. func (m *MockFullNode) StateAccountKey(arg0 context.Context, arg1 address.Address, arg2 types.TipSetKey) (address.Address, error) { m.ctrl.T.Helper() diff --git a/api/proxy_gen.go b/api/proxy_gen.go index b466d6336..0631a22bd 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -80,6 +80,8 @@ type CommonStruct struct { Shutdown func(p0 context.Context) error `perm:"admin"` + StartTime func(p0 context.Context) (time.Time, error) `perm:"read"` + Version func(p0 context.Context) (APIVersion, error) `perm:"read"` } } @@ -340,6 +342,10 @@ type FullNodeStruct struct { PaychVoucherSubmit func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (cid.Cid, error) `perm:"sign"` + RaftLeader func(p0 context.Context) (peer.ID, error) `perm:"read"` + + RaftState func(p0 context.Context) (*RaftStateData, error) `perm:"read"` + StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` StateActorCodeCIDs func(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) `perm:"read"` @@ -677,7 +683,7 @@ type StorageMinerStruct struct { BeneficiaryWithdrawBalance func(p0 context.Context, p1 abi.TokenAmount) (cid.Cid, error) `perm:"admin"` - CheckProvable func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storiface.SectorRef, p3 bool) (map[abi.SectorNumber]string, error) `perm:"admin"` + CheckProvable func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storiface.SectorRef) (map[abi.SectorNumber]string, error) `perm:"admin"` ComputeDataCid func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data) (abi.PieceInfo, error) `perm:"admin"` @@ -1173,6 +1179,17 @@ func (s *CommonStub) Shutdown(p0 context.Context) error { return ErrNotSupported } +func (s *CommonStruct) StartTime(p0 context.Context) (time.Time, error) { + if s.Internal.StartTime == nil { + return *new(time.Time), ErrNotSupported + } + return s.Internal.StartTime(p0) +} + +func (s *CommonStub) StartTime(p0 context.Context) (time.Time, error) { + return *new(time.Time), ErrNotSupported +} + func (s *CommonStruct) Version(p0 context.Context) (APIVersion, error) { if s.Internal.Version == nil { return *new(APIVersion), ErrNotSupported @@ -2460,6 +2477,28 @@ func (s *FullNodeStub) PaychVoucherSubmit(p0 context.Context, p1 address.Address return *new(cid.Cid), ErrNotSupported } +func (s *FullNodeStruct) RaftLeader(p0 context.Context) (peer.ID, error) { + if s.Internal.RaftLeader == nil { + return *new(peer.ID), ErrNotSupported + } + return s.Internal.RaftLeader(p0) +} + +func (s *FullNodeStub) RaftLeader(p0 context.Context) (peer.ID, error) { + return *new(peer.ID), ErrNotSupported +} + +func (s *FullNodeStruct) RaftState(p0 context.Context) (*RaftStateData, error) { + if s.Internal.RaftState == nil { + return nil, ErrNotSupported + } + return s.Internal.RaftState(p0) +} + +func (s *FullNodeStub) RaftState(p0 context.Context) (*RaftStateData, error) { + return nil, ErrNotSupported +} + func (s *FullNodeStruct) StateAccountKey(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) { if s.Internal.StateAccountKey == nil { return *new(address.Address), ErrNotSupported @@ -4121,14 +4160,14 @@ func (s *StorageMinerStub) BeneficiaryWithdrawBalance(p0 context.Context, p1 abi return *new(cid.Cid), ErrNotSupported } -func (s *StorageMinerStruct) CheckProvable(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storiface.SectorRef, p3 bool) (map[abi.SectorNumber]string, error) { +func (s *StorageMinerStruct) CheckProvable(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storiface.SectorRef) (map[abi.SectorNumber]string, error) { if s.Internal.CheckProvable == nil { return *new(map[abi.SectorNumber]string), ErrNotSupported } - return s.Internal.CheckProvable(p0, p1, p2, p3) + return s.Internal.CheckProvable(p0, p1, p2) } -func (s *StorageMinerStub) CheckProvable(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storiface.SectorRef, p3 bool) (map[abi.SectorNumber]string, error) { +func (s *StorageMinerStub) CheckProvable(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storiface.SectorRef) (map[abi.SectorNumber]string, error) { return *new(map[abi.SectorNumber]string), ErrNotSupported } diff --git a/api/types.go b/api/types.go index 0de44549f..5cbe0edef 100644 --- a/api/types.go +++ b/api/types.go @@ -59,6 +59,11 @@ type MessageSendSpec struct { MsgUuid uuid.UUID } +type MpoolMessageWhole struct { + Msg *types.Message + Spec *MessageSendSpec +} + // GraphSyncDataTransfer provides diagnostics on a data transfer happening over graphsync type GraphSyncDataTransfer struct { // GraphSync request id for this transfer @@ -334,3 +339,61 @@ type ForkUpgradeParams struct { UpgradeSkyrHeight abi.ChainEpoch UpgradeSharkHeight abi.ChainEpoch } + +type NonceMapType map[address.Address]uint64 +type MsgUuidMapType map[uuid.UUID]*types.SignedMessage + +type RaftStateData struct { + NonceMap NonceMapType + MsgUuids MsgUuidMapType +} + +func (n *NonceMapType) MarshalJSON() ([]byte, error) { + marshalled := make(map[string]uint64) + for a, n := range *n { + marshalled[a.String()] = n + } + return json.Marshal(marshalled) +} + +func (n *NonceMapType) UnmarshalJSON(b []byte) error { + unmarshalled := make(map[string]uint64) + err := json.Unmarshal(b, &unmarshalled) + if err != nil { + return err + } + *n = make(map[address.Address]uint64) + for saddr, nonce := range unmarshalled { + a, err := address.NewFromString(saddr) + if err != nil { + return err + } + (*n)[a] = nonce + } + return nil +} + +func (m *MsgUuidMapType) MarshalJSON() ([]byte, error) { + marshalled := make(map[string]*types.SignedMessage) + for u, msg := range *m { + marshalled[u.String()] = msg + } + return json.Marshal(marshalled) +} + +func (m *MsgUuidMapType) UnmarshalJSON(b []byte) error { + unmarshalled := make(map[string]*types.SignedMessage) + err := json.Unmarshal(b, &unmarshalled) + if err != nil { + return err + } + *m = make(map[uuid.UUID]*types.SignedMessage) + for suid, msg := range unmarshalled { + u, err := uuid.Parse(suid) + if err != nil { + return err + } + (*m)[u] = msg + } + return nil +} diff --git a/api/v0api/v0mocks/mock_full.go b/api/v0api/v0mocks/mock_full.go index 85ef2ddb0..2b815c4ca 100644 --- a/api/v0api/v0mocks/mock_full.go +++ b/api/v0api/v0mocks/mock_full.go @@ -2158,6 +2158,21 @@ func (mr *MockFullNodeMockRecorder) Shutdown(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Shutdown", reflect.TypeOf((*MockFullNode)(nil).Shutdown), arg0) } +// StartTime mocks base method. +func (m *MockFullNode) StartTime(arg0 context.Context) (time.Time, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StartTime", arg0) + ret0, _ := ret[0].(time.Time) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// StartTime indicates an expected call of StartTime. +func (mr *MockFullNodeMockRecorder) StartTime(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartTime", reflect.TypeOf((*MockFullNode)(nil).StartTime), arg0) +} + // StateAccountKey mocks base method. func (m *MockFullNode) StateAccountKey(arg0 context.Context, arg1 address.Address, arg2 types.TipSetKey) (address.Address, error) { m.ctrl.T.Helper() diff --git a/blockstore/cbor_gen.go b/blockstore/cbor_gen.go new file mode 100644 index 000000000..b8ebdb474 --- /dev/null +++ b/blockstore/cbor_gen.go @@ -0,0 +1,441 @@ +// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT. + +package blockstore + +import ( + "fmt" + "io" + "math" + "sort" + + cid "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" +) + +var _ = xerrors.Errorf +var _ = cid.Undef +var _ = math.E +var _ = sort.Sort + +var lengthBufNetRpcReq = []byte{132} + +func (t *NetRpcReq) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write(lengthBufNetRpcReq); err != nil { + return err + } + + // t.Type (blockstore.NetRPCReqType) (uint8) + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.Type)); err != nil { + return err + } + + // t.ID (uint64) (uint64) + + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.ID)); err != nil { + return err + } + + // t.Cid ([]cid.Cid) (slice) + if len(t.Cid) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.Cid was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Cid))); err != nil { + return err + } + for _, v := range t.Cid { + if err := cbg.WriteCid(w, v); err != nil { + return xerrors.Errorf("failed writing cid field t.Cid: %w", err) + } + } + + // t.Data ([][]uint8) (slice) + if len(t.Data) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.Data was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Data))); err != nil { + return err + } + for _, v := range t.Data { + if len(v) > cbg.ByteArrayMaxLen { + return xerrors.Errorf("Byte array in field v was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(v))); err != nil { + return err + } + + if _, err := cw.Write(v[:]); err != nil { + return err + } + } + return nil +} + +func (t *NetRpcReq) UnmarshalCBOR(r io.Reader) (err error) { + *t = NetRpcReq{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 4 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Type (blockstore.NetRPCReqType) (uint8) + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint8 field") + } + if extra > math.MaxUint8 { + return fmt.Errorf("integer in input was too large for uint8 field") + } + t.Type = NetRPCReqType(extra) + // t.ID (uint64) (uint64) + + { + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.ID = uint64(extra) + + } + // t.Cid ([]cid.Cid) (slice) + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.Cid: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Cid = make([]cid.Cid, extra) + } + + for i := 0; i < int(extra); i++ { + + c, err := cbg.ReadCid(cr) + if err != nil { + return xerrors.Errorf("reading cid field t.Cid failed: %w", err) + } + t.Cid[i] = c + } + + // t.Data ([][]uint8) (slice) + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.Data: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Data = make([][]uint8, extra) + } + + for i := 0; i < int(extra); i++ { + { + var maj byte + var extra uint64 + var err error + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > cbg.ByteArrayMaxLen { + return fmt.Errorf("t.Data[i]: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.Data[i] = make([]uint8, extra) + } + + if _, err := io.ReadFull(cr, t.Data[i][:]); err != nil { + return err + } + } + } + + return nil +} + +var lengthBufNetRpcResp = []byte{131} + +func (t *NetRpcResp) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write(lengthBufNetRpcResp); err != nil { + return err + } + + // t.Type (blockstore.NetRPCRespType) (uint8) + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.Type)); err != nil { + return err + } + + // t.ID (uint64) (uint64) + + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.ID)); err != nil { + return err + } + + // t.Data ([]uint8) (slice) + if len(t.Data) > cbg.ByteArrayMaxLen { + return xerrors.Errorf("Byte array in field t.Data was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Data))); err != nil { + return err + } + + if _, err := cw.Write(t.Data[:]); err != nil { + return err + } + return nil +} + +func (t *NetRpcResp) UnmarshalCBOR(r io.Reader) (err error) { + *t = NetRpcResp{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 3 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Type (blockstore.NetRPCRespType) (uint8) + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint8 field") + } + if extra > math.MaxUint8 { + return fmt.Errorf("integer in input was too large for uint8 field") + } + t.Type = NetRPCRespType(extra) + // t.ID (uint64) (uint64) + + { + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.ID = uint64(extra) + + } + // t.Data ([]uint8) (slice) + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > cbg.ByteArrayMaxLen { + return fmt.Errorf("t.Data: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + if extra > 0 { + t.Data = make([]uint8, extra) + } + + if _, err := io.ReadFull(cr, t.Data[:]); err != nil { + return err + } + return nil +} + +var lengthBufNetRpcErr = []byte{131} + +func (t *NetRpcErr) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write(lengthBufNetRpcErr); err != nil { + return err + } + + // t.Type (blockstore.NetRPCErrType) (uint8) + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.Type)); err != nil { + return err + } + + // t.Msg (string) (string) + if len(t.Msg) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.Msg was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Msg))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.Msg)); err != nil { + return err + } + + // t.Cid (cid.Cid) (struct) + + if t.Cid == nil { + if _, err := cw.Write(cbg.CborNull); err != nil { + return err + } + } else { + if err := cbg.WriteCid(cw, *t.Cid); err != nil { + return xerrors.Errorf("failed to write cid field t.Cid: %w", err) + } + } + + return nil +} + +func (t *NetRpcErr) UnmarshalCBOR(r io.Reader) (err error) { + *t = NetRpcErr{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 3 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Type (blockstore.NetRPCErrType) (uint8) + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint8 field") + } + if extra > math.MaxUint8 { + return fmt.Errorf("integer in input was too large for uint8 field") + } + t.Type = NetRPCErrType(extra) + // t.Msg (string) (string) + + { + sval, err := cbg.ReadString(cr) + if err != nil { + return err + } + + t.Msg = string(sval) + } + // t.Cid (cid.Cid) (struct) + + { + + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + + c, err := cbg.ReadCid(cr) + if err != nil { + return xerrors.Errorf("failed to read cid field t.Cid: %w", err) + } + + t.Cid = &c + } + + } + return nil +} diff --git a/blockstore/mem.go b/blockstore/mem.go index 15708dcd4..7cfefafd7 100644 --- a/blockstore/mem.go +++ b/blockstore/mem.go @@ -47,6 +47,9 @@ func (m MemBlockstore) Get(ctx context.Context, k cid.Cid) (blocks.Block, error) if !ok { return nil, ipld.ErrNotFound{Cid: k} } + if b.Cid().Prefix().Codec != k.Prefix().Codec { + return blocks.NewBlockWithCid(b.RawData(), k) + } return b, nil } diff --git a/blockstore/mem_test.go b/blockstore/mem_test.go new file mode 100644 index 000000000..4d4a77624 --- /dev/null +++ b/blockstore/mem_test.go @@ -0,0 +1,45 @@ +package blockstore + +import ( + "context" + "testing" + + blocks "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" + mh "github.com/multiformats/go-multihash" + "github.com/stretchr/testify/require" +) + +func TestMemGetCodec(t *testing.T) { + ctx := context.Background() + bs := NewMemory() + + cborArr := []byte{0x82, 1, 2} + + h, err := mh.Sum(cborArr, mh.SHA2_256, -1) + require.NoError(t, err) + + rawCid := cid.NewCidV1(cid.Raw, h) + rawBlk, err := blocks.NewBlockWithCid(cborArr, rawCid) + require.NoError(t, err) + + err = bs.Put(ctx, rawBlk) + require.NoError(t, err) + + cborCid := cid.NewCidV1(cid.DagCBOR, h) + + cborBlk, err := bs.Get(ctx, cborCid) + require.NoError(t, err) + + require.Equal(t, cborCid.Prefix(), cborBlk.Cid().Prefix()) + require.EqualValues(t, cborArr, cborBlk.RawData()) + + // was allocated + require.NotEqual(t, cborBlk, rawBlk) + + gotRawBlk, err := bs.Get(ctx, rawCid) + require.NoError(t, err) + + // not allocated + require.Equal(t, rawBlk, gotRawBlk) +} diff --git a/blockstore/net.go b/blockstore/net.go new file mode 100644 index 000000000..77da764a5 --- /dev/null +++ b/blockstore/net.go @@ -0,0 +1,424 @@ +package blockstore + +import ( + "bytes" + "context" + "encoding/binary" + "fmt" + "sync" + "sync/atomic" + + blocks "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" + ipld "github.com/ipfs/go-ipld-format" + "github.com/libp2p/go-msgio" + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" +) + +type NetRPCReqType byte + +const ( + NRpcHas NetRPCReqType = iota + NRpcGet + NRpcGetSize + NRpcPut + NRpcDelete + + // todo cancel req +) + +type NetRPCRespType byte + +const ( + NRpcOK NetRPCRespType = iota + NRpcErr + NRpcMore +) + +type NetRPCErrType byte + +const ( + NRpcErrGeneric NetRPCErrType = iota + NRpcErrNotFound +) + +type NetRpcReq struct { + Type NetRPCReqType + ID uint64 + + Cid []cid.Cid // todo maxsize? + Data [][]byte // todo maxsize? +} + +type NetRpcResp struct { + Type NetRPCRespType + ID uint64 + + // error or cids in allkeys + Data []byte // todo maxsize? + + next <-chan NetRpcResp +} + +type NetRpcErr struct { + Type NetRPCErrType + + Msg string + + // in case of NRpcErrNotFound + Cid *cid.Cid +} + +type NetworkStore struct { + // note: writer is thread-safe + msgStream msgio.ReadWriteCloser + + // atomic + reqCount uint64 + + respLk sync.Mutex + + // respMap is nil after store closes + respMap map[uint64]chan<- NetRpcResp + + closing chan struct{} + closed chan struct{} + + closeLk sync.Mutex + onClose []func() +} + +func NewNetworkStore(mss msgio.ReadWriteCloser) *NetworkStore { + ns := &NetworkStore{ + msgStream: mss, + + respMap: map[uint64]chan<- NetRpcResp{}, + + closing: make(chan struct{}), + closed: make(chan struct{}), + } + + go ns.receive() + + return ns +} + +func (n *NetworkStore) shutdown(msg string) { + if err := n.msgStream.Close(); err != nil { + log.Errorw("closing netstore msg stream", "error", err) + } + + nerr := NetRpcErr{ + Type: NRpcErrGeneric, + Msg: msg, + Cid: nil, + } + + var errb bytes.Buffer + if err := nerr.MarshalCBOR(&errb); err != nil { + log.Errorw("netstore shutdown: error marshaling error", "err", err) + } + + n.respLk.Lock() + for id, resps := range n.respMap { + resps <- NetRpcResp{ + Type: NRpcErr, + ID: id, + Data: errb.Bytes(), + } + } + + n.respMap = nil + + n.respLk.Unlock() +} + +func (n *NetworkStore) OnClose(cb func()) { + n.closeLk.Lock() + defer n.closeLk.Unlock() + + select { + case <-n.closed: + cb() + default: + n.onClose = append(n.onClose, cb) + } +} + +func (n *NetworkStore) receive() { + defer func() { + n.closeLk.Lock() + defer n.closeLk.Unlock() + + close(n.closed) + if n.onClose != nil { + for _, f := range n.onClose { + f() + } + } + }() + + for { + select { + case <-n.closing: + n.shutdown("netstore stopping") + return + default: + } + + msg, err := n.msgStream.ReadMsg() + if err != nil { + n.shutdown(fmt.Sprintf("netstore ReadMsg: %s", err)) + return + } + + var resp NetRpcResp + if err := resp.UnmarshalCBOR(bytes.NewReader(msg)); err != nil { + n.shutdown(fmt.Sprintf("unmarshaling netstore response: %s", err)) + return + } + + n.msgStream.ReleaseMsg(msg) + + n.respLk.Lock() + if ch, ok := n.respMap[resp.ID]; ok { + if resp.Type == NRpcMore { + nch := make(chan NetRpcResp, 1) + resp.next = nch + n.respMap[resp.ID] = nch + } else { + delete(n.respMap, resp.ID) + } + + ch <- resp + } + n.respLk.Unlock() + } +} + +func (n *NetworkStore) sendRpc(rt NetRPCReqType, cids []cid.Cid, data [][]byte) (uint64, <-chan NetRpcResp, error) { + rid := atomic.AddUint64(&n.reqCount, 1) + + respCh := make(chan NetRpcResp, 1) // todo pool? + + n.respLk.Lock() + if n.respMap == nil { + n.respLk.Unlock() + return 0, nil, xerrors.Errorf("netstore closed") + } + n.respMap[rid] = respCh + n.respLk.Unlock() + + req := NetRpcReq{ + Type: rt, + ID: rid, + Cid: cids, + Data: data, + } + + var rbuf bytes.Buffer // todo buffer pool + if err := req.MarshalCBOR(&rbuf); err != nil { + n.respLk.Lock() + defer n.respLk.Unlock() + + if n.respMap == nil { + return 0, nil, xerrors.Errorf("netstore closed") + } + delete(n.respMap, rid) + + return 0, nil, err + } + + if err := n.msgStream.WriteMsg(rbuf.Bytes()); err != nil { + n.respLk.Lock() + defer n.respLk.Unlock() + + if n.respMap == nil { + return 0, nil, xerrors.Errorf("netstore closed") + } + delete(n.respMap, rid) + + return 0, nil, err + } + + return rid, respCh, nil +} + +func (n *NetworkStore) waitResp(ctx context.Context, rch <-chan NetRpcResp, rid uint64) (NetRpcResp, error) { + select { + case resp := <-rch: + if resp.Type == NRpcErr { + var e NetRpcErr + if err := e.UnmarshalCBOR(bytes.NewReader(resp.Data)); err != nil { + return NetRpcResp{}, xerrors.Errorf("unmarshaling error data: %w", err) + } + + var err error + switch e.Type { + case NRpcErrNotFound: + if e.Cid != nil { + err = ipld.ErrNotFound{ + Cid: *e.Cid, + } + } else { + err = xerrors.Errorf("block not found, but cid was null") + } + case NRpcErrGeneric: + err = xerrors.Errorf("generic error") + default: + err = xerrors.Errorf("unknown error type") + } + + return NetRpcResp{}, xerrors.Errorf("netstore error response: %s (%w)", e.Msg, err) + } + + return resp, nil + case <-ctx.Done(): + // todo send cancel req + + n.respLk.Lock() + if n.respMap != nil { + delete(n.respMap, rid) + } + n.respLk.Unlock() + + return NetRpcResp{}, ctx.Err() + } +} + +func (n *NetworkStore) Has(ctx context.Context, c cid.Cid) (bool, error) { + req, rch, err := n.sendRpc(NRpcHas, []cid.Cid{c}, nil) + if err != nil { + return false, err + } + + resp, err := n.waitResp(ctx, rch, req) + if err != nil { + return false, err + } + + if len(resp.Data) != 1 { + return false, xerrors.Errorf("expected reposnse length to be 1 byte") + } + switch resp.Data[0] { + case cbg.CborBoolTrue[0]: + return true, nil + case cbg.CborBoolFalse[0]: + return false, nil + default: + return false, xerrors.Errorf("has: bad response: %x", resp.Data[0]) + } +} + +func (n *NetworkStore) Get(ctx context.Context, c cid.Cid) (blocks.Block, error) { + req, rch, err := n.sendRpc(NRpcGet, []cid.Cid{c}, nil) + if err != nil { + return nil, err + } + + resp, err := n.waitResp(ctx, rch, req) + if err != nil { + return nil, err + } + + return blocks.NewBlockWithCid(resp.Data, c) +} + +func (n *NetworkStore) View(ctx context.Context, c cid.Cid, callback func([]byte) error) error { + req, rch, err := n.sendRpc(NRpcGet, []cid.Cid{c}, nil) + if err != nil { + return err + } + + resp, err := n.waitResp(ctx, rch, req) + if err != nil { + return err + } + + return callback(resp.Data) // todo return buf to pool +} + +func (n *NetworkStore) GetSize(ctx context.Context, c cid.Cid) (int, error) { + req, rch, err := n.sendRpc(NRpcGetSize, []cid.Cid{c}, nil) + if err != nil { + return 0, err + } + + resp, err := n.waitResp(ctx, rch, req) + if err != nil { + return 0, err + } + + if len(resp.Data) != 4 { + return 0, xerrors.Errorf("expected getsize response to be 4 bytes, was %d", resp.Data) + } + + return int(binary.LittleEndian.Uint32(resp.Data)), nil +} + +func (n *NetworkStore) Put(ctx context.Context, block blocks.Block) error { + return n.PutMany(ctx, []blocks.Block{block}) +} + +func (n *NetworkStore) PutMany(ctx context.Context, blocks []blocks.Block) error { + // todo pool + cids := make([]cid.Cid, len(blocks)) + blkDatas := make([][]byte, len(blocks)) + for i, block := range blocks { + cids[i] = block.Cid() + blkDatas[i] = block.RawData() + } + + req, rch, err := n.sendRpc(NRpcPut, cids, blkDatas) + if err != nil { + return err + } + + _, err = n.waitResp(ctx, rch, req) + if err != nil { + return err + } + + return nil +} + +func (n *NetworkStore) DeleteBlock(ctx context.Context, c cid.Cid) error { + return n.DeleteMany(ctx, []cid.Cid{c}) +} + +func (n *NetworkStore) DeleteMany(ctx context.Context, cids []cid.Cid) error { + req, rch, err := n.sendRpc(NRpcDelete, cids, nil) + if err != nil { + return err + } + + _, err = n.waitResp(ctx, rch, req) + if err != nil { + return err + } + + return nil +} + +func (n *NetworkStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) { + return nil, xerrors.Errorf("not supported") +} + +func (n *NetworkStore) HashOnRead(enabled bool) { + // todo + return +} + +func (n *NetworkStore) Stop(ctx context.Context) error { + close(n.closing) + + select { + case <-n.closed: + return nil + case <-ctx.Done(): + return ctx.Err() + } +} + +var _ Blockstore = &NetworkStore{} diff --git a/blockstore/net_serve.go b/blockstore/net_serve.go new file mode 100644 index 000000000..2540c845e --- /dev/null +++ b/blockstore/net_serve.go @@ -0,0 +1,237 @@ +package blockstore + +import ( + "bytes" + "context" + "encoding/binary" + + block "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" + ipld "github.com/ipfs/go-ipld-format" + "github.com/libp2p/go-msgio" + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" +) + +type NetworkStoreHandler struct { + msgStream msgio.ReadWriteCloser + + bs Blockstore +} + +// NOTE: This code isn't yet hardened to accept untrusted input. See TODOs here and in net.go +func HandleNetBstoreStream(ctx context.Context, bs Blockstore, mss msgio.ReadWriteCloser) *NetworkStoreHandler { + ns := &NetworkStoreHandler{ + msgStream: mss, + bs: bs, + } + + go ns.handle(ctx) + + return ns +} + +func (h *NetworkStoreHandler) handle(ctx context.Context) { + defer func() { + if err := h.msgStream.Close(); err != nil { + log.Errorw("error closing blockstore stream", "error", err) + } + }() + + for { + var req NetRpcReq + + ms, err := h.msgStream.ReadMsg() + if err != nil { + log.Warnw("bstore stream err", "error", err) + return + } + + if err := req.UnmarshalCBOR(bytes.NewReader(ms)); err != nil { + return + } + + h.msgStream.ReleaseMsg(ms) + + switch req.Type { + case NRpcHas: + if len(req.Cid) != 1 { + if err := h.respondError(req.ID, xerrors.New("expected request for 1 cid"), cid.Undef); err != nil { + log.Warnw("writing error response", "error", err) + return + } + continue + } + + res, err := h.bs.Has(ctx, req.Cid[0]) + if err != nil { + if err := h.respondError(req.ID, err, req.Cid[0]); err != nil { + log.Warnw("writing error response", "error", err) + return + } + continue + } + + var resData [1]byte + if res { + resData[0] = cbg.CborBoolTrue[0] + } else { + resData[0] = cbg.CborBoolFalse[0] + } + + if err := h.respond(req.ID, NRpcOK, resData[:]); err != nil { + log.Warnw("writing response", "error", err) + return + } + + case NRpcGet: + if len(req.Cid) != 1 { + if err := h.respondError(req.ID, xerrors.New("expected request for 1 cid"), cid.Undef); err != nil { + log.Warnw("writing error response", "error", err) + return + } + continue + } + + err := h.bs.View(ctx, req.Cid[0], func(bdata []byte) error { + return h.respond(req.ID, NRpcOK, bdata) + }) + if err != nil { + if err := h.respondError(req.ID, err, req.Cid[0]); err != nil { + log.Warnw("writing error response", "error", err) + return + } + continue + } + + case NRpcGetSize: + if len(req.Cid) != 1 { + if err := h.respondError(req.ID, xerrors.New("expected request for 1 cid"), cid.Undef); err != nil { + log.Warnw("writing error response", "error", err) + return + } + continue + } + + sz, err := h.bs.GetSize(ctx, req.Cid[0]) + if err != nil { + if err := h.respondError(req.ID, err, req.Cid[0]); err != nil { + log.Warnw("writing error response", "error", err) + return + } + continue + } + + var resData [4]byte + binary.LittleEndian.PutUint32(resData[:], uint32(sz)) + + if err := h.respond(req.ID, NRpcOK, resData[:]); err != nil { + log.Warnw("writing response", "error", err) + return + } + + case NRpcPut: + blocks := make([]block.Block, len(req.Cid)) + + if len(req.Cid) != len(req.Data) { + if err := h.respondError(req.ID, xerrors.New("cid count didn't match data count"), cid.Undef); err != nil { + log.Warnw("writing error response", "error", err) + } + return + } + + for i := range req.Cid { + blocks[i], err = block.NewBlockWithCid(req.Data[i], req.Cid[i]) + if err != nil { + log.Warnw("make block", "error", err) + return + } + } + + err := h.bs.PutMany(ctx, blocks) + if err != nil { + if err := h.respondError(req.ID, err, cid.Undef); err != nil { + log.Warnw("writing error response", "error", err) + return + } + continue + } + + if err := h.respond(req.ID, NRpcOK, []byte{}); err != nil { + log.Warnw("writing response", "error", err) + return + } + case NRpcDelete: + err := h.bs.DeleteMany(ctx, req.Cid) + if err != nil { + if err := h.respondError(req.ID, err, cid.Undef); err != nil { + log.Warnw("writing error response", "error", err) + return + } + continue + } + + if err := h.respond(req.ID, NRpcOK, []byte{}); err != nil { + log.Warnw("writing response", "error", err) + return + } + default: + if err := h.respondError(req.ID, xerrors.New("unsupported request type"), cid.Undef); err != nil { + log.Warnw("writing error response", "error", err) + return + } + continue + } + } +} + +func (h *NetworkStoreHandler) respondError(req uint64, uerr error, c cid.Cid) error { + var resp NetRpcResp + resp.ID = req + resp.Type = NRpcErr + + nerr := NetRpcErr{ + Type: NRpcErrGeneric, + Msg: uerr.Error(), + } + if ipld.IsNotFound(uerr) { + nerr.Type = NRpcErrNotFound + nerr.Cid = &c + } + + var edata bytes.Buffer + if err := nerr.MarshalCBOR(&edata); err != nil { + return xerrors.Errorf("marshaling error data: %w", err) + } + + resp.Data = edata.Bytes() + + var msg bytes.Buffer + if err := resp.MarshalCBOR(&msg); err != nil { + return xerrors.Errorf("marshaling error response: %w", err) + } + + if err := h.msgStream.WriteMsg(msg.Bytes()); err != nil { + return xerrors.Errorf("write error response: %w", err) + } + + return nil +} + +func (h *NetworkStoreHandler) respond(req uint64, rt NetRPCRespType, data []byte) error { + var resp NetRpcResp + resp.ID = req + resp.Type = rt + resp.Data = data + + var msg bytes.Buffer + if err := resp.MarshalCBOR(&msg); err != nil { + return xerrors.Errorf("marshaling response: %w", err) + } + + if err := h.msgStream.WriteMsg(msg.Bytes()); err != nil { + return xerrors.Errorf("write response: %w", err) + } + + return nil +} diff --git a/blockstore/net_test.go b/blockstore/net_test.go new file mode 100644 index 000000000..d8c33818e --- /dev/null +++ b/blockstore/net_test.go @@ -0,0 +1,63 @@ +package blockstore + +import ( + "context" + "fmt" + "io" + "testing" + + block "github.com/ipfs/go-block-format" + ipld "github.com/ipfs/go-ipld-format" + "github.com/libp2p/go-msgio" + "github.com/stretchr/testify/require" +) + +func TestNetBstore(t *testing.T) { + ctx := context.Background() + + cr, sw := io.Pipe() + sr, cw := io.Pipe() + + cm := msgio.Combine(msgio.NewWriter(cw), msgio.NewReader(cr)) + sm := msgio.Combine(msgio.NewWriter(sw), msgio.NewReader(sr)) + + bbs := NewMemorySync() + _ = HandleNetBstoreStream(ctx, bbs, sm) + + nbs := NewNetworkStore(cm) + + tb1 := block.NewBlock([]byte("aoeu")) + + h, err := nbs.Has(ctx, tb1.Cid()) + require.NoError(t, err) + require.False(t, h) + + err = nbs.Put(ctx, tb1) + require.NoError(t, err) + + h, err = nbs.Has(ctx, tb1.Cid()) + require.NoError(t, err) + require.True(t, h) + + sz, err := nbs.GetSize(ctx, tb1.Cid()) + require.NoError(t, err) + require.Equal(t, 4, sz) + + err = nbs.DeleteBlock(ctx, tb1.Cid()) + require.NoError(t, err) + + h, err = nbs.Has(ctx, tb1.Cid()) + require.NoError(t, err) + require.False(t, h) + + _, err = nbs.Get(ctx, tb1.Cid()) + fmt.Println(err) + require.True(t, ipld.IsNotFound(err)) + + err = nbs.Put(ctx, tb1) + require.NoError(t, err) + + b, err := nbs.Get(ctx, tb1.Cid()) + require.NoError(t, err) + require.Equal(t, "aoeu", string(b.RawData())) +} diff --git a/blockstore/net_ws.go b/blockstore/net_ws.go new file mode 100644 index 000000000..5c9a70d84 --- /dev/null +++ b/blockstore/net_ws.go @@ -0,0 +1,100 @@ +package blockstore + +import ( + "bytes" + "context" + + "github.com/gorilla/websocket" + "github.com/libp2p/go-msgio" + "golang.org/x/xerrors" +) + +type wsWrapper struct { + wc *websocket.Conn + + nextMsg []byte +} + +func (w *wsWrapper) Read(b []byte) (int, error) { + return 0, xerrors.New("read unsupported") +} + +func (w *wsWrapper) ReadMsg() ([]byte, error) { + if w.nextMsg != nil { + nm := w.nextMsg + w.nextMsg = nil + return nm, nil + } + + mt, r, err := w.wc.NextReader() + if err != nil { + return nil, err + } + + switch mt { + case websocket.BinaryMessage, websocket.TextMessage: + default: + return nil, xerrors.Errorf("unexpected message type") + } + + // todo pool + // todo limit sizes + var mbuf bytes.Buffer + if _, err := mbuf.ReadFrom(r); err != nil { + return nil, err + } + + return mbuf.Bytes(), nil +} + +func (w *wsWrapper) ReleaseMsg(bytes []byte) { + // todo use a pool +} + +func (w *wsWrapper) NextMsgLen() (int, error) { + if w.nextMsg != nil { + return len(w.nextMsg), nil + } + + mt, msg, err := w.wc.ReadMessage() + if err != nil { + return 0, err + } + + switch mt { + case websocket.BinaryMessage, websocket.TextMessage: + default: + return 0, xerrors.Errorf("unexpected message type") + } + + w.nextMsg = msg + return len(w.nextMsg), nil +} + +func (w *wsWrapper) Write(bytes []byte) (int, error) { + return 0, xerrors.New("write unsupported") +} + +func (w *wsWrapper) WriteMsg(bytes []byte) error { + return w.wc.WriteMessage(websocket.BinaryMessage, bytes) +} + +func (w *wsWrapper) Close() error { + return w.wc.Close() +} + +var _ msgio.ReadWriteCloser = &wsWrapper{} + +func wsConnToMio(wc *websocket.Conn) msgio.ReadWriteCloser { + return &wsWrapper{ + wc: wc, + } +} + +func HandleNetBstoreWS(ctx context.Context, bs Blockstore, wc *websocket.Conn) *NetworkStoreHandler { + return HandleNetBstoreStream(ctx, bs, wsConnToMio(wc)) +} + +func NewNetworkStoreWS(wc *websocket.Conn) *NetworkStore { + return NewNetworkStore(wsConnToMio(wc)) +} diff --git a/blockstore/splitstore/splitstore.go b/blockstore/splitstore/splitstore.go index 01c53f61e..dee6e784c 100644 --- a/blockstore/splitstore/splitstore.go +++ b/blockstore/splitstore/splitstore.go @@ -98,6 +98,10 @@ type Config struct { // and directly purges cold blocks. DiscardColdBlocks bool + // UniversalColdBlocks indicates whether all blocks being garbage collected and purged + // from the hotstore should be written to the cold store + UniversalColdBlocks bool + // HotstoreMessageRetention indicates the hotstore retention policy for messages. // It has the following semantics: // - a value of 0 will only retain messages within the compaction boundary (4 finalities) @@ -111,21 +115,6 @@ type Config struct { // A positive value is the number of compactions before a full GC is performed; // a value of 1 will perform full GC in every compaction. HotStoreFullGCFrequency uint64 - - // EnableColdStoreAutoPrune turns on compaction of the cold store i.e. pruning - // where hotstore compaction occurs every finality epochs pruning happens every 3 finalities - // Default is false - EnableColdStoreAutoPrune bool - - // ColdStoreFullGCFrequency specifies how often to performa a full (moving) GC on the coldstore. - // Only applies if auto prune is enabled. A value of 0 disables while a value of 1 will do - // full GC in every prune. - // Default is 7 (about once every a week) - ColdStoreFullGCFrequency uint64 - - // ColdStoreRetention specifies the retention policy for data reachable from the chain, in - // finalities beyond the compaction boundary, default is 0, -1 retains everything - ColdStoreRetention int64 } // ChainAccessor allows the Splitstore to access the chain. It will most likely diff --git a/blockstore/splitstore/splitstore_check.go b/blockstore/splitstore/splitstore_check.go index 6452b3ee2..336515980 100644 --- a/blockstore/splitstore/splitstore_check.go +++ b/blockstore/splitstore/splitstore_check.go @@ -125,7 +125,7 @@ func (s *SplitStore) doCheck(curTs *types.TipSet) error { } return nil - }) + }, func(cid.Cid) error { return nil }) if err != nil { err = xerrors.Errorf("error walking chain: %w", err) diff --git a/blockstore/splitstore/splitstore_compact.go b/blockstore/splitstore/splitstore_compact.go index 272d0afab..1c4c903ff 100644 --- a/blockstore/splitstore/splitstore_compact.go +++ b/blockstore/splitstore/splitstore_compact.go @@ -20,7 +20,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" - bstore "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/metrics" @@ -134,39 +133,6 @@ func (s *SplitStore) HeadChange(_, apply []*types.TipSet) error { log.Infow("compaction done", "took", time.Since(start)) }() // only prune if auto prune is enabled and after at least one compaction - } else if s.cfg.EnableColdStoreAutoPrune && epoch-s.pruneEpoch > PruneThreshold && s.compactionIndex > 0 { - s.beginTxnProtect() - s.compactType = cold - go func() { - defer atomic.StoreInt32(&s.compacting, 0) - defer s.endTxnProtect() - - log.Info("pruning splitstore") - start := time.Now() - - var retainP func(int64) bool - switch { - case s.cfg.ColdStoreRetention > int64(0): - retainP = func(depth int64) bool { - return depth <= int64(CompactionBoundary)+s.cfg.ColdStoreRetention*int64(build.Finality) - } - case s.cfg.ColdStoreRetention < 0: - retainP = func(_ int64) bool { return true } - default: - retainP = func(depth int64) bool { - return depth <= int64(CompactionBoundary) - } - } - movingGC := s.cfg.ColdStoreFullGCFrequency > 0 && s.pruneIndex%int64(s.cfg.ColdStoreFullGCFrequency) == 0 - var gcOpts []bstore.BlockstoreGCOption - if movingGC { - gcOpts = append(gcOpts, bstore.WithFullGC(true)) - } - doGC := func() error { return s.gcBlockstore(s.cold, gcOpts) } - - s.prune(curTs, retainP, doGC) - log.Infow("prune done", "took", time.Since(start)) - }() } else { // no compaction necessary atomic.StoreInt32(&s.compacting, 0) @@ -562,6 +528,12 @@ func (s *SplitStore) doCompact(curTs *types.TipSet) error { defer markSet.Close() //nolint:errcheck defer s.debug.Flush() + coldSet, err := s.markSetEnv.New("cold", s.markSetSize) + if err != nil { + return xerrors.Errorf("error creating cold mark set: %w", err) + } + defer coldSet.Close() //nolint:errcheck + if err := s.checkClosing(); err != nil { return err } @@ -580,24 +552,52 @@ func (s *SplitStore) doCompact(curTs *types.TipSet) error { startMark := time.Now() count := new(int64) - err = s.walkChain(curTs, boundaryEpoch, inclMsgsEpoch, &noopVisitor{}, - func(c cid.Cid) error { - if isUnitaryObject(c) { - return errStopWalk - } - visit, err := markSet.Visit(c) - if err != nil { - return xerrors.Errorf("error visiting object: %w", err) - } - - if !visit { - return errStopWalk - } - - atomic.AddInt64(count, 1) + coldCount := new(int64) + fCold := func(c cid.Cid) error { + // Writes to cold set optimized away in universal and discard mode + // + // Nothing gets written to cold store in discard mode so no cold objects to write + // Everything not marked hot gets written to cold store in universal mode so no need to track cold objects separately + if s.cfg.DiscardColdBlocks || s.cfg.UniversalColdBlocks { return nil - }) + } + + if isUnitaryObject(c) { + return errStopWalk + } + + visit, err := coldSet.Visit(c) + if err != nil { + return xerrors.Errorf("error visiting object: %w", err) + } + + if !visit { + return errStopWalk + } + + atomic.AddInt64(coldCount, 1) + return nil + } + fHot := func(c cid.Cid) error { + if isUnitaryObject(c) { + return errStopWalk + } + + visit, err := markSet.Visit(c) + if err != nil { + return xerrors.Errorf("error visiting object: %w", err) + } + + if !visit { + return errStopWalk + } + + atomic.AddInt64(count, 1) + return nil + } + + err = s.walkChain(curTs, boundaryEpoch, inclMsgsEpoch, &noopVisitor{}, fHot, fCold) if err != nil { return xerrors.Errorf("error marking: %w", err) @@ -631,8 +631,14 @@ func (s *SplitStore) doCompact(curTs *types.TipSet) error { } defer coldw.Close() //nolint:errcheck + purgew, err := NewColdSetWriter(s.discardSetPath()) + if err != nil { + return xerrors.Errorf("error creating deadset: %w", err) + } + defer purgew.Close() //nolint:errcheck + // some stats for logging - var hotCnt, coldCnt int + var hotCnt, coldCnt, purgeCnt int err = s.hot.ForEachKey(func(c cid.Cid) error { // was it marked? mark, err := markSet.Has(c) @@ -645,9 +651,27 @@ func (s *SplitStore) doCompact(curTs *types.TipSet) error { return nil } - // it's cold, mark it as candidate for move + // it needs to be removed from hot store, mark it as candidate for purge + if err := purgew.Write(c); err != nil { + return xerrors.Errorf("error writing cid to purge set: %w", err) + } + purgeCnt++ + + coldMark, err := coldSet.Has(c) + if err != nil { + return xerrors.Errorf("error checking cold mark set for %s: %w", c, err) + } + + // Discard mode: coldMark == false, s.cfg.UniversalColdBlocks == false, always return here, no writes to cold store + // Universal mode: coldMark == false, s.cfg.UniversalColdBlocks == true, never stop here, all writes to cold store + // Otherwise: s.cfg.UniversalColdBlocks == false, if !coldMark stop here and don't write to cold store, if coldMark continue and write to cold store + if !coldMark && !s.cfg.UniversalColdBlocks { // universal mode means mark everything as cold + return nil + } + + // it's cold, mark as candidate for move if err := coldw.Write(c); err != nil { - return xerrors.Errorf("error writing cid to coldstore: %w", err) + return xerrors.Errorf("error writing cid to cold set") } coldCnt++ @@ -656,7 +680,9 @@ func (s *SplitStore) doCompact(curTs *types.TipSet) error { if err != nil { return xerrors.Errorf("error collecting cold objects: %w", err) } - + if err := purgew.Close(); err != nil { + return xerrors.Errorf("erroring closing purgeset: %w", err) + } if err := coldw.Close(); err != nil { return xerrors.Errorf("error closing coldset: %w", err) } @@ -705,6 +731,12 @@ func (s *SplitStore) doCompact(curTs *types.TipSet) error { } } + purger, err := NewColdSetReader(s.discardSetPath()) + if err != nil { + return xerrors.Errorf("error opening coldset: %w", err) + } + defer purger.Close() //nolint:errcheck + // 4. Purge cold objects with checkpointing for recovery. // This is the critical section of compaction, whereby any cold object not in the markSet is // considered already deleted. @@ -736,7 +768,7 @@ func (s *SplitStore) doCompact(curTs *types.TipSet) error { // 5. purge cold objects from the hotstore, taking protected references into account log.Info("purging cold objects from the hotstore") startPurge := time.Now() - err = s.purge(coldr, checkpoint, markSet) + err = s.purge(purger, checkpoint, markSet) if err != nil { return xerrors.Errorf("error purging cold objects: %w", err) } @@ -864,7 +896,7 @@ func (s *SplitStore) endCriticalSection() { } func (s *SplitStore) walkChain(ts *types.TipSet, inclState, inclMsgs abi.ChainEpoch, - visitor ObjectVisitor, f func(cid.Cid) error) error { + visitor ObjectVisitor, fHot, fCold func(cid.Cid) error) error { var walked ObjectVisitor var mx sync.Mutex // we copy the tipset first into a new slice, which allows us to reuse it in every epoch. @@ -886,7 +918,7 @@ func (s *SplitStore) walkChain(ts *types.TipSet, inclState, inclMsgs abi.ChainEp atomic.AddInt64(walkCnt, 1) - if err := f(c); err != nil { + if err := fHot(c); err != nil { return err } @@ -904,27 +936,37 @@ func (s *SplitStore) walkChain(ts *types.TipSet, inclState, inclMsgs abi.ChainEp if inclMsgs < inclState { // we need to use walkObjectIncomplete here, as messages/receipts may be missing early on if we // synced from snapshot and have a long HotStoreMessageRetentionPolicy. - if err := s.walkObjectIncomplete(hdr.Messages, visitor, f, stopWalk); err != nil { + if err := s.walkObjectIncomplete(hdr.Messages, visitor, fHot, stopWalk); err != nil { return xerrors.Errorf("error walking messages (cid: %s): %w", hdr.Messages, err) } - if err := s.walkObjectIncomplete(hdr.ParentMessageReceipts, visitor, f, stopWalk); err != nil { + if err := s.walkObjectIncomplete(hdr.ParentMessageReceipts, visitor, fHot, stopWalk); err != nil { return xerrors.Errorf("error walking messages receipts (cid: %s): %w", hdr.ParentMessageReceipts, err) } } else { - if err := s.walkObject(hdr.Messages, visitor, f); err != nil { + if err := s.walkObject(hdr.Messages, visitor, fHot); err != nil { return xerrors.Errorf("error walking messages (cid: %s): %w", hdr.Messages, err) } - if err := s.walkObject(hdr.ParentMessageReceipts, visitor, f); err != nil { + if err := s.walkObject(hdr.ParentMessageReceipts, visitor, fHot); err != nil { return xerrors.Errorf("error walking message receipts (cid: %s): %w", hdr.ParentMessageReceipts, err) } } } + // messages and receipts outside of inclMsgs are included in the cold store + if hdr.Height < inclMsgs && hdr.Height > 0 { + if err := s.walkObjectIncomplete(hdr.Messages, visitor, fCold, stopWalk); err != nil { + return xerrors.Errorf("error walking messages (cid: %s): %w", hdr.Messages, err) + } + if err := s.walkObjectIncomplete(hdr.ParentMessageReceipts, visitor, fCold, stopWalk); err != nil { + return xerrors.Errorf("error walking messages receipts (cid: %s): %w", hdr.ParentMessageReceipts, err) + } + } + // state is only retained if within the inclState boundary, with the exception of genesis if hdr.Height >= inclState || hdr.Height == 0 { - if err := s.walkObject(hdr.ParentStateRoot, visitor, f); err != nil { + if err := s.walkObject(hdr.ParentStateRoot, visitor, fHot); err != nil { return xerrors.Errorf("error walking state root (cid: %s): %w", hdr.ParentStateRoot, err) } atomic.AddInt64(scanCnt, 1) @@ -1296,7 +1338,7 @@ func (s *SplitStore) coldSetPath() string { return filepath.Join(s.path, "coldset") } -func (s *SplitStore) deadSetPath() string { +func (s *SplitStore) discardSetPath() string { return filepath.Join(s.path, "deadset") } diff --git a/blockstore/splitstore/splitstore_prune.go b/blockstore/splitstore/splitstore_prune.go index 7d54d8e4e..6a26c00d2 100644 --- a/blockstore/splitstore/splitstore_prune.go +++ b/blockstore/splitstore/splitstore_prune.go @@ -208,7 +208,7 @@ func (s *SplitStore) doPrune(curTs *types.TipSet, retainStateP func(int64) bool, log.Info("collecting dead objects") startCollect := time.Now() - deadw, err := NewColdSetWriter(s.deadSetPath()) + deadw, err := NewColdSetWriter(s.discardSetPath()) if err != nil { return xerrors.Errorf("error creating coldset: %w", err) } @@ -267,7 +267,7 @@ func (s *SplitStore) doPrune(curTs *types.TipSet, retainStateP func(int64) bool, return err } - deadr, err := NewColdSetReader(s.deadSetPath()) + deadr, err := NewColdSetReader(s.discardSetPath()) if err != nil { return xerrors.Errorf("error opening deadset: %w", err) } @@ -311,10 +311,10 @@ func (s *SplitStore) doPrune(curTs *types.TipSet, retainStateP func(int64) bool, log.Warnf("error removing checkpoint: %s", err) } if err := deadr.Close(); err != nil { - log.Warnf("error closing deadset: %s", err) + log.Warnf("error closing discard set: %s", err) } - if err := os.Remove(s.deadSetPath()); err != nil { - log.Warnf("error removing deadset: %s", err) + if err := os.Remove(s.discardSetPath()); err != nil { + log.Warnf("error removing discard set: %s", err) } // we are done; do some housekeeping @@ -344,7 +344,7 @@ func (s *SplitStore) completePrune() error { } defer checkpoint.Close() //nolint:errcheck - deadr, err := NewColdSetReader(s.deadSetPath()) + deadr, err := NewColdSetReader(s.discardSetPath()) if err != nil { return xerrors.Errorf("error opening deadset: %w", err) } @@ -378,7 +378,7 @@ func (s *SplitStore) completePrune() error { if err := deadr.Close(); err != nil { log.Warnf("error closing deadset: %s", err) } - if err := os.Remove(s.deadSetPath()); err != nil { + if err := os.Remove(s.discardSetPath()); err != nil { log.Warnf("error removing deadset: %s", err) } diff --git a/blockstore/splitstore/splitstore_test.go b/blockstore/splitstore/splitstore_test.go index d23a78cf0..750a2efed 100644 --- a/blockstore/splitstore/splitstore_test.go +++ b/blockstore/splitstore/splitstore_test.go @@ -38,6 +38,7 @@ func init() { func testSplitStore(t *testing.T, cfg *Config) { ctx := context.Background() chain := &mockChain{t: t} + fmt.Printf("Config: %v\n", cfg) // the myriads of stores ds := dssync.MutexWrap(datastore.NewMapDatastore()) @@ -225,7 +226,7 @@ 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", UniversalColdBlocks: true}) } func TestSplitStoreCompactionWithBadger(t *testing.T) { @@ -237,7 +238,7 @@ func TestSplitStoreCompactionWithBadger(t *testing.T) { t.Cleanup(func() { badgerMarkSetBatchSize = bs }) - testSplitStore(t, &Config{MarkSetType: "badger"}) + testSplitStore(t, &Config{MarkSetType: "badger", UniversalColdBlocks: true}) } func TestSplitStoreSuppressCompactionNearUpgrade(t *testing.T) { @@ -283,7 +284,7 @@ func TestSplitStoreSuppressCompactionNearUpgrade(t *testing.T) { path := t.TempDir() // open the splitstore - ss, err := Open(path, ds, hot, cold, &Config{MarkSetType: "map"}) + ss, err := Open(path, ds, hot, cold, &Config{MarkSetType: "map", UniversalColdBlocks: true}) if err != nil { t.Fatal(err) } @@ -422,7 +423,7 @@ func testSplitStoreReification(t *testing.T, f func(context.Context, blockstore. path := t.TempDir() - ss, err := Open(path, ds, hot, cold, &Config{MarkSetType: "map"}) + ss, err := Open(path, ds, hot, cold, &Config{MarkSetType: "map", UniversalColdBlocks: true}) if err != nil { t.Fatal(err) } @@ -522,7 +523,7 @@ func testSplitStoreReificationLimit(t *testing.T, f func(context.Context, blocks path := t.TempDir() - ss, err := Open(path, ds, hot, cold, &Config{MarkSetType: "map"}) + ss, err := Open(path, ds, hot, cold, &Config{MarkSetType: "map", UniversalColdBlocks: true}) if err != nil { t.Fatal(err) } diff --git a/blockstore/splitstore/splitstore_warmup.go b/blockstore/splitstore/splitstore_warmup.go index e1a121125..e387263da 100644 --- a/blockstore/splitstore/splitstore_warmup.go +++ b/blockstore/splitstore/splitstore_warmup.go @@ -110,7 +110,7 @@ func (s *SplitStore) doWarmup(curTs *types.TipSet) error { mx.Unlock() return nil - }) + }, func(cid.Cid) error { return nil }) if err != nil { return err diff --git a/build/builtin_actors_test.go b/build/builtin_actors_test.go index 87f9aa45f..384193fee 100644 --- a/build/builtin_actors_test.go +++ b/build/builtin_actors_test.go @@ -21,16 +21,18 @@ func TestEmbeddedMetadata(t *testing.T) { // Test that we're registering the manifest correctly. func TestRegistration(t *testing.T) { - manifestCid, found := actors.GetManifest(actorstypes.Version8) - require.True(t, found) - require.True(t, manifestCid.Defined()) + for _, av := range []actorstypes.Version{actorstypes.Version8, actorstypes.Version9} { + manifestCid, found := actors.GetManifest(av) + require.True(t, found) + require.True(t, manifestCid.Defined()) - for _, key := range actors.GetBuiltinActorsKeys(actorstypes.Version8) { - actorCid, found := actors.GetActorCodeID(actorstypes.Version8, key) - require.True(t, found) - name, version, found := actors.GetActorMetaByCode(actorCid) - require.True(t, found) - require.Equal(t, actorstypes.Version8, version) - require.Equal(t, key, name) + for _, key := range actors.GetBuiltinActorsKeys(av) { + actorCid, found := actors.GetActorCodeID(av, key) + require.True(t, found) + name, version, found := actors.GetActorMetaByCode(actorCid) + require.True(t, found) + require.Equal(t, av, version) + require.Equal(t, key, name) + } } } diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 491068bf6..9d24212d2 100644 Binary files a/build/openrpc/full.json.gz and b/build/openrpc/full.json.gz differ diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index 288609431..876ae6cea 100644 Binary files a/build/openrpc/gateway.json.gz and b/build/openrpc/gateway.json.gz differ diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 16cde18aa..404a39214 100644 Binary files a/build/openrpc/miner.json.gz and b/build/openrpc/miner.json.gz differ diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 464f445a4..787ad29fb 100644 Binary files a/build/openrpc/worker.json.gz and b/build/openrpc/worker.json.gz differ diff --git a/build/version.go b/build/version.go index a7508e1b3..99fe6b53d 100644 --- a/build/version.go +++ b/build/version.go @@ -37,7 +37,7 @@ func BuildTypeString() string { } // BuildVersion is the local build version -const BuildVersion = "1.18.2" +const BuildVersion = "1.19.0" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { diff --git a/chain/actors/builtin/datacap/actor.go.template b/chain/actors/builtin/datacap/actor.go.template index 4a9ac7c35..9a3f2bdb8 100644 --- a/chain/actors/builtin/datacap/actor.go.template +++ b/chain/actors/builtin/datacap/actor.go.template @@ -15,8 +15,8 @@ import ( ) var ( - Address = builtin9.DatacapActorAddr - Methods = builtin9.MethodsDatacap + Address = builtin{{.latestVersion}}.DatacapActorAddr + Methods = builtin{{.latestVersion}}.MethodsDatacap ) func Load(store adt.Store, act *types.Actor) (State, error) { diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 9a4204b48..7016b7242 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -82,6 +82,7 @@ var ( ErrRBFTooLowPremium = errors.New("replace by fee has too low GasPremium") ErrTooManyPendingMessages = errors.New("too many pending messages for actor") ErrNonceGap = errors.New("unfulfilled nonce gap") + ErrExistingNonce = errors.New("message with nonce already exists") ) const ( @@ -112,7 +113,7 @@ type MessagePoolEvtMessage struct { func init() { // if the republish interval is too short compared to the pubsub timecache, adjust it - minInterval := pubsub.TimeCacheDuration + time.Duration(build.PropagationDelaySecs) + minInterval := pubsub.TimeCacheDuration + time.Duration(build.PropagationDelaySecs)*time.Second if RepublishInterval < minInterval { RepublishInterval = minInterval } @@ -276,7 +277,7 @@ func (ms *msgSet) add(m *types.SignedMessage, mp *MessagePool, strict, untrusted } } else { return false, xerrors.Errorf("message from %s with nonce %d already in mpool: %w", - m.Message.From, m.Message.Nonce, ErrSoftValidationFailure) + m.Message.From, m.Message.Nonce, ErrExistingNonce) } ms.requiredFunds.Sub(ms.requiredFunds, exms.Message.RequiredFunds().Int) @@ -667,7 +668,9 @@ func (mp *MessagePool) verifyMsgBeforeAdd(ctx context.Context, m *types.SignedMe return publish, nil } -func (mp *MessagePool) Push(ctx context.Context, m *types.SignedMessage) (cid.Cid, error) { +// Push checks the signed message for any violations, adds the message to the message pool and +// publishes the message if the publish flag is set +func (mp *MessagePool) Push(ctx context.Context, m *types.SignedMessage, publish bool) (cid.Cid, error) { done := metrics.Timer(ctx, metrics.MpoolPushDuration) defer done() @@ -683,14 +686,14 @@ func (mp *MessagePool) Push(ctx context.Context, m *types.SignedMessage) (cid.Ci }() mp.curTsLk.Lock() - publish, err := mp.addTs(ctx, m, mp.curTs, true, false) + ok, err := mp.addTs(ctx, m, mp.curTs, true, false) if err != nil { mp.curTsLk.Unlock() return cid.Undef, err } mp.curTsLk.Unlock() - if publish { + if ok && publish { msgb, err := m.Serialize() if err != nil { return cid.Undef, xerrors.Errorf("error serializing message: %w", err) @@ -1583,3 +1586,8 @@ func getBaseFeeLowerBound(baseFee, factor types.BigInt) types.BigInt { return baseFeeLowerBound } + +type MpoolNonceAPI interface { + GetNonce(context.Context, address.Address, types.TipSetKey) (uint64, error) + GetActor(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) +} diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index 5822a68b7..37122492e 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -545,7 +545,7 @@ func TestLoadLocal(t *testing.T) { for i := 0; i < 10; i++ { m := makeTestMessage(w1, a1, a2, uint64(i), gasLimit, uint64(i+1)) //stm: @CHAIN_MEMPOOL_PUSH_001 - cid, err := mp.Push(context.TODO(), m) + cid, err := mp.Push(context.TODO(), m, true) if err != nil { t.Fatal(err) } @@ -618,7 +618,7 @@ func TestClearAll(t *testing.T) { for i := 0; i < 10; i++ { m := makeTestMessage(w1, a1, a2, uint64(i), gasLimit, uint64(i+1)) //stm: @CHAIN_MEMPOOL_PUSH_001 - _, err := mp.Push(context.TODO(), m) + _, err := mp.Push(context.TODO(), m, true) if err != nil { t.Fatal(err) } @@ -676,7 +676,7 @@ func TestClearNonLocal(t *testing.T) { for i := 0; i < 10; i++ { m := makeTestMessage(w1, a1, a2, uint64(i), gasLimit, uint64(i+1)) //stm: @CHAIN_MEMPOOL_PUSH_001 - _, err := mp.Push(context.TODO(), m) + _, err := mp.Push(context.TODO(), m, true) if err != nil { t.Fatal(err) } @@ -749,7 +749,7 @@ func TestUpdates(t *testing.T) { for i := 0; i < 10; i++ { m := makeTestMessage(w1, a1, a2, uint64(i), gasLimit, uint64(i+1)) //stm: @CHAIN_MEMPOOL_PUSH_001 - _, err := mp.Push(context.TODO(), m) + _, err := mp.Push(context.TODO(), m, true) if err != nil { t.Fatal(err) } diff --git a/chain/messagepool/provider.go b/chain/messagepool/provider.go index 50a1bf30f..f8bbbc01e 100644 --- a/chain/messagepool/provider.go +++ b/chain/messagepool/provider.go @@ -12,7 +12,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/network" - "github.com/filecoin-project/lotus/chain/messagesigner" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" @@ -42,7 +41,7 @@ type mpoolProvider struct { sm *stmgr.StateManager ps *pubsub.PubSub - lite messagesigner.MpoolNonceAPI + lite MpoolNonceAPI } var _ Provider = (*mpoolProvider)(nil) @@ -51,7 +50,7 @@ func NewProvider(sm *stmgr.StateManager, ps *pubsub.PubSub) Provider { return &mpoolProvider{sm: sm, ps: ps} } -func NewProviderLite(sm *stmgr.StateManager, ps *pubsub.PubSub, noncer messagesigner.MpoolNonceAPI) Provider { +func NewProviderLite(sm *stmgr.StateManager, ps *pubsub.PubSub, noncer MpoolNonceAPI) Provider { return &mpoolProvider{sm: sm, ps: ps, lite: noncer} } diff --git a/chain/messagepool/repub_test.go b/chain/messagepool/repub_test.go index f6130282c..9cdabc02f 100644 --- a/chain/messagepool/repub_test.go +++ b/chain/messagepool/repub_test.go @@ -60,7 +60,7 @@ func TestRepubMessages(t *testing.T) { for i := 0; i < 10; i++ { m := makeTestMessage(w1, a1, a2, uint64(i), gasLimit, uint64(i+1)) //stm: @CHAIN_MEMPOOL_PUSH_001 - _, err := mp.Push(context.TODO(), m) + _, err := mp.Push(context.TODO(), m, true) if err != nil { t.Fatal(err) } diff --git a/chain/messagesigner/messagesigner.go b/chain/messagesigner/messagesigner.go index 249639d2a..96457e9f8 100644 --- a/chain/messagesigner/messagesigner.go +++ b/chain/messagesigner/messagesigner.go @@ -15,6 +15,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node/modules/dtypes" ) @@ -24,9 +25,12 @@ const dsKeyMsgUUIDSet = "MsgUuidSet" var log = logging.Logger("messagesigner") -type MpoolNonceAPI interface { - GetNonce(context.Context, address.Address, types.TipSetKey) (uint64, error) - GetActor(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) +type MsgSigner interface { + SignMessage(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, cb func(*types.SignedMessage) error) (*types.SignedMessage, error) + GetSignedMessage(ctx context.Context, uuid uuid.UUID) (*types.SignedMessage, error) + StoreSignedMessage(ctx context.Context, uuid uuid.UUID, message *types.SignedMessage) error + NextNonce(ctx context.Context, addr address.Address) (uint64, error) + SaveNonce(ctx context.Context, addr address.Address, nonce uint64) error } // MessageSigner keeps track of nonces per address, and increments the nonce @@ -34,11 +38,11 @@ type MpoolNonceAPI interface { type MessageSigner struct { wallet api.Wallet lk sync.Mutex - mpool MpoolNonceAPI + mpool messagepool.MpoolNonceAPI ds datastore.Batching } -func NewMessageSigner(wallet api.Wallet, mpool MpoolNonceAPI, ds dtypes.MetadataDS) *MessageSigner { +func NewMessageSigner(wallet api.Wallet, mpool messagepool.MpoolNonceAPI, ds dtypes.MetadataDS) *MessageSigner { ds = namespace.Wrap(ds, datastore.NewKey("/message-signer/")) return &MessageSigner{ wallet: wallet, @@ -49,12 +53,12 @@ func NewMessageSigner(wallet api.Wallet, mpool MpoolNonceAPI, ds dtypes.Metadata // SignMessage increments the nonce for the message From address, and signs // the message -func (ms *MessageSigner) SignMessage(ctx context.Context, msg *types.Message, cb func(*types.SignedMessage) error) (*types.SignedMessage, error) { +func (ms *MessageSigner) SignMessage(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, cb func(*types.SignedMessage) error) (*types.SignedMessage, error) { ms.lk.Lock() defer ms.lk.Unlock() // Get the next message nonce - nonce, err := ms.nextNonce(ctx, msg.From) + nonce, err := ms.NextNonce(ctx, msg.From) if err != nil { return nil, xerrors.Errorf("failed to create nonce: %w", err) } @@ -72,7 +76,7 @@ func (ms *MessageSigner) SignMessage(ctx context.Context, msg *types.Message, cb Extra: mb.RawData(), }) if err != nil { - return nil, xerrors.Errorf("failed to sign message: %w", err) + return nil, xerrors.Errorf("failed to sign message: %w, addr=%s", err, msg.From) } // Callback with the signed message @@ -80,13 +84,14 @@ func (ms *MessageSigner) SignMessage(ctx context.Context, msg *types.Message, cb Message: *msg, Signature: *sig, } + err = cb(smsg) if err != nil { return nil, err } // If the callback executed successfully, write the nonce to the datastore - if err := ms.saveNonce(ctx, msg.From, nonce); err != nil { + if err := ms.SaveNonce(ctx, msg.From, nonce); err != nil { return nil, xerrors.Errorf("failed to save nonce: %w", err) } @@ -113,9 +118,9 @@ func (ms *MessageSigner) StoreSignedMessage(ctx context.Context, uuid uuid.UUID, return ms.ds.Put(ctx, key, serializedMsg) } -// nextNonce gets the next nonce for the given address. +// NextNonce gets the next nonce for the given address. // If there is no nonce in the datastore, gets the nonce from the message pool. -func (ms *MessageSigner) nextNonce(ctx context.Context, addr address.Address) (uint64, error) { +func (ms *MessageSigner) NextNonce(ctx context.Context, addr address.Address) (uint64, error) { // Nonces used to be created by the mempool and we need to support nodes // that have mempool nonces, so first check the mempool for a nonce for // this address. Note that the mempool returns the actor state's nonce @@ -159,9 +164,9 @@ func (ms *MessageSigner) nextNonce(ctx context.Context, addr address.Address) (u } } -// saveNonce increments the nonce for this address and writes it to the +// SaveNonce increments the nonce for this address and writes it to the // datastore -func (ms *MessageSigner) saveNonce(ctx context.Context, addr address.Address, nonce uint64) error { +func (ms *MessageSigner) SaveNonce(ctx context.Context, addr address.Address, nonce uint64) error { // Increment the nonce nonce++ diff --git a/chain/messagesigner/messagesigner_consensus.go b/chain/messagesigner/messagesigner_consensus.go new file mode 100644 index 000000000..905bb7199 --- /dev/null +++ b/chain/messagesigner/messagesigner_consensus.go @@ -0,0 +1,98 @@ +package messagesigner + +import ( + "context" + + "github.com/google/uuid" + "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/namespace" + "github.com/libp2p/go-libp2p/core/peer" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/messagepool" + "github.com/filecoin-project/lotus/chain/types" + consensus "github.com/filecoin-project/lotus/lib/consensus/raft" + "github.com/filecoin-project/lotus/node/modules/dtypes" +) + +type MessageSignerConsensus struct { + MsgSigner + Consensus *consensus.Consensus +} + +func NewMessageSignerConsensus( + wallet api.Wallet, + mpool messagepool.MpoolNonceAPI, + ds dtypes.MetadataDS, + consensus *consensus.Consensus) *MessageSignerConsensus { + + ds = namespace.Wrap(ds, datastore.NewKey("/message-signer-consensus/")) + return &MessageSignerConsensus{ + MsgSigner: &MessageSigner{ + wallet: wallet, + mpool: mpool, + ds: ds, + }, + Consensus: consensus, + } +} + +func (ms *MessageSignerConsensus) IsLeader(ctx context.Context) bool { + return ms.Consensus.IsLeader(ctx) +} + +func (ms *MessageSignerConsensus) RedirectToLeader(ctx context.Context, method string, arg interface{}, ret interface{}) (bool, error) { + ok, err := ms.Consensus.RedirectToLeader(method, arg, ret.(*types.SignedMessage)) + if err != nil { + return ok, err + } + return ok, nil +} + +func (ms *MessageSignerConsensus) SignMessage( + ctx context.Context, + msg *types.Message, + spec *api.MessageSendSpec, + cb func(*types.SignedMessage) error) (*types.SignedMessage, error) { + + signedMsg, err := ms.MsgSigner.SignMessage(ctx, msg, spec, cb) + if err != nil { + return nil, err + } + + op := &consensus.ConsensusOp{ + Nonce: signedMsg.Message.Nonce, + Uuid: spec.MsgUuid, + Addr: signedMsg.Message.From, + SignedMsg: signedMsg, + } + err = ms.Consensus.Commit(ctx, op) + if err != nil { + return nil, err + } + + return signedMsg, nil +} + +func (ms *MessageSignerConsensus) GetSignedMessage(ctx context.Context, uuid uuid.UUID) (*types.SignedMessage, error) { + cstate, err := ms.Consensus.State(ctx) + if err != nil { + return nil, err + } + + //cstate := state.(Consensus.RaftState) + msg, ok := cstate.MsgUuids[uuid] + if !ok { + return nil, xerrors.Errorf("Msg with Uuid %s not available", uuid) + } + return msg, nil +} + +func (ms *MessageSignerConsensus) GetRaftState(ctx context.Context) (*consensus.RaftState, error) { + return ms.Consensus.State(ctx) +} + +func (ms *MessageSignerConsensus) Leader(ctx context.Context) (peer.ID, error) { + return ms.Consensus.Leader(ctx) +} diff --git a/chain/messagesigner/messagesigner_test.go b/chain/messagesigner/messagesigner_test.go index 87a5e8615..637f17b46 100644 --- a/chain/messagesigner/messagesigner_test.go +++ b/chain/messagesigner/messagesigner_test.go @@ -13,6 +13,7 @@ import ( "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" ) @@ -22,7 +23,7 @@ type mockMpool struct { nonces map[address.Address]uint64 } -var _ MpoolNonceAPI = (*mockMpool)(nil) +var _ messagepool.MpoolNonceAPI = (*mockMpool)(nil) func newMockMpool() *mockMpool { return &mockMpool{nonces: make(map[address.Address]uint64)} @@ -187,7 +188,7 @@ func TestMessageSignerSignMessage(t *testing.T) { mpool.setNonce(m.msg.From, m.mpoolNonce[0]) } merr := m.cbErr - smsg, err := ms.SignMessage(ctx, m.msg, func(message *types.SignedMessage) error { + smsg, err := ms.SignMessage(ctx, m.msg, nil, func(message *types.SignedMessage) error { return merr }) diff --git a/chain/types/message.go b/chain/types/message.go index 547d4c353..352548d0c 100644 --- a/chain/types/message.go +++ b/chain/types/message.go @@ -159,10 +159,18 @@ func (m *Message) ValidForBlockInclusion(minGas int64, version network.Version) return xerrors.New("invalid 'To' address") } + if !abi.AddressValidForNetworkVersion(m.To, version) { + return xerrors.New("'To' address protocol unsupported for network version") + } + if m.From == address.Undef { return xerrors.New("'From' address cannot be empty") } + if !abi.AddressValidForNetworkVersion(m.From, version) { + return xerrors.New("'From' address protocol unsupported for network version") + } + if m.Value.Int == nil { return xerrors.New("'Value' cannot be nil") } diff --git a/chain/vm/syscalls.go b/chain/vm/syscalls.go index 757453887..f6adc8940 100644 --- a/chain/vm/syscalls.go +++ b/chain/vm/syscalls.go @@ -105,10 +105,20 @@ func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime7.Conse return nil, xerrors.Errorf("cannot decode first block header: %w", decodeErr) } + // A _valid_ block must use an ID address, but that's not what we're checking here. We're + // just making sure that adding additional address protocols won't lead to consensus issues. + if !abi.AddressValidForNetworkVersion(blockA.Miner, ss.networkVersion) { + return nil, xerrors.Errorf("address protocol unsupported in current network version: %d", blockA.Miner.Protocol()) + } + if decodeErr := blockB.UnmarshalCBOR(bytes.NewReader(b)); decodeErr != nil { return nil, xerrors.Errorf("cannot decode second block header: %f", decodeErr) } + if !abi.AddressValidForNetworkVersion(blockB.Miner, ss.networkVersion) { + return nil, xerrors.Errorf("address protocol unsupported in current network version: %d", blockB.Miner.Protocol()) + } + // workaround chain halt if build.IsNearUpgrade(blockA.Height, build.UpgradeOrangeHeight) { return nil, xerrors.Errorf("consensus reporting disabled around Upgrade Orange") @@ -170,6 +180,10 @@ func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime7.Conse return nil, xerrors.Errorf("cannot decode extra: %w", decodeErr) } + if !abi.AddressValidForNetworkVersion(blockC.Miner, ss.networkVersion) { + return nil, xerrors.Errorf("address protocol unsupported in current network version: %d", blockC.Miner.Protocol()) + } + if types.CidArrsEqual(blockA.Parents, blockC.Parents) && blockA.Height == blockC.Height && types.CidArrsContains(blockB.Parents, blockC.Cid()) && !types.CidArrsContains(blockB.Parents, blockA.Cid()) { consensusFault = &runtime7.ConsensusFault{ diff --git a/chain/vm/vm.go b/chain/vm/vm.go index c5b47fd10..669f7e306 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -227,6 +227,10 @@ type VMOpts struct { } func NewLegacyVM(ctx context.Context, opts *VMOpts) (*LegacyVM, error) { + if opts.NetworkVersion >= network.Version16 { + return nil, xerrors.Errorf("the legacy VM does not support network versions 16+") + } + buf := blockstore.NewBuffered(opts.Bstore) cst := cbor.NewCborStore(buf) state, err := state.LoadStateTree(cst, opts.StateBase) diff --git a/cli/chain.go b/cli/chain.go index 6ecb3f6b1..296b4dc70 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -62,6 +62,7 @@ var ChainCmd = &cli.Command{ ChainDecodeCmd, ChainEncodeCmd, ChainDisputeSetCmd, + ChainPruneCmd, }, } diff --git a/cli/client_retr.go b/cli/client_retr.go index 3fe656f15..b619a2871 100644 --- a/cli/client_retr.go +++ b/cli/client_retr.go @@ -3,14 +3,9 @@ package cli import ( "bytes" "context" - "encoding/json" "fmt" "io" - "io/ioutil" - "net/http" - "net/url" "os" - "path" "sort" "strings" "time" @@ -29,8 +24,6 @@ import ( "github.com/ipld/go-ipld-prime/traversal/selector/builder" selectorparse "github.com/ipld/go-ipld-prime/traversal/selector/parse" textselector "github.com/ipld/go-ipld-selector-text-lite" - "github.com/multiformats/go-multiaddr" - manet "github.com/multiformats/go-multiaddr/net" "github.com/urfave/cli/v2" "golang.org/x/xerrors" @@ -40,6 +33,7 @@ import ( lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" + cliutil "github.com/filecoin-project/lotus/cli/util" "github.com/filecoin-project/lotus/markets/utils" "github.com/filecoin-project/lotus/node/repo" ) @@ -181,12 +175,14 @@ func retrieve(ctx context.Context, cctx *cli.Context, fapi lapi.FullNode, sel *l event = retrievalmarket.ClientEvents[*evt.Event] } - printf("Recv %s, Paid %s, %s (%s), %s\n", + printf("Recv %s, Paid %s, %s (%s), %s [%d|%d]\n", types.SizeStr(types.NewInt(evt.BytesReceived)), types.FIL(evt.TotalPaid), strings.TrimPrefix(event, "ClientEvent"), strings.TrimPrefix(retrievalmarket.DealStatuses[evt.Status], "DealStatus"), time.Now().Sub(start).Truncate(time.Millisecond), + evt.ID, + types.NewInt(evt.BytesReceived), ) switch evt.Status { @@ -335,60 +331,6 @@ Examples: }, } -func ClientExportStream(apiAddr string, apiAuth http.Header, eref lapi.ExportRef, car bool) (io.ReadCloser, error) { - rj, err := json.Marshal(eref) - if err != nil { - return nil, xerrors.Errorf("marshaling export ref: %w", err) - } - - ma, err := multiaddr.NewMultiaddr(apiAddr) - if err == nil { - _, addr, err := manet.DialArgs(ma) - if err != nil { - return nil, err - } - - // todo: make cliutil helpers for this - apiAddr = "http://" + addr - } - - aa, err := url.Parse(apiAddr) - if err != nil { - return nil, xerrors.Errorf("parsing api address: %w", err) - } - switch aa.Scheme { - case "ws": - aa.Scheme = "http" - case "wss": - aa.Scheme = "https" - } - - aa.Path = path.Join(aa.Path, "rest/v0/export") - req, err := http.NewRequest("GET", fmt.Sprintf("%s?car=%t&export=%s", aa, car, url.QueryEscape(string(rj))), nil) - if err != nil { - return nil, err - } - - req.Header = apiAuth - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - em, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, xerrors.Errorf("reading error body: %w", err) - } - - resp.Body.Close() // nolint - return nil, xerrors.Errorf("getting root car: http %d: %s", resp.StatusCode, string(em)) - } - - return resp.Body, nil -} - var clientRetrieveCatCmd = &cli.Command{ Name: "cat", Usage: "Show data from network", @@ -438,7 +380,7 @@ var clientRetrieveCatCmd = &cli.Command{ eref.DAGs = append(eref.DAGs, lapi.DagSpec{DataSelector: &sel}) } - rc, err := ClientExportStream(ainfo.Addr, ainfo.AuthHeader(), *eref, false) + rc, err := cliutil.ClientExportStream(ainfo.Addr, ainfo.AuthHeader(), *eref, false) if err != nil { return err } @@ -526,7 +468,7 @@ var clientRetrieveLsCmd = &cli.Command{ DataSelector: &dataSelector, }) - rc, err := ClientExportStream(ainfo.Addr, ainfo.AuthHeader(), *eref, true) + rc, err := cliutil.ClientExportStream(ainfo.Addr, ainfo.AuthHeader(), *eref, true) if err != nil { return xerrors.Errorf("export: %w", err) } @@ -581,6 +523,7 @@ var clientRetrieveLsCmd = &cli.Command{ dserv, roots[0], sel, + nil, func(p traversal.Progress, n ipld.Node, r traversal.VisitReason) error { if r == traversal.VisitReason_SelectionMatch { fmt.Println(p.Path) diff --git a/cli/info.go b/cli/info.go index 0d036875a..007e3655f 100644 --- a/cli/info.go +++ b/cli/info.go @@ -41,7 +41,13 @@ func infoCmdAct(cctx *cli.Context) error { return err } + start, err := fullapi.StartTime(ctx) + if err != nil { + return err + } + fmt.Printf("Network: %s\n", network.NetworkName) + fmt.Printf("StartTime: %s (started at %s)\n", time.Now().Sub(start).Truncate(time.Second), start.Truncate(time.Second)) fmt.Print("Chain: ") err = SyncBasefeeCheck(ctx, fullapi) if err != nil { diff --git a/cli/net.go b/cli/net.go index b0615e0b1..6b10dbffc 100644 --- a/cli/net.go +++ b/cli/net.go @@ -124,8 +124,9 @@ var NetPeers = &cli.Command{ } var NetPing = &cli.Command{ - Name: "ping", - Usage: "Ping peers", + Name: "ping", + Usage: "Ping peers", + ArgsUsage: "[peerMultiaddr]", Flags: []cli.Flag{ &cli.IntFlag{ Name: "count", diff --git a/cli/state.go b/cli/state.go index d5ce46f4c..cd134b49d 100644 --- a/cli/state.go +++ b/cli/state.go @@ -44,7 +44,9 @@ import ( "github.com/filecoin-project/lotus/chain/consensus/filcns" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/stmgr" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" + cliutil "github.com/filecoin-project/lotus/cli/util" ) var StateCmd = &cli.Command{ @@ -229,7 +231,7 @@ var StateMinerInfo = &cli.Command{ return xerrors.Errorf("getting miner info: %w", err) } - fmt.Printf("Proving Period Start:\t%s\n", EpochTime(cd.CurrentEpoch, cd.PeriodStart)) + fmt.Printf("Proving Period Start:\t%s\n", cliutil.EpochTime(cd.CurrentEpoch, cd.PeriodStart)) return nil }, @@ -294,6 +296,28 @@ func ParseTipSetRef(ctx context.Context, api v0api.FullNode, tss string) (*types return ts, nil } +func ParseTipSetRefOffline(ctx context.Context, cs *store.ChainStore, tss string) (*types.TipSet, error) { + switch { + + case tss == "" || tss == "@head": + return cs.GetHeaviestTipSet(), nil + + case tss[0] != '@': + cids, err := ParseTipSetString(tss) + if err != nil { + return nil, xerrors.Errorf("failed to parse tipset (%q): %w", tss, err) + } + return cs.LoadTipSet(ctx, types.NewTipSetKey(cids...)) + + default: + var h uint64 + if _, err := fmt.Sscanf(tss, "@%d", &h); err != nil { + return nil, xerrors.Errorf("parsing height tipset ref: %w", err) + } + return cs.GetTipsetByHeight(ctx, abi.ChainEpoch(h), cs.GetHeaviestTipSet(), true) + } +} + var StatePowerCmd = &cli.Command{ Name: "power", Usage: "Query network or miner power", @@ -1793,8 +1817,8 @@ var StateSectorCmd = &cli.Command{ } fmt.Println("DealIDs: ", si.DealIDs) fmt.Println() - fmt.Println("Activation: ", EpochTimeTs(ts.Height(), si.Activation, ts)) - fmt.Println("Expiration: ", EpochTimeTs(ts.Height(), si.Expiration, ts)) + fmt.Println("Activation: ", cliutil.EpochTimeTs(ts.Height(), si.Activation, ts)) + fmt.Println("Expiration: ", cliutil.EpochTimeTs(ts.Height(), si.Expiration, ts)) fmt.Println() fmt.Println("DealWeight: ", si.DealWeight) fmt.Println("VerifiedDealWeight: ", si.VerifiedDealWeight) diff --git a/cli/util.go b/cli/util.go index 69c45b382..03de817f9 100644 --- a/cli/util.go +++ b/cli/util.go @@ -2,19 +2,13 @@ package cli import ( "context" - "fmt" "os" - "time" "github.com/fatih/color" - "github.com/hako/durafmt" "github.com/ipfs/go-cid" "github.com/mattn/go-isatty" - "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/lotus/api/v0api" - "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" ) @@ -43,36 +37,3 @@ func parseTipSet(ctx context.Context, api v0api.FullNode, vals []string) (*types return types.NewTipSet(headers) } - -func EpochTime(curr, e abi.ChainEpoch) string { - switch { - case curr > e: - return fmt.Sprintf("%d (%s ago)", e, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(curr-e))).LimitFirstN(2)) - case curr == e: - return fmt.Sprintf("%d (now)", e) - case curr < e: - return fmt.Sprintf("%d (in %s)", e, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(e-curr))).LimitFirstN(2)) - } - - panic("math broke") -} - -// EpochTimeTs is like EpochTime, but also outputs absolute time. `ts` is only -// used to provide a timestamp at some epoch to calculate time from. It can be -// a genesis tipset. -// -// Example output: `1944975 (01 Jul 22 08:07 CEST, 10 hours 29 minutes ago)` -func EpochTimeTs(curr, e abi.ChainEpoch, ts *types.TipSet) string { - timeStr := time.Unix(int64(ts.MinTimestamp()+(uint64(e-ts.Height())*build.BlockDelaySecs)), 0).Format(time.RFC822) - - switch { - case curr > e: - return fmt.Sprintf("%d (%s, %s ago)", e, timeStr, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(curr-e))).LimitFirstN(2)) - case curr == e: - return fmt.Sprintf("%d (%s, now)", e, timeStr) - case curr < e: - return fmt.Sprintf("%d (%s, in %s)", e, timeStr, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(e-curr))).LimitFirstN(2)) - } - - panic("math broke") -} diff --git a/cli/util/api.go b/cli/util/api.go index 6c673d91f..596322ab8 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -8,8 +8,10 @@ import ( "net/url" "os" "os/signal" + "reflect" "strings" "syscall" + "time" "github.com/mitchellh/go-homedir" "github.com/urfave/cli/v2" @@ -21,6 +23,7 @@ import ( "github.com/filecoin-project/lotus/api/client" "github.com/filecoin-project/lotus/api/v0api" "github.com/filecoin-project/lotus/api/v1api" + "github.com/filecoin-project/lotus/lib/retry" "github.com/filecoin-project/lotus/node/repo" ) @@ -36,7 +39,7 @@ const ( // 2. *_API_INFO environment variables // 3. deprecated *_API_INFO environment variables // 4. *-repo command line flags. -func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { +func GetAPIInfoMulti(ctx *cli.Context, t repo.RepoType) ([]APIInfo, error) { // Check if there was a flag passed with the listen address of the API // server (only used by the tests) for _, f := range t.APIFlags() { @@ -46,7 +49,7 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { strma := ctx.String(f) strma = strings.TrimSpace(strma) - return APIInfo{Addr: strma}, nil + return []APIInfo{{Addr: strma}}, nil } // @@ -56,14 +59,14 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { primaryEnv, fallbacksEnvs, deprecatedEnvs := t.APIInfoEnvVars() env, ok := os.LookupEnv(primaryEnv) if ok { - return ParseApiInfo(env), nil + return ParseApiInfoMulti(env), nil } for _, env := range deprecatedEnvs { env, ok := os.LookupEnv(env) if ok { log.Warnf("Using deprecated env(%s) value, please use env(%s) instead.", env, primaryEnv) - return ParseApiInfo(env), nil + return ParseApiInfoMulti(env), nil } } @@ -76,26 +79,26 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { p, err := homedir.Expand(path) if err != nil { - return APIInfo{}, xerrors.Errorf("could not expand home dir (%s): %w", f, err) + return []APIInfo{}, xerrors.Errorf("could not expand home dir (%s): %w", f, err) } r, err := repo.NewFS(p) if err != nil { - return APIInfo{}, xerrors.Errorf("could not open repo at path: %s; %w", p, err) + return []APIInfo{}, xerrors.Errorf("could not open repo at path: %s; %w", p, err) } exists, err := r.Exists() if err != nil { - return APIInfo{}, xerrors.Errorf("repo.Exists returned an error: %w", err) + return []APIInfo{}, xerrors.Errorf("repo.Exists returned an error: %w", err) } if !exists { - return APIInfo{}, errors.New("repo directory does not exist. Make sure your configuration is correct") + return []APIInfo{}, errors.New("repo directory does not exist. Make sure your configuration is correct") } ma, err := r.APIEndpoint() if err != nil { - return APIInfo{}, xerrors.Errorf("could not get api endpoint: %w", err) + return []APIInfo{}, xerrors.Errorf("could not get api endpoint: %w", err) } token, err := r.APIToken() @@ -103,38 +106,75 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { log.Warnf("Couldn't load CLI token, capabilities may be limited: %v", err) } - return APIInfo{ + return []APIInfo{{ Addr: ma.String(), Token: token, - }, nil + }}, nil } for _, env := range fallbacksEnvs { env, ok := os.LookupEnv(env) if ok { - return ParseApiInfo(env), nil + return ParseApiInfoMulti(env), nil } } - return APIInfo{}, fmt.Errorf("could not determine API endpoint for node type: %v", t.Type()) + return []APIInfo{}, fmt.Errorf("could not determine API endpoint for node type: %v", t.Type()) } -func GetRawAPI(ctx *cli.Context, t repo.RepoType, version string) (string, http.Header, error) { - ainfo, err := GetAPIInfo(ctx, t) - if err != nil { - return "", nil, xerrors.Errorf("could not get API info for %s: %w", t.Type(), err) +func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) { + ainfos, err := GetAPIInfoMulti(ctx, t) + if err != nil || len(ainfos) == 0 { + return APIInfo{}, err } - addr, err := ainfo.DialArgs(version) - if err != nil { - return "", nil, xerrors.Errorf("could not get DialArgs: %w", err) + if len(ainfos) > 1 { + log.Warn("multiple API infos received when only one was expected") + } + + return ainfos[0], nil + +} + +type HttpHead struct { + addr string + header http.Header +} + +func GetRawAPIMulti(ctx *cli.Context, t repo.RepoType, version string) ([]HttpHead, error) { + + var httpHeads []HttpHead + ainfos, err := GetAPIInfoMulti(ctx, t) + if err != nil || len(ainfos) == 0 { + return httpHeads, xerrors.Errorf("could not get API info for %s: %w", t.Type(), err) + } + + for _, ainfo := range ainfos { + addr, err := ainfo.DialArgs(version) + if err != nil { + return httpHeads, xerrors.Errorf("could not get DialArgs: %w", err) + } + httpHeads = append(httpHeads, HttpHead{addr: addr, header: ainfo.AuthHeader()}) } if IsVeryVerbose { - _, _ = fmt.Fprintf(ctx.App.Writer, "using raw API %s endpoint: %s\n", version, addr) + _, _ = fmt.Fprintf(ctx.App.Writer, "using raw API %s endpoint: %s\n", version, httpHeads[0].addr) } - return addr, ainfo.AuthHeader(), nil + return httpHeads, nil +} + +func GetRawAPI(ctx *cli.Context, t repo.RepoType, version string) (string, http.Header, error) { + heads, err := GetRawAPIMulti(ctx, t, version) + if err != nil { + return "", nil, err + } + + if len(heads) > 1 { + log.Warnf("More than 1 header received when expecting only one") + } + + return heads[0].addr, heads[0].header, nil } func GetCommonAPI(ctx *cli.Context) (api.CommonNet, jsonrpc.ClientCloser, error) { @@ -185,7 +225,72 @@ func GetFullNodeAPI(ctx *cli.Context) (v0api.FullNode, jsonrpc.ClientCloser, err return client.NewFullNodeRPCV0(ctx.Context, addr, headers) } -func GetFullNodeAPIV1(ctx *cli.Context) (v1api.FullNode, jsonrpc.ClientCloser, error) { +type contextKey string + +// Not thread safe +func OnSingleNode(ctx context.Context) context.Context { + return context.WithValue(ctx, contextKey("retry-node"), new(*int)) +} + +func FullNodeProxy[T api.FullNode](ins []T, outstr *api.FullNodeStruct) { + outs := api.GetInternalStructs(outstr) + + var rins []reflect.Value + for _, in := range ins { + rins = append(rins, reflect.ValueOf(in)) + } + + for _, out := range outs { + rProxyInternal := reflect.ValueOf(out).Elem() + + for f := 0; f < rProxyInternal.NumField(); f++ { + field := rProxyInternal.Type().Field(f) + + var fns []reflect.Value + for _, rin := range rins { + fns = append(fns, rin.MethodByName(field.Name)) + } + + rProxyInternal.Field(f).Set(reflect.MakeFunc(field.Type, func(args []reflect.Value) (results []reflect.Value) { + errorsToRetry := []error{&jsonrpc.RPCConnectionError{}, &jsonrpc.ErrClient{}} + initialBackoff, err := time.ParseDuration("1s") + if err != nil { + return nil + } + + ctx := args[0].Interface().(context.Context) + + curr := -1 + + // for calls that need to be performed on the same node + // primarily for miner when calling create block and submit block subsequently + key := contextKey("retry-node") + if ctx.Value(key) != nil { + if (*ctx.Value(key).(**int)) == nil { + *ctx.Value(key).(**int) = &curr + } else { + curr = **ctx.Value(key).(**int) - 1 + } + } + + total := len(rins) + result, err := retry.Retry(ctx, 5, initialBackoff, errorsToRetry, func() (results []reflect.Value, err2 error) { + curr = (curr + 1) % total + + result := fns[curr].Call(args) + if result[len(result)-1].IsNil() { + return result, nil + } + e := result[len(result)-1].Interface().(error) + return result, e + }) + return result + })) + } + } +} + +func GetFullNodeAPIV1Single(ctx *cli.Context) (v1api.FullNode, jsonrpc.ClientCloser, error) { if tn, ok := ctx.App.Metadata["testnode-full"]; ok { return tn.(v1api.FullNode), func() {}, nil } @@ -214,6 +319,58 @@ func GetFullNodeAPIV1(ctx *cli.Context) (v1api.FullNode, jsonrpc.ClientCloser, e return v1API, closer, nil } +func GetFullNodeAPIV1(ctx *cli.Context) (v1api.FullNode, jsonrpc.ClientCloser, error) { + if tn, ok := ctx.App.Metadata["testnode-full"]; ok { + return tn.(v1api.FullNode), func() {}, nil + } + + heads, err := GetRawAPIMulti(ctx, repo.FullNode, "v1") + if err != nil { + return nil, nil, err + } + + if IsVeryVerbose { + _, _ = fmt.Fprintln(ctx.App.Writer, "using full node API v1 endpoint:", heads[0].addr) + } + + var fullNodes []api.FullNode + var closers []jsonrpc.ClientCloser + + for _, head := range heads { + v1api, closer, err := client.NewFullNodeRPCV1(ctx.Context, head.addr, head.header) + if err != nil { + log.Warnf("Not able to establish connection to node with addr: ", head.addr) + continue + } + fullNodes = append(fullNodes, v1api) + closers = append(closers, closer) + } + + // When running in cluster mode and trying to establish connections to multiple nodes, fail + // if less than 2 lotus nodes are actually running + if len(heads) > 1 && len(fullNodes) < 2 { + return nil, nil, xerrors.Errorf("Not able to establish connection to more than a single node") + } + + finalCloser := func() { + for _, c := range closers { + c() + } + } + + var v1API api.FullNodeStruct + FullNodeProxy(fullNodes, &v1API) + + v, err := v1API.Version(ctx.Context) + if err != nil { + return nil, nil, err + } + if !v.APIVersion.EqMajorMinor(api.FullAPIVersion1) { + return nil, nil, xerrors.Errorf("Remote API version didn't match (expected %s, remote %s)", api.FullAPIVersion1, v.APIVersion) + } + return &v1API, finalCloser, nil +} + type GetStorageMinerOptions struct { PreferHttp bool } diff --git a/cli/util/apiinfo.go b/cli/util/apiinfo.go index 41ca18c61..30eff9f28 100644 --- a/cli/util/apiinfo.go +++ b/cli/util/apiinfo.go @@ -24,6 +24,7 @@ type APIInfo struct { func ParseApiInfo(s string) APIInfo { var tok []byte + if infoWithToken.Match([]byte(s)) { sp := strings.SplitN(s, ":", 2) tok = []byte(sp[0]) @@ -36,6 +37,18 @@ func ParseApiInfo(s string) APIInfo { } } +func ParseApiInfoMulti(s string) []APIInfo { + var apiInfos []APIInfo + + allAddrs := strings.SplitN(s, ",", -1) + + for _, addr := range allAddrs { + apiInfos = append(apiInfos, ParseApiInfo(addr)) + } + + return apiInfos +} + func (a APIInfo) DialArgs(version string) (string, error) { ma, err := multiaddr.NewMultiaddr(a.Addr) if err == nil { diff --git a/cli/util/epoch.go b/cli/util/epoch.go new file mode 100644 index 000000000..81c92a7e3 --- /dev/null +++ b/cli/util/epoch.go @@ -0,0 +1,46 @@ +package cliutil + +import ( + "fmt" + "time" + + "github.com/hako/durafmt" + + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/types" +) + +func EpochTime(curr, e abi.ChainEpoch) string { + switch { + case curr > e: + return fmt.Sprintf("%d (%s ago)", e, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(curr-e))).LimitFirstN(2)) + case curr == e: + return fmt.Sprintf("%d (now)", e) + case curr < e: + return fmt.Sprintf("%d (in %s)", e, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(e-curr))).LimitFirstN(2)) + } + + panic("math broke") +} + +// EpochTimeTs is like EpochTime, but also outputs absolute time. `ts` is only +// used to provide a timestamp at some epoch to calculate time from. It can be +// a genesis tipset. +// +// Example output: `1944975 (01 Jul 22 08:07 CEST, 10 hours 29 minutes ago)` +func EpochTimeTs(curr, e abi.ChainEpoch, ts *types.TipSet) string { + timeStr := time.Unix(int64(ts.MinTimestamp()+(uint64(e-ts.Height())*build.BlockDelaySecs)), 0).Format(time.RFC822) + + switch { + case curr > e: + return fmt.Sprintf("%d (%s, %s ago)", e, timeStr, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(curr-e))).LimitFirstN(2)) + case curr == e: + return fmt.Sprintf("%d (%s, now)", e, timeStr) + case curr < e: + return fmt.Sprintf("%d (%s, in %s)", e, timeStr, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(e-curr))).LimitFirstN(2)) + } + + panic("math broke") +} diff --git a/cli/util/retrieval.go b/cli/util/retrieval.go new file mode 100644 index 000000000..3a2ef6077 --- /dev/null +++ b/cli/util/retrieval.go @@ -0,0 +1,78 @@ +package cliutil + +import ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "path" + + "github.com/multiformats/go-multiaddr" + manet "github.com/multiformats/go-multiaddr/net" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/api" +) + +func ApiAddrToUrl(apiAddr string) (*url.URL, error) { + ma, err := multiaddr.NewMultiaddr(apiAddr) + if err == nil { + _, addr, err := manet.DialArgs(ma) + if err != nil { + return nil, err + } + // todo: make cliutil helpers for this + apiAddr = "http://" + addr + } + aa, err := url.Parse(apiAddr) + if err != nil { + return nil, xerrors.Errorf("parsing api address: %w", err) + } + switch aa.Scheme { + case "ws": + aa.Scheme = "http" + case "wss": + aa.Scheme = "https" + } + + return aa, nil +} + +func ClientExportStream(apiAddr string, apiAuth http.Header, eref api.ExportRef, car bool) (io.ReadCloser, error) { + rj, err := json.Marshal(eref) + if err != nil { + return nil, xerrors.Errorf("marshaling export ref: %w", err) + } + + aa, err := ApiAddrToUrl(apiAddr) + if err != nil { + return nil, err + } + + aa.Path = path.Join(aa.Path, "rest/v0/export") + req, err := http.NewRequest("GET", fmt.Sprintf("%s?car=%t&export=%s", aa, car, url.QueryEscape(string(rj))), nil) + if err != nil { + return nil, err + } + + req.Header = apiAuth + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + + if resp.StatusCode != http.StatusOK { + em, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, xerrors.Errorf("reading error body: %w", err) + } + + resp.Body.Close() // nolint + return nil, xerrors.Errorf("getting root car: http %d: %s", resp.StatusCode, string(em)) + } + + return resp.Body, nil +} diff --git a/cli/wallet.go b/cli/wallet.go index 56c1532f4..3a21cdaba 100644 --- a/cli/wallet.go +++ b/cli/wallet.go @@ -260,6 +260,7 @@ var walletSetDefault = &cli.Command{ return err } + fmt.Println("Default address set to:", addr) return api.WalletSetDefault(ctx, addr) }, } @@ -517,6 +518,8 @@ var walletDelete = &cli.Command{ return err } + fmt.Println("Soft deleting address:", addr) + fmt.Println("Hard deletion of the address in `~/.lotus/keystore` is needed for permanent removal") return api.WalletDelete(ctx, addr) }, } diff --git a/cmd/lotus-miner/actor.go b/cmd/lotus-miner/actor.go index 476467282..843862d92 100644 --- a/cmd/lotus-miner/actor.go +++ b/cmd/lotus-miner/actor.go @@ -595,6 +595,7 @@ var actorControlList = &cli.Command{ printKey("owner", mi.Owner) printKey("worker", mi.Worker) + printKey("beneficiary", mi.Beneficiary) for i, ca := range mi.ControlAddresses { printKey(fmt.Sprintf("control-%d", i), ca) } diff --git a/cmd/lotus-miner/info.go b/cmd/lotus-miner/info.go index 9065139eb..b1075be37 100644 --- a/cmd/lotus-miner/info.go +++ b/cmd/lotus-miner/info.go @@ -33,6 +33,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin/reward" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" + cliutil "github.com/filecoin-project/lotus/cli/util" "github.com/filecoin-project/lotus/journal/alerting" sealing "github.com/filecoin-project/lotus/storage/pipeline" "github.com/filecoin-project/lotus/storage/sealer/sealtasks" @@ -92,6 +93,12 @@ func infoCmdAct(cctx *cli.Context) error { fmt.Println("Enabled subsystems (from markets API):", subsystems) + start, err := fullapi.StartTime(ctx) + if err != nil { + return err + } + fmt.Printf("StartTime: %s (started at %s)\n", time.Now().Sub(start).Truncate(time.Second), start.Truncate(time.Second)) + fmt.Print("Chain: ") err = lcli.SyncBasefeeCheck(ctx, fullapi) @@ -528,6 +535,7 @@ var stateList = []stateMeta{ {col: color.FgYellow, state: sealing.ProveReplicaUpdate}, {col: color.FgYellow, state: sealing.SubmitReplicaUpdate}, {col: color.FgYellow, state: sealing.ReplicaUpdateWait}, + {col: color.FgYellow, state: sealing.WaitMutable}, {col: color.FgYellow, state: sealing.FinalizeReplicaUpdate}, {col: color.FgYellow, state: sealing.ReleaseSectorKey}, @@ -658,7 +666,7 @@ func producedBlocks(ctx context.Context, count int, maddr address.Address, napi fmt.Printf("%8d | %s | %s\n", ts.Height(), bh.Cid(), types.FIL(minerReward)) count-- } else if tty && bh.Height%120 == 0 { - _, _ = fmt.Fprintf(os.Stderr, "\r\x1b[0KChecking epoch %s", lcli.EpochTime(head.Height(), bh.Height)) + _, _ = fmt.Fprintf(os.Stderr, "\r\x1b[0KChecking epoch %s", cliutil.EpochTime(head.Height(), bh.Height)) } } tsk = ts.Parents() diff --git a/cmd/lotus-miner/init.go b/cmd/lotus-miner/init.go index 2d094b55a..66a6691af 100644 --- a/cmd/lotus-miner/init.go +++ b/cmd/lotus-miner/init.go @@ -49,6 +49,7 @@ import ( "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/journal/fsjournal" storageminer "github.com/filecoin-project/lotus/miner" + "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/repo" @@ -218,7 +219,7 @@ var initCmd = &cli.Command{ return err } - var localPaths []paths.LocalPath + var localPaths []storiface.LocalPath if pssb := cctx.StringSlice("pre-sealed-sectors"); len(pssb) != 0 { log.Infof("Setting up storage config with presealed sectors: %v", pssb) @@ -228,14 +229,14 @@ var initCmd = &cli.Command{ if err != nil { return err } - localPaths = append(localPaths, paths.LocalPath{ + localPaths = append(localPaths, storiface.LocalPath{ Path: psp, }) } } if !cctx.Bool("no-local-storage") { - b, err := json.MarshalIndent(&paths.LocalStorageMeta{ + b, err := json.MarshalIndent(&storiface.LocalStorageMeta{ ID: storiface.ID(uuid.New().String()), Weight: 10, CanSeal: true, @@ -249,12 +250,12 @@ var initCmd = &cli.Command{ return xerrors.Errorf("persisting storage metadata (%s): %w", filepath.Join(lr.Path(), "sectorstore.json"), err) } - localPaths = append(localPaths, paths.LocalPath{ + localPaths = append(localPaths, storiface.LocalPath{ Path: lr.Path(), }) } - if err := lr.SetStorage(func(sc *paths.StorageConfig) { + if err := lr.SetStorage(func(sc *storiface.StorageConfig) { sc.StoragePaths = append(sc.StoragePaths, localPaths...) }); err != nil { return xerrors.Errorf("set storage config: %w", err) @@ -471,7 +472,7 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api v1api.FullNode } stor := paths.NewRemote(lstor, si, http.Header(sa), 10, &paths.DefaultPartialFileHandler{}) - smgr, err := sealer.New(ctx, lstor, stor, lr, si, sealer.Config{ + smgr, err := sealer.New(ctx, lstor, stor, lr, si, config.SealerConfig{ ParallelFetchLimit: 10, AllowAddPiece: true, AllowPreCommit1: true, @@ -481,7 +482,7 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api v1api.FullNode AllowReplicaUpdate: true, AllowProveReplicaUpdate2: true, AllowRegenSectorKey: true, - }, wsts, smsts) + }, config.ProvingConfig{}, wsts, smsts) if err != nil { return err } diff --git a/cmd/lotus-miner/init_restore.go b/cmd/lotus-miner/init_restore.go index 3d179f3ba..618825a27 100644 --- a/cmd/lotus-miner/init_restore.go +++ b/cmd/lotus-miner/init_restore.go @@ -27,7 +27,7 @@ import ( "github.com/filecoin-project/lotus/lib/backupds" "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/repo" - "github.com/filecoin-project/lotus/storage/paths" + "github.com/filecoin-project/lotus/storage/sealer/storiface" ) var restoreCmd = &cli.Command{ @@ -52,7 +52,7 @@ var restoreCmd = &cli.Command{ ctx := lcli.ReqContext(cctx) log.Info("Initializing lotus miner using a backup") - var storageCfg *paths.StorageConfig + var storageCfg *storiface.StorageConfig if cctx.IsSet("storage-config") { cf, err := homedir.Expand(cctx.String("storage-config")) if err != nil { @@ -64,7 +64,7 @@ var restoreCmd = &cli.Command{ return xerrors.Errorf("reading storage config: %w", err) } - storageCfg = &paths.StorageConfig{} + storageCfg = &storiface.StorageConfig{} err = json.Unmarshal(cfb, storageCfg) if err != nil { return xerrors.Errorf("cannot unmarshal json for storage config: %w", err) @@ -95,7 +95,7 @@ var restoreCmd = &cli.Command{ }, } -func restore(ctx context.Context, cctx *cli.Context, targetPath string, strConfig *paths.StorageConfig, manageConfig func(*config.StorageMiner) error, after func(api lapi.FullNode, addr address.Address, peerid peer.ID, mi api.MinerInfo) error) error { +func restore(ctx context.Context, cctx *cli.Context, targetPath string, strConfig *storiface.StorageConfig, manageConfig func(*config.StorageMiner) error, after func(api lapi.FullNode, addr address.Address, peerid peer.ID, mi api.MinerInfo) error) error { if cctx.NArg() != 1 { return lcli.IncorrectNumArgs(cctx) } @@ -214,7 +214,7 @@ func restore(ctx context.Context, cctx *cli.Context, targetPath string, strConfi if strConfig != nil { log.Info("Restoring storage path config") - err = lr.SetStorage(func(scfg *paths.StorageConfig) { + err = lr.SetStorage(func(scfg *storiface.StorageConfig) { *scfg = *strConfig }) if err != nil { @@ -223,8 +223,8 @@ func restore(ctx context.Context, cctx *cli.Context, targetPath string, strConfi } else { log.Warn("--storage-config NOT SET. NO SECTOR PATHS WILL BE CONFIGURED") // setting empty config to allow miner to be started - if err := lr.SetStorage(func(sc *paths.StorageConfig) { - sc.StoragePaths = append(sc.StoragePaths, paths.LocalPath{}) + if err := lr.SetStorage(func(sc *storiface.StorageConfig) { + sc.StoragePaths = append(sc.StoragePaths, storiface.LocalPath{}) }); err != nil { return xerrors.Errorf("set storage config: %w", err) } diff --git a/cmd/lotus-miner/init_service.go b/cmd/lotus-miner/init_service.go index 41838965a..235e4e4c8 100644 --- a/cmd/lotus-miner/init_service.go +++ b/cmd/lotus-miner/init_service.go @@ -17,7 +17,7 @@ import ( lcli "github.com/filecoin-project/lotus/cli" cliutil "github.com/filecoin-project/lotus/cli/util" "github.com/filecoin-project/lotus/node/config" - "github.com/filecoin-project/lotus/storage/paths" + "github.com/filecoin-project/lotus/storage/sealer/storiface" ) const ( @@ -78,7 +78,7 @@ var serviceCmd = &cli.Command{ return xerrors.Errorf("please provide Lotus markets repo path via flag %s", FlagMarketsRepo) } - if err := restore(ctx, cctx, repoPath, &paths.StorageConfig{}, func(cfg *config.StorageMiner) error { + if err := restore(ctx, cctx, repoPath, &storiface.StorageConfig{}, func(cfg *config.StorageMiner) error { cfg.Subsystems.EnableMarkets = es.Contains(MarketsService) cfg.Subsystems.EnableMining = false cfg.Subsystems.EnableSealing = false diff --git a/cmd/lotus-miner/proving.go b/cmd/lotus-miner/proving.go index 6f6fd6635..9ae8bdd48 100644 --- a/cmd/lotus-miner/proving.go +++ b/cmd/lotus-miner/proving.go @@ -26,6 +26,7 @@ import ( "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" + cliutil "github.com/filecoin-project/lotus/cli/util" "github.com/filecoin-project/lotus/storage/sealer/storiface" ) @@ -185,18 +186,18 @@ var provingInfoCmd = &cli.Command{ fmt.Printf("Current Epoch: %d\n", cd.CurrentEpoch) fmt.Printf("Proving Period Boundary: %d\n", cd.PeriodStart%cd.WPoStProvingPeriod) - fmt.Printf("Proving Period Start: %s\n", lcli.EpochTimeTs(cd.CurrentEpoch, cd.PeriodStart, head)) - fmt.Printf("Next Period Start: %s\n\n", lcli.EpochTimeTs(cd.CurrentEpoch, cd.PeriodStart+cd.WPoStProvingPeriod, head)) + fmt.Printf("Proving Period Start: %s\n", cliutil.EpochTimeTs(cd.CurrentEpoch, cd.PeriodStart, head)) + fmt.Printf("Next Period Start: %s\n\n", cliutil.EpochTimeTs(cd.CurrentEpoch, cd.PeriodStart+cd.WPoStProvingPeriod, head)) fmt.Printf("Faults: %d (%.2f%%)\n", faults, faultPerc) fmt.Printf("Recovering: %d\n", recovering) fmt.Printf("Deadline Index: %d\n", cd.Index) fmt.Printf("Deadline Sectors: %d\n", curDeadlineSectors) - fmt.Printf("Deadline Open: %s\n", lcli.EpochTime(cd.CurrentEpoch, cd.Open)) - fmt.Printf("Deadline Close: %s\n", lcli.EpochTime(cd.CurrentEpoch, cd.Close)) - fmt.Printf("Deadline Challenge: %s\n", lcli.EpochTime(cd.CurrentEpoch, cd.Challenge)) - fmt.Printf("Deadline FaultCutoff: %s\n", lcli.EpochTime(cd.CurrentEpoch, cd.FaultCutoff)) + fmt.Printf("Deadline Open: %s\n", cliutil.EpochTime(cd.CurrentEpoch, cd.Open)) + fmt.Printf("Deadline Close: %s\n", cliutil.EpochTime(cd.CurrentEpoch, cd.Close)) + fmt.Printf("Deadline Challenge: %s\n", cliutil.EpochTime(cd.CurrentEpoch, cd.Challenge)) + fmt.Printf("Deadline FaultCutoff: %s\n", cliutil.EpochTime(cd.CurrentEpoch, cd.FaultCutoff)) return nil }, } @@ -582,7 +583,7 @@ var provingCheckProvableCmd = &cli.Command{ }) } - bad, err := minerApi.CheckProvable(ctx, info.WindowPoStProofType, tocheck, cctx.Bool("slow")) + bad, err := minerApi.CheckProvable(ctx, info.WindowPoStProofType, tocheck) if err != nil { return err } diff --git a/cmd/lotus-miner/sectors.go b/cmd/lotus-miner/sectors.go index 1beaf0cbb..3bb904d7a 100644 --- a/cmd/lotus-miner/sectors.go +++ b/cmd/lotus-miner/sectors.go @@ -32,6 +32,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" + cliutil "github.com/filecoin-project/lotus/cli/util" "github.com/filecoin-project/lotus/lib/strle" "github.com/filecoin-project/lotus/lib/tablewriter" sealing "github.com/filecoin-project/lotus/storage/pipeline" @@ -485,9 +486,9 @@ var sectorsListCmd = &cli.Command{ if !inSSet { m["Expiration"] = "n/a" } else { - m["Expiration"] = lcli.EpochTime(head.Height(), exp) + m["Expiration"] = cliutil.EpochTime(head.Height(), exp) if st.Early > 0 { - m["RecoveryTimeout"] = color.YellowString(lcli.EpochTime(head.Height(), st.Early)) + m["RecoveryTimeout"] = color.YellowString(cliutil.EpochTime(head.Height(), st.Early)) } } if inSSet && cctx.Bool("initial-pledge") { @@ -666,10 +667,10 @@ var sectorsCheckExpireCmd = &cli.Command{ "ID": sector.SectorNumber, "SealProof": sector.SealProof, "InitialPledge": types.FIL(sector.InitialPledge).Short(), - "Activation": lcli.EpochTime(currEpoch, sector.Activation), - "Expiration": lcli.EpochTime(currEpoch, sector.Expiration), - "MaxExpiration": lcli.EpochTime(currEpoch, MaxExpiration), - "MaxExtendNow": lcli.EpochTime(currEpoch, MaxExtendNow), + "Activation": cliutil.EpochTime(currEpoch, sector.Activation), + "Expiration": cliutil.EpochTime(currEpoch, sector.Expiration), + "MaxExpiration": cliutil.EpochTime(currEpoch, MaxExpiration), + "MaxExtendNow": cliutil.EpochTime(currEpoch, MaxExtendNow), }) } @@ -1909,7 +1910,7 @@ var sectorsExpiredCmd = &cli.Command{ toRemove = append(toRemove, s) } - fmt.Printf("%d%s\t%s\t%s\n", s, rmMsg, st.State, lcli.EpochTime(head.Height(), st.Expiration)) + fmt.Printf("%d%s\t%s\t%s\n", s, rmMsg, st.State, cliutil.EpochTime(head.Height(), st.Expiration)) return nil }) diff --git a/cmd/lotus-miner/storage.go b/cmd/lotus-miner/storage.go index 290d128e4..b5bfb730d 100644 --- a/cmd/lotus-miner/storage.go +++ b/cmd/lotus-miner/storage.go @@ -29,7 +29,6 @@ import ( "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/lib/tablewriter" - "github.com/filecoin-project/lotus/storage/paths" sealing "github.com/filecoin-project/lotus/storage/pipeline" "github.com/filecoin-project/lotus/storage/sealer/fsutil" "github.com/filecoin-project/lotus/storage/sealer/storiface" @@ -148,7 +147,7 @@ over time } } - cfg := &paths.LocalStorageMeta{ + cfg := &storiface.LocalStorageMeta{ ID: storiface.ID(uuid.New().String()), Weight: cctx.Uint64("weight"), CanSeal: cctx.Bool("seal"), diff --git a/cmd/lotus-seed/seed/seed.go b/cmd/lotus-seed/seed/seed.go index 70ee77921..3b6359e0f 100644 --- a/cmd/lotus-seed/seed/seed.go +++ b/cmd/lotus-seed/seed/seed.go @@ -27,7 +27,6 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet/key" "github.com/filecoin-project/lotus/genesis" - "github.com/filecoin-project/lotus/storage/paths" "github.com/filecoin-project/lotus/storage/sealer/ffiwrapper" "github.com/filecoin-project/lotus/storage/sealer/ffiwrapper/basicfs" "github.com/filecoin-project/lotus/storage/sealer/storiface" @@ -126,7 +125,7 @@ func PreSeal(maddr address.Address, spt abi.RegisteredSealProof, offset abi.Sect } { - b, err := json.MarshalIndent(&paths.LocalStorageMeta{ + b, err := json.MarshalIndent(&storiface.LocalStorageMeta{ ID: storiface.ID(uuid.New().String()), Weight: 0, // read-only CanSeal: false, diff --git a/cmd/lotus-shed/actor.go b/cmd/lotus-shed/actor.go index 5f9d823bb..037b6d433 100644 --- a/cmd/lotus-shed/actor.go +++ b/cmd/lotus-shed/actor.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "encoding/hex" "fmt" "os" @@ -420,6 +421,11 @@ var actorControlSet = &cli.Command{ Name: "actor", Usage: "specify the address of miner actor", }, + &cli.BoolFlag{ + Name: "dump-bytes", + Usage: "Dumps the bytes of the message that would propose this change", + Value: false, + }, &cli.BoolFlag{ Name: "really-do-it", Usage: "Actually send transaction performing the action", @@ -427,11 +433,6 @@ var actorControlSet = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { - if !cctx.Bool("really-do-it") { - fmt.Println("Pass --really-do-it to actually execute this action") - return nil - } - var maddr address.Address if act := cctx.String("actor"); act != "" { var err error @@ -521,14 +522,36 @@ var actorControlSet = &cli.Command{ return xerrors.Errorf("serializing params: %w", err) } - smsg, err := nodeAPI.MpoolPushMessage(ctx, &types.Message{ + msg := &types.Message{ From: mi.Owner, To: maddr, Method: builtin.MethodsMiner.ChangeWorkerAddress, - Value: big.Zero(), Params: sp, - }, nil) + } + + if cctx.Bool("dump-bytes") { + + msg, err = nodeAPI.GasEstimateMessageGas(ctx, msg, nil, types.EmptyTSK) + if err != nil { + return err + } + + msgBytes, err := msg.Serialize() + if err != nil { + return err + } + + fmt.Fprintln(cctx.App.Writer, hex.EncodeToString(msgBytes)) + return nil + } + + if !cctx.Bool("really-do-it") { + fmt.Fprintln(cctx.App.Writer, "Pass --really-do-it to actually execute this action") + return nil + } + + smsg, err := nodeAPI.MpoolPushMessage(ctx, msg, nil) if err != nil { return xerrors.Errorf("mpool push: %w", err) } diff --git a/cmd/lotus-shed/export-car.go b/cmd/lotus-shed/export-car.go index 214b1d5df..5cb4737ea 100644 --- a/cmd/lotus-shed/export-car.go +++ b/cmd/lotus-shed/export-car.go @@ -14,6 +14,8 @@ import ( "github.com/urfave/cli/v2" "golang.org/x/xerrors" + "github.com/filecoin-project/lotus/blockstore" + "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/node/repo" ) @@ -30,18 +32,18 @@ func carWalkFunc(nd format.Node) (out []*format.Link, err error) { var exportCarCmd = &cli.Command{ Name: "export-car", - Description: "Export a car from repo (requires node to be offline)", + Description: "Export a car from repo", Flags: []cli.Flag{ &cli.StringFlag{ Name: "repo", Value: "~/.lotus", }, }, + ArgsUsage: "[outfile] [root cid]", Action: func(cctx *cli.Context) error { if cctx.NArg() != 2 { return lcli.IncorrectNumArgs(cctx) } - outfile := cctx.Args().First() var roots []cid.Cid for _, arg := range cctx.Args().Tail() { @@ -51,14 +53,11 @@ var exportCarCmd = &cli.Command{ } roots = append(roots, c) } - ctx := lcli.ReqContext(cctx) - r, err := repo.NewFS(cctx.String("repo")) if err != nil { return xerrors.Errorf("opening fs repo: %w", err) } - exists, err := r.Exists() if err != nil { return err @@ -67,11 +66,25 @@ var exportCarCmd = &cli.Command{ return xerrors.Errorf("lotus repo doesn't exist") } + var bs blockstore.Blockstore + lr, err := r.Lock(repo.FullNode) - if err != nil { - return err + if err == nil { + bs, err = lr.Blockstore(ctx, repo.UniversalBlockstore) + if err != nil { + return fmt.Errorf("failed to open blockstore: %w", err) + } + defer lr.Close() //nolint:errcheck + } else { + api, closer, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return err + } + + defer closer() + + bs = blockstore.NewAPIBlockstore(api) } - defer lr.Close() //nolint:errcheck fi, err := os.Create(outfile) if err != nil { @@ -80,11 +93,6 @@ var exportCarCmd = &cli.Command{ defer fi.Close() //nolint:errcheck - bs, err := lr.Blockstore(ctx, repo.UniversalBlockstore) - if err != nil { - return fmt.Errorf("failed to open blockstore: %w", err) - } - defer func() { if c, ok := bs.(io.Closer); ok { if err := c.Close(); err != nil { @@ -98,6 +106,14 @@ var exportCarCmd = &cli.Command{ if err != nil { return err } + + sz, err := fi.Seek(0, io.SeekEnd) + if err != nil { + return err + } + + fmt.Printf("done %s\n", types.SizeStr(types.NewInt(uint64(sz)))) + return nil }, } diff --git a/cmd/lotus-shed/export.go b/cmd/lotus-shed/export.go index 8de3f48df..459de3383 100644 --- a/cmd/lotus-shed/export.go +++ b/cmd/lotus-shed/export.go @@ -32,7 +32,6 @@ import ( "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/chain/store" - "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/cmd/lotus-shed/shedgen" "github.com/filecoin-project/lotus/node/repo" @@ -125,22 +124,9 @@ var exportChainCmd = &cli.Command{ fullstate := cctx.Bool("full-state") skipoldmsgs := cctx.Bool("skip-old-msgs") - var ts *types.TipSet - if tss := cctx.String("tipset"); tss != "" { - cids, err := lcli.ParseTipSetString(tss) - if err != nil { - return xerrors.Errorf("failed to parse tipset (%q): %w", tss, err) - } - - tsk := types.NewTipSetKey(cids...) - - selts, err := cs.LoadTipSet(context.Background(), tsk) - if err != nil { - return xerrors.Errorf("loading tipset: %w", err) - } - ts = selts - } else { - ts = cs.GetHeaviestTipSet() + ts, err := lcli.ParseTipSetRefOffline(ctx, cs, cctx.String("tipset")) + if err != nil { + return err } if fullstate { diff --git a/cmd/lotus-shed/fip-0036.go b/cmd/lotus-shed/fip-0036.go new file mode 100644 index 000000000..2725f205f --- /dev/null +++ b/cmd/lotus-shed/fip-0036.go @@ -0,0 +1,554 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "sort" + "strconv" + + "github.com/ipfs/go-cid" + cbor "github.com/ipfs/go-ipld-cbor" + "github.com/mitchellh/go-homedir" + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "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/miner" + "github.com/filecoin-project/lotus/chain/actors/builtin/multisig" + "github.com/filecoin-project/lotus/chain/actors/builtin/power" + "github.com/filecoin-project/lotus/chain/consensus/filcns" + "github.com/filecoin-project/lotus/chain/state" + "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/node/repo" +) + +type Option uint64 + +const ( + Approve Option = 49 + Reject = 50 +) + +type Vote struct { + ID uint64 + OptionID Option + SignerAddress address.Address +} + +type msigVote struct { + Multisig msigBriefInfo + ApproveCount uint64 + RejectCount uint64 +} + +// https://filpoll.io/poll/16 +// snapshot height: 2162760 +// state root: bafy2bzacebdnzh43hw66bmvguk65wiwr5ssaejlq44fpdei2ysfh3eefpdlqs +var fip36PollCmd = &cli.Command{ + Name: "fip36poll", + Usage: "Process the FIP0036 FilPoll result", + ArgsUsage: "[state root, votes]", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + }, + }, + Subcommands: []*cli.Command{ + finalResultCmd, + }, +} + +var finalResultCmd = &cli.Command{ + Name: "results", + Usage: "get poll results", + ArgsUsage: "[state root] [height] [votes json]", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + }, + }, + + Action: func(cctx *cli.Context) error { + if cctx.NArg() != 3 { + return xerrors.New("filpoll0036 results [state root] [height] [votes.json]") + } + + ctx := context.TODO() + if !cctx.Args().Present() { + return fmt.Errorf("must pass state root") + } + + sroot, err := cid.Decode(cctx.Args().First()) + if err != nil { + return fmt.Errorf("failed to parse input: %w", err) + } + + fsrepo, err := repo.NewFS(cctx.String("repo")) + if err != nil { + return err + } + + lkrepo, err := fsrepo.Lock(repo.FullNode) + if err != nil { + return err + } + + defer lkrepo.Close() //nolint:errcheck + + bs, err := lkrepo.Blockstore(ctx, repo.UniversalBlockstore) + if err != nil { + return fmt.Errorf("failed to open blockstore: %w", err) + } + + defer func() { + if c, ok := bs.(io.Closer); ok { + if err := c.Close(); err != nil { + log.Warnf("failed to close blockstore: %s", err) + } + } + }() + + mds, err := lkrepo.Datastore(context.Background(), "/metadata") + if err != nil { + return err + } + + cs := store.NewChainStore(bs, bs, mds, filcns.Weight, nil) + defer cs.Close() //nolint:errcheck + + cst := cbor.NewCborStore(bs) + store := adt.WrapStore(ctx, cst) + + st, err := state.LoadStateTree(cst, sroot) + if err != nil { + return err + } + + height, err := strconv.Atoi(cctx.Args().Get(1)) + if err != nil { + return err + } + + //get all the votes' signer ID address && their vote + vj, err := homedir.Expand(cctx.Args().Get(2)) + if err != nil { + return xerrors.Errorf("fail to get votes json") + } + votes, err := getVotesMap(vj) + if err != nil { + return xerrors.Errorf("failed to get voters: ", err) + } + + type minerBriefInfo struct { + rawBytePower abi.StoragePower + dealPower abi.StoragePower + balance abi.TokenAmount + } + + // power actor + pa, err := st.GetActor(power.Address) + if err != nil { + return xerrors.Errorf("failed to get power actor: \n", err) + } + + powerState, err := power.Load(store, pa) + if err != nil { + return xerrors.Errorf("failed to get power state: \n", err) + } + + //market actor + ma, err := st.GetActor(market.Address) + if err != nil { + return xerrors.Errorf("fail to get market actor: ", err) + } + + marketState, err := market.Load(store, ma) + if err != nil { + return xerrors.Errorf("fail to load market state: ", err) + } + + lookupId := func(addr address.Address) address.Address { + ret, err := st.LookupID(addr) + if err != nil { + panic(err) + } + + return ret + } + + // we need to build several pieces of information, as we traverse the state tree: + // a map of accounts to every msig that they are a signer of + accountsToMultisigs := make(map[address.Address][]address.Address) + // a map of multisigs to some info about them for quick lookup + msigActorsInfo := make(map[address.Address]msigBriefInfo) + // a map of actors (accounts+multisigs) to every miner that they are an owner of + ownerMap := make(map[address.Address][]address.Address) + // a map of accounts to every miner that they are a worker of + workerMap := make(map[address.Address][]address.Address) + // a map of miners to some info about them for quick lookup + minerActorsInfo := make(map[address.Address]minerBriefInfo) + // a map of client addresses to deal data stored in proposals + clientToDealStorage := make(map[address.Address]abi.StoragePower) + + fmt.Println("iterating over all actors") + count := 0 + err = st.ForEach(func(addr address.Address, act *types.Actor) error { + if count%200000 == 0 { + fmt.Println("processed ", count, " actors building maps") + } + count++ + if builtin.IsMultisigActor(act.Code) { + ms, err := multisig.Load(store, act) + if err != nil { + return fmt.Errorf("load msig failed %v", err) + + } + + // TODO: Confirm that these are always ID addresses + signers, err := ms.Signers() + if err != nil { + return xerrors.Errorf("fail to get msig signers", err) + } + for _, s := range signers { + signerId := lookupId(s) + accountsToMultisigs[signerId] = append(accountsToMultisigs[signerId], addr) + } + + locked, err := ms.LockedBalance(abi.ChainEpoch(height)) + if err != nil { + return xerrors.Errorf("failed to compute locked multisig balance: %w", err) + } + + threshold, _ := ms.Threshold() + info := msigBriefInfo{ + ID: addr, + Signer: signers, + Balance: big.Max(big.Zero(), types.BigSub(act.Balance, locked)), + Threshold: threshold, + } + msigActorsInfo[addr] = info + } + + if builtin.IsStorageMinerActor(act.Code) { + m, err := miner.Load(store, act) + if err != nil { + return xerrors.Errorf("fail to load miner actor: \n", err) + } + + info, err := m.Info() + if err != nil { + return xerrors.Errorf("fail to get miner info: \n", err) + } + + ownerId := lookupId(info.Owner) + ownerMap[ownerId] = append(ownerMap[ownerId], addr) + + workerId := lookupId(info.Worker) + workerMap[workerId] = append(workerMap[workerId], addr) + + lockedFunds, err := m.LockedFunds() + if err != nil { + return err + } + + bal := big.Sub(act.Balance, lockedFunds.TotalLockedFunds()) + bal = big.Max(big.Zero(), bal) + + pow, ok, err := powerState.MinerPower(addr) + if err != nil { + return err + } + + if !ok { + pow.RawBytePower = big.Zero() + } + + minerActorsInfo[addr] = minerBriefInfo{ + rawBytePower: pow.RawBytePower, + // gets added up outside this loop + dealPower: big.Zero(), + balance: bal, + } + } + + return nil + }) + + if err != nil { + return err + } + + fmt.Println("iterating over proposals") + dealProposals, err := marketState.Proposals() + if err != nil { + return err + } + + dealStates, err := marketState.States() + if err != nil { + return err + } + + if err := dealProposals.ForEach(func(dealID abi.DealID, d market.DealProposal) error { + + dealState, ok, err := dealStates.Get(dealID) + if err != nil { + return err + } + if !ok || dealState.SectorStartEpoch == -1 { + // effectively a continue + return nil + } + + clientId := lookupId(d.Client) + if cd, found := clientToDealStorage[clientId]; found { + clientToDealStorage[clientId] = big.Add(cd, big.NewInt(int64(d.PieceSize))) + } else { + clientToDealStorage[clientId] = big.NewInt(int64(d.PieceSize)) + } + + providerId := lookupId(d.Provider) + mai, found := minerActorsInfo[providerId] + + if !found { + return xerrors.Errorf("didn't find miner %s", providerId) + } + + mai.dealPower = big.Add(mai.dealPower, big.NewInt(int64(d.PieceSize))) + minerActorsInfo[providerId] = mai + return nil + }); err != nil { + return xerrors.Errorf("fail to get deals") + } + + // now tabulate votes + + approveBalance := abi.NewTokenAmount(0) + rejectionBalance := abi.NewTokenAmount(0) + clientApproveBytes := big.Zero() + clientRejectBytes := big.Zero() + msigPendingVotes := make(map[address.Address]msigVote) //map[msig ID]msigVote + msigVotes := make(map[address.Address]Option) + minerVotes := make(map[address.Address]Option) + fmt.Println("counting account and multisig votes") + for _, vote := range votes { + signerId, err := st.LookupID(vote.SignerAddress) + if err != nil { + fmt.Println("voter ", vote.SignerAddress, " not found in state tree, skipping") + continue + } + + //process votes for regular accounts + accountActor, err := st.GetActor(signerId) + if err != nil { + return xerrors.Errorf("fail to get account account for signer: ", err) + } + + clientBytes, ok := clientToDealStorage[signerId] + if !ok { + clientBytes = big.Zero() + } + + if vote.OptionID == Approve { + approveBalance = types.BigAdd(approveBalance, accountActor.Balance) + clientApproveBytes = big.Add(clientApproveBytes, clientBytes) + } else { + rejectionBalance = types.BigAdd(rejectionBalance, accountActor.Balance) + clientRejectBytes = big.Add(clientRejectBytes, clientBytes) + } + + if minerInfos, found := ownerMap[signerId]; found { + for _, minerInfo := range minerInfos { + minerVotes[minerInfo] = vote.OptionID + } + } + if minerInfos, found := workerMap[signerId]; found { + for _, minerInfo := range minerInfos { + if _, ok := minerVotes[minerInfo]; !ok { + minerVotes[minerInfo] = vote.OptionID + } + } + } + + //process msigs + // There is a possibility that enough signers have voted for BOTH options in the poll to be above the threshold + // Because we are iterating over votes in order they arrived, the first option to go over the threshold will win + // This is in line with onchain behaviour (consider a case where signers are competing to withdraw all the funds + // in an msig into 2 different accounts) + if mss, found := accountsToMultisigs[signerId]; found { + for _, ms := range mss { //get all the msig signer has + if _, ok := msigVotes[ms]; ok { + // msig has already voted, skip + continue + } + if mpv, found := msigPendingVotes[ms]; found { //other signers of the multisig have voted, yet the threshold has not met + if vote.OptionID == Approve { + if mpv.ApproveCount+1 == mpv.Multisig.Threshold { //met threshold + approveBalance = types.BigAdd(approveBalance, mpv.Multisig.Balance) + delete(msigPendingVotes, ms) //threshold, can skip later signer votes + msigVotes[ms] = vote.OptionID + + } else { + mpv.ApproveCount++ + msigPendingVotes[ms] = mpv + } + } else { + if mpv.RejectCount+1 == mpv.Multisig.Threshold { //met threshold + rejectionBalance = types.BigAdd(rejectionBalance, mpv.Multisig.Balance) + delete(msigPendingVotes, ms) //threshold, can skip later signer votes + msigVotes[ms] = vote.OptionID + + } else { + mpv.RejectCount++ + msigPendingVotes[ms] = mpv + } + } + } else { //first vote received from one of the signers of the msig + msi, ok := msigActorsInfo[ms] + if !ok { + return xerrors.Errorf("didn't find msig %s in msig map", ms) + } + + if msi.Threshold == 1 { //met threshold with this signer's single vote + if vote.OptionID == Approve { + approveBalance = types.BigAdd(approveBalance, msi.Balance) + msigVotes[ms] = Approve + + } else { + rejectionBalance = types.BigAdd(rejectionBalance, msi.Balance) + msigVotes[ms] = Reject + } + } else { //threshold not met, add to pending vote + if vote.OptionID == Approve { + msigPendingVotes[ms] = msigVote{ + Multisig: msi, + ApproveCount: 1, + } + } else { + msigPendingVotes[ms] = msigVote{ + Multisig: msi, + RejectCount: 1, + } + } + } + } + } + } + } + + for s, v := range msigVotes { + if minerInfos, found := ownerMap[s]; found { + for _, minerInfo := range minerInfos { + minerVotes[minerInfo] = v + } + } + if minerInfos, found := workerMap[s]; found { + for _, minerInfo := range minerInfos { + if _, ok := minerVotes[minerInfo]; !ok { + minerVotes[minerInfo] = v + } + } + } + } + + approveRBP := big.Zero() + approveDealPower := big.Zero() + rejectionRBP := big.Zero() + rejectionDealPower := big.Zero() + fmt.Println("adding up miner votes") + for minerAddr, vote := range minerVotes { + mbi, ok := minerActorsInfo[minerAddr] + if !ok { + return xerrors.Errorf("failed to find miner info for %s", minerAddr) + } + + if vote == Approve { + approveBalance = big.Add(approveBalance, mbi.balance) + approveRBP = big.Add(approveRBP, mbi.rawBytePower) + approveDealPower = big.Add(approveDealPower, mbi.dealPower) + } else { + rejectionBalance = big.Add(rejectionBalance, mbi.balance) + rejectionRBP = big.Add(rejectionRBP, mbi.rawBytePower) + rejectionDealPower = big.Add(rejectionDealPower, mbi.dealPower) + } + } + + fmt.Println("Total acceptance token: ", approveBalance) + fmt.Println("Total rejection token: ", rejectionBalance) + + fmt.Println("Total acceptance SP deal power: ", approveDealPower) + fmt.Println("Total rejection SP deal power: ", rejectionDealPower) + + fmt.Println("Total acceptance SP rb power: ", approveRBP) + fmt.Println("Total rejection SP rb power: ", rejectionRBP) + + fmt.Println("Total acceptance Client rb power: ", clientApproveBytes) + fmt.Println("Total rejection Client rb power: ", clientRejectBytes) + + fmt.Println("\n\nFinal results **drumroll**") + if rejectionBalance.GreaterThanEqual(big.Mul(approveBalance, big.NewInt(3))) { + fmt.Println("token holders VETO FIP-0036!") + } else if approveBalance.LessThanEqual(rejectionBalance) { + fmt.Println("token holders REJECT FIP-0036") + } else { + fmt.Println("token holders ACCEPT FIP-0036") + } + + if rejectionDealPower.GreaterThanEqual(big.Mul(approveDealPower, big.NewInt(3))) { + fmt.Println("SPs by deal data stored VETO FIP-0036!") + } else if approveDealPower.LessThanEqual(rejectionDealPower) { + fmt.Println("SPs by deal data stored REJECT FIP-0036") + } else { + fmt.Println("SPs by deal data stored ACCEPT FIP-0036") + } + + if rejectionRBP.GreaterThanEqual(big.Mul(approveRBP, big.NewInt(3))) { + fmt.Println("SPs by total raw byte power VETO FIP-0036!") + } else if approveRBP.LessThanEqual(rejectionRBP) { + fmt.Println("SPs by total raw byte power REJECT FIP-0036") + } else { + fmt.Println("SPs by total raw byte power ACCEPT FIP-0036") + } + + if clientRejectBytes.GreaterThanEqual(big.Mul(clientApproveBytes, big.NewInt(3))) { + fmt.Println("Storage Clients VETO FIP-0036!") + } else if clientApproveBytes.LessThanEqual(clientRejectBytes) { + fmt.Println("Storage Clients REJECT FIP-0036") + } else { + fmt.Println("Storage Clients ACCEPT FIP-0036") + } + + return nil + }, +} + +// Returns voted sorted by votes from earliest to latest +func getVotesMap(file string) ([]Vote, error) { + var votes []Vote + vb, err := ioutil.ReadFile(file) + if err != nil { + return nil, xerrors.Errorf("read vote: %w", err) + } + + if err := json.Unmarshal(vb, &votes); err != nil { + return nil, xerrors.Errorf("unmarshal vote: %w", err) + } + + sort.SliceStable(votes, func(i, j int) bool { + return votes[i].ID < votes[j].ID + }) + + return votes, nil +} diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index c661b04ef..3972a625b 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -73,6 +73,8 @@ func main() { migrationsCmd, diffCmd, itestdCmd, + msigCmd, + fip36PollCmd, invariantsCmd, } diff --git a/cmd/lotus-shed/msig.go b/cmd/lotus-shed/msig.go new file mode 100644 index 000000000..7d37d3d2d --- /dev/null +++ b/cmd/lotus-shed/msig.go @@ -0,0 +1,131 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "io" + + "github.com/ipfs/go-cid" + cbor "github.com/ipfs/go-ipld-cbor" + "github.com/urfave/cli/v2" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors/builtin/multisig" + "github.com/filecoin-project/lotus/chain/consensus/filcns" + "github.com/filecoin-project/lotus/chain/state" + "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/node/repo" +) + +type msigBriefInfo struct { + ID address.Address + Signer []address.Address + Balance abi.TokenAmount + Threshold uint64 +} + +var msigCmd = &cli.Command{ + Name: "msig", + Subcommands: []*cli.Command{ + multisigGetAllCmd, + }, +} + +var multisigGetAllCmd = &cli.Command{ + Name: "all", + Usage: "get all multisig actor on chain with id, signers, threshold and balance at a tipset", + ArgsUsage: "[state root]", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + }, + }, + Action: func(cctx *cli.Context) error { + ctx := context.TODO() + if !cctx.Args().Present() { + return fmt.Errorf("must pass state root") + } + + sroot, err := cid.Decode(cctx.Args().First()) + if err != nil { + return fmt.Errorf("failed to parse input: %w", err) + } + + fsrepo, err := repo.NewFS(cctx.String("repo")) + if err != nil { + return err + } + + lkrepo, err := fsrepo.Lock(repo.FullNode) + if err != nil { + return err + } + + defer lkrepo.Close() //nolint:errcheck + + bs, err := lkrepo.Blockstore(ctx, repo.UniversalBlockstore) + if err != nil { + return fmt.Errorf("failed to open blockstore: %w", err) + } + + defer func() { + if c, ok := bs.(io.Closer); ok { + if err := c.Close(); err != nil { + log.Warnf("failed to close blockstore: %s", err) + } + } + }() + + mds, err := lkrepo.Datastore(context.Background(), "/metadata") + if err != nil { + return err + } + + cs := store.NewChainStore(bs, bs, mds, filcns.Weight, nil) + defer cs.Close() //nolint:errcheck + + cst := cbor.NewCborStore(bs) + store := adt.WrapStore(ctx, cst) + + tree, err := state.LoadStateTree(cst, sroot) + if err != nil { + return err + } + + var msigActorsInfo []msigBriefInfo + err = tree.ForEach(func(addr address.Address, act *types.Actor) error { + if builtin.IsMultisigActor(act.Code) { + ms, err := multisig.Load(store, act) + if err != nil { + return fmt.Errorf("load msig failed %v", err) + + } + + signers, _ := ms.Signers() + threshold, _ := ms.Threshold() + info := msigBriefInfo{ + ID: addr, + Signer: signers, + Balance: act.Balance, + Threshold: threshold, + } + msigActorsInfo = append(msigActorsInfo, info) + + } + return nil + }) + out, err := json.MarshalIndent(msigActorsInfo, "", " ") + if err != nil { + return err + } + fmt.Println(string(out)) + return nil + }, +} diff --git a/cmd/lotus-sim/create.go b/cmd/lotus-sim/create.go index 23ea454a3..bc7f9ade9 100644 --- a/cmd/lotus-sim/create.go +++ b/cmd/lotus-sim/create.go @@ -31,12 +31,7 @@ var createSimCommand = &cli.Command{ } ts = node.Chainstore.GetHeaviestTipSet() case 1: - cids, err := lcli.ParseTipSetString(cctx.Args().Get(1)) - if err != nil { - return err - } - tsk := types.NewTipSetKey(cids...) - ts, err = node.Chainstore.LoadTipSet(cctx.Context, tsk) + ts, err = lcli.ParseTipSetRefOffline(cctx.Context, node.Chainstore, cctx.Args().Get(1)) if err != nil { return err } diff --git a/cmd/lotus-worker/main.go b/cmd/lotus-worker/main.go index 8b8db5aa7..afee6f1e1 100644 --- a/cmd/lotus-worker/main.go +++ b/cmd/lotus-worker/main.go @@ -447,10 +447,10 @@ var runCmd = &cli.Command{ return err } - var localPaths []paths.LocalPath + var localPaths []storiface.LocalPath if !cctx.Bool("no-local-storage") { - b, err := json.MarshalIndent(&paths.LocalStorageMeta{ + b, err := json.MarshalIndent(&storiface.LocalStorageMeta{ ID: storiface.ID(uuid.New().String()), Weight: 10, CanSeal: true, @@ -464,12 +464,12 @@ var runCmd = &cli.Command{ return xerrors.Errorf("persisting storage metadata (%s): %w", filepath.Join(lr.Path(), "sectorstore.json"), err) } - localPaths = append(localPaths, paths.LocalPath{ + localPaths = append(localPaths, storiface.LocalPath{ Path: lr.Path(), }) } - if err := lr.SetStorage(func(sc *paths.StorageConfig) { + if err := lr.SetStorage(func(sc *storiface.StorageConfig) { sc.StoragePaths = append(sc.StoragePaths, localPaths...) }); err != nil { return xerrors.Errorf("set storage config: %w", err) diff --git a/cmd/lotus-worker/sealworker/rpc.go b/cmd/lotus-worker/sealworker/rpc.go index 7d84b5c8b..97f78942e 100644 --- a/cmd/lotus-worker/sealworker/rpc.go +++ b/cmd/lotus-worker/sealworker/rpc.go @@ -92,8 +92,8 @@ func (w *Worker) StorageAddLocal(ctx context.Context, path string) error { return xerrors.Errorf("opening local path: %w", err) } - if err := w.Storage.SetStorage(func(sc *paths.StorageConfig) { - sc.StoragePaths = append(sc.StoragePaths, paths.LocalPath{Path: path}) + if err := w.Storage.SetStorage(func(sc *storiface.StorageConfig) { + sc.StoragePaths = append(sc.StoragePaths, storiface.LocalPath{Path: path}) }); err != nil { return xerrors.Errorf("get storage config: %w", err) } @@ -127,8 +127,8 @@ func (w *Worker) StorageDetachLocal(ctx context.Context, path string) error { // drop from the persisted storage.json var found bool - if err := w.Storage.SetStorage(func(sc *paths.StorageConfig) { - out := make([]paths.LocalPath, 0, len(sc.StoragePaths)) + if err := w.Storage.SetStorage(func(sc *storiface.StorageConfig) { + out := make([]storiface.LocalPath, 0, len(sc.StoragePaths)) for _, storagePath := range sc.StoragePaths { if storagePath.Path != path { out = append(out, storagePath) diff --git a/cmd/lotus-worker/storage.go b/cmd/lotus-worker/storage.go index 0736ffbfb..6b5994c17 100644 --- a/cmd/lotus-worker/storage.go +++ b/cmd/lotus-worker/storage.go @@ -13,7 +13,6 @@ import ( "golang.org/x/xerrors" lcli "github.com/filecoin-project/lotus/cli" - "github.com/filecoin-project/lotus/storage/paths" "github.com/filecoin-project/lotus/storage/sealer/storiface" ) @@ -103,7 +102,7 @@ var storageAttachCmd = &cli.Command{ } } - cfg := &paths.LocalStorageMeta{ + cfg := &storiface.LocalStorageMeta{ ID: storiface.ID(uuid.New().String()), Weight: cctx.Uint64("weight"), CanSeal: cctx.Bool("seal"), diff --git a/cmd/tvx/stores.go b/cmd/tvx/stores.go index 0f4f81397..9035c482a 100644 --- a/cmd/tvx/stores.go +++ b/cmd/tvx/stores.go @@ -16,6 +16,7 @@ import ( cbor "github.com/ipfs/go-ipld-cbor" format "github.com/ipfs/go-ipld-format" "github.com/ipfs/go-merkledag" + "golang.org/x/xerrors" "github.com/filecoin-project/lotus/api/v0api" "github.com/filecoin-project/lotus/blockstore" @@ -158,3 +159,12 @@ func (pb *proxyingBlockstore) PutMany(ctx context.Context, blocks []blocks.Block pb.lk.Unlock() return pb.Blockstore.PutMany(ctx, blocks) } + +func (pb *proxyingBlockstore) View(ctx context.Context, c cid.Cid, callback func([]byte) error) error { + blk, err := pb.Get(ctx, c) + if err != nil { + return xerrors.Errorf("failed to Get cid %s: %w", c, err) + } + + return callback(blk.RawData()) +} diff --git a/conformance/driver.go b/conformance/driver.go index ba9f49176..db8f2ccba 100644 --- a/conformance/driver.go +++ b/conformance/driver.go @@ -160,7 +160,7 @@ func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, params return big.Zero(), nil } - return vm.NewLegacyVM(ctx, vmopt) + return vm.NewVM(ctx, vmopt) }) postcid, receiptsroot, err := tse.ApplyBlocks(context.Background(), @@ -242,23 +242,38 @@ func (d *Driver) ExecuteMessage(bs blockstore.Blockstore, params ExecuteMessageP LookbackState: lookback, } - lvm, err := vm.NewLegacyVM(context.TODO(), vmOpts) - if err != nil { - return nil, cid.Undef, err - } - - invoker := filcns.NewActorRegistry() - - // register the chaos actor if required by the vector. + var vmi vm.Interface if chaosOn, ok := d.selector["chaos_actor"]; ok && chaosOn == "true" { + lvm, err := vm.NewLegacyVM(context.TODO(), vmOpts) + if err != nil { + return nil, cid.Undef, err + } + + invoker := filcns.NewActorRegistry() av, _ := actorstypes.VersionForNetwork(params.NetworkVersion) registry := builtin.MakeRegistryLegacy([]rtt.VMActor{chaos.Actor{}}) invoker.Register(av, nil, registry) + lvm.SetInvoker(invoker) + vmi = lvm + } else { + if vmOpts.NetworkVersion >= network.Version16 { + fvm, err := vm.NewFVM(context.TODO(), vmOpts) + if err != nil { + return nil, cid.Undef, err + } + vmi = fvm + } else { + lvm, err := vm.NewLegacyVM(context.TODO(), vmOpts) + if err != nil { + return nil, cid.Undef, err + } + invoker := filcns.NewActorRegistry() + lvm.SetInvoker(invoker) + vmi = lvm + } } - lvm.SetInvoker(invoker) - - ret, err := lvm.ApplyMessage(d.ctx, toChainMsg(params.Message)) + ret, err := vmi.ApplyMessage(d.ctx, toChainMsg(params.Message)) if err != nil { return nil, cid.Undef, err } @@ -266,10 +281,10 @@ func (d *Driver) ExecuteMessage(bs blockstore.Blockstore, params ExecuteMessageP var root cid.Cid if d.vmFlush { // flush the VM, committing the state tree changes and forcing a - // recursive copoy from the temporary blcokstore to the real blockstore. - root, err = lvm.Flush(d.ctx) + // recursive copy from the temporary blockstore to the real blockstore. + root, err = vmi.Flush(d.ctx) } else { - root, err = lvm.StateTree().(*state.StateTree).Flush(d.ctx) + root, err = vmi.(*vm.LegacyVM).StateTree().(*state.StateTree).Flush(d.ctx) } return ret, root, err diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index a1eef0533..413499c1a 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -167,6 +167,8 @@ * [SectorsSummary](#SectorsSummary) * [SectorsUnsealPiece](#SectorsUnsealPiece) * [SectorsUpdate](#SectorsUpdate) +* [Start](#Start) + * [StartTime](#StartTime) * [Storage](#Storage) * [StorageAddLocal](#StorageAddLocal) * [StorageAttach](#StorageAttach) @@ -413,8 +415,7 @@ Inputs: }, "ProofType": 8 } - ], - true + ] ] ``` @@ -3623,6 +3624,18 @@ Inputs: Response: `{}` +## Start + + +### StartTime + + +Perms: read + +Inputs: `null` + +Response: `"0001-01-01T00:00:00Z"` + ## Storage diff --git a/documentation/en/api-v0-methods.md b/documentation/en/api-v0-methods.md index 27ab7bd08..7ee6ceaa9 100644 --- a/documentation/en/api-v0-methods.md +++ b/documentation/en/api-v0-methods.md @@ -156,6 +156,8 @@ * [PaychVoucherCreate](#PaychVoucherCreate) * [PaychVoucherList](#PaychVoucherList) * [PaychVoucherSubmit](#PaychVoucherSubmit) +* [Start](#Start) + * [StartTime](#StartTime) * [State](#State) * [StateAccountKey](#StateAccountKey) * [StateActorCodeCIDs](#StateActorCodeCIDs) @@ -4620,6 +4622,18 @@ Response: } ``` +## Start + + +### StartTime + + +Perms: read + +Inputs: `null` + +Response: `"0001-01-01T00:00:00Z"` + ## State The State methods are used to query, inspect, and interact with chain state. Most methods take a TipSetKey as a parameter. The state looked up is the parent state of the tipset. diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index cbab6bfbf..9c104718c 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -164,6 +164,11 @@ * [PaychVoucherCreate](#PaychVoucherCreate) * [PaychVoucherList](#PaychVoucherList) * [PaychVoucherSubmit](#PaychVoucherSubmit) +* [Raft](#Raft) + * [RaftLeader](#RaftLeader) + * [RaftState](#RaftState) +* [Start](#Start) + * [StartTime](#StartTime) * [State](#State) * [StateAccountKey](#StateAccountKey) * [StateActorCodeCIDs](#StateActorCodeCIDs) @@ -1990,7 +1995,8 @@ Inputs: "Address": "f01234", "ID": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", "PieceCID": null - } + }, + "RemoteStore": "00000000-0000-0000-0000-000000000000" } ] ``` @@ -5052,6 +5058,45 @@ Response: } ``` +## Raft + + +### RaftLeader + + +Perms: read + +Inputs: `null` + +Response: `"12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf"` + +### RaftState + + +Perms: read + +Inputs: `null` + +Response: +```json +{ + "NonceMap": {}, + "MsgUuids": {} +} +``` + +## Start + + +### StartTime + + +Perms: read + +Inputs: `null` + +Response: `"0001-01-01T00:00:00Z"` + ## State The State methods are used to query, inspect, and interact with chain state. Most methods take a TipSetKey as a parameter. The state looked up is the parent state of the tipset. diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 7e5d01508..a3b02e23f 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -7,7 +7,7 @@ USAGE: lotus-miner [global options] command [command options] [arguments...] VERSION: - 1.18.2 + 1.19.0 COMMANDS: init Initialize a lotus miner repo @@ -1241,7 +1241,7 @@ NAME: lotus-miner net ping - Ping peers USAGE: - lotus-miner net ping [command options] [arguments...] + lotus-miner net ping [command options] [peerMultiaddr] OPTIONS: --count value, -c value specify the number of times it should ping (default: 10) diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index 277eb8597..0b5c3f936 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -7,7 +7,7 @@ USAGE: lotus-worker [global options] command [command options] [arguments...] VERSION: - 1.18.2 + 1.19.0 COMMANDS: run Start lotus worker diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 4c1709bb3..39b9b6f53 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -7,7 +7,7 @@ USAGE: lotus [global options] command [command options] [arguments...] VERSION: - 1.18.2 + 1.19.0 COMMANDS: daemon Start a lotus daemon process @@ -2087,6 +2087,7 @@ COMMANDS: decode decode various types encode encode various types disputer interact with the window post disputer + prune prune the stored chain state and perform garbage collection help, h Shows a list of commands or help for one command OPTIONS: @@ -2409,6 +2410,22 @@ OPTIONS: ``` +### lotus chain prune +``` +NAME: + lotus chain prune - prune the stored chain state and perform garbage collection + +USAGE: + lotus chain prune [command options] [arguments...] + +OPTIONS: + --move-to value specify new path for coldstore during moving gc + --moving-gc use moving gc for garbage collecting the coldstore (default: false) + --online-gc use online gc for garbage collecting the coldstore (default: false) + --retention value specify state retention policy (default: -1) + +``` + ## lotus log ``` NAME: @@ -2570,7 +2587,7 @@ NAME: lotus net ping - Ping peers USAGE: - lotus net ping [command options] [arguments...] + lotus net ping [command options] [peerMultiaddr] OPTIONS: --count value, -c value specify the number of times it should ping (default: 10) diff --git a/documentation/en/default-lotus-config.toml b/documentation/en/default-lotus-config.toml index 27162a6ae..889b87e4e 100644 --- a/documentation/en/default-lotus-config.toml +++ b/documentation/en/default-lotus-config.toml @@ -166,11 +166,11 @@ [Chainstore.Splitstore] # ColdStoreType specifies the type of the coldstore. - # It can be "universal" (default) or "discard" for discarding cold blocks. + # It can be "messages" (default) to store only messages, "universal" to store all chain state or "discard" for discarding cold blocks. # # type: string # env var: LOTUS_CHAINSTORE_SPLITSTORE_COLDSTORETYPE - #ColdStoreType = "universal" + #ColdStoreType = "messages" # HotStoreType specifies the type of the hotstore. # Only currently supported value is "badger". @@ -201,28 +201,66 @@ # env var: LOTUS_CHAINSTORE_SPLITSTORE_HOTSTOREFULLGCFREQUENCY #HotStoreFullGCFrequency = 20 - # EnableColdStoreAutoPrune turns on compaction of the cold store i.e. pruning - # where hotstore compaction occurs every finality epochs pruning happens every 3 finalities - # Default is false - # - # type: bool - # env var: LOTUS_CHAINSTORE_SPLITSTORE_ENABLECOLDSTOREAUTOPRUNE - #EnableColdStoreAutoPrune = false - # ColdStoreFullGCFrequency specifies how often to performa a full (moving) GC on the coldstore. - # Only applies if auto prune is enabled. A value of 0 disables while a value of 1 will do - # full GC in every prune. - # Default is 7 (about once every a week) - # - # type: uint64 - # env var: LOTUS_CHAINSTORE_SPLITSTORE_COLDSTOREFULLGCFREQUENCY - #ColdStoreFullGCFrequency = 7 +[Cluster] + # EXPERIMENTAL. config to enabled node cluster with raft consensus + # + # type: bool + # env var: LOTUS_CLUSTER_CLUSTERMODEENABLED + #ClusterModeEnabled = false - # ColdStoreRetention specifies the retention policy for data reachable from the chain, in - # finalities beyond the compaction boundary, default is 0, -1 retains everything - # - # type: int64 - # env var: LOTUS_CHAINSTORE_SPLITSTORE_COLDSTORERETENTION - #ColdStoreRetention = 0 + # A folder to store Raft's data. + # + # type: string + # env var: LOTUS_CLUSTER_DATAFOLDER + #DataFolder = "" + + # InitPeersetMultiAddr provides the list of initial cluster peers for new Raft + # peers (with no prior state). It is ignored when Raft was already + # initialized or when starting in staging mode. + # + # type: []string + # env var: LOTUS_CLUSTER_INITPEERSETMULTIADDR + #InitPeersetMultiAddr = [] + + # LeaderTimeout specifies how long to wait for a leader before + # failing an operation. + # + # type: Duration + # env var: LOTUS_CLUSTER_WAITFORLEADERTIMEOUT + #WaitForLeaderTimeout = "15s" + + # NetworkTimeout specifies how long before a Raft network + # operation is timed out + # + # type: Duration + # env var: LOTUS_CLUSTER_NETWORKTIMEOUT + #NetworkTimeout = "1m40s" + + # CommitRetries specifies how many times we retry a failed commit until + # we give up. + # + # type: int + # env var: LOTUS_CLUSTER_COMMITRETRIES + #CommitRetries = 1 + + # How long to wait between retries + # + # type: Duration + # env var: LOTUS_CLUSTER_COMMITRETRYDELAY + #CommitRetryDelay = "200ms" + + # BackupsRotate specifies the maximum number of Raft's DataFolder + # copies that we keep as backups (renaming) after cleanup. + # + # type: int + # env var: LOTUS_CLUSTER_BACKUPSROTATE + #BackupsRotate = 6 + + # Tracing enables propagation of contexts across binary boundaries. + # + # type: bool + # env var: LOTUS_CLUSTER_TRACING + #Tracing = false diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index b51e325e8..939bac0cc 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -325,6 +325,29 @@ # env var: LOTUS_PROVING_PARALLELCHECKLIMIT #ParallelCheckLimit = 128 + # Maximum amount of time a proving pre-check can take for a sector. If the check times out the sector will be skipped + # + # WARNING: Setting this value too low risks in sectors being skipped even though they are accessible, just reading the + # test challenge took longer than this timeout + # WARNING: Setting this value too high risks missing PoSt deadline in case IO operations related to this sector are + # blocked (e.g. in case of disconnected NFS mount) + # + # type: Duration + # env var: LOTUS_PROVING_SINGLECHECKTIMEOUT + #SingleCheckTimeout = "10m0s" + + # Maximum amount of time a proving pre-check can take for an entire partition. If the check times out, sectors in + # the partition which didn't get checked on time will be skipped + # + # WARNING: Setting this value too low risks in sectors being skipped even though they are accessible, just reading the + # test challenge took longer than this timeout + # WARNING: Setting this value too high risks missing PoSt deadline in case IO operations related to this partition are + # blocked or slow + # + # type: Duration + # env var: LOTUS_PROVING_PARTITIONCHECKTIMEOUT + #PartitionCheckTimeout = "20m0s" + # Disable Window PoSt computation on the lotus-miner process even if no window PoSt workers are present. # # WARNING: If no windowPoSt workers are connected, window PoSt WILL FAIL resulting in faulty sectors which will need @@ -694,7 +717,7 @@ # to use when evaluating tasks against this worker. An empty value defaults # to "hardware". # - # type: sealer.ResourceFilteringStrategy + # type: ResourceFilteringStrategy # env var: LOTUS_STORAGE_RESOURCEFILTERING #ResourceFiltering = "hardware" diff --git a/documentation/misc/RELEASE_ISSUE_TEMPLATE.md b/documentation/misc/RELEASE_ISSUE_TEMPLATE.md index 5a4884669..8c3cce944 100644 --- a/documentation/misc/RELEASE_ISSUE_TEMPLATE.md +++ b/documentation/misc/RELEASE_ISSUE_TEMPLATE.md @@ -21,11 +21,12 @@ First steps: - [ ] Fork a new branch (`release/vX.Y.Z`) from `master` and make any further release related changes to this branch. If any "non-trivial" changes get added to the release, uncheck all the checkboxes and return to this stage. - - [ ] Bump the version in `version.go` in the `master` branch to `vX.Y.(Z+1)-dev` (bump from feature release) or `vX.(Y+1).0-dev` (bump from mandatory release) + - [ ] Bump the version in `build/version.go` in the `master` branch to `vX.Y.(Z+1)-dev` (bump from feature release) or `vX.(Y+1).0-dev` (bump from mandatory release) Prepping an RC: - [ ] version string in `build/version.go` has been updated (in the `release/vX.Y.Z` branch). +- [ ] run `make gen && make docsgen-cli` - [ ] tag commit with `vX.Y.Z-rcN` - [ ] cut a pre-release [here](https://github.com/filecoin-project/lotus/releases/new?prerelease=true) @@ -66,14 +67,14 @@ Testing an RC: - [ ] Update the [CHANGELOG.md](https://github.com/filecoin-project/lotus/blob/master/CHANGELOG.md) to the state that can be used as release note. - [ ] Invite the wider community through (link to the release issue) -- [ ] **Stage 4 - Release** +- [ ] **Stage 4 - Stable Release** - [ ] Final preparation - - [ ] Verify that version string in [`version.go`](https://github.com/ipfs/go-ipfs/tree/master/version.go) has been updated. - - [ ] Prep the changelog using `scripts/mkreleaselog`, and add it to `CHANGELOG.md`. Ensure that [CHANGELOG.md](https://github.com/filecoin-project/lotus/blob/master/CHANGELOG.md) is up to date + - [ ] Verify that version string in [`version.go`](https://github.com/filecoin-project/lotus/blob/master/build/version.go) has been updated. + - [ ] Verify that codegen is up to date (`make gen && make docsgen-cli`) + - [ ] Ensure that [CHANGELOG.md](https://github.com/filecoin-project/lotus/blob/master/CHANGELOG.md) is up to date - [ ] Merge `release-vX.Y.Z` into the `releases` branch. - [ ] Tag this merge commit (on the `releases` branch) with `vX.Y.Z` - - [ ] Cut the release [here](https://github.com/filecoin-project/lotus/releases/new?prerelease=true&target=releases). - - [ ] Check `Create a discussion for this release` + - [ ] Cut the release [here](https://github.com/filecoin-project/lotus/releases/new?prerelease=false&target=releases). - [ ] **Post-Release** diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 20f104e88..280c4f8b9 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 20f104e88065aae59fd212d64be5bed108604e78 +Subproject commit 280c4f8b94fd46dc824a5c827dece73ec7fe3efd diff --git a/gen/main.go b/gen/main.go index 02548e18f..439194ef4 100644 --- a/gen/main.go +++ b/gen/main.go @@ -7,6 +7,7 @@ import ( gen "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/chain/exchange" "github.com/filecoin-project/lotus/chain/market" "github.com/filecoin-project/lotus/chain/types" @@ -127,4 +128,13 @@ func main() { fmt.Println(err) os.Exit(1) } + err = gen.WriteTupleEncodersToFile("./blockstore/cbor_gen.go", "blockstore", + blockstore.NetRpcReq{}, + blockstore.NetRpcResp{}, + blockstore.NetRpcErr{}, + ) + if err != nil { + fmt.Println(err) + os.Exit(1) + } } diff --git a/go.mod b/go.mod index d51d7b05b..a5ce1e3d8 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/fatih/color v1.13.0 github.com/filecoin-project/dagstore v0.5.2 github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f - github.com/filecoin-project/go-address v1.0.0 + github.com/filecoin-project/go-address v1.1.0 github.com/filecoin-project/go-bitfield v0.2.4 github.com/filecoin-project/go-cbor-util v0.0.1 github.com/filecoin-project/go-commp-utils v0.1.3 @@ -37,12 +37,12 @@ require ( github.com/filecoin-project/go-data-transfer v1.15.2 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.24.0-v17 + github.com/filecoin-project/go-fil-markets v1.25.0 github.com/filecoin-project/go-jsonrpc v0.1.8 github.com/filecoin-project/go-legs v0.4.4 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.4 - github.com/filecoin-project/go-state-types v0.9.8 + github.com/filecoin-project/go-state-types v0.10.0-alpha-2 github.com/filecoin-project/go-statemachine v1.0.2 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 @@ -63,10 +63,13 @@ require ( github.com/golang/mock v1.6.0 github.com/google/uuid v1.3.0 github.com/gorilla/mux v1.7.4 + github.com/gorilla/websocket v1.5.0 github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/golang-lru v0.5.4 + github.com/hashicorp/raft v1.1.1 + github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94 github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab github.com/ipfs/bbloom v0.0.4 @@ -94,14 +97,14 @@ require ( github.com/ipfs/go-ipld-cbor v0.0.6 github.com/ipfs/go-ipld-format v0.4.0 github.com/ipfs/go-log/v2 v2.5.1 - github.com/ipfs/go-merkledag v0.8.0 + github.com/ipfs/go-merkledag v0.8.1 github.com/ipfs/go-metrics-interface v0.0.1 github.com/ipfs/go-metrics-prometheus v0.0.2 github.com/ipfs/go-unixfs v0.3.1 github.com/ipfs/go-unixfsnode v1.4.0 github.com/ipfs/interface-go-ipfs-core v0.7.0 github.com/ipld/go-car v0.4.0 - github.com/ipld/go-car/v2 v2.4.1 + github.com/ipld/go-car/v2 v2.5.0 github.com/ipld/go-codec-dagpb v1.3.2 github.com/ipld/go-ipld-prime v0.17.0 github.com/ipld/go-ipld-selector-text-lite v0.0.1 @@ -109,12 +112,16 @@ require ( github.com/koalacxr/quantile v0.0.1 github.com/libp2p/go-buffer-pool v0.1.0 github.com/libp2p/go-libp2p v0.22.0 + github.com/libp2p/go-libp2p-consensus v0.0.1 + github.com/libp2p/go-libp2p-gorpc v0.4.0 github.com/libp2p/go-libp2p-kad-dht v0.18.0 github.com/libp2p/go-libp2p-peerstore v0.8.0 github.com/libp2p/go-libp2p-pubsub v0.8.0 + github.com/libp2p/go-libp2p-raft v0.1.8 github.com/libp2p/go-libp2p-record v0.2.0 github.com/libp2p/go-libp2p-routing-helpers v0.2.3 github.com/libp2p/go-maddr-filter v0.1.0 + github.com/libp2p/go-msgio v0.2.0 github.com/mattn/go-isatty v0.0.16 github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/mitchellh/go-homedir v1.1.0 @@ -145,6 +152,7 @@ require ( go.uber.org/fx v1.15.0 go.uber.org/multierr v1.8.0 go.uber.org/zap v1.22.0 + golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 golang.org/x/net v0.0.0-20220812174116-3211cb980234 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab @@ -163,9 +171,11 @@ require ( github.com/Stebalien/go-bitfield v0.0.1 // indirect github.com/akavel/rsrc v0.8.0 // indirect github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a // indirect + github.com/armon/go-metrics v0.3.9 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bep/debounce v1.2.0 // indirect + github.com/boltdb/bolt v1.3.1 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cheekybits/genny v1.0.0 // indirect @@ -213,9 +223,11 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/go-cmp v0.5.8 // indirect github.com/google/gopacket v1.1.19 // indirect - github.com/gorilla/websocket v1.5.0 // indirect github.com/hannahhoward/cbor-gen-for v0.0.0-20200817222906-ea96cece81f1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-hclog v0.16.2 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/huin/goupnp v1.0.3 // indirect github.com/iancoleman/orderedmap v0.1.0 // indirect github.com/ipfs/go-bitfield v1.0.0 // indirect @@ -254,7 +266,6 @@ require ( github.com/libp2p/go-libp2p-kbucket v0.5.0 // indirect github.com/libp2p/go-libp2p-noise v0.5.0 // indirect github.com/libp2p/go-libp2p-tls v0.5.0 // indirect - github.com/libp2p/go-msgio v0.2.0 // indirect github.com/libp2p/go-nat v0.1.0 // indirect github.com/libp2p/go-netroute v0.2.0 // indirect github.com/libp2p/go-openssl v0.1.0 // indirect @@ -304,6 +315,7 @@ require ( github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect + github.com/ugorji/go/codec v1.2.6 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.0.1 // indirect github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 // indirect @@ -311,7 +323,7 @@ require ( github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - github.com/zondax/hid v0.9.0 // indirect + github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.12.1 // indirect go.opentelemetry.io/otel/metric v0.25.0 // indirect go.opentelemetry.io/otel/sdk/export/metric v0.25.0 // indirect @@ -320,7 +332,6 @@ require ( go.uber.org/dig v1.12.0 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect - golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect diff --git a/go.sum b/go.sum index 0de078b5c..30bd7d5b5 100644 --- a/go.sum +++ b/go.sum @@ -49,6 +49,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg= @@ -99,6 +101,9 @@ github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= +github.com/armon/go-metrics v0.3.9 h1:O2sNqxBdvq8Eq5xmzljcYzAORli6RWCvEym4cJf9m18= +github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= @@ -120,6 +125,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bep/debounce v1.2.0 h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo= github.com/bep/debounce v1.2.0/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/briandowns/spinner v1.11.1/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= @@ -164,6 +171,8 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= github.com/cilium/ebpf v0.4.0 h1:QlHdikaxALkqWasW8hAC1mfR0jdmvbfaBdBPFmRSglA= github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -286,8 +295,8 @@ github.com/filecoin-project/dagstore v0.5.2/go.mod h1:mdqKzYrRBHf1pRMthYfMv3n37o github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.6/go.mod h1:7B0/5DA13n6nHkB8bbGx1gWzG/dbTsZ0fgOJVGsM3TE= -github.com/filecoin-project/go-address v1.0.0 h1:IrexI0kpADLaPP+CdmU3CVAUqnW/FQC0KTmz4lVKiFU= -github.com/filecoin-project/go-address v1.0.0/go.mod h1:5t3z6qPmIADZBtuE9EIzi0EwzcRy2nVhpo0I/c1r0OA= +github.com/filecoin-project/go-address v1.1.0 h1:ofdtUtEsNxkIxkDw67ecSmvtzaVSdcea4boAmLbnHfE= +github.com/filecoin-project/go-address v1.1.0/go.mod h1:5t3z6qPmIADZBtuE9EIzi0EwzcRy2nVhpo0I/c1r0OA= github.com/filecoin-project/go-amt-ipld/v2 v2.1.0 h1:t6qDiuGYYngDqaLc2ZUvdtAg4UNxPeOYaXhBWSNsVaM= github.com/filecoin-project/go-amt-ipld/v2 v2.1.0/go.mod h1:nfFPoGyX0CU9SkXX8EoCcSuHN1XcbN0c6KBh7yvP5fs= github.com/filecoin-project/go-amt-ipld/v3 v3.0.0/go.mod h1:Qa95YNAbtoVCTSVtX38aAC1ptBnJfPma1R/zZsKmx4o= @@ -318,8 +327,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.24.0-v17 h1:YjT0usMeR6kdAo3RBfftTPe5bNIgNmBbo5YzJHF1iLk= -github.com/filecoin-project/go-fil-markets v1.24.0-v17/go.mod h1:JW/UHkHDqP4MikCIIWNY5IHvTTsdv/zNMk9jJXKzhIU= +github.com/filecoin-project/go-fil-markets v1.25.0 h1:zWkc1v84JL9KttiqOy2IIZB0jksIdAt1WLCdOP/KvAg= +github.com/filecoin-project/go-fil-markets v1.25.0/go.mod h1:3lzXZt5mRHTHAmZ10sUviiutaLVL57B99FgBU1MYqWY= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -343,8 +352,8 @@ github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psS github.com/filecoin-project/go-state-types v0.1.6/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= github.com/filecoin-project/go-state-types v0.1.8/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= github.com/filecoin-project/go-state-types v0.1.10/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= -github.com/filecoin-project/go-state-types v0.9.8 h1:xkdITiR7h691z1tWOhNCJxHI+cq+Mq7ATkpHQ7f1gu8= -github.com/filecoin-project/go-state-types v0.9.8/go.mod h1:+HCZifUV+e8TlQkgll22Ucuiq8OrVJkK+4Kh4u75iiw= +github.com/filecoin-project/go-state-types v0.10.0-alpha-2 h1:xz8+sXAuCMane7SkEYCtQjD/zYJ4n1d5bxwYNL8Thf0= +github.com/filecoin-project/go-state-types v0.10.0-alpha-2/go.mod h1:7ty480tvttEAqWKywhAaDCElk7ksTqEXtXWAzTSdEKo= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc= github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= @@ -380,6 +389,7 @@ github.com/filecoin-project/storetheindex v0.4.17/go.mod h1:y2dL8C5D3PXi183hdxgG github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ= github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= @@ -593,17 +603,27 @@ github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyN github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= +github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= @@ -615,6 +635,10 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/raft v1.1.1 h1:HJr7UE1x/JrJSc9Oy6aDBHtNHUUBHjcQjTgvUVihoZs= +github.com/hashicorp/raft v1.1.1/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= +github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea h1:xykPFhrBAS2J0VBzVa5e80b5ZtYuNQtgXjN40qBZlD4= +github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hodgesds/perf-utils v0.0.8/go.mod h1:F6TfvsbtrF88i++hou29dTXlI2sfsJv+gRZDtmTJkAs= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -805,8 +829,8 @@ github.com/ipfs/go-merkledag v0.2.4/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB github.com/ipfs/go-merkledag v0.3.2/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= github.com/ipfs/go-merkledag v0.5.1/go.mod h1:cLMZXx8J08idkp5+id62iVftUQV+HlYJ3PIhDfZsjA4= github.com/ipfs/go-merkledag v0.6.0/go.mod h1:9HSEwRd5sV+lbykiYP+2NC/3o6MZbKNaa4hfNcH5iH0= -github.com/ipfs/go-merkledag v0.8.0 h1:ZUda+sh/MGZX4Z13DE/VQT4GmKWm4H95Nje4qcL/yPE= -github.com/ipfs/go-merkledag v0.8.0/go.mod h1:/RmH1kOs7qDMNtGKPh4d/UErNMVuAMpPS/tP57a3aoY= +github.com/ipfs/go-merkledag v0.8.1 h1:N3yrqSre/ffvdwtHL4MXy0n7XH+VzN8DlzDrJySPa94= +github.com/ipfs/go-merkledag v0.8.1/go.mod h1:uYUlWE34GhbcTjGuUDEcdPzsEtOdnOupL64NgSRjmWI= github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= github.com/ipfs/go-metrics-prometheus v0.0.2 h1:9i2iljLg12S78OhC6UAiXi176xvQGiZaGVF1CUVdE+s= @@ -837,8 +861,8 @@ github.com/ipld/go-car v0.1.0/go.mod h1:RCWzaUh2i4mOEkB3W45Vc+9jnS/M6Qay5ooytiBH github.com/ipld/go-car v0.4.0 h1:U6W7F1aKF/OJMHovnOVdst2cpQE5GhmHibQkAixgNcQ= github.com/ipld/go-car v0.4.0/go.mod h1:Uslcn4O9cBKK9wqHm/cLTFacg6RAPv6LZx2mxd2Ypl4= github.com/ipld/go-car/v2 v2.1.1/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= -github.com/ipld/go-car/v2 v2.4.1 h1:9S+FYbQzQJ/XzsdiOV13W5Iu/i+gUnr6csbSD9laFEg= -github.com/ipld/go-car/v2 v2.4.1/go.mod h1:zjpRf0Jew9gHqSvjsKVyoq9OY9SWoEKdYCQUKVaaPT0= +github.com/ipld/go-car/v2 v2.5.0 h1:S9h7A6qBAJ+B1M1jIKtau+HPDe30UbM71vsyBzwvRIE= +github.com/ipld/go-car/v2 v2.5.0/go.mod h1:jKjGOqoCj5zn6KjnabD6JbnCsMntqU2hLiU6baZVO3E= github.com/ipld/go-codec-dagpb v1.2.0/go.mod h1:6nBN7X7h8EOsEejZGqC7tej5drsdBAXbMHyBT+Fne5s= github.com/ipld/go-codec-dagpb v1.3.0/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= github.com/ipld/go-codec-dagpb v1.3.1/go.mod h1:ErNNglIi5KMur/MfFE/svtgQthzVvf+43MrzLbpcIZY= @@ -979,7 +1003,9 @@ github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZk github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= +github.com/libp2p/go-libp2p v0.13.0/go.mod h1:pM0beYdACRfHO1WcJlp65WXyG2A6NqYM+t2DTVAJxMo= github.com/libp2p/go-libp2p v0.14.3/go.mod h1:d12V4PdKbpL0T1/gsUNN8DfgMuRPDX8bS2QxCZlwRH0= +github.com/libp2p/go-libp2p v0.14.4/go.mod h1:EIRU0Of4J5S8rkockZM7eJp2S0UrCyi55m2kJVru3rM= github.com/libp2p/go-libp2p v0.16.0/go.mod h1:ump42BsirwAWxKzsCiFnTtN1Yc+DuPu76fyMX364/O4= github.com/libp2p/go-libp2p v0.17.0/go.mod h1:Fkin50rsGdv5mm5BshBUtPRZknt9esfmYXBOYcwOTgw= github.com/libp2p/go-libp2p v0.22.0 h1:2Tce0kHOp5zASFKJbNzRElvh0iZwdtG5uZheNW8chIw= @@ -993,6 +1019,7 @@ github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/ github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= github.com/libp2p/go-libp2p-autonat v0.2.1/go.mod h1:MWtAhV5Ko1l6QBsHQNSuM6b1sRkXrpk0/LqCr+vCVxI= github.com/libp2p/go-libp2p-autonat v0.2.2/go.mod h1:HsM62HkqZmHR2k1xgX34WuWDzk/nBwNHoeyyT4IWV6A= +github.com/libp2p/go-libp2p-autonat v0.4.0/go.mod h1:YxaJlpr81FhdOv3W3BTconZPfhaYivRdf53g+S2wobk= github.com/libp2p/go-libp2p-autonat v0.4.2/go.mod h1:YxaJlpr81FhdOv3W3BTconZPfhaYivRdf53g+S2wobk= github.com/libp2p/go-libp2p-autonat v0.6.0/go.mod h1:bFC6kY8jwzNNWoqc8iGE57vsfwyJ/lP4O4DOV1e0B2o= github.com/libp2p/go-libp2p-autonat v0.7.0/go.mod h1:uPvPn6J7cN+LCfFwW5tpOYvAz5NvPTc4iBamTV/WDMg= @@ -1010,6 +1037,8 @@ github.com/libp2p/go-libp2p-connmgr v0.2.4/go.mod h1:YV0b/RIm8NGPnnNWM7hG9Q38OeQ github.com/libp2p/go-libp2p-connmgr v0.3.0/go.mod h1:RVoyPjJm0J9Vd1m6qUN2Tn7kJm4rL1Ml20pFsFgPGik= github.com/libp2p/go-libp2p-connmgr v0.4.0 h1:q/KZUS1iMDIQckMZarMYwhQisJqiFPHAVC1c4DR3hDE= github.com/libp2p/go-libp2p-connmgr v0.4.0/go.mod h1:exFQQm19PFAx+QuJmBPw4MM58QejzPJRFFFYnNmgi2w= +github.com/libp2p/go-libp2p-consensus v0.0.1 h1:jcVbHRZLwTXU9iT/mPi+Lx4/OrIzq3bU1TbZNhYFCV8= +github.com/libp2p/go-libp2p-consensus v0.0.1/go.mod h1:+9Wrfhc5QOqWB0gXI0m6ARlkHfdJpcFXmRU0WoHz4Mo= github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= github.com/libp2p/go-libp2p-core v0.0.2/go.mod h1:9dAcntw/n46XycV4RnlBq3BpgrmyUi9LuoTNdPrbUco= github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE= @@ -1052,6 +1081,9 @@ github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfx github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw= github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= github.com/libp2p/go-libp2p-discovery v0.6.0/go.mod h1:/u1voHt0tKIe5oIA1RHBKQLVCWPna2dXmPNHc2zR9S8= +github.com/libp2p/go-libp2p-gorpc v0.4.0 h1:kxHg5C3IuXeOq5FHPGbMHwQzKDlTVeB/NDr0ndc8J/g= +github.com/libp2p/go-libp2p-gorpc v0.4.0/go.mod h1:jux2Mb6BfUE1n58KbVCmWtqvpiZo0DDaKobKInf4s5o= +github.com/libp2p/go-libp2p-gostream v0.3.1/go.mod h1:1V3b+u4Zhaq407UUY9JLCpboaeufAeVQbnvAt12LRsI= github.com/libp2p/go-libp2p-gostream v0.4.0 h1:heduMMEB78yBqeEQv+P7Fn5X926MHC2jDIC7/7yLpYA= github.com/libp2p/go-libp2p-gostream v0.4.0/go.mod h1:21DVGBcCQwRfEXZpCnZ2kG24QiEkBpEQvG53gYXE4u0= github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= @@ -1082,6 +1114,7 @@ github.com/libp2p/go-libp2p-net v0.0.1/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8 github.com/libp2p/go-libp2p-net v0.0.2/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= github.com/libp2p/go-libp2p-netutil v0.0.1/go.mod h1:GdusFvujWZI9Vt0X5BKqwWWmZFxecf9Gt03cKxm2f/Q= github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= +github.com/libp2p/go-libp2p-noise v0.1.1/go.mod h1:QDFLdKX7nluB7DEnlVPbz7xlLHdwHFA9HiohJRr3vwM= github.com/libp2p/go-libp2p-noise v0.2.0/go.mod h1:IEbYhBBzGyvdLBoxxULL/SGbJARhUeqlO8lVSREYu2Q= github.com/libp2p/go-libp2p-noise v0.3.0/go.mod h1:JNjHbociDJKHD64KTkzGnzqJ0FEV5gHJa6AB00kbCNQ= github.com/libp2p/go-libp2p-noise v0.5.0 h1:gwJZ/3iH3MRnBrLIyr/YLdCOnmqfJMptlsFFUIc3j0Y= @@ -1112,6 +1145,8 @@ github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqU github.com/libp2p/go-libp2p-quic-transport v0.13.0/go.mod h1:39/ZWJ1TW/jx1iFkKzzUg00W6tDJh73FC0xYudjr7Hc= github.com/libp2p/go-libp2p-quic-transport v0.15.0/go.mod h1:wv4uGwjcqe8Mhjj7N/Ic0aKjA+/10UnMlSzLO0yRpYQ= github.com/libp2p/go-libp2p-quic-transport v0.15.2/go.mod h1:wv4uGwjcqe8Mhjj7N/Ic0aKjA+/10UnMlSzLO0yRpYQ= +github.com/libp2p/go-libp2p-raft v0.1.8 h1:Fq0aWHbbhi6WJXf+yaOQeMzV+9UgkbHIIGyaJbH3vpo= +github.com/libp2p/go-libp2p-raft v0.1.8/go.mod h1:+YDisn3uszb7vxshLgKoDdRGs79WSbHRgrOdrYqDPk4= github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q= github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q= github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGdsU/9W//C8dqjQDk= @@ -1131,6 +1166,7 @@ github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaT github.com/libp2p/go-libp2p-swarm v0.2.3/go.mod h1:P2VO/EpxRyDxtChXz/VPVXyTnszHvokHKRhfkEgFKNM= github.com/libp2p/go-libp2p-swarm v0.2.8/go.mod h1:JQKMGSth4SMqonruY0a8yjlPVIkb0mdNSwckW7OYziM= github.com/libp2p/go-libp2p-swarm v0.3.0/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= +github.com/libp2p/go-libp2p-swarm v0.4.0/go.mod h1:XVFcO52VoLoo0eitSxNQWYq4D6sydGOweTOAjJNraCw= github.com/libp2p/go-libp2p-swarm v0.5.0/go.mod h1:sU9i6BoHE0Ve5SKz3y9WfKrh8dUat6JknzUehFx8xW4= github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= github.com/libp2p/go-libp2p-swarm v0.9.0/go.mod h1:2f8d8uxTJmpeqHF/1ujjdXZp+98nNIbujVOMEZxCbZ8= @@ -1158,6 +1194,7 @@ github.com/libp2p/go-libp2p-transport-upgrader v0.0.4/go.mod h1:RGq+tupk+oj7PzL2 github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= github.com/libp2p/go-libp2p-transport-upgrader v0.2.0/go.mod h1:mQcrHj4asu6ArfSoMuyojOdjx73Q47cYD7s5+gZOlns= github.com/libp2p/go-libp2p-transport-upgrader v0.3.0/go.mod h1:i+SKzbRnvXdVbU3D1dwydnTmKRPXiAR/fyvi1dXuL4o= +github.com/libp2p/go-libp2p-transport-upgrader v0.4.0/go.mod h1:J4ko0ObtZSmgn5BX5AmegP+dK3CSnU2lMCKsSq/EY0s= github.com/libp2p/go-libp2p-transport-upgrader v0.4.2/go.mod h1:NR8ne1VwfreD5VIWIU62Agt/J18ekORFU/j1i2y8zvk= github.com/libp2p/go-libp2p-transport-upgrader v0.4.3/go.mod h1:bpkldbOWXMrXhpZbSV1mQxTrefOg2Fi+k1ClDSA4ppw= github.com/libp2p/go-libp2p-transport-upgrader v0.5.0/go.mod h1:Rc+XODlB3yce7dvFV4q/RmyJGsFcCZRkeZMu/Zdg0mo= @@ -1172,6 +1209,7 @@ github.com/libp2p/go-libp2p-yamux v0.2.7/go.mod h1:X28ENrBMU/nm4I3Nx4sZ4dgjZ6VhL github.com/libp2p/go-libp2p-yamux v0.2.8/go.mod h1:/t6tDqeuZf0INZMTgd0WxIRbtK2EzI2h7HbFm9eAKI4= github.com/libp2p/go-libp2p-yamux v0.4.0/go.mod h1:+DWDjtFMzoAwYLVkNZftoucn7PelNoy5nm3tZ3/Zw30= github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= +github.com/libp2p/go-libp2p-yamux v0.5.1/go.mod h1:dowuvDu8CRWmr0iqySMiSxK+W0iL5cMVO9S94Y6gkv4= github.com/libp2p/go-libp2p-yamux v0.5.4/go.mod h1:tfrXbyaTqqSU654GTvK3ocnSZL3BuHoeTSqhcel1wsE= github.com/libp2p/go-libp2p-yamux v0.6.0/go.mod h1:MRhd6mAYnFRnSISp4M8i0ClV/j+mWHo2mYLifWGw33k= github.com/libp2p/go-libp2p-yamux v0.7.0/go.mod h1:fMyA0CsPfHkIuBU0wjRGrCjTBFiXTXxG0k5M4ETv+08= @@ -1233,7 +1271,9 @@ github.com/libp2p/go-tcp-transport v0.0.4/go.mod h1:+E8HvC8ezEVOxIo3V5vCK9l1y/19 github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= github.com/libp2p/go-tcp-transport v0.2.0/go.mod h1:vX2U0CnWimU4h0SGSEsg++AzvBcroCGYw28kh94oLe0= +github.com/libp2p/go-tcp-transport v0.2.1/go.mod h1:zskiJ70MEfWz2MKxvFB/Pv+tPIB1PpPUrHIWQ8aFw7M= github.com/libp2p/go-tcp-transport v0.2.3/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyPFvl1S/igQ5QD1SU= +github.com/libp2p/go-tcp-transport v0.2.4/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyPFvl1S/igQ5QD1SU= github.com/libp2p/go-tcp-transport v0.4.0/go.mod h1:0y52Rwrn4076xdJYu/51/qJIdxz+EWDAOG2S45sV3VI= github.com/libp2p/go-testutil v0.0.1/go.mod h1:iAcJc/DKJQanJ5ws2V+u5ywdL2n12X1WbbEG+Jjy69I= github.com/libp2p/go-testutil v0.1.0/go.mod h1:81b2n5HypcVyrCg/MJx4Wgfp/VHojytjVe/gLzZ2Ehc= @@ -1252,6 +1292,7 @@ github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZ github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= github.com/libp2p/go-yamux v1.4.0/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux/v2 v2.0.0/go.mod h1:NVWira5+sVUIU6tu1JWvaRn1dRnG+cawOJiflsAM+7U= github.com/libp2p/go-yamux/v2 v2.2.0/go.mod h1:3So6P6TV6r75R9jiBpiIKgU/66lOarCZjqROGxzPpPQ= github.com/libp2p/go-yamux/v2 v2.3.0/go.mod h1:iTU+lOIn/2h0AgKcL49clNTwfEw+WSfDYrXe05EyKIs= github.com/libp2p/go-yamux/v3 v3.1.2 h1:lNEy28MBk1HavUAlzKgShp+F6mn/ea1nDYWftZhFW9Q= @@ -1306,6 +1347,7 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= @@ -1331,6 +1373,7 @@ github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00v github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= @@ -1429,6 +1472,7 @@ github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wS github.com/multiformats/go-multistream v0.0.4/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= +github.com/multiformats/go-multistream v0.2.0/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= github.com/multiformats/go-multistream v0.2.1/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= github.com/multiformats/go-multistream v0.2.2/go.mod h1:UIcnm7Zuo8HKG+HkWgfQsGL+/MIEhyTqbODbIUwSXKs= github.com/multiformats/go-multistream v0.3.3 h1:d5PZpjwRgVlbwfdTDjife7XszfZd8KYWfROYFlGcR8o= @@ -1502,6 +1546,8 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= @@ -1531,6 +1577,7 @@ github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4 github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= @@ -1697,6 +1744,7 @@ github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0 github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.23.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.25.0+incompatible h1:IxcNZ7WRY1Y3G4poYlx24szfsn/3LvK9QHCq9oQw8+U= @@ -1704,7 +1752,12 @@ github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMW github.com/uber/jaeger-lib v1.5.1-0.20181102163054-1fc5c315e03c/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/ugorji/go v1.1.13/go.mod h1:jxau1n+/wyTGLQoCkjok9r5zFa/FxT6eI5HiHKQszjc= +github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU= +github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= +github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= @@ -1777,8 +1830,9 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= +github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.12.1 h1:hYRcyznPRJp+5mzF2sazTLP2nGvGjYDD2VzhHhFomLU= github.com/zondax/ledger-go v0.12.1/go.mod h1:KatxXrVDzgWwbssUWsF5+cOJHXPvzQ09YSlzGNuhOEo= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= @@ -1896,6 +1950,7 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -2070,6 +2125,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190524122548-abf6ff778158/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190524152521-dbbf3f1254d4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/itests/deadlines_test.go b/itests/deadlines_test.go index a00c33b68..472e66abc 100644 --- a/itests/deadlines_test.go +++ b/itests/deadlines_test.go @@ -64,7 +64,7 @@ func TestDeadlineToggling(t *testing.T) { //stm: @CHAIN_INCOMING_HANDLE_INCOMING_BLOCKS_001, @CHAIN_INCOMING_VALIDATE_BLOCK_PUBSUB_001, @CHAIN_INCOMING_VALIDATE_MESSAGE_PUBSUB_001 //stm: @MINER_SECTOR_LIST_001 - //kit.Expensive(t) + kit.Expensive(t) kit.QuietMiningLogs() @@ -160,7 +160,7 @@ func TestDeadlineToggling(t *testing.T) { build.Clock.Sleep(blocktime) } - checkMiner := func(ma address.Address, power abi.StoragePower, active, activeIfCron bool, tsk types.TipSetKey) { + checkMiner := func(ma address.Address, power abi.StoragePower, active bool, tsk types.TipSetKey) { //stm: @CHAIN_STATE_MINER_POWER_001 p, err := client.StateMinerPower(ctx, ma, tsk) require.NoError(t, err) @@ -178,21 +178,6 @@ func TestDeadlineToggling(t *testing.T) { act, err := mst.DeadlineCronActive() require.NoError(t, err) - if tsk != types.EmptyTSK { - ts, err := client.ChainGetTipSet(ctx, tsk) - require.NoError(t, err) - di, err := mst.DeadlineInfo(ts.Height()) - require.NoError(t, err) - - // cron happened on the same epoch some other condition would have happened - if di.Open == ts.Height() { - act, err := mst.DeadlineCronActive() - require.NoError(t, err) - require.Equal(t, activeIfCron, act) - return - } - } - require.Equal(t, active, act) } @@ -200,7 +185,7 @@ func TestDeadlineToggling(t *testing.T) { { uts, err := client.ChainGetTipSetByHeight(ctx, upgradeH+2, types.EmptyTSK) require.NoError(t, err) - checkMiner(maddrB, types.NewInt(0), true, true, uts.Key()) + checkMiner(maddrB, types.NewInt(0), true, uts.Key()) } //stm: @CHAIN_STATE_NETWORK_VERSION_001 @@ -218,19 +203,19 @@ func TestDeadlineToggling(t *testing.T) { require.NoError(t, err) // first round of miner checks - checkMiner(maddrA, types.NewInt(uint64(ssz)*kit.DefaultPresealsPerBootstrapMiner), true, true, types.EmptyTSK) - checkMiner(maddrC, types.NewInt(uint64(ssz)*sectorsC), true, true, types.EmptyTSK) + checkMiner(maddrA, types.NewInt(uint64(ssz)*kit.DefaultPresealsPerBootstrapMiner), true, types.EmptyTSK) + checkMiner(maddrC, types.NewInt(uint64(ssz)*sectorsC), true, types.EmptyTSK) - checkMiner(maddrB, types.NewInt(0), false, false, types.EmptyTSK) - checkMiner(maddrD, types.NewInt(0), false, false, types.EmptyTSK) - checkMiner(maddrE, types.NewInt(0), false, false, types.EmptyTSK) + checkMiner(maddrB, types.NewInt(0), false, types.EmptyTSK) + checkMiner(maddrD, types.NewInt(0), false, types.EmptyTSK) + checkMiner(maddrE, types.NewInt(0), false, types.EmptyTSK) // pledge sectors on minerB/minerD, stop post on minerC minerB.PledgeSectors(ctx, sectorsB, 0, nil) - checkMiner(maddrB, types.NewInt(0), true, true, types.EmptyTSK) + checkMiner(maddrB, types.NewInt(0), true, types.EmptyTSK) minerD.PledgeSectors(ctx, sectorsD, 0, nil) - checkMiner(maddrD, types.NewInt(0), true, true, types.EmptyTSK) + checkMiner(maddrD, types.NewInt(0), true, types.EmptyTSK) minerC.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).Fail() @@ -281,7 +266,7 @@ func TestDeadlineToggling(t *testing.T) { build.Clock.Sleep(blocktime) } - checkMiner(maddrE, types.NewInt(0), true, true, types.EmptyTSK) + checkMiner(maddrE, types.NewInt(0), true, types.EmptyTSK) // go through rest of the PP for { @@ -296,11 +281,11 @@ func TestDeadlineToggling(t *testing.T) { } // second round of miner checks - checkMiner(maddrA, types.NewInt(uint64(ssz)*kit.DefaultPresealsPerBootstrapMiner), true, true, types.EmptyTSK) - checkMiner(maddrC, types.NewInt(0), true, true, types.EmptyTSK) - checkMiner(maddrB, types.NewInt(uint64(ssz)*sectorsB), true, true, types.EmptyTSK) - checkMiner(maddrD, types.NewInt(uint64(ssz)*sectorsD), true, true, types.EmptyTSK) - checkMiner(maddrE, types.NewInt(0), false, false, types.EmptyTSK) + checkMiner(maddrA, types.NewInt(uint64(ssz)*kit.DefaultPresealsPerBootstrapMiner), true, types.EmptyTSK) + checkMiner(maddrC, types.NewInt(0), true, types.EmptyTSK) + checkMiner(maddrB, types.NewInt(uint64(ssz)*sectorsB), true, types.EmptyTSK) + checkMiner(maddrD, types.NewInt(uint64(ssz)*sectorsD), true, types.EmptyTSK) + checkMiner(maddrE, types.NewInt(0), false, types.EmptyTSK) // disable post on minerB minerB.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).Fail() @@ -353,8 +338,10 @@ func TestDeadlineToggling(t *testing.T) { require.NoError(t, err) require.Equal(t, exitcode.Ok, r.Receipt.ExitCode) - // assert inactive if the message landed in the tipset we run cron in - checkMiner(maddrD, types.NewInt(0), true, false, r.TipSet) + // assert miner has no power + p, err := client.StateMinerPower(ctx, maddrD, r.TipSet) + require.NoError(t, err) + require.True(t, p.MinerPower.RawBytePower.IsZero()) } // go through another PP @@ -369,8 +356,8 @@ func TestDeadlineToggling(t *testing.T) { build.Clock.Sleep(blocktime) } - checkMiner(maddrA, types.NewInt(uint64(ssz)*kit.DefaultPresealsPerBootstrapMiner), true, true, types.EmptyTSK) - checkMiner(maddrC, types.NewInt(0), true, true, types.EmptyTSK) - checkMiner(maddrB, types.NewInt(0), true, true, types.EmptyTSK) - checkMiner(maddrD, types.NewInt(0), false, false, types.EmptyTSK) + checkMiner(maddrA, types.NewInt(uint64(ssz)*kit.DefaultPresealsPerBootstrapMiner), true, types.EmptyTSK) + checkMiner(maddrC, types.NewInt(0), true, types.EmptyTSK) + checkMiner(maddrB, types.NewInt(0), true, types.EmptyTSK) + checkMiner(maddrD, types.NewInt(0), false, types.EmptyTSK) } diff --git a/itests/deals_remote_retrieval_test.go b/itests/deals_remote_retrieval_test.go new file mode 100644 index 000000000..c0a37e69e --- /dev/null +++ b/itests/deals_remote_retrieval_test.go @@ -0,0 +1,104 @@ +package itests + +import ( + "bytes" + "context" + "fmt" + "io" + "net/url" + "os" + "path" + "testing" + "time" + + "github.com/google/uuid" + "github.com/gorilla/websocket" + "github.com/ipld/go-car" + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/api" + bstore "github.com/filecoin-project/lotus/blockstore" + "github.com/filecoin-project/lotus/itests/kit" +) + +func TestNetStoreRetrieval(t *testing.T) { + kit.QuietMiningLogs() + + blocktime := 5 * time.Millisecond + ctx := context.Background() + + full, miner, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) + ens.InterconnectAll().BeginMining(blocktime) + + time.Sleep(5 * time.Second) + + // For these tests where the block time is artificially short, just use + // a deal start epoch that is guaranteed to be far enough in the future + // so that the deal starts sealing in time + dealStartEpoch := abi.ChainEpoch(2 << 12) + + rseed := 7 + + dh := kit.NewDealHarness(t, full, miner, miner) + dealCid, res, _ := dh.MakeOnlineDeal(context.Background(), kit.MakeFullDealParams{ + Rseed: rseed, + StartEpoch: dealStartEpoch, + UseCARFileForStorageDeal: true, + }) + + // create deal store + id := uuid.New() + rstore := bstore.NewMemorySync() + + au, err := url.Parse(full.ListenURL) + require.NoError(t, err) + + switch au.Scheme { + case "http": + au.Scheme = "ws" + case "https": + au.Scheme = "wss" + } + + au.Path = path.Join(au.Path, "/rest/v0/store/"+id.String()) + + conn, _, err := websocket.DefaultDialer.Dial(au.String(), nil) + require.NoError(t, err) + + _ = bstore.HandleNetBstoreWS(ctx, rstore, conn) + + dh.PerformRetrievalWithOrder(ctx, dealCid, res.Root, false, func(offer api.QueryOffer, address address.Address) api.RetrievalOrder { + order := offer.Order(address) + + order.RemoteStore = &id + + return order + }) + + // check blockstore blocks + carv1FilePath, _ := kit.CreateRandomCARv1(t, rseed, 200) + cb, err := os.ReadFile(carv1FilePath) + require.NoError(t, err) + + cr, err := car.NewCarReader(bytes.NewReader(cb)) + require.NoError(t, err) + + var blocks int + for { + cb, err := cr.Next() + if err == io.EOF { + fmt.Println("blocks: ", blocks) + return + } + require.NoError(t, err) + + sb, err := rstore.Get(ctx, cb.Cid()) + require.NoError(t, err) + require.EqualValues(t, cb.RawData(), sb.RawData()) + + blocks++ + } +} diff --git a/itests/deals_retry_deal_no_funds_test.go b/itests/deals_retry_deal_no_funds_test.go index 8d5a02172..650b2436e 100644 --- a/itests/deals_retry_deal_no_funds_test.go +++ b/itests/deals_retry_deal_no_funds_test.go @@ -101,7 +101,7 @@ func testDealsRetryLackOfFunds(t *testing.T, publishStorageAccountFunds abi.Toke propcid := *deal go func() { - time.Sleep(3 * time.Second) + time.Sleep(30 * time.Second) kit.SendFunds(ctx, t, minerFullNode, publishStorageDealKey.Address, types.FromFil(1)) diff --git a/itests/gateway_test.go b/itests/gateway_test.go index a7d9d353b..b9c861bf3 100644 --- a/itests/gateway_test.go +++ b/itests/gateway_test.go @@ -297,7 +297,7 @@ func startNodes( l, err := net.Listen("tcp", "127.0.0.1:0") require.NoError(t, err) - srv, _ := kit.CreateRPCServer(t, handler, l) + srv, _, _ := kit.CreateRPCServer(t, handler, l) // Create a gateway client API that connects to the gateway server var gapi api.Gateway diff --git a/itests/kit/deals.go b/itests/kit/deals.go index 794a63803..1f3a7dfb5 100644 --- a/itests/kit/deals.go +++ b/itests/kit/deals.go @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/shared_testutil" "github.com/filecoin-project/go-fil-markets/storagemarket" @@ -308,6 +309,12 @@ func (dh *DealHarness) StartSealingWaiting(ctx context.Context) { } func (dh *DealHarness) PerformRetrieval(ctx context.Context, deal *cid.Cid, root cid.Cid, carExport bool, offers ...api.QueryOffer) (path string) { + return dh.PerformRetrievalWithOrder(ctx, deal, root, carExport, func(offer api.QueryOffer, a address.Address) api.RetrievalOrder { + return offer.Order(a) + }, offers...) +} + +func (dh *DealHarness) PerformRetrievalWithOrder(ctx context.Context, deal *cid.Cid, root cid.Cid, carExport bool, makeOrder func(api.QueryOffer, address.Address) api.RetrievalOrder, offers ...api.QueryOffer) (path string) { var offer api.QueryOffer if len(offers) == 0 { // perform retrieval. @@ -331,7 +338,9 @@ func (dh *DealHarness) PerformRetrieval(ctx context.Context, deal *cid.Cid, root updates, err := dh.client.ClientGetRetrievalUpdates(updatesCtx) require.NoError(dh.t, err) - retrievalRes, err := dh.client.ClientRetrieve(ctx, offer.Order(caddr)) + order := makeOrder(offer, caddr) + + retrievalRes, err := dh.client.ClientRetrieve(ctx, order) require.NoError(dh.t, err) consumeEvents: for { @@ -357,6 +366,11 @@ consumeEvents: } cancel() + if order.RemoteStore != nil { + // if we're retrieving into a remote store, skip export + return "" + } + require.NoError(dh.t, dh.client.ClientExport(ctx, api.ExportRef{ Root: root, diff --git a/itests/kit/ensemble.go b/itests/kit/ensemble.go index 8fa781e65..956d243a3 100644 --- a/itests/kit/ensemble.go +++ b/itests/kit/ensemble.go @@ -13,6 +13,7 @@ import ( "testing" "time" + "github.com/google/uuid" "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/namespace" libp2pcrypto "github.com/libp2p/go-libp2p/core/crypto" @@ -175,6 +176,16 @@ func (n *Ensemble) Mocknet() mocknet.Mocknet { return n.mn } +func (n *Ensemble) NewPrivKey() (libp2pcrypto.PrivKey, peer.ID) { + privkey, _, err := libp2pcrypto.GenerateEd25519Key(rand.Reader) + require.NoError(n.t, err) + + peerId, err := peer.IDFromPrivateKey(privkey) + require.NoError(n.t, err) + + return privkey, peerId +} + // FullNode enrolls a new full node. func (n *Ensemble) FullNode(full *TestFullNode, opts ...NodeOpt) *Ensemble { options := DefaultNodeOpts @@ -200,13 +211,14 @@ func (n *Ensemble) FullNode(full *TestFullNode, opts ...NodeOpt) *Ensemble { } *full = TestFullNode{t: n.t, options: options, DefaultKey: key} + n.inactive.fullnodes = append(n.inactive.fullnodes, full) return n } // Miner enrolls a new miner, using the provided full node for chain // interactions. -func (n *Ensemble) Miner(minerNode *TestMiner, full *TestFullNode, opts ...NodeOpt) *Ensemble { +func (n *Ensemble) MinerEnroll(minerNode *TestMiner, full *TestFullNode, opts ...NodeOpt) *Ensemble { require.NotNil(n.t, full, "full node required when instantiating miner") options := DefaultNodeOpts @@ -291,8 +303,16 @@ func (n *Ensemble) Miner(minerNode *TestMiner, full *TestFullNode, opts ...NodeO minerNode.Libp2p.PeerID = peerId minerNode.Libp2p.PrivKey = privkey - n.inactive.miners = append(n.inactive.miners, minerNode) + return n +} +func (n *Ensemble) AddInactiveMiner(m *TestMiner) { + n.inactive.miners = append(n.inactive.miners, m) +} + +func (n *Ensemble) Miner(minerNode *TestMiner, full *TestFullNode, opts ...NodeOpt) *Ensemble { + n.MinerEnroll(minerNode, full, opts...) + n.AddInactiveMiner(minerNode) return n } @@ -358,6 +378,21 @@ func (n *Ensemble) Start() *Ensemble { lr, err := r.Lock(repo.FullNode) require.NoError(n.t, err) + ks, err := lr.KeyStore() + require.NoError(n.t, err) + + if full.Pkey != nil { + pk, err := libp2pcrypto.MarshalPrivateKey(full.Pkey.PrivKey) + require.NoError(n.t, err) + + err = ks.Put("libp2p-host", types.KeyInfo{ + Type: "libp2p-host", + PrivateKey: pk, + }) + require.NoError(n.t, err) + + } + c, err := lr.Config() require.NoError(n.t, err) @@ -416,6 +451,7 @@ func (n *Ensemble) Start() *Ensemble { // Construct the full node. stop, err := node.New(ctx, opts...) + full.Stop = stop require.NoError(n.t, err) @@ -425,15 +461,31 @@ func (n *Ensemble) Start() *Ensemble { err = full.WalletSetDefault(context.Background(), addr) require.NoError(n.t, err) + var rpcShutdownOnce sync.Once + var stopOnce sync.Once + var stopErr error + + stopFunc := stop + stop = func(ctx context.Context) error { + stopOnce.Do(func() { + stopErr = stopFunc(ctx) + }) + return stopErr + } + // Are we hitting this node through its RPC? if full.options.rpc { - withRPC := fullRpc(n.t, full) + withRPC, rpcCloser := fullRpc(n.t, full) n.inactive.fullnodes[i] = withRPC + full.Stop = func(ctx2 context.Context) error { + rpcShutdownOnce.Do(rpcCloser) + return stop(ctx) + } + n.t.Cleanup(func() { rpcShutdownOnce.Do(rpcCloser) }) } n.t.Cleanup(func() { _ = stop(context.Background()) - }) n.active.fullnodes = append(n.active.fullnodes, full) @@ -477,7 +529,9 @@ func (n *Ensemble) Start() *Ensemble { Method: power.Methods.CreateMiner, Params: params, } - signed, err := m.FullNode.FullNode.MpoolPushMessage(ctx, createStorageMinerMsg, nil) + signed, err := m.FullNode.FullNode.MpoolPushMessage(ctx, createStorageMinerMsg, &api.MessageSendSpec{ + MsgUuid: uuid.New(), + }) require.NoError(n.t, err) mw, err := m.FullNode.FullNode.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence, api.LookbackNoLimit, true) @@ -501,7 +555,9 @@ func (n *Ensemble) Start() *Ensemble { Value: types.NewInt(0), } - signed, err2 := m.FullNode.FullNode.MpoolPushMessage(ctx, msg, nil) + signed, err2 := m.FullNode.FullNode.MpoolPushMessage(ctx, msg, &api.MessageSendSpec{ + MsgUuid: uuid.New(), + }) require.NoError(n.t, err2) mw, err2 := m.FullNode.FullNode.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence, api.LookbackNoLimit, true) @@ -586,11 +642,11 @@ func (n *Ensemble) Start() *Ensemble { psd := m.PresealDir noPaths := m.options.noStorage - err := lr.SetStorage(func(sc *paths.StorageConfig) { + err := lr.SetStorage(func(sc *storiface.StorageConfig) { if noPaths { - sc.StoragePaths = []paths.LocalPath{} + sc.StoragePaths = []storiface.LocalPath{} } - sc.StoragePaths = append(sc.StoragePaths, paths.LocalPath{Path: psd}) + sc.StoragePaths = append(sc.StoragePaths, storiface.LocalPath{Path: psd}) }) require.NoError(n.t, err) @@ -611,7 +667,9 @@ func (n *Ensemble) Start() *Ensemble { Value: types.NewInt(0), } - _, err2 := m.FullNode.MpoolPushMessage(ctx, msg, nil) + _, err2 := m.FullNode.MpoolPushMessage(ctx, msg, &api.MessageSendSpec{ + MsgUuid: uuid.New(), + }) require.NoError(n.t, err2) } @@ -620,6 +678,13 @@ func (n *Ensemble) Start() *Ensemble { disallowRemoteFinalize := m.options.disallowRemoteFinalize var mineBlock = make(chan lotusminer.MineReq) + + copy := *m.FullNode + copy.FullNode = modules.MakeUuidWrapper(copy.FullNode) + m.FullNode = © + + //m.FullNode.FullNode = modules.MakeUuidWrapper(fn.FullNode) + opts := []node.Option{ node.StorageMiner(&m.StorageMiner, cfg.Subsystems), node.Base(), @@ -627,12 +692,14 @@ func (n *Ensemble) Start() *Ensemble { node.Test(), node.If(m.options.disableLibp2p, node.MockHost(n.mn)), - node.Override(new(v1api.RawFullNodeAPI), m.FullNode.FullNode), + //node.Override(new(v1api.RawFullNodeAPI), func() api.FullNode { return modules.MakeUuidWrapper(m.FullNode) }), + //node.Override(new(v1api.RawFullNodeAPI), modules.MakeUuidWrapper), + node.Override(new(v1api.RawFullNodeAPI), m.FullNode), node.Override(new(*lotusminer.Miner), lotusminer.NewTestMiner(mineBlock, m.ActorAddr)), // disable resource filtering so that local worker gets assigned tasks // regardless of system pressure. - node.Override(new(sectorstorage.Config), func() sectorstorage.Config { + node.Override(new(config.SealerConfig), func() config.SealerConfig { scfg := config.DefaultStorageMiner() if noLocal { @@ -645,8 +712,8 @@ func (n *Ensemble) Start() *Ensemble { scfg.Storage.Assigner = assigner scfg.Storage.DisallowRemoteFinalize = disallowRemoteFinalize - scfg.Storage.ResourceFiltering = sectorstorage.ResourceFilteringDisabled - return scfg.StorageManager() + scfg.Storage.ResourceFiltering = config.ResourceFilteringDisabled + return scfg.Storage }), // upgrades @@ -737,8 +804,8 @@ func (n *Ensemble) Start() *Ensemble { require.NoError(n.t, err) if m.options.noStorage { - err := lr.SetStorage(func(sc *paths.StorageConfig) { - sc.StoragePaths = []paths.LocalPath{} + err := lr.SetStorage(func(sc *storiface.StorageConfig) { + sc.StoragePaths = []storiface.LocalPath{} }) require.NoError(n.t, err) } @@ -814,9 +881,9 @@ func (n *Ensemble) Start() *Ensemble { wait.Unlock() }) wait.Lock() + n.bootstrapped = true } - n.bootstrapped = true return n } diff --git a/itests/kit/node_full.go b/itests/kit/node_full.go index 710962e6a..12db91c68 100644 --- a/itests/kit/node_full.go +++ b/itests/kit/node_full.go @@ -6,6 +6,8 @@ import ( "testing" "time" + libp2pcrypto "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/peer" "github.com/multiformats/go-multiaddr" "github.com/stretchr/testify/require" @@ -16,8 +18,15 @@ import ( "github.com/filecoin-project/lotus/api/v1api" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet/key" + cliutil "github.com/filecoin-project/lotus/cli/util" + "github.com/filecoin-project/lotus/node" ) +type Libp2p struct { + PeerID peer.ID + PrivKey libp2pcrypto.PrivKey +} + // TestFullNode represents a full node enrolled in an Ensemble. type TestFullNode struct { v1api.FullNode @@ -27,11 +36,36 @@ type TestFullNode struct { // ListenAddr is the address on which an API server is listening, if an // API server is created for this Node. ListenAddr multiaddr.Multiaddr + ListenURL string DefaultKey *key.Key + Pkey *Libp2p + + Stop node.StopFunc + options nodeOpts } +func MergeFullNodes(fullNodes []*TestFullNode) *TestFullNode { + var wrappedFullNode TestFullNode + var fns api.FullNodeStruct + wrappedFullNode.FullNode = &fns + + cliutil.FullNodeProxy(fullNodes, &fns) + + wrappedFullNode.t = fullNodes[0].t + wrappedFullNode.ListenAddr = fullNodes[0].ListenAddr + wrappedFullNode.DefaultKey = fullNodes[0].DefaultKey + wrappedFullNode.Stop = fullNodes[0].Stop + wrappedFullNode.options = fullNodes[0].options + + return &wrappedFullNode +} + +func (f TestFullNode) Shutdown(ctx context.Context) error { + return f.Stop(ctx) +} + func (f *TestFullNode) ClientImportCARFile(ctx context.Context, rseed int, size int) (res *api.ImportRes, carv1FilePath string, origFilePath string) { carv1FilePath, origFilePath = CreateRandomCARv1(f.t, rseed, size) res, err := f.ClientImport(ctx, api.FileRef{Path: carv1FilePath, IsCAR: true}) @@ -86,6 +120,10 @@ func (f *TestFullNode) WaitForSectorActive(ctx context.Context, t *testing.T, sn } } +func (f *TestFullNode) AssignPrivKey(pkey *Libp2p) { + f.Pkey = pkey +} + // ChainPredicate encapsulates a chain condition. type ChainPredicate func(set *types.TipSet) bool diff --git a/itests/kit/node_miner.go b/itests/kit/node_miner.go index 83f6178f7..032cef87c 100644 --- a/itests/kit/node_miner.go +++ b/itests/kit/node_miner.go @@ -26,7 +26,6 @@ import ( "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/wallet/key" "github.com/filecoin-project/lotus/miner" - "github.com/filecoin-project/lotus/storage/paths" sealing "github.com/filecoin-project/lotus/storage/pipeline" "github.com/filecoin-project/lotus/storage/sealer/storiface" ) @@ -175,7 +174,7 @@ func (tm *TestMiner) FlushSealingBatches(ctx context.Context) { const metaFile = "sectorstore.json" -func (tm *TestMiner) AddStorage(ctx context.Context, t *testing.T, conf func(*paths.LocalStorageMeta)) storiface.ID { +func (tm *TestMiner) AddStorage(ctx context.Context, t *testing.T, conf func(*storiface.LocalStorageMeta)) storiface.ID { p := t.TempDir() if err := os.MkdirAll(p, 0755); err != nil { @@ -189,7 +188,7 @@ func (tm *TestMiner) AddStorage(ctx context.Context, t *testing.T, conf func(*pa require.NoError(t, err) } - cfg := &paths.LocalStorageMeta{ + cfg := &storiface.LocalStorageMeta{ ID: storiface.ID(uuid.New().String()), Weight: 10, CanSeal: false, diff --git a/itests/kit/node_opts.go b/itests/kit/node_opts.go index 2849485a9..9c482700c 100644 --- a/itests/kit/node_opts.go +++ b/itests/kit/node_opts.go @@ -256,9 +256,6 @@ type CfgOption func(cfg *config.FullNode) error func SplitstoreDiscard() NodeOpt { return WithCfgOpt(func(cfg *config.FullNode) error { - //cfg.Chainstore.Splitstore.HotStoreType = "badger" // default - //cfg.Chainstore.Splitstore.MarkSetType = "badger" // default - //cfg.Chainstore.Splitstore.HotStoreMessageRetention = 0 // default cfg.Chainstore.EnableSplitstore = true cfg.Chainstore.Splitstore.HotStoreFullGCFrequency = 0 // turn off full gc cfg.Chainstore.Splitstore.ColdStoreType = "discard" // no cold store @@ -268,9 +265,6 @@ func SplitstoreDiscard() NodeOpt { func SplitstoreUniversal() NodeOpt { return WithCfgOpt(func(cfg *config.FullNode) error { - //cfg.Chainstore.Splitstore.HotStoreType = "badger" // default - //cfg.Chainstore.Splitstore.MarkSetType = "badger" // default - //cfg.Chainstore.Splitstore.HotStoreMessageRetention = 0 // default cfg.Chainstore.EnableSplitstore = true cfg.Chainstore.Splitstore.HotStoreFullGCFrequency = 0 // turn off full gc cfg.Chainstore.Splitstore.ColdStoreType = "universal" // universal bs is coldstore @@ -278,10 +272,11 @@ func SplitstoreUniversal() NodeOpt { }) } -func SplitstoreAutoPrune() NodeOpt { +func SplitstoreMessges() NodeOpt { return WithCfgOpt(func(cfg *config.FullNode) error { - cfg.Chainstore.Splitstore.EnableColdStoreAutoPrune = true // turn on - cfg.Chainstore.Splitstore.ColdStoreFullGCFrequency = 0 // turn off full gc + cfg.Chainstore.EnableSplitstore = true + cfg.Chainstore.Splitstore.HotStoreFullGCFrequency = 0 // turn off full gc + cfg.Chainstore.Splitstore.ColdStoreType = "messages" // universal bs is coldstore, and it accepts messages return nil }) } diff --git a/itests/kit/node_worker.go b/itests/kit/node_worker.go index 3a6a55c55..ac200fb0f 100644 --- a/itests/kit/node_worker.go +++ b/itests/kit/node_worker.go @@ -15,7 +15,6 @@ import ( "github.com/stretchr/testify/require" "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/storage/paths" "github.com/filecoin-project/lotus/storage/sealer/storiface" ) @@ -38,7 +37,7 @@ type TestWorker struct { options nodeOpts } -func (tm *TestWorker) AddStorage(ctx context.Context, t *testing.T, conf func(*paths.LocalStorageMeta)) storiface.ID { +func (tm *TestWorker) AddStorage(ctx context.Context, t *testing.T, conf func(*storiface.LocalStorageMeta)) storiface.ID { p := t.TempDir() if err := os.MkdirAll(p, 0755); err != nil { @@ -52,7 +51,7 @@ func (tm *TestWorker) AddStorage(ctx context.Context, t *testing.T, conf func(*p require.NoError(t, err) } - cfg := &paths.LocalStorageMeta{ + cfg := &storiface.LocalStorageMeta{ ID: storiface.ID(uuid.New().String()), Weight: 10, CanSeal: false, diff --git a/itests/kit/rpc.go b/itests/kit/rpc.go index 45fb095d5..684742ad3 100644 --- a/itests/kit/rpc.go +++ b/itests/kit/rpc.go @@ -7,7 +7,6 @@ import ( "net/http" "net/http/httptest" "testing" - "time" "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" @@ -18,63 +17,49 @@ import ( "github.com/filecoin-project/lotus/node" ) -func CreateRPCServer(t *testing.T, handler http.Handler, listener net.Listener) (*httptest.Server, multiaddr.Multiaddr) { +type Closer func() + +func CreateRPCServer(t *testing.T, handler http.Handler, listener net.Listener) (*httptest.Server, multiaddr.Multiaddr, Closer) { testServ := &httptest.Server{ Listener: listener, Config: &http.Server{Handler: handler}, } testServ.Start() - t.Cleanup(func() { - waitUpTo(testServ.Close, time.Second, "Gave up waiting for RPC server to close after 1s") - }) - t.Cleanup(testServ.CloseClientConnections) - addr := testServ.Listener.Addr() maddr, err := manet.FromNetAddr(addr) require.NoError(t, err) - return testServ, maddr -} - -func waitUpTo(fn func(), waitTime time.Duration, errMsg string) { - ch := make(chan struct{}) - go func() { - fn() - close(ch) - }() - - select { - case <-ch: - case <-time.After(waitTime): - fmt.Println(errMsg) - return + closer := func() { + testServ.CloseClientConnections() + testServ.Close() } + + return testServ, maddr, closer } -func fullRpc(t *testing.T, f *TestFullNode) *TestFullNode { +func fullRpc(t *testing.T, f *TestFullNode) (*TestFullNode, Closer) { handler, err := node.FullNodeHandler(f.FullNode, false) require.NoError(t, err) l, err := net.Listen("tcp", "127.0.0.1:0") require.NoError(t, err) - srv, maddr := CreateRPCServer(t, handler, l) + srv, maddr, rpcCloser := CreateRPCServer(t, handler, l) fmt.Printf("FULLNODE RPC ENV FOR CLI DEBUGGING `export FULLNODE_API_INFO=%s`\n", "ws://"+srv.Listener.Addr().String()) sendItestdNotif("FULLNODE_API_INFO", t.Name(), "ws://"+srv.Listener.Addr().String()) cl, stop, err := client.NewFullNodeRPCV1(context.Background(), "ws://"+srv.Listener.Addr().String()+"/rpc/v1", nil) require.NoError(t, err) - t.Cleanup(stop) - f.ListenAddr, f.FullNode = maddr, cl + f.ListenAddr, f.ListenURL, f.FullNode = maddr, srv.URL, cl - return f + return f, func() { stop(); rpcCloser() } } func minerRpc(t *testing.T, m *TestMiner) *TestMiner { handler, err := node.MinerHandler(m.StorageMiner, false) require.NoError(t, err) - srv, maddr := CreateRPCServer(t, handler, m.RemoteListener) + srv, maddr, _ := CreateRPCServer(t, handler, m.RemoteListener) fmt.Printf("creating RPC server for %s at %s\n", m.ActorAddr, srv.Listener.Addr().String()) fmt.Printf("SP RPC ENV FOR CLI DEBUGGING `export MINER_API_INFO=%s`\n", "ws://"+srv.Listener.Addr().String()) @@ -92,7 +77,7 @@ func minerRpc(t *testing.T, m *TestMiner) *TestMiner { func workerRpc(t *testing.T, m *TestWorker) *TestWorker { handler := sealworker.WorkerHandler(m.MinerNode.AuthVerify, m.FetchHandler, m.Worker, false) - srv, maddr := CreateRPCServer(t, handler, m.RemoteListener) + srv, maddr, _ := CreateRPCServer(t, handler, m.RemoteListener) fmt.Println("creating RPC server for a worker at: ", srv.Listener.Addr().String()) url := "ws://" + srv.Listener.Addr().String() + "/rpc/v0" diff --git a/itests/mpool_push_with_uuid_test.go b/itests/mpool_push_with_uuid_test.go new file mode 100644 index 000000000..6b94dbad1 --- /dev/null +++ b/itests/mpool_push_with_uuid_test.go @@ -0,0 +1,54 @@ +package itests + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/go-state-types/exitcode" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/itests/kit" + "github.com/filecoin-project/lotus/node/config" +) + +func TestMpoolPushWithoutUuidWithMaxFee(t *testing.T) { + //stm: @TOKEN_WALLET_SIGN_001, @CHAIN_MEMPOOL_PUSH_001 + ctx := context.Background() + + kit.QuietMiningLogs() + + client15, _, ens := kit.EnsembleMinimal(t, kit.MockProofs()) + ens.InterconnectAll().BeginMining(10 * time.Millisecond) + + bal, err := client15.WalletBalance(ctx, client15.DefaultKey.Address) + require.NoError(t, err) + + // send self half of account balance + msgHalfBal := &types.Message{ + From: client15.DefaultKey.Address, + To: client15.DefaultKey.Address, + Value: big.Div(bal, big.NewInt(2)), + } + smHalfBal, err := client15.MpoolPushMessage(ctx, msgHalfBal, &api.MessageSendSpec{MaxFee: abi.TokenAmount(config.DefaultDefaultMaxFee)}) + require.NoError(t, err) + mLookup, err := client15.StateWaitMsg(ctx, smHalfBal.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) + + msgQuarterBal := &types.Message{ + From: client15.DefaultKey.Address, + To: client15.DefaultKey.Address, + Value: big.Div(bal, big.NewInt(4)), + } + smcid, err := client15.MpoolPushMessage(ctx, msgQuarterBal, &api.MessageSendSpec{MaxFee: abi.TokenAmount(config.DefaultDefaultMaxFee)}) + require.NoError(t, err) + mLookup, err = client15.StateWaitMsg(ctx, smcid.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) +} diff --git a/itests/path_detach_redeclare_test.go b/itests/path_detach_redeclare_test.go index 124266b7d..10774d012 100644 --- a/itests/path_detach_redeclare_test.go +++ b/itests/path_detach_redeclare_test.go @@ -15,7 +15,6 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/itests/kit" - "github.com/filecoin-project/lotus/storage/paths" "github.com/filecoin-project/lotus/storage/sealer/sealtasks" "github.com/filecoin-project/lotus/storage/sealer/storiface" ) @@ -74,7 +73,7 @@ func TestPathDetachRedeclare(t *testing.T) { checkSectors(ctx, t, client, miner, 2, 2) // attach a new path - newId := miner.AddStorage(ctx, t, func(cfg *paths.LocalStorageMeta) { + newId := miner.AddStorage(ctx, t, func(cfg *storiface.LocalStorageMeta) { cfg.CanStore = true }) @@ -194,7 +193,7 @@ func TestPathDetachRedeclareWorker(t *testing.T) { checkSectors(ctx, t, client, miner, 2, 2) // attach a new path - newId := sealw.AddStorage(ctx, t, func(cfg *paths.LocalStorageMeta) { + newId := sealw.AddStorage(ctx, t, func(cfg *storiface.LocalStorageMeta) { cfg.CanStore = true }) @@ -239,7 +238,7 @@ func TestPathDetachRedeclareWorker(t *testing.T) { require.Len(t, local, 0) // add a new one again, and move the sectors there - newId = sealw.AddStorage(ctx, t, func(cfg *paths.LocalStorageMeta) { + newId = sealw.AddStorage(ctx, t, func(cfg *storiface.LocalStorageMeta) { cfg.CanStore = true }) @@ -407,7 +406,7 @@ func checkSectors(ctx context.Context, t *testing.T, api kit.TestFullNode, miner require.Len(t, tocheck, expectChecked) - bad, err := miner.CheckProvable(ctx, info.WindowPoStProofType, tocheck, true) + bad, err := miner.CheckProvable(ctx, info.WindowPoStProofType, tocheck) require.NoError(t, err) require.Len(t, bad, expectBad) } diff --git a/itests/path_type_filters_test.go b/itests/path_type_filters_test.go index 03dd5ea16..d41e2c215 100644 --- a/itests/path_type_filters_test.go +++ b/itests/path_type_filters_test.go @@ -10,7 +10,6 @@ import ( "github.com/stretchr/testify/require" "github.com/filecoin-project/lotus/itests/kit" - "github.com/filecoin-project/lotus/storage/paths" "github.com/filecoin-project/lotus/storage/sealer/sealtasks" "github.com/filecoin-project/lotus/storage/sealer/storiface" ) @@ -45,7 +44,7 @@ func TestPathTypeFilters(t *testing.T) { } runTest(t, "invalid-type-alert", func(t *testing.T, ctx context.Context, miner *kit.TestMiner, run func()) { - slU := miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + slU := miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.CanSeal = true meta.AllowTypes = []string{"unsealed", "seeled"} }) @@ -79,18 +78,18 @@ func TestPathTypeFilters(t *testing.T) { runTest(t, "seal-to-stor-unseal-allowdeny", func(t *testing.T, ctx context.Context, miner *kit.TestMiner, run func()) { // allow all types in the sealing path - sealScratch := miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + sealScratch := miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.CanSeal = true }) // unsealed storage - unsStor := miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + unsStor := miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.CanStore = true meta.AllowTypes = []string{"unsealed"} }) // other storage - sealStor := miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + sealStor := miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.CanStore = true meta.DenyTypes = []string{"unsealed"} }) @@ -115,14 +114,14 @@ func TestPathTypeFilters(t *testing.T) { runTest(t, "sealstor-unseal-allowdeny", func(t *testing.T, ctx context.Context, miner *kit.TestMiner, run func()) { // unsealed storage - unsStor := miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + unsStor := miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.CanStore = true meta.CanSeal = true meta.AllowTypes = []string{"unsealed"} }) // other storage - sealStor := miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + sealStor := miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.CanStore = true meta.CanSeal = true meta.DenyTypes = []string{"unsealed"} @@ -147,29 +146,29 @@ func TestPathTypeFilters(t *testing.T) { runTest(t, "seal-store-allseparate", func(t *testing.T, ctx context.Context, miner *kit.TestMiner, run func()) { // sealing stores - slU := miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + slU := miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.CanSeal = true meta.AllowTypes = []string{"unsealed"} }) - slS := miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + slS := miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.CanSeal = true meta.AllowTypes = []string{"sealed"} }) - slC := miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + slC := miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.CanSeal = true meta.AllowTypes = []string{"cache"} }) // storage stores - stU := miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + stU := miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.CanStore = true meta.AllowTypes = []string{"unsealed"} }) - stS := miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + stS := miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.CanStore = true meta.AllowTypes = []string{"sealed"} }) - stC := miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + stC := miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.CanStore = true meta.AllowTypes = []string{"cache"} }) diff --git a/itests/raft_messagesigner_test.go b/itests/raft_messagesigner_test.go new file mode 100644 index 000000000..f94095b90 --- /dev/null +++ b/itests/raft_messagesigner_test.go @@ -0,0 +1,577 @@ +package itests + +import ( + "context" + "crypto/rand" + "fmt" + "reflect" + "testing" + "time" + + "github.com/google/uuid" + gorpc "github.com/libp2p/go-libp2p-gorpc" + libp2pcrypto "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/go-state-types/exitcode" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/messagesigner" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/itests/kit" + consensus "github.com/filecoin-project/lotus/lib/consensus/raft" + "github.com/filecoin-project/lotus/node" + "github.com/filecoin-project/lotus/node/config" + "github.com/filecoin-project/lotus/node/impl" + "github.com/filecoin-project/lotus/node/modules" +) + +func generatePrivKey() (*kit.Libp2p, error) { + privkey, _, err := libp2pcrypto.GenerateEd25519Key(rand.Reader) + if err != nil { + return nil, err + } + + peerId, err := peer.IDFromPrivateKey(privkey) + if err != nil { + return nil, err + } + + return &kit.Libp2p{PeerID: peerId, PrivKey: privkey}, nil +} + +func getRaftState(ctx context.Context, t *testing.T, node *kit.TestFullNode) *api.RaftStateData { + raftState, err := node.RaftState(ctx) + require.NoError(t, err) + return raftState +} + +func setup(ctx context.Context, t *testing.T, node0 *kit.TestFullNode, node1 *kit.TestFullNode, node2 *kit.TestFullNode, miner *kit.TestMiner) *kit.Ensemble { + + blockTime := 1 * time.Second + + pkey0, _ := generatePrivKey() + pkey1, _ := generatePrivKey() + pkey2, _ := generatePrivKey() + + pkeys := []*kit.Libp2p{pkey0, pkey1, pkey2} + initPeerSet := []string{} + for _, pkey := range pkeys { + initPeerSet = append(initPeerSet, "/p2p/"+pkey.PeerID.String()) + } + + //initPeerSet := []peer.ID{pkey0.PeerID, pkey1.PeerID, pkey2.PeerID} + + raftOps := kit.ConstructorOpts( + node.Override(new(*gorpc.Client), modules.NewRPCClient), + node.Override(new(*consensus.ClusterRaftConfig), func() *consensus.ClusterRaftConfig { + cfg := consensus.DefaultClusterRaftConfig() + cfg.InitPeerset = initPeerSet + return cfg + }), + node.Override(new(*consensus.Consensus), consensus.NewConsensusWithRPCClient(false)), + node.Override(new(*messagesigner.MessageSignerConsensus), messagesigner.NewMessageSignerConsensus), + node.Override(new(messagesigner.MsgSigner), func(ms *messagesigner.MessageSignerConsensus) *messagesigner.MessageSignerConsensus { return ms }), + node.Override(new(*modules.RPCHandler), modules.NewRPCHandler), + node.Override(node.GoRPCServer, modules.NewRPCServer), + ) + //raftOps := kit.ConstructorOpts() + kit.ThroughRPC() + + ens := kit.NewEnsemble(t).FullNode(node0, raftOps, kit.ThroughRPC()).FullNode(node1, raftOps, kit.ThroughRPC()).FullNode(node2, raftOps, kit.ThroughRPC()) + node0.AssignPrivKey(pkey0) + node1.AssignPrivKey(pkey1) + node2.AssignPrivKey(pkey2) + + nodes := []*kit.TestFullNode{node0, node1, node2} + wrappedFullNode := kit.MergeFullNodes(nodes) + + ens.MinerEnroll(miner, wrappedFullNode, kit.WithAllSubsystems(), kit.ThroughRPC()) + ens.Start() + + // Import miner wallet to all nodes + addr0, err := node0.WalletImport(ctx, &miner.OwnerKey.KeyInfo) + require.NoError(t, err) + addr1, err := node1.WalletImport(ctx, &miner.OwnerKey.KeyInfo) + require.NoError(t, err) + addr2, err := node2.WalletImport(ctx, &miner.OwnerKey.KeyInfo) + require.NoError(t, err) + + fmt.Println(addr0, addr1, addr2) + + ens.InterconnectAll() + + ens.AddInactiveMiner(miner) + ens.Start() + + ens.InterconnectAll().BeginMining(blockTime) + + return ens +} + +func TestRaftState(t *testing.T) { + + kit.QuietMiningLogs() + ctx := context.Background() + + var ( + node0 kit.TestFullNode + node1 kit.TestFullNode + node2 kit.TestFullNode + miner kit.TestMiner + ) + + setup(ctx, t, &node0, &node1, &node2, &miner) + + fmt.Println(node0.WalletList(context.Background())) + fmt.Println(node1.WalletList(context.Background())) + fmt.Println(node2.WalletList(context.Background())) + + bal, err := node0.WalletBalance(ctx, node0.DefaultKey.Address) + require.NoError(t, err) + + msgHalfBal := &types.Message{ + From: miner.OwnerKey.Address, + To: node0.DefaultKey.Address, + Value: big.Div(bal, big.NewInt(2)), + } + + mu := uuid.New() + smHalfBal, err := node0.MpoolPushMessage(ctx, msgHalfBal, &api.MessageSendSpec{ + MsgUuid: mu, + }) + require.NoError(t, err) + mLookup, err := node0.StateWaitMsg(ctx, smHalfBal.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) + + rstate0 := getRaftState(ctx, t, &node0) + rstate1 := getRaftState(ctx, t, &node1) + rstate2 := getRaftState(ctx, t, &node2) + + require.EqualValues(t, rstate0, rstate1) + require.EqualValues(t, rstate0, rstate2) +} + +func TestRaftStateLeaderDisconnects(t *testing.T) { + + kit.QuietMiningLogs() + ctx := context.Background() + + var ( + node0 kit.TestFullNode + node1 kit.TestFullNode + node2 kit.TestFullNode + miner kit.TestMiner + ) + + nodes := []*kit.TestFullNode{&node0, &node1, &node2} + + setup(ctx, t, &node0, &node1, &node2, &miner) + + peerToNode := make(map[peer.ID]*kit.TestFullNode) + for _, n := range nodes { + peerToNode[n.Pkey.PeerID] = n + } + + bal, err := node0.WalletBalance(ctx, node0.DefaultKey.Address) + require.NoError(t, err) + + msgHalfBal := &types.Message{ + From: miner.OwnerKey.Address, + To: node0.DefaultKey.Address, + Value: big.Div(bal, big.NewInt(2)), + } + mu := uuid.New() + smHalfBal, err := node0.MpoolPushMessage(ctx, msgHalfBal, &api.MessageSendSpec{ + MsgUuid: mu, + }) + require.NoError(t, err) + mLookup, err := node0.StateWaitMsg(ctx, smHalfBal.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) + + rstate0 := getRaftState(ctx, t, &node0) + rstate1 := getRaftState(ctx, t, &node1) + rstate2 := getRaftState(ctx, t, &node2) + + require.True(t, reflect.DeepEqual(rstate0, rstate1)) + require.True(t, reflect.DeepEqual(rstate0, rstate2)) + + leader, err := node1.RaftLeader(ctx) + require.NoError(t, err) + leaderNode := peerToNode[leader] + + err = leaderNode.Stop(ctx) + require.NoError(t, err) + oldLeaderNode := leaderNode + + time.Sleep(5 * time.Second) + + newLeader := leader + for _, n := range nodes { + if n != leaderNode { + newLeader, err = n.RaftLeader(ctx) + require.NoError(t, err) + require.NotEqual(t, newLeader, leader) + } + } + + require.NotEqual(t, newLeader, leader) + leaderNode = peerToNode[newLeader] + + msg2 := &types.Message{ + From: miner.OwnerKey.Address, + To: leaderNode.DefaultKey.Address, + Value: big.NewInt(100000), + } + mu2 := uuid.New() + signedMsg2, err := leaderNode.MpoolPushMessage(ctx, msg2, &api.MessageSendSpec{ + MsgUuid: mu2, + }) + require.NoError(t, err) + mLookup, err = leaderNode.StateWaitMsg(ctx, signedMsg2.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) + + rstate := getRaftState(ctx, t, leaderNode) + + for _, n := range nodes { + if n != oldLeaderNode { + rs := getRaftState(ctx, t, n) + require.True(t, reflect.DeepEqual(rs, rstate)) + } + } +} + +func TestRaftStateMiner(t *testing.T) { + + kit.QuietMiningLogs() + ctx := context.Background() + + var ( + node0 kit.TestFullNode + node1 kit.TestFullNode + node2 kit.TestFullNode + miner kit.TestMiner + ) + + setup(ctx, t, &node0, &node1, &node2, &miner) + + fmt.Println(node0.WalletList(context.Background())) + fmt.Println(node1.WalletList(context.Background())) + fmt.Println(node2.WalletList(context.Background())) + + bal, err := node0.WalletBalance(ctx, node0.DefaultKey.Address) + require.NoError(t, err) + + msgHalfBal := &types.Message{ + From: miner.OwnerKey.Address, + To: node0.DefaultKey.Address, + Value: big.Div(bal, big.NewInt(2)), + } + mu := uuid.New() + smHalfBal, err := miner.FullNode.MpoolPushMessage(ctx, msgHalfBal, &api.MessageSendSpec{ + MsgUuid: mu, + }) + require.NoError(t, err) + mLookup, err := node0.StateWaitMsg(ctx, smHalfBal.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) + + rstate0 := getRaftState(ctx, t, &node0) + rstate1 := getRaftState(ctx, t, &node1) + rstate2 := getRaftState(ctx, t, &node2) + + require.EqualValues(t, rstate0, rstate1) + require.EqualValues(t, rstate0, rstate2) +} + +func TestRaftStateLeaderDisconnectsMiner(t *testing.T) { + + kit.QuietMiningLogs() + ctx := context.Background() + + var ( + node0 kit.TestFullNode + node1 kit.TestFullNode + node2 kit.TestFullNode + miner kit.TestMiner + ) + + nodes := []*kit.TestFullNode{&node0, &node1, &node2} + + setup(ctx, t, &node0, &node1, &node2, &miner) + + peerToNode := make(map[peer.ID]*kit.TestFullNode) + for _, n := range nodes { + peerToNode[n.Pkey.PeerID] = n + } + + leader, err := node0.RaftLeader(ctx) + require.NoError(t, err) + leaderNode := peerToNode[leader] + + // Take leader node down + err = leaderNode.Stop(ctx) + require.NoError(t, err) + oldLeaderNode := leaderNode + + time.Sleep(5 * time.Second) + + newLeader := leader + for _, n := range nodes { + if n != leaderNode { + newLeader, err = n.RaftLeader(ctx) + require.NoError(t, err) + require.NotEqual(t, newLeader, leader) + } + } + + require.NotEqual(t, newLeader, leader) + leaderNode = peerToNode[newLeader] + + msg2 := &types.Message{ + From: miner.OwnerKey.Address, + To: node0.DefaultKey.Address, + Value: big.NewInt(100000), + } + mu2 := uuid.New() + + signedMsg2, err := miner.FullNode.MpoolPushMessage(ctx, msg2, &api.MessageSendSpec{ + MaxFee: abi.TokenAmount(config.DefaultDefaultMaxFee), + MsgUuid: mu2, + }) + require.NoError(t, err) + + mLookup, err := leaderNode.StateWaitMsg(ctx, signedMsg2.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) + + rstate := getRaftState(ctx, t, leaderNode) + + for _, n := range nodes { + if n != oldLeaderNode { + rs := getRaftState(ctx, t, n) + require.True(t, reflect.DeepEqual(rs, rstate)) + } + } +} + +// Miner sends message on leader +// Leader disconnects +// Call StateWaitMsg on new leader +func TestLeaderDisconnectsCheckMsgStateOnNewLeader(t *testing.T) { + + kit.QuietMiningLogs() + ctx := context.Background() + + var ( + node0 kit.TestFullNode + node1 kit.TestFullNode + node2 kit.TestFullNode + miner kit.TestMiner + ) + + nodes := []*kit.TestFullNode{&node0, &node1, &node2} + + setup(ctx, t, &node0, &node1, &node2, &miner) + + peerToNode := make(map[peer.ID]*kit.TestFullNode) + for _, n := range nodes { + peerToNode[n.Pkey.PeerID] = n + } + + bal, err := node0.WalletBalance(ctx, node0.DefaultKey.Address) + require.NoError(t, err) + + msgHalfBal := &types.Message{ + From: miner.OwnerKey.Address, + To: node0.DefaultKey.Address, + Value: big.Div(bal, big.NewInt(2)), + } + mu := uuid.New() + smHalfBal, err := miner.FullNode.MpoolPushMessage(ctx, msgHalfBal, &api.MessageSendSpec{ + MsgUuid: mu, + }) + require.NoError(t, err) + + leader, err := node0.RaftLeader(ctx) + require.NoError(t, err) + leaderNode := peerToNode[leader] + + // Take leader node down + err = leaderNode.Stop(ctx) + require.NoError(t, err) + oldLeaderNode := leaderNode + + time.Sleep(5 * time.Second) + + // Check if all active nodes update their leader + newLeader := leader + for _, n := range nodes { + if n != leaderNode { + newLeader, err = n.RaftLeader(ctx) + require.NoError(t, err) + require.NotEqual(t, newLeader, leader) + } + } + + require.NotEqual(t, newLeader, leader) + leaderNode = peerToNode[newLeader] + + mLookup, err := leaderNode.StateWaitMsg(ctx, smHalfBal.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) + + rstate := getRaftState(ctx, t, leaderNode) + + // Check if Raft state is consistent on all active nodes + for _, n := range nodes { + if n != oldLeaderNode { + rs := getRaftState(ctx, t, n) + require.True(t, reflect.DeepEqual(rs, rstate)) + } + } +} + +func TestChainStoreSync(t *testing.T) { + + kit.QuietMiningLogs() + ctx := context.Background() + + var ( + node0 kit.TestFullNode + node1 kit.TestFullNode + node2 kit.TestFullNode + miner kit.TestMiner + ) + + nodes := []*kit.TestFullNode{&node0, &node1, &node2} + + setup(ctx, t, &node0, &node1, &node2, &miner) + + peerToNode := make(map[peer.ID]*kit.TestFullNode) + for _, n := range nodes { + peerToNode[n.Pkey.PeerID] = n + } + + bal, err := node0.WalletBalance(ctx, node0.DefaultKey.Address) + require.NoError(t, err) + + leader, err := node0.RaftLeader(ctx) + require.NoError(t, err) + leaderNode := peerToNode[leader] + + msgHalfBal := &types.Message{ + From: miner.OwnerKey.Address, + To: node0.DefaultKey.Address, + Value: big.Div(bal, big.NewInt(2)), + } + mu := uuid.New() + smHalfBal, err := miner.FullNode.MpoolPushMessage(ctx, msgHalfBal, &api.MessageSendSpec{ + MsgUuid: mu, + }) + require.NoError(t, err) + + for _, n := range nodes { + fmt.Println(n != leaderNode) + if n != leaderNode { + mLookup, err := n.StateWaitMsg(ctx, smHalfBal.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) + //break + } + } +} + +func TestGoRPCAuth(t *testing.T) { + + blockTime := 1 * time.Second + + kit.QuietMiningLogs() + ctx := context.Background() + + var ( + node0 kit.TestFullNode + node1 kit.TestFullNode + node2 kit.TestFullNode + node3 kit.TestFullNode + miner kit.TestMiner + ) + + pkey0, _ := generatePrivKey() + pkey1, _ := generatePrivKey() + pkey2, _ := generatePrivKey() + + pkeys := []*kit.Libp2p{pkey0, pkey1, pkey2} + initPeerSet := []string{} + for _, pkey := range pkeys { + initPeerSet = append(initPeerSet, "/p2p/"+pkey.PeerID.String()) + } + + raftOps := kit.ConstructorOpts( + node.Override(new(*gorpc.Client), modules.NewRPCClient), + node.Override(new(*consensus.ClusterRaftConfig), func() *consensus.ClusterRaftConfig { + cfg := consensus.DefaultClusterRaftConfig() + cfg.InitPeerset = initPeerSet + return cfg + }), + node.Override(new(*consensus.Consensus), consensus.NewConsensusWithRPCClient(false)), + node.Override(new(*messagesigner.MessageSignerConsensus), messagesigner.NewMessageSignerConsensus), + node.Override(new(messagesigner.MsgSigner), func(ms *messagesigner.MessageSignerConsensus) *messagesigner.MessageSignerConsensus { return ms }), + node.Override(new(*modules.RPCHandler), modules.NewRPCHandler), + node.Override(node.GoRPCServer, modules.NewRPCServer), + ) + //raftOps := kit.ConstructorOpts() + kit.ThroughRPC() + + ens := kit.NewEnsemble(t).FullNode(&node0, raftOps, kit.ThroughRPC()).FullNode(&node1, raftOps, kit.ThroughRPC()).FullNode(&node2, raftOps, kit.ThroughRPC()).FullNode(&node3, raftOps) + node0.AssignPrivKey(pkey0) + node1.AssignPrivKey(pkey1) + node2.AssignPrivKey(pkey2) + + nodes := []*kit.TestFullNode{&node0, &node1, &node2} + wrappedFullNode := kit.MergeFullNodes(nodes) + + ens.MinerEnroll(&miner, wrappedFullNode, kit.WithAllSubsystems(), kit.ThroughRPC()) + ens.Start() + + // Import miner wallet to all nodes + addr0, err := node0.WalletImport(ctx, &miner.OwnerKey.KeyInfo) + require.NoError(t, err) + addr1, err := node1.WalletImport(ctx, &miner.OwnerKey.KeyInfo) + require.NoError(t, err) + addr2, err := node2.WalletImport(ctx, &miner.OwnerKey.KeyInfo) + require.NoError(t, err) + + fmt.Println(addr0, addr1, addr2) + + ens.InterconnectAll() + + ens.AddInactiveMiner(&miner) + ens.Start() + + ens.InterconnectAll().BeginMining(blockTime) + + leader, err := node0.RaftLeader(ctx) + require.NoError(t, err) + + client := node3.FullNode.(*impl.FullNodeAPI).RaftAPI.MessageSigner.Consensus.RpcClient + method := "MpoolPushMessage" + + msg := &types.Message{ + From: miner.OwnerKey.Address, + To: node0.DefaultKey.Address, + Value: big.NewInt(100000), + } + msgWhole := &api.MpoolMessageWhole{Msg: msg} + var ret types.SignedMessage + + err = client.CallContext(ctx, leader, "Consensus", method, msgWhole, &ret) + require.True(t, gorpc.IsAuthorizationError(err)) + +} diff --git a/itests/sector_finalize_early_test.go b/itests/sector_finalize_early_test.go index 8678e6a28..fb7d9d94d 100644 --- a/itests/sector_finalize_early_test.go +++ b/itests/sector_finalize_early_test.go @@ -11,7 +11,7 @@ import ( "github.com/filecoin-project/lotus/itests/kit" "github.com/filecoin-project/lotus/node/config" - "github.com/filecoin-project/lotus/storage/paths" + "github.com/filecoin-project/lotus/storage/sealer/storiface" ) func TestDealsWithFinalizeEarly(t *testing.T) { @@ -36,11 +36,11 @@ func TestDealsWithFinalizeEarly(t *testing.T) { ctx := context.Background() - miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.Weight = 1000000000 meta.CanSeal = true }) - miner.AddStorage(ctx, t, func(meta *paths.LocalStorageMeta) { + miner.AddStorage(ctx, t, func(meta *storiface.LocalStorageMeta) { meta.Weight = 1000000000 meta.CanStore = true }) diff --git a/itests/splitstore_test.go b/itests/splitstore_test.go index db74e86a9..957efe32f 100644 --- a/itests/splitstore_test.go +++ b/itests/splitstore_test.go @@ -63,7 +63,16 @@ func TestHotstoreCompactCleansGarbage(t *testing.T) { // create garbage g := NewGarbager(ctx, t, full) - garbage, e := g.Drop(ctx) + // state + garbageS, eS := g.Drop(ctx) + // message + garbageM, eM := g.Message(ctx) + e := eM + if eS > eM { + e = eS + } + assert.True(g.t, g.Exists(ctx, garbageS), "Garbage state not found in splitstore") + assert.True(g.t, g.Exists(ctx, garbageM), "Garbage message not found in splitstore") // calculate next compaction where we should actually see cleanup @@ -94,7 +103,8 @@ func TestHotstoreCompactCleansGarbage(t *testing.T) { waitForCompaction(ctx, t, garbageCompactionIndex, full) // check that garbage is cleaned up - assert.False(t, g.Exists(ctx, garbage), "Garbage still exists in blockstore") + assert.False(t, g.Exists(ctx, garbageS), "Garbage state still exists in blockstore") + assert.False(t, g.Exists(ctx, garbageM), "Garbage message still exists in blockstore") } // Create unreachable state @@ -112,8 +122,16 @@ func TestColdStorePrune(t *testing.T) { // create garbage g := NewGarbager(ctx, t, full) - garbage, e := g.Drop(ctx) - assert.True(g.t, g.Exists(ctx, garbage), "Garbage not found in splitstore") + // state + garbageS, eS := g.Drop(ctx) + // message + garbageM, eM := g.Message(ctx) + e := eM + if eS > eM { + e = eS + } + assert.True(g.t, g.Exists(ctx, garbageS), "Garbage state not found in splitstore") + assert.True(g.t, g.Exists(ctx, garbageM), "Garbage message not found in splitstore") // calculate next compaction where we should actually see cleanup @@ -148,7 +166,8 @@ func TestColdStorePrune(t *testing.T) { // This data should now be moved to the coldstore. // Access it without hotview to keep it there while checking that it still exists // Only state compute uses hot view so garbager Exists backed by ChainReadObj is all good - assert.True(g.t, g.Exists(ctx, garbage), "Garbage not found in splitstore") + assert.True(g.t, g.Exists(ctx, garbageS), "Garbage state not found in splitstore") + assert.True(g.t, g.Exists(ctx, garbageM), "Garbage message not found in splitstore") bm.Restart() // wait for compaction to finsih and pause to make sure it doesn't start to avoid racing @@ -165,14 +184,15 @@ func TestColdStorePrune(t *testing.T) { require.NoError(t, full.ChainPrune(ctx, pruneOpts)) bm.Restart() waitForPrune(ctx, t, 1, full) - assert.False(g.t, g.Exists(ctx, garbage), "Garbage should be removed from cold store after prune but it's still there") + assert.False(g.t, g.Exists(ctx, garbageS), "Garbage state should be removed from cold store after prune but it's still there") + assert.True(g.t, g.Exists(ctx, garbageM), "Garbage message should be on the cold store after prune") } -func TestAutoPrune(t *testing.T) { +func TestMessagesMode(t *testing.T) { ctx := context.Background() // disable sync checking because efficient itests require that the node is out of sync : / splitstore.CheckSyncGap = false - opts := []interface{}{kit.MockProofs(), kit.SplitstoreUniversal(), kit.SplitstoreAutoPrune(), kit.FsRepo()} + opts := []interface{}{kit.MockProofs(), kit.SplitstoreMessges(), kit.FsRepo()} full, genesisMiner, ens := kit.EnsembleMinimal(t, opts...) bm := ens.InterconnectAll().BeginMining(4 * time.Millisecond)[0] _ = full @@ -180,8 +200,16 @@ func TestAutoPrune(t *testing.T) { // create garbage g := NewGarbager(ctx, t, full) - garbage, e := g.Drop(ctx) - assert.True(g.t, g.Exists(ctx, garbage), "Garbage not found in splitstore") + // state + garbageS, eS := g.Drop(ctx) + // message + garbageM, eM := g.Message(ctx) + e := eM + if eS > eM { + e = eS + } + assert.True(g.t, g.Exists(ctx, garbageS), "Garbage state not found in splitstore") + assert.True(g.t, g.Exists(ctx, garbageM), "Garbage message not found in splitstore") // calculate next compaction where we should actually see cleanup @@ -213,13 +241,12 @@ func TestAutoPrune(t *testing.T) { bm.Pause() - // This data should now be moved to the coldstore. + // Messages should be moved to the coldstore + // State should be gced // Access it without hotview to keep it there while checking that it still exists // Only state compute uses hot view so garbager Exists backed by ChainReadObj is all good - assert.True(g.t, g.Exists(ctx, garbage), "Garbage not found in splitstore") - bm.Restart() - waitForPrune(ctx, t, 1, full) - assert.False(g.t, g.Exists(ctx, garbage), "Garbage should be removed from cold store through auto prune but it's still there") + assert.False(g.t, g.Exists(ctx, garbageS), "Garbage state not found in splitstore") + assert.True(g.t, g.Exists(ctx, garbageM), "Garbage message not found in splitstore") } func waitForCompaction(ctx context.Context, t *testing.T, cIdx int64, n *kit.TestFullNode) { @@ -304,7 +331,7 @@ func NewGarbager(ctx context.Context, t *testing.T, n *kit.TestFullNode) *Garbag latest: 0, maddr4Data: address.Undef, } - g.createMiner(ctx) + g.createMiner4Data(ctx) g.newPeerID(ctx) return g } @@ -320,6 +347,12 @@ func (g *Garbager) Drop(ctx context.Context) (cid.Cid, abi.ChainEpoch) { return c, g.newPeerID(ctx) } +// message returns the cid referencing a message and the chain epoch it went on chain +func (g *Garbager) Message(ctx context.Context) (cid.Cid, abi.ChainEpoch) { + mw := g.createMiner(ctx) + return mw.Message, mw.Height +} + // exists checks whether the cid is reachable through the node func (g *Garbager) Exists(ctx context.Context, c cid.Cid) bool { // check chain get / blockstore get @@ -374,8 +407,15 @@ func (g *Garbager) mInfoCid(ctx context.Context) cid.Cid { return mSt.Info } -func (g *Garbager) createMiner(ctx context.Context) { +func (g *Garbager) createMiner4Data(ctx context.Context) { require.True(g.t, g.maddr4Data == address.Undef, "garbager miner actor already created") + mw := g.createMiner(ctx) + var retval power6.CreateMinerReturn + require.NoError(g.t, retval.UnmarshalCBOR(bytes.NewReader(mw.Receipt.Return))) + g.maddr4Data = retval.IDAddress +} + +func (g *Garbager) createMiner(ctx context.Context) *lapi.MsgLookup { owner, err := g.node.WalletDefaultAddress(ctx) require.NoError(g.t, err) worker := owner @@ -401,8 +441,5 @@ func (g *Garbager) createMiner(ctx context.Context) { mw, err := g.node.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence, lapi.LookbackNoLimit, true) require.NoError(g.t, err) require.True(g.t, mw.Receipt.ExitCode == 0, "garbager's internal create miner message failed") - - var retval power6.CreateMinerReturn - require.NoError(g.t, retval.UnmarshalCBOR(bytes.NewReader(mw.Receipt.Return))) - g.maddr4Data = retval.IDAddress + return mw } diff --git a/itests/wdpost_worker_config_test.go b/itests/wdpost_worker_config_test.go index a84896eae..d1672c20f 100644 --- a/itests/wdpost_worker_config_test.go +++ b/itests/wdpost_worker_config_test.go @@ -17,7 +17,6 @@ import ( "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/impl" "github.com/filecoin-project/lotus/node/modules" - "github.com/filecoin-project/lotus/storage/sealer" "github.com/filecoin-project/lotus/storage/sealer/sealtasks" "github.com/filecoin-project/lotus/storage/sealer/storiface" "github.com/filecoin-project/lotus/storage/wdpost" @@ -35,10 +34,10 @@ func TestWindowPostNoBuiltinWindow(t *testing.T) { kit.PresealSectors(sectors), // 2 sectors per partition, 2 partitions in all 48 deadlines kit.LatestActorsAt(-1), kit.ConstructorOpts( - node.Override(new(sealer.Config), func() sealer.Config { - c := config.DefaultStorageMiner().StorageManager() - c.DisableBuiltinWindowPoSt = true - return c + node.Override(new(config.ProvingConfig), func() config.ProvingConfig { + c := config.DefaultStorageMiner() + c.Proving.DisableBuiltinWindowPoSt = true + return c.Proving }), node.Override(new(*wdpost.WindowPoStScheduler), modules.WindowPostScheduler( config.DefaultStorageMiner().Fees, @@ -92,10 +91,10 @@ func TestWindowPostNoBuiltinWindowWithWorker(t *testing.T) { kit.PresealSectors(sectors), // 2 sectors per partition, 2 partitions in all 48 deadlines kit.LatestActorsAt(-1), kit.ConstructorOpts( - node.Override(new(sealer.Config), func() sealer.Config { - c := config.DefaultStorageMiner().StorageManager() - c.DisableBuiltinWindowPoSt = true - return c + node.Override(new(config.ProvingConfig), func() config.ProvingConfig { + c := config.DefaultStorageMiner() + c.Proving.DisableBuiltinWindowPoSt = true + return c.Proving }), node.Override(new(*wdpost.WindowPoStScheduler), modules.WindowPostScheduler( config.DefaultStorageMiner().Fees, diff --git a/itests/worker_test.go b/itests/worker_test.go index 5b26f481c..2e3722884 100644 --- a/itests/worker_test.go +++ b/itests/worker_test.go @@ -408,10 +408,10 @@ func TestWindowPostWorkerManualPoSt(t *testing.T) { func TestSchedulerRemoveRequest(t *testing.T) { ctx := context.Background() - _, miner, worker, ens := kit.EnsembleWorker(t, kit.WithAllSubsystems(), kit.ThroughRPC(), kit.WithNoLocalSealing(true), + _, miner, worker, _ := kit.EnsembleWorker(t, kit.WithAllSubsystems(), kit.ThroughRPC(), kit.WithNoLocalSealing(true), kit.WithTaskTypes([]sealtasks.TaskType{sealtasks.TTFetch, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTDataCid, sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTCommit2, sealtasks.TTUnseal})) // no mock proofs - ens.InterconnectAll().BeginMining(50 * time.Millisecond) + //ens.InterconnectAll().BeginMining(50 * time.Millisecond) e, err := worker.Enabled(ctx) require.NoError(t, err) diff --git a/lib/consensus/raft/config.go b/lib/consensus/raft/config.go new file mode 100644 index 000000000..983e4cc4d --- /dev/null +++ b/lib/consensus/raft/config.go @@ -0,0 +1,135 @@ +package consensus + +import ( + "io/ioutil" + "path/filepath" + "time" + + hraft "github.com/hashicorp/raft" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/node/config" + "github.com/filecoin-project/lotus/node/repo" +) + +// Configuration defaults +var ( + DefaultDataSubFolder = "raft-cluster" + DefaultWaitForLeaderTimeout = 15 * time.Second + DefaultCommitRetries = 1 + DefaultNetworkTimeout = 100 * time.Second + DefaultCommitRetryDelay = 200 * time.Millisecond + DefaultBackupsRotate = 6 +) + +// ClusterRaftConfig allows to configure the Raft Consensus component for the node cluster. +type ClusterRaftConfig struct { + // config to enabled node cluster with raft consensus + ClusterModeEnabled bool + // A folder to store Raft's data. + DataFolder string + // InitPeerset provides the list of initial cluster peers for new Raft + // peers (with no prior state). It is ignored when Raft was already + // initialized or when starting in staging mode. + InitPeerset []string + // LeaderTimeout specifies how long to wait for a leader before + // failing an operation. + WaitForLeaderTimeout time.Duration + // NetworkTimeout specifies how long before a Raft network + // operation is timed out + NetworkTimeout time.Duration + // CommitRetries specifies how many times we retry a failed commit until + // we give up. + CommitRetries int + // How long to wait between retries + CommitRetryDelay time.Duration + // BackupsRotate specifies the maximum number of Raft's DataFolder + // copies that we keep as backups (renaming) after cleanup. + BackupsRotate int + // A Hashicorp Raft's configuration object. + RaftConfig *hraft.Config + + // Tracing enables propagation of contexts across binary boundaries. + Tracing bool +} + +func DefaultClusterRaftConfig() *ClusterRaftConfig { + var cfg ClusterRaftConfig + cfg.DataFolder = "" // empty so it gets omitted + cfg.InitPeerset = []string{} + cfg.WaitForLeaderTimeout = DefaultWaitForLeaderTimeout + cfg.NetworkTimeout = DefaultNetworkTimeout + cfg.CommitRetries = DefaultCommitRetries + cfg.CommitRetryDelay = DefaultCommitRetryDelay + cfg.BackupsRotate = DefaultBackupsRotate + cfg.RaftConfig = hraft.DefaultConfig() + + // These options are imposed over any Default Raft Config. + cfg.RaftConfig.ShutdownOnRemove = false + cfg.RaftConfig.LocalID = "will_be_set_automatically" + + // Set up logging + cfg.RaftConfig.LogOutput = ioutil.Discard + return &cfg +} + +func NewClusterRaftConfig(userRaftConfig *config.UserRaftConfig) *ClusterRaftConfig { + var cfg ClusterRaftConfig + cfg.DataFolder = userRaftConfig.DataFolder + cfg.InitPeerset = userRaftConfig.InitPeersetMultiAddr + cfg.WaitForLeaderTimeout = time.Duration(userRaftConfig.WaitForLeaderTimeout) + cfg.NetworkTimeout = time.Duration(userRaftConfig.NetworkTimeout) + cfg.CommitRetries = userRaftConfig.CommitRetries + cfg.CommitRetryDelay = time.Duration(userRaftConfig.CommitRetryDelay) + cfg.BackupsRotate = userRaftConfig.BackupsRotate + + // Keep this to be default hraft config for now + cfg.RaftConfig = hraft.DefaultConfig() + + // These options are imposed over any Default Raft Config. + cfg.RaftConfig.ShutdownOnRemove = false + cfg.RaftConfig.LocalID = "will_be_set_automatically" + + // Set up logging + cfg.RaftConfig.LogOutput = ioutil.Discard + + return &cfg + +} + +// // Validate checks that this configuration has working values, +// // at least in appearance. +func ValidateConfig(cfg *ClusterRaftConfig) error { + if cfg.RaftConfig == nil { + return xerrors.Errorf("no hashicorp/raft.Config") + } + if cfg.WaitForLeaderTimeout <= 0 { + return xerrors.Errorf("wait_for_leader_timeout <= 0") + } + + if cfg.NetworkTimeout <= 0 { + return xerrors.Errorf("network_timeout <= 0") + } + + if cfg.CommitRetries < 0 { + return xerrors.Errorf("commit_retries is invalid") + } + + if cfg.CommitRetryDelay <= 0 { + return xerrors.Errorf("commit_retry_delay is invalid") + } + + if cfg.BackupsRotate <= 0 { + return xerrors.Errorf("backups_rotate should be larger than 0") + } + + return hraft.ValidateConfig(cfg.RaftConfig) +} + +// GetDataFolder returns the Raft data folder that we are using. +func (cfg *ClusterRaftConfig) GetDataFolder(repo repo.LockedRepo) string { + if cfg.DataFolder == "" { + return filepath.Join(repo.Path(), DefaultDataSubFolder) + } + return filepath.Join(repo.Path(), cfg.DataFolder) +} diff --git a/lib/consensus/raft/consensus.go b/lib/consensus/raft/consensus.go new file mode 100644 index 000000000..085f94c72 --- /dev/null +++ b/lib/consensus/raft/consensus.go @@ -0,0 +1,506 @@ +// Package raft implements a Consensus component for IPFS Cluster which uses +// Raft (go-libp2p-raft). +package consensus + +import ( + "bytes" + "context" + "errors" + "fmt" + "sort" + "time" + + "github.com/google/uuid" + "golang.org/x/exp/slices" + + addr "github.com/filecoin-project/go-address" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/messagepool" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/lib/addrutil" + "github.com/filecoin-project/lotus/node/repo" + + //ds "github.com/ipfs/go-datastore" + logging "github.com/ipfs/go-log/v2" + consensus "github.com/libp2p/go-libp2p-consensus" + rpc "github.com/libp2p/go-libp2p-gorpc" + libp2praft "github.com/libp2p/go-libp2p-raft" + host "github.com/libp2p/go-libp2p/core/host" + peer "github.com/libp2p/go-libp2p/core/peer" +) + +var logger = logging.Logger("raft") + +type RaftState struct { + NonceMap api.NonceMapType + MsgUuids api.MsgUuidMapType + + // TODO: add comment explaining why this is needed + // We need a reference to the messagepool in the raft state in order to + // sync messages that have been sent by the leader node + // Miner calls StateWaitMsg after MpoolPushMessage to check if the message has + // landed on chain. This check requires the message be stored in the local chainstore + // If a leadernode goes down after sending a message to the chain and is replaced by + // another node, the other node needs to have this message in its chainstore for the + // above check to succeed. + + // This is because the miner only stores signed CIDs but the message received from in a + // block will be unsigned (for BLS). Hence, the process relies on the node to store the + // signed message which holds a copy of the unsigned message to properly perform all the + // needed checks + Mpool *messagepool.MessagePool +} + +func newRaftState(mpool *messagepool.MessagePool) *RaftState { + return &RaftState{ + NonceMap: make(map[addr.Address]uint64), + MsgUuids: make(map[uuid.UUID]*types.SignedMessage), + Mpool: mpool, + } +} + +type ConsensusOp struct { + Nonce uint64 `codec:"nonce,omitempty"` + Uuid uuid.UUID `codec:"uuid,omitempty"` + Addr addr.Address `codec:"addr,omitempty"` + SignedMsg *types.SignedMessage `codec:"signedMsg,omitempty"` +} + +func (c ConsensusOp) ApplyTo(state consensus.State) (consensus.State, error) { + s := state.(*RaftState) + s.NonceMap[c.Addr] = c.Nonce + if c.SignedMsg != nil { + + // Deep copy to tmp + var buffer bytes.Buffer + err := c.SignedMsg.MarshalCBOR(&buffer) + if err != nil { + return nil, err + } + tmp, err := types.DecodeSignedMessage(buffer.Bytes()) + if err != nil { + return nil, err + } + s.MsgUuids[c.Uuid] = tmp + + _, err = s.Mpool.Push(context.TODO(), tmp, false) + // Since this is only meant to keep messages in sync, ignore any error which + // shows the message already exists in the mpool + if err != nil && !api.ErrorIsIn(err, []error{messagepool.ErrExistingNonce}) { + return nil, err + } + } + + return s, nil +} + +var _ consensus.Op = &ConsensusOp{} + +// Consensus handles the work of keeping a shared-state between +// the peers of a Lotus Cluster, as well as modifying that state and +// applying any updates in a thread-safe manner. +type Consensus struct { + ctx context.Context + cancel func() + config *ClusterRaftConfig + + host host.Host + + consensus consensus.OpLogConsensus + actor consensus.Actor + raft *raftWrapper + state *RaftState + + RpcClient *rpc.Client + rpcReady chan struct{} + readyCh chan struct{} + + peerSet []peer.ID + repo repo.LockedRepo +} + +// NewConsensus builds a new ClusterConsensus component using Raft. +// +// Raft saves state snapshots regularly and persists log data in a bolt +// datastore. Therefore, unless memory usage is a concern, it is recommended +// to use an in-memory go-datastore as store parameter. +// +// The staging parameter controls if the Raft peer should start in +// staging mode (used when joining a new Raft peerset with other peers). +func NewConsensus(host host.Host, cfg *ClusterRaftConfig, mpool *messagepool.MessagePool, repo repo.LockedRepo, staging bool) (*Consensus, error) { + err := ValidateConfig(cfg) + if err != nil { + return nil, err + } + + ctx, cancel := context.WithCancel(context.Background()) + + logger.Debug("starting Consensus and waiting for a leader...") + state := newRaftState(mpool) + + consensus := libp2praft.NewOpLog(state, &ConsensusOp{}) + + raft, err := newRaftWrapper(host, cfg, consensus.FSM(), repo, staging) + if err != nil { + logger.Error("error creating raft: ", err) + cancel() + return nil, err + } + actor := libp2praft.NewActor(raft.raft) + consensus.SetActor(actor) + + peers := []peer.ID{} + addrInfos, err := addrutil.ParseAddresses(ctx, cfg.InitPeerset) + for _, addrInfo := range addrInfos { + peers = append(peers, addrInfo.ID) + + // Add peer to address book + host.Peerstore().AddAddrs(addrInfo.ID, addrInfo.Addrs, time.Hour*100) + } + + cc := &Consensus{ + ctx: ctx, + cancel: cancel, + config: cfg, + host: host, + consensus: consensus, + actor: actor, + state: state, + raft: raft, + peerSet: peers, + rpcReady: make(chan struct{}, 1), + readyCh: make(chan struct{}, 1), + repo: repo, + } + + go cc.finishBootstrap() + return cc, nil + +} + +// TODO: Merge with NewConsensus and remove the rpcReady chan +func NewConsensusWithRPCClient(staging bool) func(host host.Host, + cfg *ClusterRaftConfig, + rpcClient *rpc.Client, + mpool *messagepool.MessagePool, + repo repo.LockedRepo, +) (*Consensus, error) { + + return func(host host.Host, cfg *ClusterRaftConfig, rpcClient *rpc.Client, mpool *messagepool.MessagePool, repo repo.LockedRepo) (*Consensus, error) { + cc, err := NewConsensus(host, cfg, mpool, repo, staging) + if err != nil { + return nil, err + } + cc.RpcClient = rpcClient + cc.rpcReady <- struct{}{} + return cc, nil + } +} + +// WaitForSync waits for a leader and for the state to be up to date, then returns. +func (cc *Consensus) WaitForSync(ctx context.Context) error { + + leaderCtx, cancel := context.WithTimeout(ctx, cc.config.WaitForLeaderTimeout) + defer cancel() + + // 1 - wait for leader + // 2 - wait until we are a Voter + // 3 - wait until last index is applied + + // From raft docs: + + // once a staging server receives enough log entries to be sufficiently + // caught up to the leader's log, the leader will invoke a membership + // change to change the Staging server to a Voter + + // Thus, waiting to be a Voter is a guarantee that we have a reasonable + // up to date state. Otherwise, we might return too early (see + // https://github.com/ipfs-cluster/ipfs-cluster/issues/378) + + _, err := cc.raft.WaitForLeader(leaderCtx) + if err != nil { + return errors.New("error waiting for leader: " + err.Error()) + } + + err = cc.raft.WaitForVoter(ctx) + if err != nil { + return errors.New("error waiting to become a Voter: " + err.Error()) + } + + err = cc.raft.WaitForUpdates(ctx) + if err != nil { + return errors.New("error waiting for consensus updates: " + err.Error()) + } + return nil +} + +// waits until there is a consensus leader and syncs the state +// to the tracker. If errors happen, this will return and never +// signal the component as Ready. +func (cc *Consensus) finishBootstrap() { + // wait until we have RPC to perform any actions. + select { + case <-cc.ctx.Done(): + return + case <-cc.rpcReady: + } + + // Sometimes bootstrap is a no-Op. It only applies when + // no state exists and staging=false. + _, err := cc.raft.Bootstrap() + if err != nil { + return + } + + logger.Debugf("Bootstrap finished") + err = cc.WaitForSync(cc.ctx) + if err != nil { + return + } + logger.Debug("Raft state is now up to date") + logger.Debug("consensus ready") + cc.readyCh <- struct{}{} +} + +// Shutdown stops the component so it will not process any +// more updates. The underlying consensus is permanently +// shutdown, along with the libp2p transport. +func (cc *Consensus) Shutdown(ctx context.Context) error { + + logger.Info("stopping Consensus component") + + // Raft Shutdown + err := cc.raft.Shutdown(ctx) + if err != nil { + logger.Error(err) + } + + cc.cancel() + close(cc.rpcReady) + return nil +} + +// Ready returns a channel which is signaled when the Consensus +// algorithm has finished bootstrapping and is ready to use +func (cc *Consensus) Ready(ctx context.Context) <-chan struct{} { + return cc.readyCh +} + +// IsTrustedPeer returns true. In Raft we trust all peers. +func (cc *Consensus) IsTrustedPeer(ctx context.Context, p peer.ID) bool { + return slices.Contains(cc.peerSet, p) +} + +// Trust is a no-Op. +func (cc *Consensus) Trust(ctx context.Context, pid peer.ID) error { return nil } + +// Distrust is a no-Op. +func (cc *Consensus) Distrust(ctx context.Context, pid peer.ID) error { return nil } + +// returns true if the operation was redirected to the leader +// note that if the leader just dissappeared, the rpc call will +// fail because we haven't heard that it's gone. +func (cc *Consensus) RedirectToLeader(method string, arg interface{}, ret interface{}) (bool, error) { + ctx := cc.ctx + + var finalErr error + + // Retry redirects + for i := 0; i <= cc.config.CommitRetries; i++ { + logger.Debugf("redirect try %d", i) + leader, err := cc.Leader(ctx) + + // No leader, wait for one + if err != nil { + logger.Warn("there seems to be no leader. Waiting for one") + rctx, cancel := context.WithTimeout(ctx, cc.config.WaitForLeaderTimeout) + defer cancel() + pidstr, err := cc.raft.WaitForLeader(rctx) + + // means we timed out waiting for a leader + // we don't retry in this case + if err != nil { + return false, fmt.Errorf("timed out waiting for leader: %s", err) + } + leader, err = peer.Decode(pidstr) + if err != nil { + return false, err + } + } + + logger.Infof("leader: %s, curr host: %s, peerSet: %s", leader, cc.host.ID(), cc.peerSet) + + // We are the leader. Do not redirect + if leader == cc.host.ID() { + return false, nil + } + + logger.Debugf("redirecting %s to leader: %s", method, leader.Pretty()) + finalErr = cc.RpcClient.CallContext( + ctx, + leader, + "Consensus", + method, + arg, + ret, + ) + if finalErr != nil { + logger.Errorf("retrying to redirect request to leader: %s", finalErr) + time.Sleep(2 * cc.config.RaftConfig.HeartbeatTimeout) + continue + } + break + } + + // We tried to redirect, but something happened + return true, finalErr +} + +// commit submits a cc.consensus commit. It retries upon failures. +func (cc *Consensus) Commit(ctx context.Context, op *ConsensusOp) error { + + var finalErr error + for i := 0; i <= cc.config.CommitRetries; i++ { + logger.Debugf("attempt #%d: committing %+v", i, op) + + // this means we are retrying + if finalErr != nil { + logger.Errorf("retrying upon failed commit (retry %d): %s ", + i, finalErr) + } + + // Being here means we are the LEADER. We can commit. + // now commit the changes to our state + _, finalErr = cc.consensus.CommitOp(op) + if finalErr != nil { + goto RETRY + } + + RETRY: + time.Sleep(cc.config.CommitRetryDelay) + } + return finalErr +} + +// AddPeer adds a new peer to participate in this consensus. It will +// forward the operation to the leader if this is not it. +func (cc *Consensus) AddPeer(ctx context.Context, pid peer.ID) error { + var finalErr error + for i := 0; i <= cc.config.CommitRetries; i++ { + logger.Debugf("attempt #%d: AddPeer %s", i, pid.Pretty()) + if finalErr != nil { + logger.Errorf("retrying to add peer. Attempt #%d failed: %s", i, finalErr) + } + ok, err := cc.RedirectToLeader("AddPeer", pid, struct{}{}) + if err != nil || ok { + return err + } + // Being here means we are the leader and can commit + finalErr = cc.raft.AddPeer(ctx, pid) + if finalErr != nil { + time.Sleep(cc.config.CommitRetryDelay) + continue + } + logger.Infof("peer added to Raft: %s", pid.Pretty()) + break + } + return finalErr +} + +// RmPeer removes a peer from this consensus. It will +// forward the operation to the leader if this is not it. +func (cc *Consensus) RmPeer(ctx context.Context, pid peer.ID) error { + var finalErr error + for i := 0; i <= cc.config.CommitRetries; i++ { + logger.Debugf("attempt #%d: RmPeer %s", i, pid.Pretty()) + if finalErr != nil { + logger.Errorf("retrying to remove peer. Attempt #%d failed: %s", i, finalErr) + } + ok, err := cc.RedirectToLeader("RmPeer", pid, struct{}{}) + if err != nil || ok { + return err + } + // Being here means we are the leader and can commit + finalErr = cc.raft.RemovePeer(ctx, peer.Encode(pid)) + if finalErr != nil { + time.Sleep(cc.config.CommitRetryDelay) + continue + } + logger.Infof("peer removed from Raft: %s", pid.Pretty()) + break + } + return finalErr +} + +// RaftState retrieves the current consensus RaftState. It may error if no RaftState has +// been agreed upon or the state is not consistent. The returned RaftState is the +// last agreed-upon RaftState known by this node. No writes are allowed, as all +// writes to the shared state should happen through the Consensus component +// methods. +func (cc *Consensus) State(ctx context.Context) (*RaftState, error) { + st, err := cc.consensus.GetLogHead() + if err == libp2praft.ErrNoState { + return newRaftState(nil), nil + } + + if err != nil { + return nil, err + } + state, ok := st.(*RaftState) + if !ok { + return nil, errors.New("wrong state type") + } + return state, nil +} + +// Leader returns the peerID of the Leader of the +// cluster. It returns an error when there is no leader. +func (cc *Consensus) Leader(ctx context.Context) (peer.ID, error) { + // Note the hard-dependency on raft here... + raftactor := cc.actor.(*libp2praft.Actor) + return raftactor.Leader() +} + +// Clean removes the Raft persisted state. +func (cc *Consensus) Clean(ctx context.Context) error { + //return CleanupRaft(cc.config) + return nil +} + +//Rollback replaces the current agreed-upon +//state with the state provided. Only the consensus leader +//can perform this operation. +//func (cc *Consensus) Rollback(state RaftState) error { +// // This is unused. It *might* be used for upgrades. +// // There is rather untested magic in libp2p-raft's FSM() +// // to make this possible. +// return cc.consensus.Rollback(state) +//} + +// Peers return the current list of peers in the consensus. +// The list will be sorted alphabetically. +func (cc *Consensus) Peers(ctx context.Context) ([]peer.ID, error) { + + peers := []peer.ID{} + raftPeers, err := cc.raft.Peers(ctx) + if err != nil { + return nil, fmt.Errorf("cannot retrieve list of peers: %s", err) + } + + sort.Strings(raftPeers) + + for _, p := range raftPeers { + id, err := peer.Decode(p) + if err != nil { + panic("could not decode peer") + } + peers = append(peers, id) + } + return peers, nil +} + +func (cc *Consensus) IsLeader(ctx context.Context) bool { + leader, _ := cc.Leader(ctx) + return leader == cc.host.ID() +} diff --git a/lib/consensus/raft/interfaces.go b/lib/consensus/raft/interfaces.go new file mode 100644 index 000000000..2b77d1ebe --- /dev/null +++ b/lib/consensus/raft/interfaces.go @@ -0,0 +1,41 @@ +package consensus + +import ( + "context" + + consensus "github.com/libp2p/go-libp2p-consensus" + "github.com/libp2p/go-libp2p/core/peer" +) + +type ConsensusAPI interface { + // Returns a channel to signal that the consensus layer is ready + // allowing the main component to wait for it during start. + Ready(context.Context) <-chan struct{} + + AddPeer(context.Context, peer.ID) error + RmPeer(context.Context, peer.ID) error + State(context.Context) (consensus.State, error) + // Provide a node which is responsible to perform + // specific tasks which must only run in 1 cluster peer. + Leader(context.Context) (peer.ID, error) + // Only returns when the consensus state has all log + // updates applied to it. + WaitForSync(context.Context) error + // Clean removes all consensus data. + Clean(context.Context) error + // Peers returns the peerset participating in the Consensus. + Peers(context.Context) ([]peer.ID, error) + // IsTrustedPeer returns true if the given peer is "trusted". + // This will grant access to more rpc endpoints and a + // non-trusted one. This should be fast as it will be + // called repeatedly for every remote RPC request. + IsTrustedPeer(context.Context, peer.ID) bool + // Trust marks a peer as "trusted". + Trust(context.Context, peer.ID) error + // Distrust removes a peer from the "trusted" set. + Distrust(context.Context, peer.ID) error + // Returns true if current node is the cluster leader + IsLeader(ctx context.Context) bool + + Shutdown(context.Context) error +} diff --git a/lib/consensus/raft/raft.go b/lib/consensus/raft/raft.go new file mode 100644 index 000000000..76c23a6d1 --- /dev/null +++ b/lib/consensus/raft/raft.go @@ -0,0 +1,592 @@ +package consensus + +import ( + "context" + "errors" + "fmt" + "os" + "path/filepath" + "time" + + hraft "github.com/hashicorp/raft" + raftboltdb "github.com/hashicorp/raft-boltdb" + "github.com/ipfs/go-log/v2" + p2praft "github.com/libp2p/go-libp2p-raft" + host "github.com/libp2p/go-libp2p/core/host" + peer "github.com/libp2p/go-libp2p/core/peer" + "go.uber.org/multierr" + "go.uber.org/zap" + + "github.com/filecoin-project/lotus/lib/addrutil" + "github.com/filecoin-project/lotus/node/repo" +) + +var raftLogger = log.Logger("raft-cluster") + +// ErrWaitingForSelf is returned when we are waiting for ourselves to depart +// the peer set, which won't happen +var errWaitingForSelf = errors.New("waiting for ourselves to depart") + +// RaftMaxSnapshots indicates how many snapshots to keep in the consensus data +// folder. +// TODO: Maybe include this in Config. Not sure how useful it is to touch +// this anyways. +var RaftMaxSnapshots = 5 + +// RaftLogCacheSize is the maximum number of logs to cache in-memory. +// This is used to reduce disk I/O for the recently committed entries. +var RaftLogCacheSize = 512 + +// How long we wait for updates during shutdown before snapshotting +var waitForUpdatesShutdownTimeout = 5 * time.Second +var waitForUpdatesInterval = 400 * time.Millisecond + +// How many times to retry snapshotting when shutting down +var maxShutdownSnapshotRetries = 5 + +// raftWrapper wraps the hraft.Raft object and related things like the +// different stores used or the hraft.Configuration. +// Its methods provide functionality for working with Raft. +type raftWrapper struct { + ctx context.Context + cancel context.CancelFunc + raft *hraft.Raft + config *ClusterRaftConfig + host host.Host + serverConfig hraft.Configuration + transport *hraft.NetworkTransport + snapshotStore hraft.SnapshotStore + logStore hraft.LogStore + stableStore hraft.StableStore + boltdb *raftboltdb.BoltStore + repo repo.LockedRepo + staging bool +} + +// newRaftWrapper creates a Raft instance and initializes +// everything leaving it ready to use. Note, that Bootstrap() should be called +// to make sure the raft instance is usable. +func newRaftWrapper( + host host.Host, + cfg *ClusterRaftConfig, + fsm hraft.FSM, + repo repo.LockedRepo, + staging bool, +) (*raftWrapper, error) { + + raftW := &raftWrapper{} + raftW.config = cfg + raftW.host = host + raftW.staging = staging + raftW.repo = repo + // Set correct LocalID + cfg.RaftConfig.LocalID = hraft.ServerID(peer.Encode(host.ID())) + + df := cfg.GetDataFolder(repo) + err := makeDataFolder(df) + if err != nil { + return nil, err + } + + err = raftW.makeServerConfig() + if err != nil { + return nil, err + } + + err = raftW.makeTransport() + if err != nil { + return nil, err + } + + err = raftW.makeStores() + if err != nil { + return nil, err + } + + raftLogger.Debug("creating Raft") + raftW.raft, err = hraft.NewRaft( + cfg.RaftConfig, + fsm, + raftW.logStore, + raftW.stableStore, + raftW.snapshotStore, + raftW.transport, + ) + if err != nil { + raftLogger.Error("initializing raft: ", err) + return nil, err + } + + raftW.ctx, raftW.cancel = context.WithCancel(context.Background()) + + return raftW, nil +} + +// makeDataFolder creates the folder that is meant to store Raft data. Ensures +// we always set 0700 mode. +func makeDataFolder(folder string) error { + return os.MkdirAll(folder, 0700) +} + +func (rw *raftWrapper) makeTransport() (err error) { + raftLogger.Debug("creating libp2p Raft transport") + rw.transport, err = p2praft.NewLibp2pTransport( + rw.host, + rw.config.NetworkTimeout, + ) + return err +} + +func (rw *raftWrapper) makeStores() error { + raftLogger.Debug("creating BoltDB store") + df := rw.config.GetDataFolder(rw.repo) + store, err := raftboltdb.NewBoltStore(filepath.Join(df, "raft.db")) + if err != nil { + return err + } + + // wraps the store in a LogCache to improve performance. + // See consul/agent/consul/server.go + cacheStore, err := hraft.NewLogCache(RaftLogCacheSize, store) + if err != nil { + return err + } + + raftLogger.Debug("creating raft snapshot store") + snapstore, err := hraft.NewFileSnapshotStoreWithLogger( + df, + RaftMaxSnapshots, + zap.NewStdLog(log.Logger("raft-snapshot").SugaredLogger.Desugar()), + ) + if err != nil { + return err + } + + rw.logStore = cacheStore + rw.stableStore = store + rw.snapshotStore = snapstore + rw.boltdb = store + return nil +} + +// Bootstrap calls BootstrapCluster on the Raft instance with a valid +// Configuration (generated from InitPeerset) when Raft has no state +// and we are not setting up a staging peer. It returns if Raft +// was boostrapped (true) and an error. +func (rw *raftWrapper) Bootstrap() (bool, error) { + logger.Debug("checking for existing raft states") + hasState, err := hraft.HasExistingState( + rw.logStore, + rw.stableStore, + rw.snapshotStore, + ) + if err != nil { + return false, err + } + + if hasState { + logger.Debug("raft cluster is already initialized") + + // Inform the user that we are working with a pre-existing peerset + logger.Info("existing Raft state found! raft.InitPeerset will be ignored") + cf := rw.raft.GetConfiguration() + if err := cf.Error(); err != nil { + logger.Debug(err) + return false, err + } + currentCfg := cf.Configuration() + srvs := "" + for _, s := range currentCfg.Servers { + srvs += fmt.Sprintf(" %s\n", s.ID) + } + + logger.Debugf("Current Raft Peerset:\n%s\n", srvs) + return false, nil + } + + if rw.staging { + logger.Debug("staging servers do not need initialization") + logger.Info("peer is ready to join a cluster") + return false, nil + } + + voters := "" + for _, s := range rw.serverConfig.Servers { + voters += fmt.Sprintf(" %s\n", s.ID) + } + + logger.Infof("initializing raft cluster with the following voters:\n%s\n", voters) + + future := rw.raft.BootstrapCluster(rw.serverConfig) + if err := future.Error(); err != nil { + logger.Error("bootstrapping cluster: ", err) + return true, err + } + return true, nil +} + +// create Raft servers configuration. The result is used +// by Bootstrap() when it proceeds to Bootstrap. +func (rw *raftWrapper) makeServerConfig() error { + peers := []peer.ID{} + addrInfos, err := addrutil.ParseAddresses(context.Background(), rw.config.InitPeerset) + if err != nil { + return err + } + for _, addrInfo := range addrInfos { + peers = append(peers, addrInfo.ID) + } + rw.serverConfig = makeServerConf(append(peers, rw.host.ID())) + return nil +} + +// creates a server configuration with all peers as Voters. +func makeServerConf(peers []peer.ID) hraft.Configuration { + sm := make(map[string]struct{}) + + servers := make([]hraft.Server, 0) + + // Servers are peers + self. We avoid duplicate entries below + for _, pid := range peers { + p := peer.Encode(pid) + _, ok := sm[p] + if !ok { // avoid dups + sm[p] = struct{}{} + servers = append(servers, hraft.Server{ + Suffrage: hraft.Voter, + ID: hraft.ServerID(p), + Address: hraft.ServerAddress(p), + }) + } + } + return hraft.Configuration{Servers: servers} +} + +// WaitForLeader holds until Raft says we have a leader. +// Returns if ctx is canceled. +func (rw *raftWrapper) WaitForLeader(ctx context.Context) (string, error) { + ticker := time.NewTicker(time.Second / 2) + for { + select { + case <-ticker.C: + if l := rw.raft.Leader(); l != "" { + logger.Debug("waitForleaderTimer") + logger.Infof("Current Raft Leader: %s", l) + ticker.Stop() + return string(l), nil + } + case <-ctx.Done(): + return "", ctx.Err() + } + } +} + +func (rw *raftWrapper) WaitForVoter(ctx context.Context) error { + logger.Debug("waiting until we are promoted to a voter") + + pid := hraft.ServerID(peer.Encode(rw.host.ID())) + for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + logger.Debugf("%s: get configuration", pid) + configFuture := rw.raft.GetConfiguration() + if err := configFuture.Error(); err != nil { + return err + } + + if isVoter(pid, configFuture.Configuration()) { + return nil + } + logger.Debugf("%s: not voter yet", pid) + + time.Sleep(waitForUpdatesInterval) + } + } +} + +func isVoter(srvID hraft.ServerID, cfg hraft.Configuration) bool { + for _, server := range cfg.Servers { + if server.ID == srvID && server.Suffrage == hraft.Voter { + return true + } + } + return false +} + +// WaitForUpdates holds until Raft has synced to the last index in the log +func (rw *raftWrapper) WaitForUpdates(ctx context.Context) error { + + logger.Debug("Raft state is catching up to the latest known version. Please wait...") + for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + lai := rw.raft.AppliedIndex() + li := rw.raft.LastIndex() + logger.Debugf("current Raft index: %d/%d", + lai, li) + if lai == li { + return nil + } + time.Sleep(waitForUpdatesInterval) + } + } +} + +func (rw *raftWrapper) WaitForPeer(ctx context.Context, pid string, depart bool) error { + + for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + peers, err := rw.Peers(ctx) + if err != nil { + return err + } + + if len(peers) == 1 && pid == peers[0] && depart { + return errWaitingForSelf + } + + found := find(peers, pid) + + // departing + if depart && !found { + return nil + } + + // joining + if !depart && found { + return nil + } + + time.Sleep(50 * time.Millisecond) + } + } +} + +// Snapshot tells Raft to take a snapshot. +func (rw *raftWrapper) Snapshot() error { + future := rw.raft.Snapshot() + err := future.Error() + if err != nil && err.Error() != hraft.ErrNothingNewToSnapshot.Error() { + return err + } + return nil +} + +// snapshotOnShutdown attempts to take a snapshot before a shutdown. +// Snapshotting might fail if the raft applied index is not the last index. +// This waits for the updates and tries to take a snapshot when the +// applied index is up to date. +// It will retry if the snapshot still fails, in case more updates have arrived. +// If waiting for updates times-out, it will not try anymore, since something +// is wrong. This is a best-effort solution as there is no way to tell Raft +// to stop processing entries because we want to take a snapshot before +// shutting down. +func (rw *raftWrapper) snapshotOnShutdown() error { + var err error + for i := 0; i < maxShutdownSnapshotRetries; i++ { + ctx, cancel := context.WithTimeout(context.Background(), waitForUpdatesShutdownTimeout) + err = rw.WaitForUpdates(ctx) + cancel() + if err != nil { + logger.Warn("timed out waiting for state updates before shutdown. Snapshotting may fail") + return rw.Snapshot() + } + + err = rw.Snapshot() + if err == nil { + return nil // things worked + } + + // There was an error + err = errors.New("could not snapshot raft: " + err.Error()) + logger.Warnf("retrying to snapshot (%d/%d)...", i+1, maxShutdownSnapshotRetries) + } + return err +} + +// Shutdown shutdown Raft and closes the BoltDB. +func (rw *raftWrapper) Shutdown(ctx context.Context) error { + + rw.cancel() + + var finalErr error + + err := rw.snapshotOnShutdown() + if err != nil { + finalErr = multierr.Append(finalErr, err) + } + + future := rw.raft.Shutdown() + err = future.Error() + if err != nil { + finalErr = multierr.Append(finalErr, err) + } + + err = rw.boltdb.Close() // important! + if err != nil { + finalErr = multierr.Append(finalErr, err) + } + + return finalErr +} + +// AddPeer adds a peer to Raft +func (rw *raftWrapper) AddPeer(ctx context.Context, peerId peer.ID) error { + + // Check that we don't have it to not waste + // log entries if so. + peers, err := rw.Peers(ctx) + if err != nil { + return err + } + if find(peers, peerId.String()) { + logger.Infof("%s is already a raft peerStr", peerId.String()) + return nil + } + + err = rw.host.Connect(ctx, peer.AddrInfo{ID: peerId}) + if err != nil { + return err + } + + future := rw.raft.AddVoter( + hraft.ServerID(peerId.String()), + hraft.ServerAddress(peerId.String()), + 0, + 0, + ) // TODO: Extra cfg value? + err = future.Error() + if err != nil { + logger.Error("raft cannot add peer: ", err) + } + return err +} + +// RemovePeer removes a peer from Raft +func (rw *raftWrapper) RemovePeer(ctx context.Context, peer string) error { + // Check that we have it to not waste + // log entries if we don't. + peers, err := rw.Peers(ctx) + if err != nil { + return err + } + if !find(peers, peer) { + logger.Infof("%s is not among raft peers", peer) + return nil + } + + if len(peers) == 1 && peers[0] == peer { + return errors.New("cannot remove ourselves from a 1-peer cluster") + } + + rmFuture := rw.raft.RemoveServer( + hraft.ServerID(peer), + 0, + 0, + ) + err = rmFuture.Error() + if err != nil { + logger.Error("raft cannot remove peer: ", err) + return err + } + + return nil +} + +// Leader returns Raft's leader. It may be an empty string if +// there is no leader or it is unknown. +func (rw *raftWrapper) Leader(ctx context.Context) string { + return string(rw.raft.Leader()) +} + +func (rw *raftWrapper) Peers(ctx context.Context) ([]string, error) { + ids := make([]string, 0) + + configFuture := rw.raft.GetConfiguration() + if err := configFuture.Error(); err != nil { + return nil, err + } + + for _, server := range configFuture.Configuration().Servers { + ids = append(ids, string(server.ID)) + } + + return ids, nil +} + +// CleanupRaft moves the current data folder to a backup location +//func CleanupRaft(cfg *Config) error { +// dataFolder := cfg.GetDataFolder() +// keep := cfg.BackupsRotate +// +// meta, _, err := latestSnapshot(dataFolder) +// if meta == nil && err == nil { +// // no snapshots at all. Avoid creating backups +// // from empty state folders. +// logger.Infof("cleaning empty Raft data folder (%s)", dataFolder) +// os.RemoveAll(dataFolder) +// return nil +// } +// +// logger.Infof("cleaning and backing up Raft data folder (%s)", dataFolder) +// dbh := newDataBackupHelper(dataFolder, keep) +// err = dbh.makeBackup() +// if err != nil { +// logger.Warn(err) +// logger.Warn("the state could not be cleaned properly") +// logger.Warn("manual intervention may be needed before starting cluster again") +// } +// return nil +//} + +// only call when Raft is shutdown +func (rw *raftWrapper) Clean() error { + //return CleanupRaft(rw.config) + return nil +} + +func find(s []string, elem string) bool { + for _, selem := range s { + if selem == elem { + return true + } + } + return false +} + +func (rw *raftWrapper) observePeers() { + obsCh := make(chan hraft.Observation, 1) + defer close(obsCh) + + observer := hraft.NewObserver(obsCh, true, func(o *hraft.Observation) bool { + po, ok := o.Data.(hraft.PeerObservation) + return ok && po.Removed + }) + + rw.raft.RegisterObserver(observer) + defer rw.raft.DeregisterObserver(observer) + + for { + select { + case obs := <-obsCh: + pObs := obs.Data.(hraft.PeerObservation) + logger.Info("raft peer departed. Removing from peerstore: ", pObs.Peer.ID) + pID, err := peer.Decode(string(pObs.Peer.ID)) + if err != nil { + logger.Error(err) + continue + } + rw.host.Peerstore().ClearAddrs(pID) + case <-rw.ctx.Done(): + logger.Debug("stopped observing raft peers") + return + } + } +} diff --git a/lib/result/result.go b/lib/result/result.go new file mode 100644 index 000000000..bec839d7a --- /dev/null +++ b/lib/result/result.go @@ -0,0 +1,35 @@ +package result + +// Result is a small wrapper type encapsulating Value/Error tuples, mostly for +// use when sending values across channels +// NOTE: Avoid adding any functionality to this, any "nice" things added here will +// make it more difficult to switch to a more standardised Result-like type when +// one gets into the stdlib, or when we will want to switch to a library providing +// those types. +type Result[T any] struct { + Value T + Error error +} + +func Ok[T any](value T) Result[T] { + return Result[T]{ + Value: value, + } +} + +func Err[T any](err error) Result[T] { + return Result[T]{ + Error: err, + } +} + +func Wrap[T any](value T, err error) Result[T] { + return Result[T]{ + Value: value, + Error: err, + } +} + +func (r *Result[T]) Unwrap() (T, error) { + return r.Value, r.Error +} diff --git a/lib/retry/retry.go b/lib/retry/retry.go index e69d1ef35..897dbb06c 100644 --- a/lib/retry/retry.go +++ b/lib/retry/retry.go @@ -1,6 +1,7 @@ package retry import ( + "context" "time" logging "github.com/ipfs/go-log/v2" @@ -10,7 +11,7 @@ import ( var log = logging.Logger("retry") -func Retry[T any](attempts int, initialBackoff time.Duration, errorTypes []error, f func() (T, error)) (result T, err error) { +func Retry[T any](ctx context.Context, attempts int, initialBackoff time.Duration, errorTypes []error, f func() (T, error)) (result T, err error) { for i := 0; i < attempts; i++ { if i > 0 { log.Info("Retrying after error:", err) @@ -21,6 +22,9 @@ func Retry[T any](attempts int, initialBackoff time.Duration, errorTypes []error if err == nil || !api.ErrorIsIn(err, errorTypes) { return result, err } + if ctx.Err() != nil { + return result, ctx.Err() + } } log.Errorf("Failed after %d attempts, last error: %s", attempts, err) return result, err diff --git a/markets/retrievaladapter/client_blockstore.go b/markets/retrievaladapter/client_blockstore.go index 84c75fdbd..37a80013a 100644 --- a/markets/retrievaladapter/client_blockstore.go +++ b/markets/retrievaladapter/client_blockstore.go @@ -8,8 +8,12 @@ import ( "github.com/ipfs/go-cid" bstore "github.com/ipfs/go-ipfs-blockstore" "github.com/ipld/go-car/v2/blockstore" + "golang.org/x/xerrors" "github.com/filecoin-project/go-fil-markets/retrievalmarket" + + "github.com/filecoin-project/lotus/api" + lbstore "github.com/filecoin-project/lotus/blockstore" ) // ProxyBlockstoreAccessor is an accessor that returns a fixed blockstore. @@ -32,6 +36,85 @@ func (p *ProxyBlockstoreAccessor) Done(_ retrievalmarket.DealID) error { return nil } +func NewAPIBlockstoreAdapter(sub retrievalmarket.BlockstoreAccessor) *APIBlockstoreAccessor { + return &APIBlockstoreAccessor{ + sub: sub, + retrStores: map[retrievalmarket.DealID]api.RemoteStoreID{}, + remoteStores: map[api.RemoteStoreID]bstore.Blockstore{}, + } +} + +// APIBlockstoreAccessor adds support to API-specified remote blockstores +type APIBlockstoreAccessor struct { + sub retrievalmarket.BlockstoreAccessor + + retrStores map[retrievalmarket.DealID]api.RemoteStoreID + remoteStores map[api.RemoteStoreID]bstore.Blockstore + + accessLk sync.Mutex +} + +func (a *APIBlockstoreAccessor) Get(id retrievalmarket.DealID, payloadCID retrievalmarket.PayloadCID) (bstore.Blockstore, error) { + a.accessLk.Lock() + defer a.accessLk.Unlock() + + as, has := a.retrStores[id] + if !has { + return a.sub.Get(id, payloadCID) + } + + return a.remoteStores[as], nil +} + +func (a *APIBlockstoreAccessor) Done(id retrievalmarket.DealID) error { + a.accessLk.Lock() + defer a.accessLk.Unlock() + + if _, has := a.retrStores[id]; has { + delete(a.retrStores, id) + return nil + } + return a.sub.Done(id) +} + +func (a *APIBlockstoreAccessor) RegisterDealToRetrievalStore(id retrievalmarket.DealID, sid api.RemoteStoreID) error { + a.accessLk.Lock() + defer a.accessLk.Unlock() + + if _, has := a.retrStores[id]; has { + return xerrors.Errorf("apistore for deal %d already registered", id) + } + if _, has := a.remoteStores[sid]; !has { + return xerrors.Errorf("remote store not found") + } + + a.retrStores[id] = sid + return nil +} + +func (a *APIBlockstoreAccessor) RegisterApiStore(sid api.RemoteStoreID, st *lbstore.NetworkStore) error { + a.accessLk.Lock() + defer a.accessLk.Unlock() + + if _, has := a.remoteStores[sid]; has { + return xerrors.Errorf("remote store already registered with this uuid") + } + + a.remoteStores[sid] = st + + st.OnClose(func() { + a.accessLk.Lock() + defer a.accessLk.Unlock() + + if _, has := a.remoteStores[sid]; has { + delete(a.remoteStores, sid) + } + }) + return nil +} + +var _ retrievalmarket.BlockstoreAccessor = &APIBlockstoreAccessor{} + type CARBlockstoreAccessor struct { rootdir string lk sync.Mutex diff --git a/markets/storageadapter/dealpublisher.go b/markets/storageadapter/dealpublisher.go index 940a09e9f..6a274e593 100644 --- a/markets/storageadapter/dealpublisher.go +++ b/markets/storageadapter/dealpublisher.go @@ -204,6 +204,26 @@ func (p *DealPublisher) processNewDeal(pdeal *pendingDeal) { return } + pdealPropCid, err := pdeal.deal.Proposal.Cid() + if err != nil { + log.Warn("failed to calculate proposal CID for new pending Deal with piece cid %s", pdeal.deal.Proposal.PieceCID) + return + } + + // Sanity check that new deal isn't already in the queue + for _, pd := range p.pending { + pdPropCid, err := pd.deal.Proposal.Cid() + if err != nil { + log.Warn("failed to calculate proposal CID for pending Deal already in publish queue with piece cid %s", pd.deal.Proposal.PieceCID) + return + } + + if pdPropCid.Equals(pdealPropCid) { + log.Warn("tried to process new pending deal with piece CID %s that is already in publish queue; returning", pdeal.deal.Proposal.PieceCID) + return + } + } + // Add the new deal to the queue p.pending = append(p.pending, pdeal) log.Infof("add deal with piece CID %s to publish deals queue - %d deals in queue (max queue size %d)", diff --git a/markets/utils/selectors.go b/markets/utils/selectors.go index e1009d1ff..1b8a62401 100644 --- a/markets/utils/selectors.go +++ b/markets/utils/selectors.go @@ -26,6 +26,7 @@ func TraverseDag( ds mdagipld.DAGService, startFrom cid.Cid, optionalSelector ipld.Node, + onOpen func(node mdagipld.Node) error, visitCallback traversal.AdvVisitFn, ) error { @@ -61,6 +62,12 @@ func TraverseDag( return nil, err } + if onOpen != nil { + if err := onOpen(node); err != nil { + return nil, err + } + } + return bytes.NewBuffer(node.RawData()), nil } unixfsnode.AddUnixFSReificationToLinkSystem(&linkSystem) diff --git a/miner/miner.go b/miner/miner.go index 4952f95fb..f954352ae 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -30,6 +30,7 @@ import ( "github.com/filecoin-project/lotus/chain/gen/slashfilter" lrand "github.com/filecoin-project/lotus/chain/rand" "github.com/filecoin-project/lotus/chain/types" + cliutil "github.com/filecoin-project/lotus/cli/util" "github.com/filecoin-project/lotus/journal" ) @@ -208,6 +209,8 @@ func (m *Miner) mine(ctx context.Context) { var lastBase MiningBase minerLoop: for { + ctx := cliutil.OnSingleNode(ctx) + select { case <-m.stop: stopping := m.stopping diff --git a/node/builder.go b/node/builder.go index ca31a2c91..eaf932e2e 100644 --- a/node/builder.go +++ b/node/builder.go @@ -121,6 +121,7 @@ const ( SettlePaymentChannelsKey RunPeerTaggerKey SetupFallbackBlockstoresKey + GoRPCServer SetApiEndpointKey @@ -155,6 +156,7 @@ func defaults() []Option { Override(new(journal.DisabledEvents), journal.EnvDisabledEvents), Override(new(journal.Journal), modules.OpenFilesystemJournal), Override(new(*alerting.Alerting), alerting.NewAlertingSystem), + Override(new(dtypes.NodeStartTime), FromVal(dtypes.NodeStartTime(time.Now()))), Override(CheckFDLimit, modules.CheckFdLimit(build.DefaultFDLimit)), diff --git a/node/builder_chain.go b/node/builder_chain.go index e24b26097..2201be2e6 100644 --- a/node/builder_chain.go +++ b/node/builder_chain.go @@ -3,6 +3,7 @@ package node import ( "os" + gorpc "github.com/libp2p/go-libp2p-gorpc" "go.uber.org/fx" "golang.org/x/xerrors" @@ -28,7 +29,9 @@ import ( "github.com/filecoin-project/lotus/chain/wallet" ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" "github.com/filecoin-project/lotus/chain/wallet/remotewallet" + raftcns "github.com/filecoin-project/lotus/lib/consensus/raft" "github.com/filecoin-project/lotus/lib/peermgr" + "github.com/filecoin-project/lotus/markets/retrievaladapter" "github.com/filecoin-project/lotus/markets/storageadapter" "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/hello" @@ -105,6 +108,7 @@ var ChainNode = Options( // Service: Wallet Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner), + Override(new(messagesigner.MsgSigner), func(ms *messagesigner.MessageSigner) *messagesigner.MessageSigner { return ms }), Override(new(*wallet.LocalWallet), wallet.NewWallet), Override(new(wallet.Default), From(new(*wallet.LocalWallet))), Override(new(api.Wallet), From(new(wallet.MultiWallet))), @@ -129,6 +133,7 @@ var ChainNode = Options( Override(new(*market.FundManager), market.NewFundManager), Override(new(dtypes.ClientDatastore), modules.NewClientDatastore), Override(new(storagemarket.BlockstoreAccessor), modules.StorageBlockstoreAccessor), + Override(new(*retrievaladapter.APIBlockstoreAccessor), retrievaladapter.NewAPIBlockstoreAdapter), Override(new(storagemarket.StorageClient), modules.StorageClient), Override(new(storagemarket.StorageClientNode), storageadapter.NewClientNodeAdapter), Override(HandleMigrateClientFundsKey, modules.HandleMigrateClientFunds), @@ -140,7 +145,7 @@ var ChainNode = Options( // Lite node API ApplyIf(isLiteNode, Override(new(messagepool.Provider), messagepool.NewProviderLite), - Override(new(messagesigner.MpoolNonceAPI), From(new(modules.MpoolNonceAPI))), + Override(new(messagepool.MpoolNonceAPI), From(new(modules.MpoolNonceAPI))), Override(new(full.ChainModuleAPI), From(new(api.Gateway))), Override(new(full.GasModuleAPI), From(new(api.Gateway))), Override(new(full.MpoolModuleAPI), From(new(api.Gateway))), @@ -151,7 +156,7 @@ var ChainNode = Options( // Full node API / service startup ApplyIf(isFullNode, Override(new(messagepool.Provider), messagepool.NewProvider), - Override(new(messagesigner.MpoolNonceAPI), From(new(*messagepool.MessagePool))), + Override(new(messagepool.MpoolNonceAPI), From(new(*messagepool.MessagePool))), Override(new(full.ChainModuleAPI), From(new(full.ChainModule))), Override(new(full.GasModuleAPI), From(new(full.GasModule))), Override(new(full.MpoolModuleAPI), From(new(full.MpoolModule))), @@ -181,7 +186,7 @@ func ConfigFullNode(c interface{}) Option { Override(new(dtypes.UniversalBlockstore), modules.UniversalBlockstore), If(cfg.Chainstore.EnableSplitstore, - If(cfg.Chainstore.Splitstore.ColdStoreType == "universal", + If(cfg.Chainstore.Splitstore.ColdStoreType == "universal" || cfg.Chainstore.Splitstore.ColdStoreType == "messages", Override(new(dtypes.ColdBlockstore), From(new(dtypes.UniversalBlockstore)))), If(cfg.Chainstore.Splitstore.ColdStoreType == "discard", Override(new(dtypes.ColdBlockstore), modules.DiscardColdBlockstore)), @@ -236,6 +241,16 @@ func ConfigFullNode(c interface{}) Option { Unset(new(*wallet.LocalWallet)), Override(new(wallet.Default), wallet.NilDefault), ), + // Chain node cluster enabled + If(cfg.Cluster.ClusterModeEnabled, + Override(new(*gorpc.Client), modules.NewRPCClient), + Override(new(*raftcns.ClusterRaftConfig), raftcns.NewClusterRaftConfig(&cfg.Cluster)), + Override(new(*raftcns.Consensus), raftcns.NewConsensusWithRPCClient(false)), + Override(new(*messagesigner.MessageSignerConsensus), messagesigner.NewMessageSignerConsensus), + Override(new(messagesigner.MsgSigner), From(new(*messagesigner.MessageSignerConsensus))), + Override(new(*modules.RPCHandler), modules.NewRPCHandler), + Override(GoRPCServer, modules.NewRPCServer), + ), ) } diff --git a/node/builder_miner.go b/node/builder_miner.go index a3eb9a7ec..2d33727f8 100644 --- a/node/builder_miner.go +++ b/node/builder_miner.go @@ -94,6 +94,10 @@ func ConfigStorageMiner(c interface{}) Option { Override(new(paths.Store), From(new(*paths.Remote))), Override(new(dtypes.RetrievalPricingFunc), modules.RetrievalPricingFunc(cfg.Dealmaking)), + If(cfg.Subsystems.EnableMining || cfg.Subsystems.EnableSealing, + Override(GetParamsKey, modules.GetParams(!cfg.Proving.DisableBuiltinWindowPoSt || !cfg.Proving.DisableBuiltinWinningPoSt || cfg.Storage.AllowCommit || cfg.Storage.AllowProveReplicaUpdate2)), + ), + If(!cfg.Subsystems.EnableMining, If(cfg.Subsystems.EnableSealing, Error(xerrors.Errorf("sealing can only be enabled on a mining node"))), If(cfg.Subsystems.EnableSectorStorage, Error(xerrors.Errorf("sealing can only be enabled on a mining node"))), @@ -107,9 +111,6 @@ func ConfigStorageMiner(c interface{}) Option { Override(new(storiface.Prover), ffiwrapper.ProofProver), Override(new(storiface.ProverPoSt), From(new(sectorstorage.SectorManager))), - // Sealing (todo should be under EnableSealing, but storagefsm is currently bundled with storage.Miner) - Override(GetParamsKey, modules.GetParams), - Override(new(dtypes.SetSealingConfigFunc), modules.NewSetSealConfigFunc), Override(new(dtypes.GetSealingConfigFunc), modules.NewGetSealConfigFunc), @@ -223,7 +224,8 @@ func ConfigStorageMiner(c interface{}) Option { Override(new(storagemarket.StorageProviderNode), storageadapter.NewProviderNodeAdapter(&cfg.Fees, &cfg.Dealmaking)), ), - Override(new(sectorstorage.Config), cfg.StorageManager()), + Override(new(config.SealerConfig), cfg.Storage), + Override(new(config.ProvingConfig), cfg.Proving), Override(new(*ctladdr.AddressSelector), modules.AddressSelector(&cfg.Addresses)), ) } diff --git a/node/config/def.go b/node/config/def.go index 0566c7d99..dc26f1661 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -15,7 +15,6 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/storage/sealer" ) const ( @@ -91,14 +90,14 @@ func DefaultFullNode() *FullNode { Chainstore: Chainstore{ EnableSplitstore: false, Splitstore: Splitstore{ - ColdStoreType: "universal", + ColdStoreType: "messages", HotStoreType: "badger", MarkSetType: "badger", - HotStoreFullGCFrequency: 20, - ColdStoreFullGCFrequency: 7, + HotStoreFullGCFrequency: 20, }, }, + Cluster: *DefaultUserRaftConfig(), } } @@ -142,7 +141,9 @@ func DefaultStorageMiner() *StorageMiner { }, Proving: ProvingConfig{ - ParallelCheckLimit: 128, + ParallelCheckLimit: 128, + PartitionCheckTimeout: Duration(20 * time.Minute), + SingleCheckTimeout: Duration(10 * time.Minute), }, Storage: SealerConfig{ @@ -163,7 +164,7 @@ func DefaultStorageMiner() *StorageMiner { Assigner: "utilization", // By default use the hardware resource filtering strategy. - ResourceFiltering: sealer.ResourceFilteringHardware, + ResourceFiltering: ResourceFilteringHardware, }, Dealmaking: DealmakingConfig{ @@ -275,3 +276,39 @@ func (dur Duration) MarshalText() ([]byte, error) { d := time.Duration(dur) return []byte(d.String()), nil } + +// ResourceFilteringStrategy is an enum indicating the kinds of resource +// filtering strategies that can be configured for workers. +type ResourceFilteringStrategy string + +const ( + // ResourceFilteringHardware specifies that available hardware resources + // should be evaluated when scheduling a task against the worker. + ResourceFilteringHardware = ResourceFilteringStrategy("hardware") + + // ResourceFilteringDisabled disables resource filtering against this + // worker. The scheduler may assign any task to this worker. + ResourceFilteringDisabled = ResourceFilteringStrategy("disabled") +) + +var ( + DefaultDataSubFolder = "raft" + DefaultWaitForLeaderTimeout = 15 * time.Second + DefaultCommitRetries = 1 + DefaultNetworkTimeout = 100 * time.Second + DefaultCommitRetryDelay = 200 * time.Millisecond + DefaultBackupsRotate = 6 +) + +func DefaultUserRaftConfig() *UserRaftConfig { + var cfg UserRaftConfig + cfg.DataFolder = "" // empty so it gets omitted + cfg.InitPeersetMultiAddr = []string{} + cfg.WaitForLeaderTimeout = Duration(DefaultWaitForLeaderTimeout) + cfg.NetworkTimeout = Duration(DefaultNetworkTimeout) + cfg.CommitRetries = DefaultCommitRetries + cfg.CommitRetryDelay = Duration(DefaultCommitRetryDelay) + cfg.BackupsRotate = DefaultBackupsRotate + + return &cfg +} diff --git a/node/config/dep_test.go b/node/config/dep_test.go new file mode 100644 index 000000000..91167e690 --- /dev/null +++ b/node/config/dep_test.go @@ -0,0 +1,34 @@ +package config + +import ( + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "testing" +) + +func goCmd() string { + var exeSuffix string + if runtime.GOOS == "windows" { + exeSuffix = ".exe" + } + path := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix) + if _, err := os.Stat(path); err == nil { + return path + } + return "go" +} + +func TestDoesntDependOnFFI(t *testing.T) { + deps, err := exec.Command(goCmd(), "list", "-deps", "github.com/filecoin-project/lotus/node/config").Output() + if err != nil { + t.Fatal(err) + } + for _, pkg := range strings.Fields(string(deps)) { + if pkg == "github.com/filecoin-project/filecoin-ffi" { + t.Fatal("config depends on filecoin-ffi") + } + } +} diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index 80538c70e..ecf533137 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -372,6 +372,12 @@ see https://lotus.filecoin.io/storage-providers/advanced-configurations/market/# Name: "Chainstore", Type: "Chainstore", + Comment: ``, + }, + { + Name: "Cluster", + Type: "UserRaftConfig", + Comment: ``, }, }, @@ -638,6 +644,29 @@ to late submission. After changing this option, confirm that the new value works in your setup by invoking 'lotus-miner proving compute window-post 0'`, + }, + { + Name: "SingleCheckTimeout", + Type: "Duration", + + Comment: `Maximum amount of time a proving pre-check can take for a sector. If the check times out the sector will be skipped + +WARNING: Setting this value too low risks in sectors being skipped even though they are accessible, just reading the +test challenge took longer than this timeout +WARNING: Setting this value too high risks missing PoSt deadline in case IO operations related to this sector are +blocked (e.g. in case of disconnected NFS mount)`, + }, + { + Name: "PartitionCheckTimeout", + Type: "Duration", + + Comment: `Maximum amount of time a proving pre-check can take for an entire partition. If the check times out, sectors in +the partition which didn't get checked on time will be skipped + +WARNING: Setting this value too low risks in sectors being skipped even though they are accessible, just reading the +test challenge took longer than this timeout +WARNING: Setting this value too high risks missing PoSt deadline in case IO operations related to this partition are +blocked or slow`, }, { Name: "DisableBuiltinWindowPoSt", @@ -894,7 +923,7 @@ If you see stuck Finalize tasks after enabling this setting, check }, { Name: "ResourceFiltering", - Type: "sealer.ResourceFilteringStrategy", + Type: "ResourceFilteringStrategy", Comment: `ResourceFiltering instructs the system which resource filtering strategy to use when evaluating tasks against this worker. An empty value defaults @@ -1116,7 +1145,7 @@ submitting proofs to the chain individually`, Type: "string", Comment: `ColdStoreType specifies the type of the coldstore. -It can be "universal" (default) or "discard" for discarding cold blocks.`, +It can be "messages" (default) to store only messages, "universal" to store all chain state or "discard" for discarding cold blocks.`, }, { Name: "HotStoreType", @@ -1147,30 +1176,6 @@ the compaction boundary; default is 0.`, A value of 0 disables, while a value 1 will do full GC in every compaction. Default is 20 (about once a week).`, }, - { - Name: "EnableColdStoreAutoPrune", - Type: "bool", - - Comment: `EnableColdStoreAutoPrune turns on compaction of the cold store i.e. pruning -where hotstore compaction occurs every finality epochs pruning happens every 3 finalities -Default is false`, - }, - { - Name: "ColdStoreFullGCFrequency", - Type: "uint64", - - Comment: `ColdStoreFullGCFrequency specifies how often to performa a full (moving) GC on the coldstore. -Only applies if auto prune is enabled. A value of 0 disables while a value of 1 will do -full GC in every prune. -Default is 7 (about once every a week)`, - }, - { - Name: "ColdStoreRetention", - Type: "int64", - - Comment: `ColdStoreRetention specifies the retention policy for data reachable from the chain, in -finalities beyond the compaction boundary, default is 0, -1 retains everything`, - }, }, "StorageMiner": []DocField{ { @@ -1228,6 +1233,68 @@ finalities beyond the compaction boundary, default is 0, -1 retains everything`, Comment: ``, }, }, + "UserRaftConfig": []DocField{ + { + Name: "ClusterModeEnabled", + Type: "bool", + + Comment: `EXPERIMENTAL. config to enabled node cluster with raft consensus`, + }, + { + Name: "DataFolder", + Type: "string", + + Comment: `A folder to store Raft's data.`, + }, + { + Name: "InitPeersetMultiAddr", + Type: "[]string", + + Comment: `InitPeersetMultiAddr provides the list of initial cluster peers for new Raft +peers (with no prior state). It is ignored when Raft was already +initialized or when starting in staging mode.`, + }, + { + Name: "WaitForLeaderTimeout", + Type: "Duration", + + Comment: `LeaderTimeout specifies how long to wait for a leader before +failing an operation.`, + }, + { + Name: "NetworkTimeout", + Type: "Duration", + + Comment: `NetworkTimeout specifies how long before a Raft network +operation is timed out`, + }, + { + Name: "CommitRetries", + Type: "int", + + Comment: `CommitRetries specifies how many times we retry a failed commit until +we give up.`, + }, + { + Name: "CommitRetryDelay", + Type: "Duration", + + Comment: `How long to wait between retries`, + }, + { + Name: "BackupsRotate", + Type: "int", + + Comment: `BackupsRotate specifies the maximum number of Raft's DataFolder +copies that we keep as backups (renaming) after cleanup.`, + }, + { + Name: "Tracing", + Type: "bool", + + Comment: `Tracing enables propagation of contexts across binary boundaries.`, + }, + }, "Wallet": []DocField{ { Name: "RemoteBackend", diff --git a/node/config/storage.go b/node/config/storage.go index 0c72eabd1..2c9d880f9 100644 --- a/node/config/storage.go +++ b/node/config/storage.go @@ -8,11 +8,10 @@ import ( "golang.org/x/xerrors" - "github.com/filecoin-project/lotus/storage/paths" - "github.com/filecoin-project/lotus/storage/sealer" + "github.com/filecoin-project/lotus/storage/sealer/storiface" ) -func StorageFromFile(path string, def *paths.StorageConfig) (*paths.StorageConfig, error) { +func StorageFromFile(path string, def *storiface.StorageConfig) (*storiface.StorageConfig, error) { file, err := os.Open(path) switch { case os.IsNotExist(err): @@ -28,8 +27,8 @@ func StorageFromFile(path string, def *paths.StorageConfig) (*paths.StorageConfi return StorageFromReader(file) } -func StorageFromReader(reader io.Reader) (*paths.StorageConfig, error) { - var cfg paths.StorageConfig +func StorageFromReader(reader io.Reader) (*storiface.StorageConfig, error) { + var cfg storiface.StorageConfig err := json.NewDecoder(reader).Decode(&cfg) if err != nil { return nil, err @@ -38,7 +37,7 @@ func StorageFromReader(reader io.Reader) (*paths.StorageConfig, error) { return &cfg, nil } -func WriteStorageFile(path string, config paths.StorageConfig) error { +func WriteStorageFile(path string, config storiface.StorageConfig) error { b, err := json.MarshalIndent(config, "", " ") if err != nil { return xerrors.Errorf("marshaling storage config: %w", err) @@ -50,28 +49,3 @@ func WriteStorageFile(path string, config paths.StorageConfig) error { return nil } - -func (c *StorageMiner) StorageManager() sealer.Config { - return sealer.Config{ - ParallelFetchLimit: c.Storage.ParallelFetchLimit, - AllowSectorDownload: c.Storage.AllowSectorDownload, - AllowAddPiece: c.Storage.AllowAddPiece, - AllowPreCommit1: c.Storage.AllowPreCommit1, - AllowPreCommit2: c.Storage.AllowPreCommit2, - AllowCommit: c.Storage.AllowCommit, - AllowUnseal: c.Storage.AllowUnseal, - AllowReplicaUpdate: c.Storage.AllowReplicaUpdate, - AllowProveReplicaUpdate2: c.Storage.AllowProveReplicaUpdate2, - AllowRegenSectorKey: c.Storage.AllowRegenSectorKey, - ResourceFiltering: c.Storage.ResourceFiltering, - DisallowRemoteFinalize: c.Storage.DisallowRemoteFinalize, - - LocalWorkerName: c.Storage.LocalWorkerName, - - Assigner: c.Storage.Assigner, - - ParallelCheckLimit: c.Proving.ParallelCheckLimit, - DisableBuiltinWindowPoSt: c.Proving.DisableBuiltinWindowPoSt, - DisableBuiltinWinningPoSt: c.Proving.DisableBuiltinWinningPoSt, - } -} diff --git a/node/config/types.go b/node/config/types.go index df5f018e3..90d878b7e 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -4,7 +4,6 @@ import ( "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/storage/sealer" ) // // NOTE: ONLY PUT STRUCT DEFINITIONS IN THIS FILE @@ -27,6 +26,7 @@ type FullNode struct { Wallet Wallet Fees FeeConfig Chainstore Chainstore + Cluster UserRaftConfig } // // Common @@ -230,6 +230,23 @@ type ProvingConfig struct { // 'lotus-miner proving compute window-post 0' ParallelCheckLimit int + // Maximum amount of time a proving pre-check can take for a sector. If the check times out the sector will be skipped + // + // WARNING: Setting this value too low risks in sectors being skipped even though they are accessible, just reading the + // test challenge took longer than this timeout + // WARNING: Setting this value too high risks missing PoSt deadline in case IO operations related to this sector are + // blocked (e.g. in case of disconnected NFS mount) + SingleCheckTimeout Duration + + // Maximum amount of time a proving pre-check can take for an entire partition. If the check times out, sectors in + // the partition which didn't get checked on time will be skipped + // + // WARNING: Setting this value too low risks in sectors being skipped even though they are accessible, just reading the + // test challenge took longer than this timeout + // WARNING: Setting this value too high risks missing PoSt deadline in case IO operations related to this partition are + // blocked or slow + PartitionCheckTimeout Duration + // Disable Window PoSt computation on the lotus-miner process even if no window PoSt workers are present. // // WARNING: If no windowPoSt workers are connected, window PoSt WILL FAIL resulting in faulty sectors which will need @@ -452,7 +469,7 @@ type SealerConfig struct { // ResourceFiltering instructs the system which resource filtering strategy // to use when evaluating tasks against this worker. An empty value defaults // to "hardware". - ResourceFiltering sealer.ResourceFilteringStrategy + ResourceFiltering ResourceFilteringStrategy } type BatchFeeConfig struct { @@ -555,7 +572,7 @@ type Chainstore struct { type Splitstore struct { // ColdStoreType specifies the type of the coldstore. - // It can be "universal" (default) or "discard" for discarding cold blocks. + // It can be "messages" (default) to store only messages, "universal" to store all chain state or "discard" for discarding cold blocks. ColdStoreType string // HotStoreType specifies the type of the hotstore. // Only currently supported value is "badger". @@ -571,21 +588,6 @@ type Splitstore struct { // A value of 0 disables, while a value 1 will do full GC in every compaction. // Default is 20 (about once a week). HotStoreFullGCFrequency uint64 - - // EnableColdStoreAutoPrune turns on compaction of the cold store i.e. pruning - // where hotstore compaction occurs every finality epochs pruning happens every 3 finalities - // Default is false - EnableColdStoreAutoPrune bool - - // ColdStoreFullGCFrequency specifies how often to performa a full (moving) GC on the coldstore. - // Only applies if auto prune is enabled. A value of 0 disables while a value of 1 will do - // full GC in every prune. - // Default is 7 (about once every a week) - ColdStoreFullGCFrequency uint64 - - // ColdStoreRetention specifies the retention policy for data reachable from the chain, in - // finalities beyond the compaction boundary, default is 0, -1 retains everything - ColdStoreRetention int64 } // // Full Node @@ -616,3 +618,30 @@ type Wallet struct { type FeeConfig struct { DefaultMaxFee types.FIL } + +type UserRaftConfig struct { + // EXPERIMENTAL. config to enabled node cluster with raft consensus + ClusterModeEnabled bool + // A folder to store Raft's data. + DataFolder string + // InitPeersetMultiAddr provides the list of initial cluster peers for new Raft + // peers (with no prior state). It is ignored when Raft was already + // initialized or when starting in staging mode. + InitPeersetMultiAddr []string + // LeaderTimeout specifies how long to wait for a leader before + // failing an operation. + WaitForLeaderTimeout Duration + // NetworkTimeout specifies how long before a Raft network + // operation is timed out + NetworkTimeout Duration + // CommitRetries specifies how many times we retry a failed commit until + // we give up. + CommitRetries int + // How long to wait between retries + CommitRetryDelay Duration + // BackupsRotate specifies the maximum number of Raft's DataFolder + // copies that we keep as backups (renaming) after cleanup. + BackupsRotate int + // Tracing enables propagation of contexts across binary boundaries. + Tracing bool +} diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 3bfd84f08..fef4d91e3 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -10,6 +10,7 @@ import ( "os" "sort" "strings" + "sync" "time" "github.com/ipfs/go-blockservice" @@ -97,6 +98,7 @@ type API struct { Imports dtypes.ClientImportMgr StorageBlockstoreAccessor storagemarket.BlockstoreAccessor RtvlBlockstoreAccessor rm.BlockstoreAccessor + ApiBlockstoreAccessor *retrievaladapter.APIBlockstoreAccessor DataTransfer dtypes.ClientDataTransfer Host host.Host @@ -837,7 +839,7 @@ func (a *API) doRetrieval(ctx context.Context, order api.RetrievalOrder, sel dat return 0, xerrors.Errorf("cannot make retrieval deal for zero bytes") } - ppb := types.BigDiv(order.Total, types.NewInt(order.Size)) + ppb := types.BigDiv(big.Sub(order.Total, order.UnsealPrice), types.NewInt(order.Size)) params, err := rm.NewParamsV1(ppb, order.PaymentInterval, order.PaymentIntervalIncrease, sel, order.Piece, order.UnsealPrice) if err != nil { @@ -845,6 +847,13 @@ func (a *API) doRetrieval(ctx context.Context, order api.RetrievalOrder, sel dat } id := a.Retrieval.NextID() + + if order.RemoteStore != nil { + if err := a.ApiBlockstoreAccessor.RegisterDealToRetrievalStore(id, *order.RemoteStore); err != nil { + return 0, xerrors.Errorf("registering api store: %w", err) + } + } + id, err = a.Retrieval.Retrieve( ctx, id, @@ -999,6 +1008,8 @@ func (a *API) outputCAR(ctx context.Context, ds format.DAGService, bs bstore.Blo roots[i] = dag.root } + var lk sync.Mutex + return dest.doWrite(func(w io.Writer) error { if err := car.WriteHeader(&car.CarHeader{ @@ -1011,13 +1022,29 @@ func (a *API) outputCAR(ctx context.Context, ds format.DAGService, bs bstore.Blo cs := cid.NewSet() for _, dagSpec := range dags { + dagSpec := dagSpec + if err := utils.TraverseDag( ctx, ds, root, dagSpec.selector, + func(node format.Node) error { + // if we're exporting merkle proofs for this dag, export all nodes read by the traversal + if dagSpec.exportAll { + lk.Lock() + defer lk.Unlock() + if cs.Visit(node.Cid()) { + err := util.LdWrite(w, node.Cid().Bytes(), node.RawData()) + if err != nil { + return xerrors.Errorf("writing block data: %w", err) + } + } + } + return nil + }, func(p traversal.Progress, n ipld.Node, r traversal.VisitReason) error { - if r == traversal.VisitReason_SelectionMatch { + if !dagSpec.exportAll && r == traversal.VisitReason_SelectionMatch { var c cid.Cid if p.LastBlock.Link == nil { c = root @@ -1082,8 +1109,9 @@ func (a *API) outputUnixFS(ctx context.Context, root cid.Cid, ds format.DAGServi } type dagSpec struct { - root cid.Cid - selector ipld.Node + root cid.Cid + selector ipld.Node + exportAll bool } func parseDagSpec(ctx context.Context, root cid.Cid, dsp []api.DagSpec, ds format.DAGService, car bool) ([]dagSpec, error) { @@ -1098,6 +1126,7 @@ func parseDagSpec(ctx context.Context, root cid.Cid, dsp []api.DagSpec, ds forma out := make([]dagSpec, len(dsp)) for i, spec := range dsp { + out[i].exportAll = spec.ExportMerkleProof if spec.DataSelector == nil { return nil, xerrors.Errorf("invalid DagSpec at position %d: `DataSelector` can not be nil", i) @@ -1131,6 +1160,7 @@ func parseDagSpec(ctx context.Context, root cid.Cid, dsp []api.DagSpec, ds forma ds, root, rsn, + nil, func(p traversal.Progress, n ipld.Node, r traversal.VisitReason) error { if r == traversal.VisitReason_SelectionMatch { if !car && p.LastBlock.Path.String() != p.Path.String() { diff --git a/node/impl/common/common.go b/node/impl/common/common.go index 182b74989..eff6b58b8 100644 --- a/node/impl/common/common.go +++ b/node/impl/common/common.go @@ -2,6 +2,7 @@ package common import ( "context" + "time" "github.com/gbrlsnchs/jwt/v3" "github.com/google/uuid" @@ -26,6 +27,8 @@ type CommonAPI struct { Alerting *alerting.Alerting APISecret *dtypes.APIAlg ShutdownChan dtypes.ShutdownChan + + Start dtypes.NodeStartTime } type jwtPayload struct { @@ -91,3 +94,7 @@ func (a *CommonAPI) Session(ctx context.Context) (uuid.UUID, error) { func (a *CommonAPI) Closing(ctx context.Context) (<-chan struct{}, error) { return make(chan struct{}), nil // relies on jsonrpc closing } + +func (a *CommonAPI) StartTime(context.Context) (time.Time, error) { + return time.Time(a.Start), nil +} diff --git a/node/impl/full.go b/node/impl/full.go index e1e7ac7a0..03a28eb75 100644 --- a/node/impl/full.go +++ b/node/impl/full.go @@ -34,6 +34,7 @@ type FullNodeAPI struct { full.MsigAPI full.WalletAPI full.SyncAPI + full.RaftAPI DS dtypes.MetadataDS NetworkName dtypes.NetworkName @@ -117,4 +118,12 @@ func (n *FullNodeAPI) NodeStatus(ctx context.Context, inclChainStatus bool) (sta return status, nil } +func (n *FullNodeAPI) RaftState(ctx context.Context) (*api.RaftStateData, error) { + return n.RaftAPI.GetRaftState(ctx) +} + +func (n *FullNodeAPI) RaftLeader(ctx context.Context) (peer.ID, error) { + return n.RaftAPI.Leader(ctx) +} + var _ api.FullNode = &FullNodeAPI{} diff --git a/node/impl/full/mpool.go b/node/impl/full/mpool.go index a2dbf0a86..31d134dac 100644 --- a/node/impl/full/mpool.go +++ b/node/impl/full/mpool.go @@ -44,7 +44,9 @@ type MpoolAPI struct { WalletAPI GasAPI - MessageSigner *messagesigner.MessageSigner + RaftAPI + + MessageSigner messagesigner.MsgSigner PushLocks *dtypes.MpoolLocker } @@ -131,7 +133,7 @@ func (a *MpoolAPI) MpoolClear(ctx context.Context, local bool) error { } func (m *MpoolModule) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) { - return m.Mpool.Push(ctx, smsg) + return m.Mpool.Push(ctx, smsg, true) } func (a *MpoolAPI) MpoolPushUntrusted(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) { @@ -143,8 +145,29 @@ func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message, spe msg = &cp inMsg := *msg - // Check if this uuid has already been processed. Ignore if uuid is not populated - if (spec != nil) && (spec.MsgUuid != uuid.UUID{}) { + // Redirect to leader if current node is not leader. A single non raft based node is always the leader + if !a.RaftAPI.IsLeader(ctx) { + var signedMsg types.SignedMessage + redirected, err := a.RaftAPI.RedirectToLeader(ctx, "MpoolPushMessage", api.MpoolMessageWhole{Msg: msg, Spec: spec}, &signedMsg) + if err != nil { + return nil, err + } + // It's possible that the current node became the leader between the check and the redirect + // In that case, continue with rest of execution and only return signedMsg if something was redirected + if redirected { + return &signedMsg, nil + } + } + + // Generate spec and uuid if not available in the message + if spec == nil { + spec = &api.MessageSendSpec{ + MsgUuid: uuid.New(), + } + } else if (spec.MsgUuid == uuid.UUID{}) { + spec.MsgUuid = uuid.New() + } else { + // Check if this uuid has already been processed. Ignore if uuid is not populated signedMessage, err := a.MessageSigner.GetSignedMessage(ctx, spec.MsgUuid) if err == nil { log.Warnf("Message already processed. cid=%s", signedMessage.Cid()) @@ -196,7 +219,7 @@ func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message, spe } // Sign and push the message - signedMsg, err := a.MessageSigner.SignMessage(ctx, msg, func(smsg *types.SignedMessage) error { + signedMsg, err := a.MessageSigner.SignMessage(ctx, msg, spec, func(smsg *types.SignedMessage) error { if _, err := a.MpoolModuleAPI.MpoolPush(ctx, smsg); err != nil { return xerrors.Errorf("mpool push: failed to push message: %w", err) } @@ -207,11 +230,9 @@ func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message, spe } // Store uuid->signed message in datastore - if (spec != nil) && (spec.MsgUuid != uuid.UUID{}) { - err = a.MessageSigner.StoreSignedMessage(ctx, spec.MsgUuid, signedMsg) - if err != nil { - return nil, err - } + err = a.MessageSigner.StoreSignedMessage(ctx, spec.MsgUuid, signedMsg) + if err != nil { + return nil, err } return signedMsg, nil @@ -220,7 +241,7 @@ func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message, spe func (a *MpoolAPI) MpoolBatchPush(ctx context.Context, smsgs []*types.SignedMessage) ([]cid.Cid, error) { var messageCids []cid.Cid for _, smsg := range smsgs { - smsgCid, err := a.Mpool.Push(ctx, smsg) + smsgCid, err := a.Mpool.Push(ctx, smsg, true) if err != nil { return messageCids, err } diff --git a/node/impl/full/raft.go b/node/impl/full/raft.go new file mode 100644 index 000000000..8d665ddd5 --- /dev/null +++ b/node/impl/full/raft.go @@ -0,0 +1,50 @@ +package full + +import ( + "context" + + "github.com/libp2p/go-libp2p/core/peer" + "go.uber.org/fx" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/messagesigner" +) + +type RaftAPI struct { + fx.In + + MessageSigner *messagesigner.MessageSignerConsensus `optional:"true"` +} + +func (r *RaftAPI) GetRaftState(ctx context.Context) (*api.RaftStateData, error) { + if r.MessageSigner == nil { + return nil, xerrors.Errorf("raft consensus not enabled. Please check your configuration") + } + raftState, err := r.MessageSigner.GetRaftState(ctx) + if err != nil { + return nil, err + } + return &api.RaftStateData{NonceMap: raftState.NonceMap, MsgUuids: raftState.MsgUuids}, nil +} + +func (r *RaftAPI) Leader(ctx context.Context) (peer.ID, error) { + if r.MessageSigner == nil { + return "", xerrors.Errorf("raft consensus not enabled. Please check your configuration") + } + return r.MessageSigner.Leader(ctx) +} + +func (r *RaftAPI) IsLeader(ctx context.Context) bool { + if r.MessageSigner == nil { + return true + } + return r.MessageSigner.IsLeader(ctx) +} + +func (r *RaftAPI) RedirectToLeader(ctx context.Context, method string, arg interface{}, ret interface{}) (bool, error) { + if r.MessageSigner == nil { + return false, xerrors.Errorf("raft consensus not enabled. Please check your configuration") + } + return r.MessageSigner.RedirectToLeader(ctx, method, arg, ret) +} diff --git a/node/impl/full/sync.go b/node/impl/full/sync.go index 2809d41dc..fda55def1 100644 --- a/node/impl/full/sync.go +++ b/node/impl/full/sync.go @@ -2,6 +2,7 @@ package full import ( "context" + "os" "sync/atomic" "github.com/ipfs/go-cid" @@ -56,7 +57,7 @@ func (a *SyncAPI) SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) erro return xerrors.Errorf("loading parent block: %w", err) } - if a.SlashFilter != nil { + if a.SlashFilter != nil && os.Getenv("LOTUS_NO_SLASHFILTER") != "_yes_i_know_i_can_and_probably_will_lose_all_my_fil_and_power_" { if err := a.SlashFilter.MinedBlock(ctx, blk.Header, parent.Height); err != nil { log.Errorf(" SLASH FILTER ERROR: %s", err) return xerrors.Errorf(" SLASH FILTER ERROR: %w", err) diff --git a/node/impl/storminer.go b/node/impl/storminer.go index c26d50410..56aa7afde 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -1295,20 +1295,17 @@ func (sm *StorageMinerAPI) CreateBackup(ctx context.Context, fpath string) error return backup(ctx, sm.DS, fpath) } -func (sm *StorageMinerAPI) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storiface.SectorRef, expensive bool) (map[abi.SectorNumber]string, error) { - var rg storiface.RGetter - if expensive { - rg = func(ctx context.Context, id abi.SectorID) (cid.Cid, bool, error) { - si, err := sm.Miner.SectorsStatus(ctx, id.Number, false) - if err != nil { - return cid.Undef, false, err - } - if si.CommR == nil { - return cid.Undef, false, xerrors.Errorf("commr is nil") - } - - return *si.CommR, si.ReplicaUpdateMessage != nil, nil +func (sm *StorageMinerAPI) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storiface.SectorRef) (map[abi.SectorNumber]string, error) { + rg := func(ctx context.Context, id abi.SectorID) (cid.Cid, bool, error) { + si, err := sm.Miner.SectorsStatus(ctx, id.Number, false) + if err != nil { + return cid.Undef, false, err } + if si.CommR == nil { + return cid.Undef, false, xerrors.Errorf("commr is nil") + } + + return *si.CommR, si.ReplicaUpdateMessage != nil, nil } bad, err := sm.StorageMgr.CheckProvable(ctx, pp, sectors, rg) diff --git a/node/modules/blockstore.go b/node/modules/blockstore.go index 21ce41875..90b7b6183 100644 --- a/node/modules/blockstore.go +++ b/node/modules/blockstore.go @@ -84,11 +84,9 @@ func SplitBlockstore(cfg *config.Chainstore) func(lc fx.Lifecycle, r repo.Locked cfg := &splitstore.Config{ MarkSetType: cfg.Splitstore.MarkSetType, DiscardColdBlocks: cfg.Splitstore.ColdStoreType == "discard", + UniversalColdBlocks: cfg.Splitstore.ColdStoreType == "universal", HotStoreMessageRetention: cfg.Splitstore.HotStoreMessageRetention, HotStoreFullGCFrequency: cfg.Splitstore.HotStoreFullGCFrequency, - EnableColdStoreAutoPrune: cfg.Splitstore.EnableColdStoreAutoPrune, - ColdStoreFullGCFrequency: cfg.Splitstore.ColdStoreFullGCFrequency, - ColdStoreRetention: cfg.Splitstore.ColdStoreRetention, } ss, err := splitstore.Open(path, ds, hot, cold, cfg) if err != nil { diff --git a/node/modules/client.go b/node/modules/client.go index 22fcbb00d..69f8db559 100644 --- a/node/modules/client.go +++ b/node/modules/client.go @@ -202,9 +202,9 @@ func StorageClient(lc fx.Lifecycle, h host.Host, dataTransfer dtypes.ClientDataT // RetrievalClient creates a new retrieval client attached to the client blockstore func RetrievalClient(forceOffChain bool) func(lc fx.Lifecycle, h host.Host, r repo.LockedRepo, dt dtypes.ClientDataTransfer, payAPI payapi.PaychAPI, resolver discovery.PeerResolver, - ds dtypes.MetadataDS, chainAPI full.ChainAPI, stateAPI full.StateAPI, accessor retrievalmarket.BlockstoreAccessor, j journal.Journal) (retrievalmarket.RetrievalClient, error) { + ds dtypes.MetadataDS, chainAPI full.ChainAPI, stateAPI full.StateAPI, accessor *retrievaladapter.APIBlockstoreAccessor, j journal.Journal) (retrievalmarket.RetrievalClient, error) { return func(lc fx.Lifecycle, h host.Host, r repo.LockedRepo, dt dtypes.ClientDataTransfer, payAPI payapi.PaychAPI, resolver discovery.PeerResolver, - ds dtypes.MetadataDS, chainAPI full.ChainAPI, stateAPI full.StateAPI, accessor retrievalmarket.BlockstoreAccessor, j journal.Journal) (retrievalmarket.RetrievalClient, error) { + ds dtypes.MetadataDS, chainAPI full.ChainAPI, stateAPI full.StateAPI, accessor *retrievaladapter.APIBlockstoreAccessor, j journal.Journal) (retrievalmarket.RetrievalClient, error) { adapter := retrievaladapter.NewRetrievalClientNode(forceOffChain, payAPI, chainAPI, stateAPI) network := rmnet.NewFromLibp2pHost(h) ds = namespace.Wrap(ds, datastore.NewKey("/retrievals/client")) diff --git a/node/modules/dtypes/api.go b/node/modules/dtypes/api.go index d57b05cfa..6de511b9d 100644 --- a/node/modules/dtypes/api.go +++ b/node/modules/dtypes/api.go @@ -1,6 +1,8 @@ package dtypes import ( + "time" + "github.com/gbrlsnchs/jwt/v3" "github.com/multiformats/go-multiaddr" ) @@ -8,3 +10,5 @@ import ( type APIAlg jwt.HMACSHA type APIEndpoint multiaddr.Multiaddr + +type NodeStartTime time.Time diff --git a/node/modules/mpoolnonceapi.go b/node/modules/mpoolnonceapi.go index 00e704727..393bee32f 100644 --- a/node/modules/mpoolnonceapi.go +++ b/node/modules/mpoolnonceapi.go @@ -9,7 +9,7 @@ import ( "github.com/filecoin-project/go-address" - "github.com/filecoin-project/lotus/chain/messagesigner" + "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node/impl/full" ) @@ -104,4 +104,4 @@ func (a *MpoolNonceAPI) GetActor(ctx context.Context, addr address.Address, tsk return act, nil } -var _ messagesigner.MpoolNonceAPI = (*MpoolNonceAPI)(nil) +var _ messagepool.MpoolNonceAPI = (*MpoolNonceAPI)(nil) diff --git a/node/modules/rpc.go b/node/modules/rpc.go new file mode 100644 index 000000000..d76949737 --- /dev/null +++ b/node/modules/rpc.go @@ -0,0 +1,55 @@ +package modules + +import ( + "context" + + rpc "github.com/libp2p/go-libp2p-gorpc" + "github.com/libp2p/go-libp2p/core/host" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/libp2p/go-libp2p/core/protocol" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types" + consensus "github.com/filecoin-project/lotus/lib/consensus/raft" + "github.com/filecoin-project/lotus/node/impl/full" +) + +type RPCHandler struct { + mpoolAPI full.MpoolAPI + cons *consensus.Consensus +} + +func NewRPCHandler(mpoolAPI full.MpoolAPI, cons *consensus.Consensus) *RPCHandler { + return &RPCHandler{mpoolAPI, cons} +} + +func (h *RPCHandler) MpoolPushMessage(ctx context.Context, msgWhole *api.MpoolMessageWhole, ret *types.SignedMessage) error { + signedMsg, err := h.mpoolAPI.MpoolPushMessage(ctx, msgWhole.Msg, msgWhole.Spec) + if err != nil { + return err + } + *ret = *signedMsg + return nil +} + +func (h *RPCHandler) AddPeer(ctx context.Context, pid peer.ID, ret *struct{}) error { + return h.cons.AddPeer(ctx, pid) +} + +// Add other consensus RPC calls here + +func NewRPCClient(host host.Host) *rpc.Client { + protocolID := protocol.ID("/rpc/lotus-chain/v0") + return rpc.NewClient(host, protocolID) +} + +func NewRPCServer(ctx context.Context, host host.Host, rpcHandler *RPCHandler) error { + + authF := func(pid peer.ID, svc, method string) bool { + return rpcHandler.cons.IsTrustedPeer(ctx, pid) + } + + protocolID := protocol.ID("/rpc/lotus-chain/v0") + rpcServer := rpc.NewServer(host, protocolID, rpc.WithAuthorizeFunc(authF)) + return rpcServer.RegisterName("Consensus", rpcHandler) +} diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 0d85cd168..04814ffdc 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -37,7 +37,6 @@ import ( storageimpl "github.com/filecoin-project/go-fil-markets/storagemarket/impl" "github.com/filecoin-project/go-fil-markets/storagemarket/impl/storedask" smnet "github.com/filecoin-project/go-fil-markets/storagemarket/network" - "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-jsonrpc/auth" "github.com/filecoin-project/go-paramfetch" "github.com/filecoin-project/go-state-types/abi" @@ -56,7 +55,6 @@ import ( "github.com/filecoin-project/lotus/chain/gen/slashfilter" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/journal" - "github.com/filecoin-project/lotus/lib/retry" "github.com/filecoin-project/lotus/markets" "github.com/filecoin-project/lotus/markets/dagstore" "github.com/filecoin-project/lotus/markets/idxprov" @@ -89,12 +87,7 @@ func (a *UuidWrapper) MpoolPushMessage(ctx context.Context, msg *types.Message, spec = new(api.MessageSendSpec) } spec.MsgUuid = uuid.New() - errorsToRetry := []error{&jsonrpc.RPCConnectionError{}} - initialBackoff, err := time.ParseDuration("1s") - if err != nil { - return nil, err - } - return retry.Retry(5, initialBackoff, errorsToRetry, func() (*types.SignedMessage, error) { return a.FullNode.MpoolPushMessage(ctx, msg, spec) }) + return a.FullNode.MpoolPushMessage(ctx, msg, spec) } func MakeUuidWrapper(a v1api.RawFullNodeAPI) v1api.FullNode { @@ -110,24 +103,31 @@ func minerAddrFromDS(ds dtypes.MetadataDS) (address.Address, error) { return address.NewFromBytes(maddrb) } -func GetParams(spt abi.RegisteredSealProof) error { - ssize, err := spt.SectorSize() - if err != nil { - return err - } +func GetParams(prover bool) func(spt abi.RegisteredSealProof) error { + return func(spt abi.RegisteredSealProof) error { + ssize, err := spt.SectorSize() + if err != nil { + return err + } + + // If built-in assets are disabled, we expect the user to have placed the right + // parameters in the right location on the filesystem (/var/tmp/filecoin-proof-parameters). + if build.DisableBuiltinAssets { + return nil + } + + var provingSize uint64 + if prover { + provingSize = uint64(ssize) + } + + // TODO: We should fetch the params for the actual proof type, not just based on the size. + if err := paramfetch.GetParams(context.TODO(), build.ParametersJSON(), build.SrsJSON(), provingSize); err != nil { + return xerrors.Errorf("fetching proof parameters: %w", err) + } - // If built-in assets are disabled, we expect the user to have placed the right - // parameters in the right location on the filesystem (/var/tmp/filecoin-proof-parameters). - if build.DisableBuiltinAssets { return nil } - - // TODO: We should fetch the params for the actual proof type, not just based on the size. - if err := paramfetch.GetParams(context.TODO(), build.ParametersJSON(), build.SrsJSON(), uint64(ssize)); err != nil { - return xerrors.Errorf("fetching proof parameters: %w", err) - } - - return nil } func MinerAddress(ds dtypes.MetadataDS) (dtypes.MinerAddress, error) { @@ -787,17 +787,17 @@ func LocalStorage(mctx helpers.MetricsCtx, lc fx.Lifecycle, ls paths.LocalStorag return paths.NewLocal(ctx, ls, si, urls) } -func RemoteStorage(lstor *paths.Local, si paths.SectorIndex, sa sealer.StorageAuth, sc sealer.Config) *paths.Remote { +func RemoteStorage(lstor *paths.Local, si paths.SectorIndex, sa sealer.StorageAuth, sc config.SealerConfig) *paths.Remote { return paths.NewRemote(lstor, si, http.Header(sa), sc.ParallelFetchLimit, &paths.DefaultPartialFileHandler{}) } -func SectorStorage(mctx helpers.MetricsCtx, lc fx.Lifecycle, lstor *paths.Local, stor paths.Store, ls paths.LocalStorage, si paths.SectorIndex, sc sealer.Config, ds dtypes.MetadataDS) (*sealer.Manager, error) { +func SectorStorage(mctx helpers.MetricsCtx, lc fx.Lifecycle, lstor *paths.Local, stor paths.Store, ls paths.LocalStorage, si paths.SectorIndex, sc config.SealerConfig, pc config.ProvingConfig, ds dtypes.MetadataDS) (*sealer.Manager, error) { ctx := helpers.LifecycleCtx(mctx, lc) wsts := statestore.New(namespace.Wrap(ds, WorkerCallsPrefix)) smsts := statestore.New(namespace.Wrap(ds, ManagerWorkPrefix)) - sst, err := sealer.New(ctx, lstor, stor, ls, si, sc, wsts, smsts) + sst, err := sealer.New(ctx, lstor, stor, ls, si, sc, pc, wsts, smsts) if err != nil { return nil, err } diff --git a/node/options.go b/node/options.go index 0793a150f..26c2c247f 100644 --- a/node/options.go +++ b/node/options.go @@ -93,6 +93,12 @@ func From(typ interface{}) interface{} { }).Interface() } +func FromVal[T any](v T) func() T { + return func() T { + return v + } +} + // from go-ipfs // as casts input constructor to a given interface (if a value is given, it // wraps it into a constructor). diff --git a/node/repo/fsrepo.go b/node/repo/fsrepo.go index 9327575dd..68550e389 100644 --- a/node/repo/fsrepo.go +++ b/node/repo/fsrepo.go @@ -25,8 +25,8 @@ import ( badgerbs "github.com/filecoin-project/lotus/blockstore/badger" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node/config" - "github.com/filecoin-project/lotus/storage/paths" "github.com/filecoin-project/lotus/storage/sealer/fsutil" + "github.com/filecoin-project/lotus/storage/sealer/storiface" ) const ( @@ -572,26 +572,26 @@ func (fsr *fsLockedRepo) SetConfig(c func(interface{})) error { return nil } -func (fsr *fsLockedRepo) GetStorage() (paths.StorageConfig, error) { +func (fsr *fsLockedRepo) GetStorage() (storiface.StorageConfig, error) { fsr.storageLk.Lock() defer fsr.storageLk.Unlock() return fsr.getStorage(nil) } -func (fsr *fsLockedRepo) getStorage(def *paths.StorageConfig) (paths.StorageConfig, error) { +func (fsr *fsLockedRepo) getStorage(def *storiface.StorageConfig) (storiface.StorageConfig, error) { c, err := config.StorageFromFile(fsr.join(fsStorageConfig), def) if err != nil { - return paths.StorageConfig{}, err + return storiface.StorageConfig{}, err } return *c, nil } -func (fsr *fsLockedRepo) SetStorage(c func(*paths.StorageConfig)) error { +func (fsr *fsLockedRepo) SetStorage(c func(*storiface.StorageConfig)) error { fsr.storageLk.Lock() defer fsr.storageLk.Unlock() - sc, err := fsr.getStorage(&paths.StorageConfig{}) + sc, err := fsr.getStorage(&storiface.StorageConfig{}) if err != nil { return xerrors.Errorf("get storage: %w", err) } diff --git a/node/repo/interface.go b/node/repo/interface.go index 4f0294713..dd0839559 100644 --- a/node/repo/interface.go +++ b/node/repo/interface.go @@ -9,8 +9,8 @@ import ( "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/storage/paths" "github.com/filecoin-project/lotus/storage/sealer/fsutil" + "github.com/filecoin-project/lotus/storage/sealer/storiface" ) // BlockstoreDomain represents the domain of a blockstore. @@ -73,8 +73,8 @@ type LockedRepo interface { Config() (interface{}, error) SetConfig(func(interface{})) error - GetStorage() (paths.StorageConfig, error) - SetStorage(func(*paths.StorageConfig)) error + GetStorage() (storiface.StorageConfig, error) + SetStorage(func(*storiface.StorageConfig)) error Stat(path string) (fsutil.FsStat, error) DiskUsage(path string) (int64, error) diff --git a/node/repo/memrepo.go b/node/repo/memrepo.go index 53fd1eeee..61d960872 100644 --- a/node/repo/memrepo.go +++ b/node/repo/memrepo.go @@ -18,7 +18,6 @@ import ( "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node/config" - "github.com/filecoin-project/lotus/storage/paths" "github.com/filecoin-project/lotus/storage/sealer/fsutil" "github.com/filecoin-project/lotus/storage/sealer/storiface" ) @@ -37,7 +36,7 @@ type MemRepo struct { keystore map[string]types.KeyInfo blockstore blockstore.Blockstore - sc *paths.StorageConfig + sc *storiface.StorageConfig tempDir string // holds the current config value @@ -59,13 +58,13 @@ func (lmem *lockedMemRepo) RepoType() RepoType { return lmem.t } -func (lmem *lockedMemRepo) GetStorage() (paths.StorageConfig, error) { +func (lmem *lockedMemRepo) GetStorage() (storiface.StorageConfig, error) { if err := lmem.checkToken(); err != nil { - return paths.StorageConfig{}, err + return storiface.StorageConfig{}, err } if lmem.mem.sc == nil { - lmem.mem.sc = &paths.StorageConfig{StoragePaths: []paths.LocalPath{ + lmem.mem.sc = &storiface.StorageConfig{StoragePaths: []storiface.LocalPath{ {Path: lmem.Path()}, }} } @@ -73,7 +72,7 @@ func (lmem *lockedMemRepo) GetStorage() (paths.StorageConfig, error) { return *lmem.mem.sc, nil } -func (lmem *lockedMemRepo) SetStorage(c func(*paths.StorageConfig)) error { +func (lmem *lockedMemRepo) SetStorage(c func(*storiface.StorageConfig)) error { if err := lmem.checkToken(); err != nil { return err } @@ -126,14 +125,14 @@ func (lmem *lockedMemRepo) Path() string { } func (lmem *lockedMemRepo) initSectorStore(t string) { - if err := config.WriteStorageFile(filepath.Join(t, fsStorageConfig), paths.StorageConfig{ - StoragePaths: []paths.LocalPath{ + if err := config.WriteStorageFile(filepath.Join(t, fsStorageConfig), storiface.StorageConfig{ + StoragePaths: []storiface.LocalPath{ {Path: t}, }}); err != nil { panic(err) } - b, err := json.MarshalIndent(&paths.LocalStorageMeta{ + b, err := json.MarshalIndent(&storiface.LocalStorageMeta{ ID: storiface.ID(uuid.New().String()), Weight: 10, CanSeal: true, diff --git a/node/rpc.go b/node/rpc.go index 2c85c71be..96a81a383 100644 --- a/node/rpc.go +++ b/node/rpc.go @@ -3,13 +3,16 @@ package node import ( "context" "encoding/json" + "fmt" "net" "net/http" _ "net/http/pprof" "runtime" "strconv" + "github.com/google/uuid" "github.com/gorilla/mux" + "github.com/gorilla/websocket" "github.com/ipfs/go-cid" logging "github.com/ipfs/go-log/v2" "github.com/multiformats/go-multiaddr" @@ -23,6 +26,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/v0api" "github.com/filecoin-project/lotus/api/v1api" + bstore "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/lib/rpcenc" "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/metrics/proxy" @@ -92,6 +96,7 @@ func FullNodeHandler(a v1api.FullNode, permissioned bool, opts ...jsonrpc.Server // Import handler handleImportFunc := handleImport(a.(*impl.FullNodeAPI)) handleExportFunc := handleExport(a.(*impl.FullNodeAPI)) + handleRemoteStoreFunc := handleRemoteStore(a.(*impl.FullNodeAPI)) if permissioned { importAH := &auth.Handler{ Verify: a.AuthVerify, @@ -104,9 +109,16 @@ func FullNodeHandler(a v1api.FullNode, permissioned bool, opts ...jsonrpc.Server Next: handleExportFunc, } m.Handle("/rest/v0/export", exportAH) + + storeAH := &auth.Handler{ + Verify: a.AuthVerify, + Next: handleRemoteStoreFunc, + } + m.Handle("/rest/v0/store/{uuid}", storeAH) } else { m.HandleFunc("/rest/v0/import", handleImportFunc) m.HandleFunc("/rest/v0/export", handleExportFunc) + m.HandleFunc("/rest/v0/store/{uuid}", handleRemoteStoreFunc) } // debugging @@ -256,3 +268,34 @@ func handleFractionOpt(name string, setter func(int)) http.HandlerFunc { setter(fr) } } + +var upgrader = websocket.Upgrader{ + CheckOrigin: func(r *http.Request) bool { + return true + }, +} + +func handleRemoteStore(a *impl.FullNodeAPI) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + id, err := uuid.Parse(vars["uuid"]) + if err != nil { + http.Error(w, fmt.Sprintf("parse uuid: %s", err), http.StatusBadRequest) + return + } + + c, err := upgrader.Upgrade(w, r, nil) + if err != nil { + log.Error(err) + w.WriteHeader(500) + return + } + + nstore := bstore.NewNetworkStoreWS(c) + if err := a.ApiBlockstoreAccessor.RegisterApiStore(id, nstore); err != nil { + log.Errorw("registering api bstore", "error", err) + _ = c.Close() + return + } + } +} diff --git a/scripts/build-appimage-bundle.sh b/scripts/build-appimage-bundle.sh index d99b459b9..d4ce6de77 100755 --- a/scripts/build-appimage-bundle.sh +++ b/scripts/build-appimage-bundle.sh @@ -20,7 +20,7 @@ PID="$!" trap "kill -9 ${PID}" EXIT sleep 30 -cp "../appimage/Lotus-${CIRCLE_TAG}-x86_64.AppImage" . +cp "/tmp/workspace/appimage/Lotus-${CIRCLE_TAG}-x86_64.AppImage" . sha512sum "Lotus-${CIRCLE_TAG}-x86_64.AppImage" > "Lotus-${CIRCLE_TAG}-x86_64.AppImage.sha512" ipfs add -q "Lotus-${CIRCLE_TAG}-x86_64.AppImage" > "Lotus-${CIRCLE_TAG}-x86_64.AppImage.cid" popd diff --git a/storage/paths/local.go b/storage/paths/local.go index ec146ba5a..2182f24ef 100644 --- a/storage/paths/local.go +++ b/storage/paths/local.go @@ -17,71 +17,14 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/proof" + "github.com/filecoin-project/lotus/lib/result" "github.com/filecoin-project/lotus/storage/sealer/fsutil" "github.com/filecoin-project/lotus/storage/sealer/storiface" ) -// LocalStorageMeta [path]/sectorstore.json -type LocalStorageMeta struct { - ID storiface.ID - - // A high weight means data is more likely to be stored in this path - Weight uint64 // 0 = readonly - - // Intermediate data for the sealing process will be stored here - CanSeal bool - - // Finalized sectors that will be proved over time will be stored here - CanStore bool - - // MaxStorage specifies the maximum number of bytes to use for sector storage - // (0 = unlimited) - MaxStorage uint64 - - // List of storage groups this path belongs to - Groups []string - - // List of storage groups to which data from this path can be moved. If none - // are specified, allow to all - AllowTo []string - - // AllowTypes lists sector file types which are allowed to be put into this - // path. If empty, all file types are allowed. - // - // Valid values: - // - "unsealed" - // - "sealed" - // - "cache" - // - "update" - // - "update-cache" - // Any other value will generate a warning and be ignored. - AllowTypes []string - - // DenyTypes lists sector file types which aren't allowed to be put into this - // path. - // - // Valid values: - // - "unsealed" - // - "sealed" - // - "cache" - // - "update" - // - "update-cache" - // Any other value will generate a warning and be ignored. - DenyTypes []string -} - -// StorageConfig .lotusstorage/storage.json -type StorageConfig struct { - StoragePaths []LocalPath -} - -type LocalPath struct { - Path string -} - type LocalStorage interface { - GetStorage() (StorageConfig, error) - SetStorage(func(*StorageConfig)) error + GetStorage() (storiface.StorageConfig, error) + SetStorage(func(*storiface.StorageConfig)) error Stat(path string) (fsutil.FsStat, error) @@ -213,7 +156,7 @@ func (st *Local) OpenPath(ctx context.Context, p string) error { return xerrors.Errorf("reading storage metadata for %s: %w", p, err) } - var meta LocalStorageMeta + var meta storiface.LocalStorageMeta if err := json.Unmarshal(mb, &meta); err != nil { return xerrors.Errorf("unmarshalling storage metadata for %s: %w", p, err) } @@ -309,7 +252,7 @@ func (st *Local) Redeclare(ctx context.Context, filterId *storiface.ID, dropMiss return xerrors.Errorf("reading storage metadata for %s: %w", p.local, err) } - var meta LocalStorageMeta + var meta storiface.LocalStorageMeta if err := json.Unmarshal(mb, &meta); err != nil { return xerrors.Errorf("unmarshalling storage metadata for %s: %w", p.local, err) } @@ -816,20 +759,22 @@ func (st *Local) GenerateSingleVanillaProof(ctx context.Context, minerID abi.Act ProofType: si.SealProof, } - var cache string - var sealed string + var cache, sealed, cacheID, sealedID string + if si.Update { - src, _, err := st.AcquireSector(ctx, sr, storiface.FTUpdate|storiface.FTUpdateCache, storiface.FTNone, storiface.PathStorage, storiface.AcquireMove) + src, si, err := st.AcquireSector(ctx, sr, storiface.FTUpdate|storiface.FTUpdateCache, storiface.FTNone, storiface.PathStorage, storiface.AcquireMove) if err != nil { return nil, xerrors.Errorf("acquire sector: %w", err) } cache, sealed = src.UpdateCache, src.Update + cacheID, sealedID = si.UpdateCache, si.Update } else { - src, _, err := st.AcquireSector(ctx, sr, storiface.FTSealed|storiface.FTCache, storiface.FTNone, storiface.PathStorage, storiface.AcquireMove) + src, si, err := st.AcquireSector(ctx, sr, storiface.FTSealed|storiface.FTCache, storiface.FTNone, storiface.PathStorage, storiface.AcquireMove) if err != nil { return nil, xerrors.Errorf("acquire sector: %w", err) } cache, sealed = src.Cache, src.Sealed + cacheID, sealedID = si.Cache, si.Sealed } if sealed == "" || cache == "" { @@ -847,7 +792,22 @@ func (st *Local) GenerateSingleVanillaProof(ctx context.Context, minerID abi.Act SealedSectorPath: sealed, } - return ffi.GenerateSingleVanillaProof(psi, si.Challenge) + start := time.Now() + + resCh := make(chan result.Result[[]byte], 1) + go func() { + resCh <- result.Wrap(ffi.GenerateSingleVanillaProof(psi, si.Challenge)) + }() + + select { + case r := <-resCh: + return r.Unwrap() + case <-ctx.Done(): + log.Errorw("failed to generate valilla PoSt proof before context cancellation", "err", ctx.Err(), "duration", time.Now().Sub(start), "cache-id", cacheID, "sealed-id", sealedID, "cache", cache, "sealed", sealed) + + // this will leave the GenerateSingleVanillaProof goroutine hanging, but that's still less bad than failing PoSt + return nil, xerrors.Errorf("failed to generate vanilla proof before context cancellation: %w", ctx.Err()) + } } var _ Store = &Local{} diff --git a/storage/paths/local_test.go b/storage/paths/local_test.go index 83e8e27fd..6b9f4a545 100644 --- a/storage/paths/local_test.go +++ b/storage/paths/local_test.go @@ -19,18 +19,18 @@ const pathSize = 16 << 20 type TestingLocalStorage struct { root string - c StorageConfig + c storiface.StorageConfig } func (t *TestingLocalStorage) DiskUsage(path string) (int64, error) { return 1, nil } -func (t *TestingLocalStorage) GetStorage() (StorageConfig, error) { +func (t *TestingLocalStorage) GetStorage() (storiface.StorageConfig, error) { return t.c, nil } -func (t *TestingLocalStorage) SetStorage(f func(*StorageConfig)) error { +func (t *TestingLocalStorage) SetStorage(f func(*storiface.StorageConfig)) error { f(&t.c) return nil } @@ -51,7 +51,7 @@ func (t *TestingLocalStorage) init(subpath string) error { metaFile := filepath.Join(path, MetaFile) - meta := &LocalStorageMeta{ + meta := &storiface.LocalStorageMeta{ ID: storiface.ID(uuid.New().String()), Weight: 1, CanSeal: true, diff --git a/storage/paths/localstorage_cached.go b/storage/paths/localstorage_cached.go index 4ccabb15e..cac0a44b6 100644 --- a/storage/paths/localstorage_cached.go +++ b/storage/paths/localstorage_cached.go @@ -7,6 +7,7 @@ import ( lru "github.com/hashicorp/golang-lru" "github.com/filecoin-project/lotus/storage/sealer/fsutil" + "github.com/filecoin-project/lotus/storage/sealer/storiface" ) var StatTimeout = 5 * time.Second @@ -47,11 +48,11 @@ type diskUsageResult struct { time time.Time } -func (c *cachedLocalStorage) GetStorage() (StorageConfig, error) { +func (c *cachedLocalStorage) GetStorage() (storiface.StorageConfig, error) { return c.base.GetStorage() } -func (c *cachedLocalStorage) SetStorage(f func(*StorageConfig)) error { +func (c *cachedLocalStorage) SetStorage(f func(*storiface.StorageConfig)) error { return c.base.SetStorage(f) } diff --git a/storage/paths/remote_test.go b/storage/paths/remote_test.go index a7bd6bf40..2d7fe2c73 100644 --- a/storage/paths/remote_test.go +++ b/storage/paths/remote_test.go @@ -38,7 +38,7 @@ func createTestStorage(t *testing.T, p string, seal bool, att ...*paths.Local) s } } - cfg := &paths.LocalStorageMeta{ + cfg := &storiface.LocalStorageMeta{ ID: storiface.ID(uuid.New().String()), Weight: 10, CanSeal: seal, @@ -77,8 +77,8 @@ func TestMoveShared(t *testing.T) { _ = lr.Close() }) - err = lr.SetStorage(func(config *paths.StorageConfig) { - *config = paths.StorageConfig{} + err = lr.SetStorage(func(config *storiface.StorageConfig) { + *config = storiface.StorageConfig{} }) require.NoError(t, err) diff --git a/storage/pipeline/fsm.go b/storage/pipeline/fsm.go index 0a75d88c8..25fd6fcef 100644 --- a/storage/pipeline/fsm.go +++ b/storage/pipeline/fsm.go @@ -188,6 +188,11 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto SubmitReplicaUpdate: planOne( on(SectorReplicaUpdateSubmitted{}, ReplicaUpdateWait), on(SectorSubmitReplicaUpdateFailed{}, ReplicaUpdateFailed), + on(SectorDeadlineImmutable{}, WaitMutable), + ), + WaitMutable: planOne( + on(SectorDeadlineMutable{}, SubmitReplicaUpdate), + on(SectorAbortUpgrade{}, AbortUpgrade), ), ReplicaUpdateWait: planOne( on(SectorReplicaUpdateLanded{}, UpdateActivating), @@ -525,6 +530,8 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta return m.handleProveReplicaUpdate, processed, nil case SubmitReplicaUpdate: return m.handleSubmitReplicaUpdate, processed, nil + case WaitMutable: + return m.handleWaitMutable, processed, nil case ReplicaUpdateWait: return m.handleReplicaUpdateWait, processed, nil case FinalizeReplicaUpdate: diff --git a/storage/pipeline/fsm_events.go b/storage/pipeline/fsm_events.go index f92f527ad..122691ca3 100644 --- a/storage/pipeline/fsm_events.go +++ b/storage/pipeline/fsm_events.go @@ -323,6 +323,9 @@ func (evt SectorStartCCUpdate) apply(state *SectorInfo) { // Clear filler piece but remember in case of abort state.CCPieces = state.Pieces state.Pieces = nil + + // Clear CreationTime in case this sector was accepting piece data previously + state.CreationTime = 0 } type SectorReplicaUpdate struct { @@ -458,6 +461,7 @@ func (evt SectorRevertUpgradeToProving) apply(state *SectorInfo) { state.ReplicaUpdateMessage = nil state.Pieces = state.CCPieces state.CCPieces = nil + state.CreationTime = 0 } type SectorRetrySubmitReplicaUpdateWait struct{} @@ -472,6 +476,14 @@ type SectorSubmitReplicaUpdateFailed struct{} func (evt SectorSubmitReplicaUpdateFailed) apply(state *SectorInfo) {} +type SectorDeadlineImmutable struct{} + +func (evt SectorDeadlineImmutable) apply(state *SectorInfo) {} + +type SectorDeadlineMutable struct{} + +func (evt SectorDeadlineMutable) apply(state *SectorInfo) {} + type SectorReleaseKeyFailed struct{ error } func (evt SectorReleaseKeyFailed) FormatError(xerrors.Printer) (next error) { diff --git a/storage/pipeline/fsm_test.go b/storage/pipeline/fsm_test.go index 53f85d1dc..f12b66f93 100644 --- a/storage/pipeline/fsm_test.go +++ b/storage/pipeline/fsm_test.go @@ -390,3 +390,64 @@ func TestTicketExpired(t *testing.T) { } } } + +func TestCreationTimeCleared(t *testing.T) { + var notif []struct{ before, after SectorInfo } + ma, _ := address.NewIDAddress(55151) + m := test{ + s: &Sealing{ + maddr: ma, + stats: SectorStats{ + bySector: map[abi.SectorID]SectorState{}, + byState: map[SectorState]int64{}, + }, + notifee: func(before, after SectorInfo) { + notif = append(notif, struct{ before, after SectorInfo }{before, after}) + }, + }, + t: t, + state: &SectorInfo{State: Available}, + } + + // sector starts with zero CreationTime + m.planSingle(SectorStartCCUpdate{}) + require.Equal(m.t, m.state.State, SnapDealsWaitDeals) + + require.Equal(t, int64(0), m.state.CreationTime) + + // First AddPiece will set CreationTime + m.planSingle(SectorAddPiece{}) + require.Equal(m.t, m.state.State, SnapDealsAddPiece) + + require.NotEqual(t, int64(0), m.state.CreationTime) + + m.planSingle(SectorPieceAdded{}) + require.Equal(m.t, m.state.State, SnapDealsWaitDeals) + + // abort shoult clean up CreationTime + m.planSingle(SectorAbortUpgrade{}) + require.Equal(m.t, m.state.State, AbortUpgrade) + + require.NotEqual(t, int64(0), m.state.CreationTime) + + m.planSingle(SectorRevertUpgradeToProving{}) + require.Equal(m.t, m.state.State, Proving) + + require.Equal(t, int64(0), m.state.CreationTime) + + m.planSingle(SectorMarkForUpdate{}) + + // in case CreationTime was set for whatever reason (lotus bug / manual sector state change) + // make sure we clean it up when starting upgrade + m.state.CreationTime = 325 + m.planSingle(SectorStartCCUpdate{}) + require.Equal(m.t, m.state.State, SnapDealsWaitDeals) + + require.Equal(t, int64(0), m.state.CreationTime) + + // "First" AddPiece will set CreationTime + m.planSingle(SectorAddPiece{}) + require.Equal(m.t, m.state.State, SnapDealsAddPiece) + + require.NotEqual(t, int64(0), m.state.CreationTime) +} diff --git a/storage/pipeline/input.go b/storage/pipeline/input.go index 7b5b8c600..25c752e5f 100644 --- a/storage/pipeline/input.go +++ b/storage/pipeline/input.go @@ -6,6 +6,7 @@ import ( "time" "github.com/ipfs/go-cid" + "go.uber.org/zap" "golang.org/x/xerrors" "github.com/filecoin-project/go-commp-utils/zerocomm" @@ -91,12 +92,17 @@ func (m *Sealing) handleWaitDeals(ctx statemachine.Context, sector SectorInfo) e } func (m *Sealing) maybeStartSealing(ctx statemachine.Context, sector SectorInfo, used abi.UnpaddedPieceSize) (bool, error) { + log := log.WithOptions(zap.Fields( + zap.Uint64("sector", uint64(sector.SectorNumber)), + zap.Int("deals", len(sector.dealIDs())), + )) + now := time.Now() st := m.sectorTimers[m.minerSectorID(sector.SectorNumber)] if st != nil { if !st.Stop() { // timer expired, SectorStartPacking was/is being sent // we send another SectorStartPacking in case one was sent in the handleAddPiece state - log.Infow("starting to seal deal sector", "sector", sector.SectorNumber, "trigger", "wait-timeout") + log.Infow("starting to seal deal sector", "trigger", "wait-timeout") return true, ctx.Send(SectorStartPacking{}) } } @@ -113,13 +119,13 @@ func (m *Sealing) maybeStartSealing(ctx statemachine.Context, sector SectorInfo, if len(sector.dealIDs()) >= maxDeals { // can't accept more deals - log.Infow("starting to seal deal sector", "sector", sector.SectorNumber, "trigger", "maxdeals") + log.Infow("starting to seal deal sector", "trigger", "maxdeals") return true, ctx.Send(SectorStartPacking{}) } if used.Padded() == abi.PaddedPieceSize(ssize) { // sector full - log.Infow("starting to seal deal sector", "sector", sector.SectorNumber, "trigger", "filled") + log.Infow("starting to seal deal sector", "trigger", "filled") return true, ctx.Send(SectorStartPacking{}) } @@ -149,15 +155,15 @@ func (m *Sealing) maybeStartSealing(ctx statemachine.Context, sector SectorInfo, } if now.After(sealTime) { - log.Infow("starting to seal deal sector", "sector", sector.SectorNumber, "trigger", "wait-timeout") + log.Infow("starting to seal deal sector", "trigger", "wait-timeout", "creation", sector.CreationTime) return true, ctx.Send(SectorStartPacking{}) } m.sectorTimers[m.minerSectorID(sector.SectorNumber)] = time.AfterFunc(sealTime.Sub(now), func() { - log.Infow("starting to seal deal sector", "sector", sector.SectorNumber, "trigger", "wait-timer") + log.Infow("starting to seal deal sector", "trigger", "wait-timer") if err := ctx.Send(SectorStartPacking{}); err != nil { - log.Errorw("sending SectorStartPacking event failed", "sector", sector.SectorNumber, "error", err) + log.Errorw("sending SectorStartPacking event failed", "error", err) } }) } diff --git a/storage/pipeline/sector_state.go b/storage/pipeline/sector_state.go index 7a56c136b..84c08f43b 100644 --- a/storage/pipeline/sector_state.go +++ b/storage/pipeline/sector_state.go @@ -53,6 +53,7 @@ var ExistSectorStateList = map[SectorState]struct{}{ UpdateReplica: {}, ProveReplicaUpdate: {}, SubmitReplicaUpdate: {}, + WaitMutable: {}, ReplicaUpdateWait: {}, UpdateActivating: {}, ReleaseSectorKey: {}, @@ -110,6 +111,7 @@ const ( UpdateReplica SectorState = "UpdateReplica" ProveReplicaUpdate SectorState = "ProveReplicaUpdate" SubmitReplicaUpdate SectorState = "SubmitReplicaUpdate" + WaitMutable SectorState = "WaitMutable" ReplicaUpdateWait SectorState = "ReplicaUpdateWait" FinalizeReplicaUpdate SectorState = "FinalizeReplicaUpdate" UpdateActivating SectorState = "UpdateActivating" @@ -161,7 +163,7 @@ func toStatState(st SectorState, finEarly bool) statSectorState { return sstStaging case Packing, GetTicket, PreCommit1, PreCommit2, PreCommitting, PreCommitWait, SubmitPreCommitBatch, PreCommitBatchWait, WaitSeed, Committing, CommitFinalize, FinalizeSector, SnapDealsPacking, UpdateReplica, ProveReplicaUpdate, FinalizeReplicaUpdate, ReceiveSector: return sstSealing - case SubmitCommit, CommitWait, SubmitCommitAggregate, CommitAggregateWait, SubmitReplicaUpdate, ReplicaUpdateWait: + case SubmitCommit, CommitWait, SubmitCommitAggregate, CommitAggregateWait, WaitMutable, SubmitReplicaUpdate, ReplicaUpdateWait: if finEarly { // we use statSectorState for throttling storage use. With FinalizeEarly // we can consider sectors in states after CommitFinalize as finalized, so @@ -184,6 +186,7 @@ func IsUpgradeState(st SectorState) bool { UpdateReplica, ProveReplicaUpdate, SubmitReplicaUpdate, + WaitMutable, SnapDealsAddPieceFailed, SnapDealsDealsExpired, diff --git a/storage/pipeline/states_failed.go b/storage/pipeline/states_failed.go index b90833b2d..942f4f8dc 100644 --- a/storage/pipeline/states_failed.go +++ b/storage/pipeline/states_failed.go @@ -257,8 +257,9 @@ func (m *Sealing) handleSubmitReplicaUpdateFailed(ctx statemachine.Context, sect return nil } if !active { - log.Errorf("sector marked for upgrade %d no longer active, aborting upgrade", sector.SectorNumber) - return ctx.Send(SectorAbortUpgrade{}) + err := xerrors.Errorf("sector marked for upgrade %d no longer active, aborting upgrade", sector.SectorNumber) + log.Errorf(err.Error()) + return ctx.Send(SectorAbortUpgrade{err}) } return ctx.Send(SectorRetrySubmitReplicaUpdate{}) @@ -421,6 +422,8 @@ func (m *Sealing) handleAbortUpgrade(ctx statemachine.Context, sector SectorInfo return xerrors.Errorf("should never reach AbortUpgrade as a non-CCUpdate sector") } + m.cleanupAssignedDeals(sector) + // Remove snap deals replica if any if err := m.sealer.ReleaseReplicaUpgrade(ctx.Context(), m.minerSector(sector.SectorType, sector.SectorNumber)); err != nil { return xerrors.Errorf("removing CC update files from sector storage") diff --git a/storage/pipeline/states_proving.go b/storage/pipeline/states_proving.go index f4b957249..bed61a452 100644 --- a/storage/pipeline/states_proving.go +++ b/storage/pipeline/states_proving.go @@ -138,6 +138,12 @@ func (m *Sealing) handleProvingSector(ctx statemachine.Context, sector SectorInf delete(m.available, m.minerSectorID(sector.SectorNumber)) m.inputLk.Unlock() + // guard against manual state updates from snap-deals states into Proving + // note: normally snap deals should be aborted through the abort command, but + // apparently sometimes some SPs would use update-state to force the sector back + // into the Proving state, breaking the deal input pipeline in the process. + m.cleanupAssignedDeals(sector) + // TODO: Watch termination // TODO: Auto-extend if set diff --git a/storage/pipeline/states_replica_update.go b/storage/pipeline/states_replica_update.go index 9170f5fb5..6a4708379 100644 --- a/storage/pipeline/states_replica_update.go +++ b/storage/pipeline/states_replica_update.go @@ -57,8 +57,9 @@ func (m *Sealing) handleProveReplicaUpdate(ctx statemachine.Context, sector Sect return nil } if !active { - log.Errorf("sector marked for upgrade %d no longer active, aborting upgrade", sector.SectorNumber) - return ctx.Send(SectorAbortUpgrade{}) + err := xerrors.Errorf("sector marked for upgrade %d no longer active, aborting upgrade", sector.SectorNumber) + log.Errorf(err.Error()) + return ctx.Send(SectorAbortUpgrade{err}) } vanillaProofs, err := m.sealer.ProveReplicaUpdate1(sector.sealingCtx(ctx.Context()), m.minerSector(sector.SectorType, sector.SectorNumber), *sector.CommR, *sector.UpdateSealed, *sector.UpdateUnsealed) @@ -97,6 +98,17 @@ func (m *Sealing) handleSubmitReplicaUpdate(ctx statemachine.Context, sector Sec log.Errorf("handleSubmitReplicaUpdate: api error, not proceeding: %+v", err) return nil } + + dlinfo, err := m.Api.StateMinerProvingDeadline(ctx.Context(), m.maddr, ts.Key()) + if err != nil { + log.Errorf("handleSubmitReplicaUpdate: api error, not proceeding: %w", err) + } + // if sector's deadline is immutable wait in a non error state + // sector's deadline is immutable if it is the current deadline or the next deadline + if sl.Deadline == dlinfo.Index || (dlinfo.Index+1)%dlinfo.WPoStPeriodDeadlines == sl.Deadline { + return ctx.Send(SectorDeadlineImmutable{}) + } + updateProof, err := sector.SectorType.RegisteredUpdateProof() if err != nil { log.Errorf("failed to get update proof type from seal proof: %+v", err) @@ -187,6 +199,67 @@ func (m *Sealing) handleSubmitReplicaUpdate(ctx statemachine.Context, sector Sec return ctx.Send(SectorReplicaUpdateSubmitted{Message: mcid}) } +func (m *Sealing) handleWaitMutable(ctx statemachine.Context, sector SectorInfo) error { + immutable := true + for immutable { + ts, err := m.Api.ChainHead(ctx.Context()) + if err != nil { + log.Errorf("handleWaitMutable: api error, not proceeding: %+v", err) + return nil + } + + sl, err := m.Api.StateSectorPartition(ctx.Context(), m.maddr, sector.SectorNumber, ts.Key()) + if err != nil { + log.Errorf("handleWaitMutable: api error, not proceeding: %+v", err) + return nil + } + + dlinfo, err := m.Api.StateMinerProvingDeadline(ctx.Context(), m.maddr, ts.Key()) + if err != nil { + log.Errorf("handleWaitMutable: api error, not proceeding: %w", err) + return nil + } + + sectorDeadlineOpen := sl.Deadline == dlinfo.Index + sectorDeadlineNext := (dlinfo.Index+1)%dlinfo.WPoStPeriodDeadlines == sl.Deadline + immutable = sectorDeadlineOpen || sectorDeadlineNext + + // Sleep for immutable epochs + if immutable { + dlineEpochsRemaining := dlinfo.NextOpen() - ts.Height() + var targetEpoch abi.ChainEpoch + if sectorDeadlineOpen { + // sleep for remainder of deadline + targetEpoch = ts.Height() + dlineEpochsRemaining + } else { + // sleep for remainder of deadline and next one + targetEpoch = ts.Height() + dlineEpochsRemaining + dlinfo.WPoStChallengeWindow + } + + atHeight := make(chan struct{}) + err := m.events.ChainAt(ctx.Context(), func(context.Context, *types.TipSet, abi.ChainEpoch) error { + close(atHeight) + return nil + }, func(ctx context.Context, ts *types.TipSet) error { + log.Warn("revert in handleWaitMutable") + return nil + }, 5, targetEpoch) + if err != nil { + log.Errorf("handleWaitMutalbe: events error: api error, not proceeding: %w", err) + return nil + } + + select { + case <-atHeight: + case <-ctx.Context().Done(): + return ctx.Context().Err() + } + } + + } + return ctx.Send(SectorDeadlineMutable{}) +} + func (m *Sealing) handleReplicaUpdateWait(ctx statemachine.Context, sector SectorInfo) error { if sector.ReplicaUpdateMessage == nil { log.Errorf("handleReplicaUpdateWait: no replica update message cid recorded") diff --git a/storage/pipeline/states_sealing.go b/storage/pipeline/states_sealing.go index b40a9bf45..5b5d2e372 100644 --- a/storage/pipeline/states_sealing.go +++ b/storage/pipeline/states_sealing.go @@ -33,7 +33,7 @@ import ( var DealSectorPriority = 1024 var MaxTicketAge = policy.MaxPreCommitRandomnessLookback -func (m *Sealing) handlePacking(ctx statemachine.Context, sector SectorInfo) error { +func (m *Sealing) cleanupAssignedDeals(sector SectorInfo) { m.inputLk.Lock() // make sure we are not accepting deals into this sector for _, c := range m.assignedPieces[m.minerSectorID(sector.SectorNumber)] { @@ -51,6 +51,10 @@ func (m *Sealing) handlePacking(ctx statemachine.Context, sector SectorInfo) err delete(m.openSectors, m.minerSectorID(sector.SectorNumber)) delete(m.assignedPieces, m.minerSectorID(sector.SectorNumber)) m.inputLk.Unlock() +} + +func (m *Sealing) handlePacking(ctx statemachine.Context, sector SectorInfo) error { + m.cleanupAssignedDeals(sector) // if this is a snapdeals sector, but it ended up not having any deals, abort the upgrade if sector.State == SnapDealsPacking && !sector.hasDeals() { diff --git a/storage/sealer/faults.go b/storage/sealer/faults.go index e05bbb7b8..db7b75bec 100644 --- a/storage/sealer/faults.go +++ b/storage/sealer/faults.go @@ -5,7 +5,6 @@ import ( "crypto/rand" "fmt" "sync" - "time" "golang.org/x/xerrors" @@ -15,8 +14,6 @@ import ( "github.com/filecoin-project/lotus/storage/sealer/storiface" ) -var PostCheckTimeout = 160 * time.Second - // FaultTracker TODO: Track things more actively type FaultTracker interface { CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storiface.SectorRef, rg storiface.RGetter) (map[abi.SectorID]string, error) @@ -50,6 +47,12 @@ func (m *Manager) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, badLk.Unlock() } + if m.partitionCheckTimeout > 0 { + var cancel2 context.CancelFunc + ctx, cancel2 = context.WithTimeout(ctx, m.partitionCheckTimeout) + defer cancel2() + } + var wg sync.WaitGroup wg.Add(len(sectors)) @@ -57,7 +60,9 @@ func (m *Manager) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, select { case throttle <- struct{}{}: case <-ctx.Done(): - return nil, ctx.Err() + addBad(sector.ID, fmt.Sprintf("waiting for check worker: %s", ctx.Err())) + wg.Done() + continue } go func(sector storiface.SectorRef) { @@ -107,8 +112,13 @@ func (m *Manager) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, return } - vctx, cancel2 := context.WithTimeout(ctx, PostCheckTimeout) - defer cancel2() + vctx := ctx + + if m.singleCheckTimeout > 0 { + var cancel2 context.CancelFunc + vctx, cancel2 = context.WithTimeout(ctx, m.singleCheckTimeout) + defer cancel2() + } _, err = m.storage.GenerateSingleVanillaProof(vctx, sector.ID.Miner, storiface.PostSectorChallenge{ SealProof: sector.ProofType, diff --git a/storage/sealer/manager.go b/storage/sealer/manager.go index b0c023b09..b0f506539 100644 --- a/storage/sealer/manager.go +++ b/storage/sealer/manager.go @@ -7,6 +7,7 @@ import ( "net/http" "sort" "sync" + "time" "github.com/google/uuid" "github.com/hashicorp/go-multierror" @@ -19,6 +20,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-statestore" + "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/storage/paths" "github.com/filecoin-project/lotus/storage/sealer/ffiwrapper" "github.com/filecoin-project/lotus/storage/sealer/fsutil" @@ -71,6 +73,8 @@ type Manager struct { work *statestore.StateStore parallelCheckLimit int + singleCheckTimeout time.Duration + partitionCheckTimeout time.Duration disableBuiltinWindowPoSt bool disableBuiltinWinningPoSt bool disallowRemoteFinalize bool @@ -90,57 +94,12 @@ type result struct { err error } -// ResourceFilteringStrategy is an enum indicating the kinds of resource -// filtering strategies that can be configured for workers. -type ResourceFilteringStrategy string - -const ( - // ResourceFilteringHardware specifies that available hardware resources - // should be evaluated when scheduling a task against the worker. - ResourceFilteringHardware = ResourceFilteringStrategy("hardware") - - // ResourceFilteringDisabled disables resource filtering against this - // worker. The scheduler may assign any task to this worker. - ResourceFilteringDisabled = ResourceFilteringStrategy("disabled") -) - -type Config struct { - ParallelFetchLimit int - - // Local worker config - AllowSectorDownload bool - AllowAddPiece bool - AllowPreCommit1 bool - AllowPreCommit2 bool - AllowCommit bool - AllowUnseal bool - AllowReplicaUpdate bool - AllowProveReplicaUpdate2 bool - AllowRegenSectorKey bool - - LocalWorkerName string - - // ResourceFiltering instructs the system which resource filtering strategy - // to use when evaluating tasks against this worker. An empty value defaults - // to "hardware". - ResourceFiltering ResourceFilteringStrategy - - // PoSt config - ParallelCheckLimit int - DisableBuiltinWindowPoSt bool - DisableBuiltinWinningPoSt bool - - DisallowRemoteFinalize bool - - Assigner string -} - type StorageAuth http.Header type WorkerStateStore *statestore.StateStore type ManagerStateStore *statestore.StateStore -func New(ctx context.Context, lstor *paths.Local, stor paths.Store, ls paths.LocalStorage, si paths.SectorIndex, sc Config, wss WorkerStateStore, mss ManagerStateStore) (*Manager, error) { +func New(ctx context.Context, lstor *paths.Local, stor paths.Store, ls paths.LocalStorage, si paths.SectorIndex, sc config.SealerConfig, pc config.ProvingConfig, wss WorkerStateStore, mss ManagerStateStore) (*Manager, error) { prover, err := ffiwrapper.New(&readonlyProvider{stor: lstor, index: si}) if err != nil { return nil, xerrors.Errorf("creating prover instance: %w", err) @@ -164,9 +123,11 @@ func New(ctx context.Context, lstor *paths.Local, stor paths.Store, ls paths.Loc localProver: prover, - parallelCheckLimit: sc.ParallelCheckLimit, - disableBuiltinWindowPoSt: sc.DisableBuiltinWindowPoSt, - disableBuiltinWinningPoSt: sc.DisableBuiltinWinningPoSt, + parallelCheckLimit: pc.ParallelCheckLimit, + singleCheckTimeout: time.Duration(pc.SingleCheckTimeout), + partitionCheckTimeout: time.Duration(pc.PartitionCheckTimeout), + disableBuiltinWindowPoSt: pc.DisableBuiltinWindowPoSt, + disableBuiltinWinningPoSt: pc.DisableBuiltinWinningPoSt, disallowRemoteFinalize: sc.DisallowRemoteFinalize, work: mss, @@ -212,7 +173,7 @@ func New(ctx context.Context, lstor *paths.Local, stor paths.Store, ls paths.Loc } wcfg := WorkerConfig{ - IgnoreResourceFiltering: sc.ResourceFiltering == ResourceFilteringDisabled, + IgnoreResourceFiltering: sc.ResourceFiltering == config.ResourceFilteringDisabled, TaskTypes: localTasks, Name: sc.LocalWorkerName, } @@ -235,8 +196,8 @@ func (m *Manager) AddLocalStorage(ctx context.Context, path string) error { return xerrors.Errorf("opening local path: %w", err) } - if err := m.ls.SetStorage(func(sc *paths.StorageConfig) { - sc.StoragePaths = append(sc.StoragePaths, paths.LocalPath{Path: path}) + if err := m.ls.SetStorage(func(sc *storiface.StorageConfig) { + sc.StoragePaths = append(sc.StoragePaths, storiface.LocalPath{Path: path}) }); err != nil { return xerrors.Errorf("get storage config: %w", err) } @@ -269,8 +230,8 @@ func (m *Manager) DetachLocalStorage(ctx context.Context, path string) error { // drop from the persisted storage.json var found bool - if err := m.ls.SetStorage(func(sc *paths.StorageConfig) { - out := make([]paths.LocalPath, 0, len(sc.StoragePaths)) + if err := m.ls.SetStorage(func(sc *storiface.StorageConfig) { + out := make([]storiface.LocalPath, 0, len(sc.StoragePaths)) for _, storagePath := range sc.StoragePaths { if storagePath.Path != path { out = append(out, storagePath) @@ -784,11 +745,6 @@ func (m *Manager) FinalizeReplicaUpdate(ctx context.Context, sector storiface.Se move := func(types storiface.SectorFileType) error { // get a selector for moving stuff into long-term storage fetchSel := newMoveSelector(m.index, sector.ID, types, storiface.PathStorage, !m.disallowRemoteFinalize) - { - if len(keepUnsealed) == 0 { - moveUnsealed = storiface.FTNone - } - } err = m.sched.Schedule(ctx, sector, sealtasks.TTFetch, fetchSel, m.schedFetch(sector, types, storiface.PathStorage, storiface.AcquireMove), @@ -804,7 +760,8 @@ func (m *Manager) FinalizeReplicaUpdate(ctx context.Context, sector storiface.Se err = multierr.Append(move(storiface.FTUpdate|storiface.FTUpdateCache), move(storiface.FTCache)) err = multierr.Append(err, move(storiface.FTSealed)) // Sealed separate from cache just in case ReleaseSectorKey was already called - if moveUnsealed != storiface.FTNone { + // if we found unsealed files, AND have been asked to keep at least one, move unsealed + if moveUnsealed != storiface.FTNone && len(keepUnsealed) != 0 { err = multierr.Append(err, move(moveUnsealed)) } diff --git a/storage/sealer/manager_test.go b/storage/sealer/manager_test.go index 739cfdd24..5759d0bc7 100644 --- a/storage/sealer/manager_test.go +++ b/storage/sealer/manager_test.go @@ -39,7 +39,7 @@ func init() { logging.SetAllLoggers(logging.LevelDebug) } -type testStorage paths.StorageConfig +type testStorage storiface.StorageConfig func (t testStorage) DiskUsage(path string) (int64, error) { return 1, nil // close enough @@ -50,7 +50,7 @@ func newTestStorage(t *testing.T) *testStorage { require.NoError(t, err) { - b, err := json.MarshalIndent(&paths.LocalStorageMeta{ + b, err := json.MarshalIndent(&storiface.LocalStorageMeta{ ID: storiface.ID(uuid.New().String()), Weight: 1, CanSeal: true, @@ -63,7 +63,7 @@ func newTestStorage(t *testing.T) *testStorage { } return &testStorage{ - StoragePaths: []paths.LocalPath{ + StoragePaths: []storiface.LocalPath{ {Path: tp}, }, } @@ -82,12 +82,12 @@ func (t testStorage) cleanup() { } } -func (t testStorage) GetStorage() (paths.StorageConfig, error) { - return paths.StorageConfig(t), nil +func (t testStorage) GetStorage() (storiface.StorageConfig, error) { + return storiface.StorageConfig(t), nil } -func (t *testStorage) SetStorage(f func(*paths.StorageConfig)) error { - f((*paths.StorageConfig)(t)) +func (t *testStorage) SetStorage(f func(*storiface.StorageConfig)) error { + f((*storiface.StorageConfig)(t)) return nil } diff --git a/storage/sealer/piece_provider_test.go b/storage/sealer/piece_provider_test.go index c4c71bc53..3605b2597 100644 --- a/storage/sealer/piece_provider_test.go +++ b/storage/sealer/piece_provider_test.go @@ -21,6 +21,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-statestore" + "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/storage/paths" "github.com/filecoin-project/lotus/storage/sealer/sealtasks" "github.com/filecoin-project/lotus/storage/sealer/storiface" @@ -30,7 +31,7 @@ import ( // only uses miner and does NOT use any remote worker. func TestPieceProviderSimpleNoRemoteWorker(t *testing.T) { // Set up sector storage manager - sealerCfg := Config{ + sealerCfg := config.SealerConfig{ ParallelFetchLimit: 10, AllowAddPiece: true, AllowPreCommit1: true, @@ -89,7 +90,7 @@ func TestReadPieceRemoteWorkers(t *testing.T) { logging.SetAllLoggers(logging.LevelDebug) // miner's worker can only add pieces to an unsealed sector. - sealerCfg := Config{ + sealerCfg := config.SealerConfig{ ParallelFetchLimit: 10, AllowAddPiece: true, AllowPreCommit1: false, @@ -198,7 +199,7 @@ func generatePieceData(size uint64) []byte { return bz } -func newPieceProviderTestHarness(t *testing.T, mgrConfig Config, sectorProofType abi.RegisteredSealProof) *pieceProviderTestHarness { +func newPieceProviderTestHarness(t *testing.T, mgrConfig config.SealerConfig, sectorProofType abi.RegisteredSealProof) *pieceProviderTestHarness { ctx := context.Background() // listen on tcp socket to create an http server later address := "0.0.0.0:0" @@ -217,7 +218,7 @@ func newPieceProviderTestHarness(t *testing.T, mgrConfig Config, sectorProofType wsts := statestore.New(namespace.Wrap(dstore, datastore.NewKey("/worker/calls"))) smsts := statestore.New(namespace.Wrap(dstore, datastore.NewKey("/stmgr/calls"))) - mgr, err := New(ctx, localStore, remoteStore, storage, index, mgrConfig, wsts, smsts) + mgr, err := New(ctx, localStore, remoteStore, storage, index, mgrConfig, config.ProvingConfig{}, wsts, smsts) require.NoError(t, err) // start a http server on the manager to serve sector file requests. diff --git a/storage/sealer/sched_post.go b/storage/sealer/sched_post.go index 64986726f..1055227d8 100644 --- a/storage/sealer/sched_post.go +++ b/storage/sealer/sched_post.go @@ -169,6 +169,12 @@ func (ps *poStScheduler) watch(wid storiface.WorkerID, worker *WorkerHandle) { }() for { + select { + case <-heartbeatTimer.C: + case <-worker.closingMgr: + return + } + sctx, scancel := context.WithTimeout(ctx, paths.HeartbeatInterval/2) curSes, err := worker.workerRpc.Session(sctx) scancel() @@ -177,12 +183,7 @@ func (ps *poStScheduler) watch(wid storiface.WorkerID, worker *WorkerHandle) { log.Warnw("failed to check worker session", "error", err) ps.disable(wid) - select { - case <-heartbeatTimer.C: - continue - case <-worker.closingMgr: - return - } + continue } if storiface.WorkerID(curSes) != wid { diff --git a/storage/sealer/storiface/storage.go b/storage/sealer/storiface/storage.go index 6d6063c54..a5aa8907a 100644 --- a/storage/sealer/storiface/storage.go +++ b/storage/sealer/storiface/storage.go @@ -153,3 +153,61 @@ type SecDataHttpHeader struct { Key string Value string } + +// StorageConfig .lotusstorage/storage.json +type StorageConfig struct { + StoragePaths []LocalPath +} + +type LocalPath struct { + Path string +} + +// LocalStorageMeta [path]/sectorstore.json +type LocalStorageMeta struct { + ID ID + + // A high weight means data is more likely to be stored in this path + Weight uint64 // 0 = readonly + + // Intermediate data for the sealing process will be stored here + CanSeal bool + + // Finalized sectors that will be proved over time will be stored here + CanStore bool + + // MaxStorage specifies the maximum number of bytes to use for sector storage + // (0 = unlimited) + MaxStorage uint64 + + // List of storage groups this path belongs to + Groups []string + + // List of storage groups to which data from this path can be moved. If none + // are specified, allow to all + AllowTo []string + + // AllowTypes lists sector file types which are allowed to be put into this + // path. If empty, all file types are allowed. + // + // Valid values: + // - "unsealed" + // - "sealed" + // - "cache" + // - "update" + // - "update-cache" + // Any other value will generate a warning and be ignored. + AllowTypes []string + + // DenyTypes lists sector file types which aren't allowed to be put into this + // path. + // + // Valid values: + // - "unsealed" + // - "sealed" + // - "cache" + // - "update" + // - "update-cache" + // Any other value will generate a warning and be ignored. + DenyTypes []string +} diff --git a/storage/wdpost/wdpost_run.go b/storage/wdpost/wdpost_run.go index 53b7d55c9..0518bd760 100644 --- a/storage/wdpost/wdpost_run.go +++ b/storage/wdpost/wdpost_run.go @@ -7,6 +7,7 @@ import ( "github.com/ipfs/go-cid" "go.opencensus.io/trace" + "go.uber.org/zap" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" @@ -253,6 +254,14 @@ func (s *WindowPoStScheduler) runPoStCycle(ctx context.Context, manual bool, di ctx, span := trace.StartSpan(ctx, "storage.runPoStCycle") defer span.End() + start := time.Now() + + log := log.WithOptions(zap.Fields(zap.Time("cycle", start))) + log.Infow("starting PoSt cycle", "manual", manual, "ts", ts, "deadline", di.Index) + defer func() { + log.Infow("post cycle done", "took", time.Now().Sub(start)) + }() + if !manual { // TODO: extract from runPoStCycle, run on fault cutoff boundaries s.asyncFaultRecover(di, ts) diff --git a/testplans/DELVING.md b/testplans/DELVING.md deleted file mode 100644 index 4c2d36390..000000000 --- a/testplans/DELVING.md +++ /dev/null @@ -1,193 +0,0 @@ -# Delving into the unknown - -This write-up summarises how to debug what appears to be a mischievous Lotus -instance during our Testground tests. It also goes enumerates which assets are -useful to report suspicious behaviours upstream, in a way that they are -actionable. - -## Querying the Lotus RPC API - -The `local:docker` and `cluster:k8s` map ports that you specify in the -composition.toml, so you can access them externally. - -All our compositions should carry this fragment: - -```toml -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } -``` - -This tells Testground to expose the following ports: - -* `6060` => Go pprof. -* `1234` => Lotus full node RPC. -* `2345` => Lotus storage miner RPC. - -### `local:docker` - -1. Install the `lotus` binary on your host. -2. Find the container that you want to connect to in `docker ps`. - * Note that our _container names_ are slightly long, and they're the last - field on every line, so if your terminal is wrapping text, the port - numbers will end up ABOVE the friendly/recognizable container name (e.g. `tg-lotus-soup-deals-e2e-acfc60bc1727-miners-1`). - * The testground output displays the _container ID_ inside coloured angle - brackets, so if you spot something spurious in a particular node, you can - hone in on that one, e.g. `<< 54dd5ad916b2 >>`. - - ``` - ⟩ docker ps - CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES - 54dd5ad916b2 be3c18d7f0d4 "/testplan" 10 seconds ago Up 8 seconds 0.0.0.0:32788->1234/tcp, 0.0.0.0:32783->2345/tcp, 0.0.0.0:32773->6060/tcp, 0.0.0.0:32777->6060/tcp tg-lotus-soup-deals-e2e-acfc60bc1727-clients-2 - 53757489ce71 be3c18d7f0d4 "/testplan" 10 seconds ago Up 8 seconds 0.0.0.0:32792->1234/tcp, 0.0.0.0:32790->2345/tcp, 0.0.0.0:32781->6060/tcp, 0.0.0.0:32786->6060/tcp tg-lotus-soup-deals-e2e-acfc60bc1727-clients-1 - 9d3e83b71087 be3c18d7f0d4 "/testplan" 10 seconds ago Up 8 seconds 0.0.0.0:32791->1234/tcp, 0.0.0.0:32789->2345/tcp, 0.0.0.0:32779->6060/tcp, 0.0.0.0:32784->6060/tcp tg-lotus-soup-deals-e2e-acfc60bc1727-clients-0 - 7bd60e75ed0e be3c18d7f0d4 "/testplan" 10 seconds ago Up 8 seconds 0.0.0.0:32787->1234/tcp, 0.0.0.0:32782->2345/tcp, 0.0.0.0:32772->6060/tcp, 0.0.0.0:32776->6060/tcp tg-lotus-soup-deals-e2e-acfc60bc1727-miners-1 - dff229d7b342 be3c18d7f0d4 "/testplan" 10 seconds ago Up 9 seconds 0.0.0.0:32778->1234/tcp, 0.0.0.0:32774->2345/tcp, 0.0.0.0:32769->6060/tcp, 0.0.0.0:32770->6060/tcp tg-lotus-soup-deals-e2e-acfc60bc1727-miners-0 - 4cd67690e3b8 be3c18d7f0d4 "/testplan" 11 seconds ago Up 8 seconds 0.0.0.0:32785->1234/tcp, 0.0.0.0:32780->2345/tcp, 0.0.0.0:32771->6060/tcp, 0.0.0.0:32775->6060/tcp tg-lotus-soup-deals-e2e-acfc60bc1727-bootstrapper-0 - aeb334adf88d iptestground/sidecar:edge "testground sidecar …" 43 hours ago Up About an hour 0.0.0.0:32768->6060/tcp testground-sidecar - c1157500282b influxdb:1.8 "/entrypoint.sh infl…" 43 hours ago Up 25 seconds 0.0.0.0:8086->8086/tcp testground-influxdb - 99ca4c07fecc redis "docker-entrypoint.s…" 43 hours ago Up About an hour 0.0.0.0:6379->6379/tcp testground-redis - bf25c87488a5 bitnami/grafana "/run.sh" 43 hours ago Up 26 seconds 0.0.0.0:3000->3000/tcp testground-grafana - cd1d6383eff7 goproxy/goproxy "/goproxy" 45 hours ago Up About a minute 8081/tcp testground-goproxy - ``` - -3. Take note of the port mapping. Imagine in the output above, we want to query - `54dd5ad916b2`. We'd use `localhost:32788`, as it forwards to the container's - 1234 port (Lotus Full Node RPC). -4. Run your Lotus CLI command setting the `FULLNODE_API_INFO` env variable, - which is a multiaddr: - - ```sh - $ FULLNODE_API_INFO=":/ip4/127.0.0.1/tcp/$port/http" lotus chain list - [...] - ``` - ---- - -Alternatively, you could download gawk and setup a script in you .bashrc or .zshrc similar to: - -``` -lprt() { - NAME=$1 - PORT=$2 - - docker ps --format "table {{.Names}}" | grep $NAME | xargs -I {} docker port {} $PORT | gawk --field-separator=":" '{print $2}' -} - -envs() { - NAME=$1 - - local REMOTE_PORT_1234=$(lprt $NAME 1234) - local REMOTE_PORT_2345=$(lprt $NAME 2345) - - export FULLNODE_API_INFO=":/ip4/127.0.0.1/tcp/$REMOTE_PORT_1234/http" - export STORAGE_API_INFO=":/ip4/127.0.0.1/tcp/$REMOTE_PORT_2345/http" - - echo "Setting \$FULLNODE_API_INFO to $FULLNODE_API_INFO" - echo "Setting \$STORAGE_API_INFO to $STORAGE_API_INFO" -} -``` - -Then call commands like: -``` -envs miners-0 -lotus chain list -``` - -### `cluster:k8s` - -Similar to `local:docker`, you pick a pod that you want to connect to and port-forward 1234 and 2345 to that specific pod, such as: - -``` -export PODNAME="tg-lotus-soup-ae620dfb2e19-miners-0" -kubectl port-forward pods/$PODNAME 1234:1234 2345:2345 - -export FULLNODE_API_INFO=":/ip4/127.0.0.1/tcp/1234/http" -export STORAGE_API_INFO=":/ip4/127.0.0.1/tcp/2345/http" -lotus-storage-miner storage-deals list -lotus-storage-miner storage-deals get-ask -``` - -### Useful commands / checks - -* **Making sure miners are on the same chain:** compare outputs of `lotus chain list`. -* **Checking deals:** `lotus client list-deals`. -* **Sector queries:** `lotus-storage-miner info` , `lotus-storage-miner proving info` -* **Sector sealing errors:** - * `STORAGE_API_INFO=":/ip4/127.0.0.1/tcp/53624/http" FULLNODE_API_INFO=":/ip4/127.0.0.1/tcp/53623/http" lotus-storage-miner sector info` - * `STORAGE_API_INFO=":/ip4/127.0.0.1/tcp/53624/http" FULLNODE_API_INFO=":/ip4/127.0.0.1/tcp/53623/http" lotus-storage-miner sector status ` - * `STORAGE_API_INFO=":/ip4/127.0.0.1/tcp/53624/http" FULLNODE_API_INFO=":/ip4/127.0.0.1/tcp/53623/http" lotus-storage-miner sector status --log ` - -## Viewing logs of a particular container `local:docker` - -This works for both started and stopped containers. Just get the container ID -(in double angle brackets in Testground output, on every log line), and do a: - -```shell script -$ docker logs $container_id -``` - -## Accessing the golang instrumentation - -Testground exposes a pprof endpoint under local port 6060, which both -`local:docker` and `cluster:k8s` map. - -For `local:docker`, see above to figure out which host port maps to the -container's 6060 port. - -## Acquiring a goroutine dump - -When things appear to be stuck, get a goroutine dump. - -```shell script -$ wget -o goroutine.out http://localhost:${pprof_port}/debug/pprof/goroutine?debug=2 -``` - -You can use whyrusleeping/stackparse to extract a summary: - -```shell script -$ go get https://github.com/whyrusleeping/stackparse -$ stackparse --summary goroutine.out -``` - -## Acquiring a CPU profile - -When the CPU appears to be spiking/rallying, grab a CPU profile. - -```shell script -$ wget -o profile.out http://localhost:${pprof_port}/debug/pprof/profile -``` - -Analyse it using `go tool pprof`. Usually, generating a `png` graph is useful: - -```shell script -$ go tool pprof profile.out -File: testground -Type: cpu -Time: Jul 3, 2020 at 12:00am (WEST) -Duration: 30.07s, Total samples = 2.81s ( 9.34%) -Entering interactive mode (type "help" for commands, "o" for options) -(pprof) png -Generating report in profile003.png -``` - -## Submitting actionable reports / findings - -This is useful both internally (within the Oni team, so that peers can help) and -externally (when submitting a finding upstream). - -We don't need to play the full bug-hunting game on Lotus, but it's tremendously -useful to provide the necessary data so that any reports are actionable. - -These include: - -* test outputs (use `testground collect`). -* stack traces that appear in logs (whether panics or not). -* output of relevant Lotus CLI commands. -* if this is some kind of blockage / deadlock, goroutine dumps. -* if this is a CPU hotspot, a CPU profile would be useful. -* if this is a memory issue, a heap dump would be useful. - -**When submitting bugs upstream (Lotus), make sure to indicate:** - -* Lotus commit. -* FFI commit. diff --git a/testplans/Makefile b/testplans/Makefile deleted file mode 100644 index 38f46baa8..000000000 --- a/testplans/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -SHELL = /bin/bash - -.DEFAULT_GOAL := download-proofs - -download-proofs: - go run github.com/filecoin-project/go-paramfetch/paramfetch 2048 ./docker-images/proof-parameters.json - -build-images: - docker build -t "iptestground/oni-buildbase:v15-lotus" -f "docker-images/Dockerfile.oni-buildbase" "docker-images" - docker build -t "iptestground/oni-runtime:v10" -f "docker-images/Dockerfile.oni-runtime" "docker-images" - docker build -t "iptestground/oni-runtime:v10-debug" -f "docker-images/Dockerfile.oni-runtime-debug" "docker-images" - -push-images: - docker push iptestground/oni-buildbase:v15-lotus - docker push iptestground/oni-runtime:v10 - docker push iptestground/oni-runtime:v10-debug - -pull-images: - docker pull iptestground/oni-buildbase:v15-lotus - docker pull iptestground/oni-runtime:v10 - docker pull iptestground/oni-runtime:v10-debug - -.PHONY: download-proofs build-images push-images pull-images diff --git a/testplans/README-old-from-oni.md b/testplans/README-old-from-oni.md deleted file mode 100644 index 1a6b5debe..000000000 --- a/testplans/README-old-from-oni.md +++ /dev/null @@ -1,254 +0,0 @@ -# Project Oni 👹 - -Our mandate is: - -> To verify the successful end-to-end outcome of the filecoin protocol and filecoin implementations, under a variety of real-world and simulated scenarios. - -➡️ Find out more about our goals, requirements, execution plan, and team culture, in our [Project Description](https://docs.google.com/document/d/16jYL--EWYpJhxT9bakYq7ZBGLQ9SB940Wd1lTDOAbNE). - -## Table of Contents - -- [Testing topics](#testing-topics) -- [Repository contents](#repository-contents) -- [Running the test cases](#running-the-test-cases) -- [Catalog](#catalog) -- [Debugging](#debugging) -- [Dependencies](#dependencies) -- [Docker images changelog](#docker-images-changelog) -- [Team](#team) - -## Testing topics - -These are the topics we are currently centering our testing efforts on. Our testing efforts include fault induction, stress tests, and end-to-end testing. - -* **slashing:** [_(view test scenarios)_](https://github.com/filecoin-project/oni/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3Atopic%2Fslashing) - * We are recreating the scenarios that lead to slashing, as they are not readily seen in mono-client testnets. - * Context: slashing is the negative economic consequence of penalising a miner that has breached protocol by deducing FIL and/or removing their power from the network. -* **windowed PoSt/sector proving faults:** [_(view test scenarios)_](https://github.com/filecoin-project/oni/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3Atopic%2Fsector-proving) - * We are recreating the proving fault scenarios and triggering them in an accelerated fasion (by modifying the system configuration), so that we're able to verify that the sector state transitions properly through the different milestones (temporary faults, termination, etc.), and under chain fork conditions. - * Context: every 24 hours there are 36 windows where miners need to submit their proofs of sector liveness, correctness, and validity. Failure to do so will mark a sector as faulted, and will eventually terminate the sector, triggering slashing consequences for the miner. -* **syncing/fork selection:** [_(view test scenarios)_](https://github.com/filecoin-project/oni/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3Atopic%2Fsync-forks) - * Newly bootstrapped clients, and paused-then-resumed clients, are able to latch on to the correct chain even in the presence of a large number of forks in the network, either in the present, or throughout history. -* **present-time mining/tipset assembly:** [_(view test scenarios)_](https://github.com/filecoin-project/oni/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3Atopic%2Fmining-present) - * Induce forks in the network, create network partitions, simulate chain halts, long-range forks, etc. Stage many kinds of convoluted chain shapes, and network partitions, and ensure that miners are always able to arrive to consensus when disruptions subside. -* **catch-up/rush mining:** [_(view test scenarios)_](https://github.com/filecoin-project/oni/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3Atopic%2Fmining-rush) - * Induce network-wide, or partition-wide arrests, and investigate what the resulting chain is after the system is allowed to recover. - * Context: catch-up/rush mining is a dedicated pathway in the mining logic that brings the chain up to speed with present time, in order to recover from network halts. Basically it entails producing backdated blocks in a hot loop. Imagine all miners recover in unison from a network-wide disruption; miners will produce blocks for their winning rounds, and will label losing rounds as _null rounds_. In the current implementation, there is no time for block propagation, so miners will produce solo-chains, and the assumption is that when all these chains hit the network, the _fork choice rule_ will pick the heaviest one. Unfortunately this process is brittle and unbalanced, as it favours the miner that held the highest power before the disruption commenced. -* **storage and retrieval deals:** [_(view test scenarios)_](https://github.com/filecoin-project/oni/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3Atopic%2Fdeals) - * end-to-end flows where clients store and retrieve pieces from miners, including stress testing the system. -* **payment channels:** [_(view test scenarios)_](https://github.com/filecoin-project/oni/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3Atopic%2Fpaych) - * stress testing payment channels via excessive lane creation, excessive payment voucher atomisation, and redemption. -* **drand incidents and impact on the filecoin network/protocol/chain:** [_(view test scenarios)_](https://github.com/filecoin-project/oni/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3Atopic%2Fdrand) - * drand total unavailabilities, drand catch-ups, drand slowness, etc. -* **mempool message selection:** [_(view test scenarios)_](https://github.com/filecoin-project/oni/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3Atopic%2Fmempool) - * soundness of message selection logic; potentially targeted attacks against miners by flooding their message pools with different kinds of messages. -* **presealing:** [_(view test scenarios)_](https://github.com/filecoin-project/oni/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3Atopic%2Fpresealing) - * TBD, anything related to this worth testing? - -## Repository contents - -This repository consists of [test plans](https://docs.testground.ai/concepts-and-architecture/test-structure) built to be run on [Testground](https://github.com/testground/testground). - -The source code for the various test cases can be found in the [`lotus-soup` directory](https://github.com/filecoin-project/oni/tree/master/lotus-soup). - -## Running the test cases - -If you are unfamiliar with Testground, we strongly suggest you read the Testground [Getting Started guide](https://docs.testground.ai/getting-started) in order to learn how to install Testground and how to use it. - -You can find various [composition files](https://docs.testground.ai/running-test-plans#composition-runs) describing various test scenarios built as part of Project Oni at [`lotus-soup/_compositions` directory](https://github.com/filecoin-project/oni/tree/master/lotus-soup/_compositions). - -We've designed the test cases so that you can run them via the `local:exec`, `local:docker` and the `cluster:k8s` runners. Note that Lotus miners are quite resource intensive, requiring gigabytes of memory. Hence you would have to run these test cases on a beafy machine (when using `local:docker` and `local:exec`), or on a Kubernetes cluster (when using `cluster:k8s`). - -Here are the basics of how to run the baseline deals end-to-end test case: - -### Running the baseline deals end-to-end test case - -1. Compile and Install Testground from source code. - * See the [Getting Started](https://github.com/testground/testground#getting-started) section of the README for instructions. - -2. Run a Testground daemon - -``` -testground daemon -``` - -3. Download required Docker images for the `lotus-soup` test plan - -``` -make pull-images -``` - -Alternatively you can build them locally with - -``` -make build-images -``` - -4. Import the `lotus-soup` test plan into your Testground home directory - -``` -testground plan import --from ./lotus-soup -``` - -5. Init the `filecoin-ffi` Git submodule in the `extra` folder. - -``` -git submodule update --init --recursive -``` - -6. Compile the `filecoin-ffi` version locally (necessary if you use `local:exec`) - -``` -cd extra/filecoin-ffi -make -``` - -7. Run a composition for the baseline deals end-to-end test case - -``` -testground run composition -f ./lotus-soup/_compositions/baseline-docker-5-1.toml -``` - -## Batch-running randomised test cases - -The Oni testkit supports [range parameters](https://github.com/filecoin-project/oni/blob/master/lotus-soup/testkit/testenv_ranges.go), -which test cases can use to generate random values, either at the instance level -(each instance computes a random value within range), or at the run level (one -instance computes the values, and propagates them to all other instances via the -sync service). - -For example: - -```toml -latency_range = '["20ms", "500ms"]' -loss_range = '[0, 0.2]' -``` - -Could pick a random latency between 20ms and 500ms, and a packet loss -probability between 0 and 0.2. We could apply those values through the -`netclient.ConfigureNetwork` Testground SDK API. - -Randomized range-based parameters are specially interesting when combined with -batch runs, as it enables Monte Carlo approaches to testing. - -The Oni codebase includes a batch test run driver in package `lotus-soup/runner`. -You can point it at a composition file that uses range parameters and tell it to -run N iterations of the test: - -```shell script -$ go run ./runner -runs 5 _compositions/net-chaos/latency.toml -``` - -This will run the test as many times as instructed, and will place all outputs -in a temporary directory. You can pass a concrete output directory with -the `-output` flag. - -## Catalog - -### Test cases part of `lotus-soup` - -* `deals-e2e` - Deals end-to-end test case. Clients pick a miner at random, start a deal, wait for it to be sealed, and try to retrieve from another random miner who offers back the data. -* `drand-halting` - Test case that instructs Drand with a sequence of halt/resume/wait events, while running deals between clients and miners at the same time. -* `deals-stress` - Deals stress test case. Clients pick a miner and send multiple deals (concurrently or serially) in order to test how many deals miners can handle. -* `paych-stress` - A test case exercising various payment channel stress tests. - -### Compositions part of `lotus-soup` - -* `baseline-docker-5-1.toml` - Runs a `baseline` test (deals e2e test) with a network of 5 clients and 1 miner targeting `local:docker` -* `baseline-k8s-10-3.toml` - Runs a `baseline` test (deals e2e test) with a network of 10 clients and 3 miner targeting `cluster:k8s` -* `baseline-k8s-3-1.toml` - Runs a `baseline` test (deals e2e test) with a network of 3 clients and 1 miner targeting `cluster:k8s` -* `baseline-k8s-3-2.toml` - Runs a `baseline` test (deals e2e test) with a network of 3 clients and 2 miner targeting `cluster:k8s` -* `baseline.toml` - Runs a `baseline` test (deals e2e test) with a network of 3 clients and 2 miner targeting `local:exec`. You have to manually download the proof parameters and place them in `/var/tmp`. -* `deals-stress-concurrent-natural-k8s.toml` -* `deals-stress-concurrent-natural.toml` -* `deals-stress-concurrent.toml` -* `deals-stress-serial-natural.toml` -* `deals-stress-serial.toml` -* `drand-halt.toml` -* `local-drand.toml` -* `natural.toml` -* `paych-stress.toml` -* `pubsub-tracer.toml` - - -## Debugging - -Find commands and how-to guides on debugging test plans at [DELVING.md](https://github.com/filecoin-project/oni/blob/master/DELVING.md) - -1. Querying the Lotus RPC API - -2. Useful commands / checks - -* Making sure miners are on the same chain - -* Checking deals - -* Sector queries - -* Sector sealing errors - -## Dependencies - -Our current test plan `lotus-soup` is building programatically the Lotus filecoin implementation and therefore requires all it's dependencies. The build process is slightly more complicated than a normal Go project, because we are binding a bit of Rust code. Lotus codebase is in Go, however its `proofs` and `crypto` libraries are in Rust (BLS signatures, SNARK verification, etc.). - -Depending on the runner you want to use to run the test plan, these dependencies are included in the build process in a different way, which you should be aware of should you require to use the test plan with a newer version of Lotus: - -### Filecoin FFI libraries - -* `local:docker` - -The Rust libraries are included in the Filecoin FFI Git submodule, which is part of the `iptestground/oni-buildbase` image. If the FFI changes on Lotus, we have to rebuild this image with the `make build-images` command, where X is the next version (see [Docker images changelog](#docker-images-changelog) -below). - -* `local:exec` - -The Rust libraries are included via the `extra` directory. Make sure that the test plan reference to Lotus in `go.mod` and the `extra` directory are pointing to the same commit of the FFI git submodule. You also need to compile the `extra/filecoin-ffi` libraries with `make`. - -* `cluster:k8s` - -The same process as for `local:docker`, however you need to make sure that the respective `iptestground/oni-buildbase` image is available as a public Docker image, so that the Kubernetes cluster can download it. - -### proof parameters - -Additional to the Filecoin FFI Git submodules, we are also bundling `proof parameters` in the `iptestground/oni-runtime` image. If these change, you will need to rebuild that image with `make build-images` command, where X is the next version. - -## Docker images changelog - -### oni-buildbase - -* `v1` => initial image locking in Filecoin FFI commit ca281af0b6c00314382a75ae869e5cb22c83655b. -* `v2` => no changes; released only for aligning both images to aesthetically please @nonsense :D -* `v3` => locking in Filecoin FFI commit 5342c7c97d1a1df4650629d14f2823d52889edd9. -* `v4` => locking in Filecoin FFI commit 6a143e06f923f3a4f544c7a652e8b4df420a3d28. -* `v5` => locking in Filecoin FFI commit cddc56607e1d851ea6d09d49404bd7db70cb3c2e. -* `v6` => locking in Filecoin FFI commit 40569104603407c999d6c9e4c3f1228cbd4d0e5c. -* `v7` => add Filecoin-BLST repo to buildbase. -* `v8` => locking in Filecoin FFI commit f640612a1a1f7a2d. -* `v9` => locking in Filecoin FFI commit 57e38efe4943f09d3127dcf6f0edd614e6acf68e and Filecoin-BLST commit 8609119cf4595d1741139c24378fcd8bc4f1c475. - - -### oni-runtime - -* `v1` => initial image with 2048 parameters. -* `v2` => adds auxiliary tools: `net-tools netcat traceroute iputils-ping wget vim curl telnet iproute2 dnsutils`. -* `v3` => bump proof parameters from v27 to v28 - -### oni-runtime-debug - -* `v1` => initial image -* `v2` => locking in Lotus commit e21ea53 -* `v3` => locking in Lotus commit d557c40 -* `v4` => bump proof parameters from v27 to v28 -* `v5` => locking in Lotus commit 1a170e18a - - -## Team - -* [@raulk](https://github.com/raulk) (Captain + TL) -* [@nonsense](https://github.com/nonsense) (Testground TG + engineer) -* [@yusefnapora](https://github.com/yusefnapora) (engineer and technical writer) -* [@vyzo](https://github.com/vyzo) (engineer) -* [@schomatis](https://github.com/schomatis) (advisor) -* [@willscott](https://github.com/willscott) (engineer) -* [@alanshaw](https://github.com/alanshaw) (engineer) - diff --git a/testplans/README.md b/testplans/README.md deleted file mode 100644 index bab10e690..000000000 --- a/testplans/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# Testground testplans for Lotus - -This directory consists of [testplans](https://docs.testground.ai/concepts-and-architecture/test-structure) built to be run on [Testground](https://github.com/testground/testground) that exercise Lotus on [TaaS](https://ci.testground.ipfs.team). - -## Table of Contents - -- [Testing topics](#testing-topics) -- [Running the test cases](#running-the-test-cases) - -## Testing topics - -* **storage and retrieval deals:** - * end-to-end flows where clients store and retrieve pieces from miners, including stress testing the system. -* **payment channels:** - * stress testing payment channels via excessive lane creation, excessive payment voucher atomisation, and redemption. - -## Running the test cases - -If you are unfamiliar with Testground, we strongly suggest you read the Testground [Getting Started guide](https://docs.testground.ai/getting-started) in order to learn how to install Testground and how to use it. - -You can find various [composition files](https://docs.testground.ai/running-test-plans#composition-runs) describing various test scenarios built as part of Project Oni at [`lotus-soup/_compositions` directory](https://github.com/filecoin-project/oni/tree/master/lotus-soup/_compositions). - -We've designed the test cases so that you can run them via the `local:exec`, `local:docker` and the `cluster:k8s` runners. Note that Lotus miners are quite resource intensive, requiring gigabytes of memory. Hence you would have to run these test cases on a beafy machine (when using `local:docker` and `local:exec`), or on a Kubernetes cluster (when using `cluster:k8s`). - -Here are the basics of how to run the baseline deals end-to-end test case: - -### Running the baseline deals end-to-end test case - -1. Compile and Install Testground from source code. - * See the [Getting Started](https://github.com/testground/testground#getting-started) section of the README for instructions. - -2. Run a Testground daemon - -``` -testground daemon -``` - -3. Download required Docker images for the `lotus-soup` test plan - -``` -make pull-images -``` - -Alternatively you can build them locally with - -``` -make build-images -``` - -4. Import the `lotus-soup` test plan into your Testground home directory - -``` -testground plan import --from ./lotus-soup -``` - -6. Run a composition for the baseline deals end-to-end test case - -``` -testground run composition -f ./lotus-soup/_compositions/baseline-docker-5-1.toml -``` diff --git a/testplans/composer/Dockerfile b/testplans/composer/Dockerfile deleted file mode 100644 index d53bef7e4..000000000 --- a/testplans/composer/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -FROM golang:1.18.1-buster as tg-build - -ARG TESTGROUND_REF="oni" -WORKDIR /usr/src -RUN git clone https://github.com/testground/testground.git -RUN cd testground && git checkout $TESTGROUND_REF && go build . - -FROM python:3.8-buster - -WORKDIR /usr/src/app - -COPY --from=tg-build /usr/src/testground/testground /usr/bin/testground - -RUN mkdir /composer && chmod 777 /composer -RUN mkdir /testground && chmod 777 /testground - -ENV HOME /composer -ENV TESTGROUND_HOME /testground -ENV LISTEN_PORT 5006 -ENV TESTGROUND_DAEMON_HOST host.docker.internal - -VOLUME /testground/plans - - -COPY requirements.txt ./ -RUN pip install -r requirements.txt -COPY . . - -CMD panel serve --address 0.0.0.0 --port $LISTEN_PORT composer.ipynb diff --git a/testplans/composer/Makefile b/testplans/composer/Makefile deleted file mode 100644 index 60f022110..000000000 --- a/testplans/composer/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -all: docker - -docker: - docker build -t "iptestground/composer:latest" . diff --git a/testplans/composer/README.md b/testplans/composer/README.md deleted file mode 100644 index 82cd130cb..000000000 --- a/testplans/composer/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# Testground Composer - -This is a work-in-progress UI for configuring and running testground compositions. - -The app code lives in [./app](./app), and there's a thin Jupyter notebook shell in [composer.ipynb](./composer.ipynb). - -## Running - -You can either run the app in docker, or in a local python virtualenv. Docker is recommended unless you're hacking -on the code for Composer itself. - -### Running with docker - -Run the `./composer.sh` script to build a container with the latest source and run it. The first build -will take a little while since it needs to build testground and fetch a bunch of python dependencies. - -You can skip the build if you set `SKIP_BUILD=true` when running `composer.sh`, and you can rebuild -manually with `make docker`. - -The contents of `$TESTGROUND_HOME/plans` will be sync'd to a temporary directory and read-only mounted -into the container. - -After building and starting the container, the script will open a browser to the composer UI. - -You should be able to load an existing composition or create a new one from one of the plans in -`$TESTGROUND_HOME/plans`. - -Right now docker only supports the standalone webapp UI; to run the UI in a Jupyter notebook, see below. - -### Running with local python - -To run without docker, make a python3 virtual environment somewhere and activate it: - -```shell -# make a virtualenv called "venv" in the current directory -python3 -m venv ./venv - -# activate (bash/zsh): -source ./venv/bin/activate - -# activate (fish): -source ./venv/bin/activate.fish -``` - -Then install the python dependencies: - -```shell -pip install -r requirements.txt -``` - -And start the UI: - -```shell -panel serve composer.ipynb -``` - -That will start the standalone webapp UI. If you want a Jupyter notebook instead, run: - -``` -jupyter notebook -``` - -and open `composer.ipynb` in the Jupyter file picker. \ No newline at end of file diff --git a/testplans/composer/app/app.py b/testplans/composer/app/app.py deleted file mode 100644 index c8d4aa3c1..000000000 --- a/testplans/composer/app/app.py +++ /dev/null @@ -1,94 +0,0 @@ -import param -import panel as pn -import toml -from .util import get_plans, get_manifest -from .composition import Composition -from .runner import TestRunner - -STAGE_WELCOME = 'Welcome' -STAGE_CONFIG_COMPOSITION = 'Configure' -STAGE_RUN_TEST = 'Run' - - -class Welcome(param.Parameterized): - composition = param.Parameter() - composition_picker = pn.widgets.FileInput(accept='.toml') - plan_picker = param.Selector() - ready = param.Boolean() - - def __init__(self, **params): - super().__init__(**params) - self.composition_picker.param.watch(self._composition_updated, 'value') - self.param.watch(self._plan_selected, 'plan_picker') - self.param['plan_picker'].objects = ['Select a Plan'] + get_plans() - - def panel(self): - tabs = pn.Tabs( - ('New Compostion', self.param['plan_picker']), - ('Existing Composition', self.composition_picker), - ) - - return pn.Column( - "Either choose an existing composition or select a plan to create a new composition:", - tabs, - ) - - def _composition_updated(self, *args): - print('composition updated') - content = self.composition_picker.value.decode('utf8') - comp_toml = toml.loads(content) - manifest = get_manifest(comp_toml['global']['plan']) - self.composition = Composition.from_dict(comp_toml, manifest=manifest) - print('existing composition: {}'.format(self.composition)) - self.ready = True - - def _plan_selected(self, evt): - if evt.new == 'Select a Plan': - return - print('plan selected: {}'.format(evt.new)) - manifest = get_manifest(evt.new) - self.composition = Composition(manifest=manifest, add_default_group=True) - print('new composition: ', self.composition) - self.ready = True - - -class ConfigureComposition(param.Parameterized): - composition = param.Parameter() - - @param.depends('composition') - def panel(self): - if self.composition is None: - return pn.Pane("no composition :(") - print('composition: ', self.composition) - return self.composition.panel() - - -class WorkflowPipeline(object): - def __init__(self): - stages = [ - (STAGE_WELCOME, Welcome(), dict(ready_parameter='ready')), - (STAGE_CONFIG_COMPOSITION, ConfigureComposition()), - (STAGE_RUN_TEST, TestRunner()), - ] - - self.pipeline = pn.pipeline.Pipeline(debug=True, stages=stages) - - def panel(self): - return pn.Column( - pn.Row( - self.pipeline.title, - self.pipeline.network, - self.pipeline.prev_button, - self.pipeline.next_button, - ), - self.pipeline.stage, - sizing_mode='stretch_width', - ) - - -class App(object): - def __init__(self): - self.workflow = WorkflowPipeline() - - def ui(self): - return self.workflow.panel().servable("Testground Composer") diff --git a/testplans/composer/app/composition.py b/testplans/composer/app/composition.py deleted file mode 100644 index f12034f8c..000000000 --- a/testplans/composer/app/composition.py +++ /dev/null @@ -1,328 +0,0 @@ -import param -import panel as pn -import toml -from .util import get_manifest, print_err - - -def value_dict(parameterized, renames=None, stringify=False): - d = dict() - if renames is None: - renames = dict() - for name, p in parameterized.param.objects().items(): - if name == 'name': - continue - if name in renames: - name = renames[name] - val = p.__get__(parameterized, type(p)) - if isinstance(val, param.Parameterized): - try: - val = val.to_dict() - except: - val = value_dict(val, renames=renames) - if stringify: - val = str(val) - d[name] = val - return d - - -def make_group_params_class(testcase): - """Returns a subclass of param.Parameterized whose params are defined by the - 'params' dict inside of the given testcase dict""" - tc_params = dict() - for name, p in testcase.get('params', {}).items(): - tc_params[name] = make_param(p) - - name = 'Test Params for testcase {}'.format(testcase.get('name', '')) - cls = param.parameterized_class(name, tc_params, GroupParamsBase) - return cls - - -def make_param(pdef): - """ - :param pdef: a parameter definition dict from a testground plan manifest - :return: a param.Parameter that has the type, bounds, default value, etc from the definition - """ - typ = pdef['type'].lower() - if typ == 'int': - return num_param(pdef, cls=param.Integer) - elif typ == 'float': - return num_param(pdef) - elif typ.startswith('bool'): - return bool_param(pdef) - else: - return str_param(pdef) - - -def num_param(pdef, cls=param.Number): - lo = pdef.get('min', None) - hi = pdef.get('max', None) - bounds = (lo, hi) - if lo == hi and lo is not None: - bounds = None - - default_val = pdef.get('default', None) - if default_val is not None: - if cls == param.Integer: - default_val = int(default_val) - else: - default_val = float(default_val) - return cls(default=default_val, bounds=bounds, doc=pdef.get('desc', '')) - - -def bool_param(pdef): - default_val = str(pdef.get('default', 'false')).lower() == 'true' - return param.Boolean( - doc=pdef.get('desc', ''), - default=default_val - ) - - -def str_param(pdef): - return param.String( - default=pdef.get('default', ''), - doc=pdef.get('desc', ''), - ) - - -class Base(param.Parameterized): - @classmethod - def from_dict(cls, d): - return cls(**d) - - def to_dict(self): - return value_dict(self) - - -class GroupParamsBase(Base): - def to_dict(self): - return value_dict(self, stringify=True) - - -class Metadata(Base): - composition_name = param.String() - author = param.String() - - @classmethod - def from_dict(cls, d): - d['composition_name'] = d.get('name', '') - del d['name'] - return Metadata(**d) - - def to_dict(self): - return value_dict(self, {'composition_name': 'name'}) - - -class Global(Base): - plan = param.String() - case = param.Selector() - builder = param.String() - runner = param.String() - - # TODO: link to instance counts in groups - total_instances = param.Integer() - # TODO: add ui widget for key/value maps instead of using Dict param type - build_config = param.Dict(default={}, allow_None=True) - run_config = param.Dict(default={}, allow_None=True) - - def set_manifest(self, manifest): - if manifest is None: - return - print('manifest:', manifest) - self.plan = manifest['name'] - cases = [tc['name'] for tc in manifest['testcases']] - self.param['case'].objects = cases - print('global config updated manifest. cases:', self.param['case'].objects) - if len(cases) != 0: - self.case = cases[0] - - if 'defaults' in manifest: - print('manifest defaults', manifest['defaults']) - if self.builder == '': - self.builder = manifest['defaults'].get('builder', '') - if self.runner == '': - self.runner = manifest['defaults'].get('runner', '') - - -class Resources(Base): - memory = param.String(allow_None=True) - cpu = param.String(allow_None=True) - - -class Instances(Base): - count = param.Integer(allow_None=True) - percentage = param.Number(allow_None=True) - - -class Dependency(Base): - module = param.String() - version = param.String() - - -class Build(Base): - selectors = param.List(class_=str, allow_None=True) - dependencies = param.List(allow_None=True) - - -class Run(Base): - artifact = param.String(allow_None=True) - test_params = param.Parameter(instantiate=True) - - def __init__(self, params_class=None, **params): - super().__init__(**params) - if params_class is not None: - self.test_params = params_class() - - @classmethod - def from_dict(cls, d, params_class=None): - return Run(artifact=d.get('artifact', None), params_class=params_class) - - def panel(self): - return pn.Column( - self.param['artifact'], - pn.Param(self.test_params) - ) - - -class Group(Base): - id = param.String() - instances = param.Parameter(Instances(), instantiate=True) - resources = param.Parameter(Resources(), allow_None=True, instantiate=True) - build = param.Parameter(Build(), instantiate=True) - run = param.Parameter(Run(), instantiate=True) - - def __init__(self, params_class=None, **params): - super().__init__(**params) - if params_class is not None: - self.run = Run(params_class=params_class) - self._set_name(self.id) - - @classmethod - def from_dict(cls, d, params_class=None): - return Group( - id=d['id'], - resources=Resources.from_dict(d.get('resources', {})), - instances=Instances.from_dict(d.get('instances', {})), - build=Build.from_dict(d.get('build', {})), - run=Run.from_dict(d.get('params', {}), params_class=params_class), - ) - - def panel(self): - print('rendering groups panel for ' + self.id) - return pn.Column( - "**Group: {}**".format(self.id), - self.param['id'], - self.instances, - self.resources, - self.build, - self.run.panel(), - ) - - -class Composition(param.Parameterized): - metadata = param.Parameter(Metadata(), instantiate=True) - global_config = param.Parameter(Global(), instantiate=True) - - groups = param.List(precedence=-1) - group_tabs = pn.Tabs() - groups_ui = None - - def __init__(self, manifest=None, add_default_group=False, **params): - super(Composition, self).__init__(**params) - self.manifest = manifest - self.testcase_param_classes = dict() - self._set_manifest(manifest) - if add_default_group: - self._add_group() - - @classmethod - def from_dict(cls, d, manifest=None): - if manifest is None: - try: - manifest = get_manifest(d['global']['plan']) - except FileNotFoundError: - print_err("Unable to find manifest for test plan {}. Please import into $TESTGROUND_HOME/plans and try again".format(d['global']['plan'])) - - c = Composition( - manifest=manifest, - metadata=Metadata.from_dict(d.get('metadata', {})), - global_config=Global.from_dict(d.get('global', {})), - ) - params_class = c._params_class_for_current_testcase() - c.groups = [Group.from_dict(g, params_class=params_class) for g in d.get('groups', [])] - - return c - - @classmethod - def from_toml_file(cls, filename, manifest=None): - with open(filename, 'rt') as f: - d = toml.load(f) - return cls.from_dict(d, manifest=manifest) - - @param.depends('groups', watch=True) - def panel(self): - add_group_button = pn.widgets.Button(name='Add Group') - add_group_button.on_click(self._add_group) - - self._refresh_tabs() - - if self.groups_ui is None: - self.groups_ui = pn.Column( - add_group_button, - self.group_tabs, - ) - - return pn.Row( - pn.Column(self.metadata, self.global_config), - self.groups_ui, - ) - - def _set_manifest(self, manifest): - if manifest is None: - return - - g = self.global_config - print('global conifg: ', g) - g.set_manifest(manifest) - for tc in manifest.get('testcases', []): - self.testcase_param_classes[tc['name']] = make_group_params_class(tc) - - def _params_class_for_current_testcase(self): - case = self.global_config.case - cls = self.testcase_param_classes.get(case, None) - if cls is None: - print_err("No testcase found in manifest named " + case) - return cls - - def _add_group(self, *args): - group_id = 'group-{}'.format(len(self.groups) + 1) - g = Group(id=group_id, params_class=self._params_class_for_current_testcase()) - g.param.watch(self._refresh_tabs, 'id') - groups = self.groups - groups.append(g) - self.groups = groups - self.group_tabs.active = len(groups)-1 - - @param.depends("global_config.case", watch=True) - def _test_case_changed(self): - print('test case changed', self.global_config.case) - cls = self._params_class_for_current_testcase() - for g in self.groups: - g.run.test_params = cls() - self._refresh_tabs() - - def _refresh_tabs(self, *args): - self.group_tabs[:] = [(g.id, g.panel()) for g in self.groups] - - def to_dict(self): - return { - 'metadata': value_dict(self.metadata, renames={'composition_name': 'name'}), - 'global': value_dict(self.global_config), - 'groups': [g.to_dict() for g in self.groups] - } - - def to_toml(self): - return toml.dumps(self.to_dict()) - - def write_to_file(self, filename): - with open(filename, 'wt') as f: - toml.dump(self.to_dict(), f) diff --git a/testplans/composer/app/runner.py b/testplans/composer/app/runner.py deleted file mode 100644 index 6eb368795..000000000 --- a/testplans/composer/app/runner.py +++ /dev/null @@ -1,111 +0,0 @@ -import os -import panel as pn -import param -from panel.io.server import unlocked -from tornado.ioloop import IOLoop, PeriodicCallback -from tornado.process import Subprocess -from subprocess import STDOUT -from bokeh.models.widgets import Div -from ansi2html import Ansi2HTMLConverter - -from .composition import Composition - -TESTGROUND = 'testground' - - -class AnsiColorText(pn.widgets.Widget): - style = param.Dict(default=None, doc=""" - Dictionary of CSS property:value pairs to apply to this Div.""") - - value = param.Parameter(default=None) - - _format = '
{value}
' - - _rename = {'name': None, 'value': 'text'} - - # _target_transforms = {'value': 'target.text.split(": ")[0]+": "+value'} - # - # _source_transforms = {'value': 'value.split(": ")[1]'} - - _widget_type = Div - - _converter = Ansi2HTMLConverter(inline=True) - - def _process_param_change(self, msg): - msg = super(AnsiColorText, self)._process_property_change(msg) - if 'value' in msg: - text = str(msg.pop('value')) - text = self._converter.convert(text) - msg['text'] = text - return msg - - def scroll_down(self): - # TODO: figure out how to automatically scroll down as text is added - pass - - -class CommandRunner(param.Parameterized): - command_output = param.String() - - def __init__(self, **params): - super().__init__(**params) - self._output_lines = [] - self.proc = None - self._updater = PeriodicCallback(self._refresh_output, callback_time=1000) - - @pn.depends('command_output') - def panel(self): - return pn.Param(self.param, show_name=False, sizing_mode='stretch_width', widgets={ - 'command_output': dict( - type=AnsiColorText, - sizing_mode='stretch_width', - height=800) - }) - - def run(self, *cmd): - self.command_output = '' - self._output_lines = [] - self.proc = Subprocess(cmd, stdout=Subprocess.STREAM, stderr=STDOUT) - self._get_next_line() - self._updater.start() - - def _get_next_line(self): - if self.proc is None: - return - loop = IOLoop.current() - loop.add_future(self.proc.stdout.read_until(bytes('\n', encoding='utf8')), self._append_output) - - def _append_output(self, future): - self._output_lines.append(future.result().decode('utf8')) - self._get_next_line() - - def _refresh_output(self): - text = ''.join(self._output_lines) - if len(text) != len(self.command_output): - with unlocked(): - self.command_output = text - - -class TestRunner(param.Parameterized): - composition = param.ClassSelector(class_=Composition, precedence=-1) - testground_daemon_endpoint = param.String(default="{}:8042".format(os.environ.get('TESTGROUND_DAEMON_HOST', 'localhost'))) - run_test = param.Action(lambda self: self.run()) - runner = CommandRunner() - - def __init__(self, **params): - super().__init__(**params) - - def run(self): - # TODO: temp file management - maybe we should mount a volume and save there? - filename = '/tmp/composition.toml' - self.composition.write_to_file(filename) - - self.runner.run(TESTGROUND, '--endpoint', self.testground_daemon_endpoint, 'run', 'composition', '-f', filename) - - def panel(self): - return pn.Column( - self.param['testground_daemon_endpoint'], - self.param['run_test'], - self.runner.panel(), - sizing_mode='stretch_width', - ) diff --git a/testplans/composer/app/util.py b/testplans/composer/app/util.py deleted file mode 100644 index 5321a95e8..000000000 --- a/testplans/composer/app/util.py +++ /dev/null @@ -1,26 +0,0 @@ -import toml -import os -import sys - - -def parse_manifest(manifest_path): - with open(manifest_path, 'rt') as f: - return toml.load(f) - - -def tg_home(): - return os.environ.get('TESTGROUND_HOME', - os.path.join(os.environ['HOME'], 'testground')) - - -def get_plans(): - return list(os.listdir(os.path.join(tg_home(), 'plans'))) - - -def get_manifest(plan_name): - manifest_path = os.path.join(tg_home(), 'plans', plan_name, 'manifest.toml') - return parse_manifest(manifest_path) - - -def print_err(*args): - print(*args, file=sys.stderr) diff --git a/testplans/composer/chain-state.ipynb b/testplans/composer/chain-state.ipynb deleted file mode 100644 index bd833dd21..000000000 --- a/testplans/composer/chain-state.ipynb +++ /dev/null @@ -1,174 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "import pandas as pd\n", - "import matplotlib.pyplot as plt\n", - "import hvplot.pandas\n", - "import panel as pn\n", - "\n", - "STATE_FILE = './chain-state.ndjson'\n", - "\n", - "MINER_STATE_COL_RENAMES = {\n", - " 'Info.MinerAddr': 'Miner',\n", - " 'Info.MinerPower.MinerPower.RawBytePower': 'Info.MinerPowerRaw',\n", - " 'Info.MinerPower.MinerPower.QualityAdjPower': 'Info.MinerPowerQualityAdj',\n", - " 'Info.MinerPower.TotalPower.RawBytePower': 'Info.TotalPowerRaw',\n", - " 'Info.MinerPower.TotalPower.QualityAdjPower': 'Info.TotalPowerQualityAdj',\n", - "}\n", - "\n", - "MINER_NUMERIC_COLS = [\n", - " 'Info.MinerPowerRaw',\n", - " 'Info.MinerPowerQualityAdj',\n", - " 'Info.TotalPowerRaw',\n", - " 'Info.TotalPowerQualityAdj',\n", - " 'Info.Balance',\n", - " 'Info.CommittedBytes',\n", - " 'Info.ProvingBytes',\n", - " 'Info.FaultyBytes',\n", - " 'Info.FaultyPercentage',\n", - " 'Info.PreCommitDeposits',\n", - " 'Info.LockedFunds',\n", - " 'Info.AvailableFunds',\n", - " 'Info.WorkerBalance',\n", - " 'Info.MarketEscrow',\n", - " 'Info.MarketLocked',\n", - "]\n", - "\n", - "DERIVED_COLS = [\n", - " 'CommittedSectors',\n", - " 'ProvingSectors',\n", - "]\n", - "\n", - "ATTO_FIL_COLS = [\n", - " 'Info.Balance',\n", - " 'Info.PreCommitDeposits',\n", - " 'Info.LockedFunds',\n", - " 'Info.AvailableFunds',\n", - " 'Info.WorkerBalance',\n", - " 'Info.MarketEscrow',\n", - " 'Info.MarketLocked',\n", - "]\n", - "\n", - "def atto_to_fil(x):\n", - " return float(x) * pow(10, -18)\n", - "\n", - "def chain_state_to_pandas(statefile):\n", - " chain = None\n", - " \n", - " with open(statefile, 'rt') as f:\n", - " for line in f.readlines():\n", - " j = json.loads(line)\n", - " chain_height = j['Height']\n", - " \n", - " miners = j['MinerStates']\n", - " for m in miners.values():\n", - " df = pd.json_normalize(m)\n", - " df['Height'] = chain_height\n", - " df.rename(columns=MINER_STATE_COL_RENAMES, inplace=True)\n", - " if chain is None:\n", - " chain = df\n", - " else:\n", - " chain = chain.append(df, ignore_index=True)\n", - " chain.fillna(0, inplace=True)\n", - " chain.set_index('Height', inplace=True)\n", - " \n", - " for c in ATTO_FIL_COLS:\n", - " chain[c] = chain[c].apply(atto_to_fil)\n", - " \n", - " for c in MINER_NUMERIC_COLS:\n", - " chain[c] = chain[c].apply(pd.to_numeric)\n", - " \n", - " # the Sectors.* fields are lists of sector ids, but we want to plot counts, so\n", - " # we pull the length of each list into a new column\n", - " chain['CommittedSectors'] = chain['Sectors.Committed'].apply(lambda x: len(x))\n", - " chain['ProvingSectors'] = chain['Sectors.Proving'].apply(lambda x: len(x))\n", - " return chain\n", - " \n", - "cs = chain_state_to_pandas(STATE_FILE)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# choose which col to plot using a widget\n", - "\n", - "cols_to_plot = MINER_NUMERIC_COLS + DERIVED_COLS\n", - "\n", - "col_selector = pn.widgets.Select(name='Field', options=cols_to_plot)\n", - "cols = ['Miner'] + cols_to_plot\n", - "plot = cs[cols].hvplot(by='Miner', y=col_selector)\n", - "pn.Column(pn.WidgetBox(col_selector), plot)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# plot all line charts in a vertical stack\n", - "\n", - "plots = []\n", - "for c in cols_to_plot:\n", - " title = c.split('.')[-1]\n", - " p = cs[['Miner', c]].hvplot(by='Miner', y=c, title=title)\n", - " plots.append(p)\n", - "pn.Column(*plots)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# miner power area chart\n", - "\n", - "mp = cs[['Miner', 'Info.MinerPowerRaw']].rename(columns={'Info.MinerPowerRaw': 'Power'})\n", - "mp = mp.pivot_table(values=['Power'], index=cs.index, columns='Miner', aggfunc='sum')\n", - "mp = mp.div(mp.sum(1), axis=0)\n", - "mp.columns = mp.columns.get_level_values(1)\n", - "mp.hvplot.area(title='Miner Power Distribution')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.2" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/testplans/composer/composer.ipynb b/testplans/composer/composer.ipynb deleted file mode 100644 index 148d1e861..000000000 --- a/testplans/composer/composer.ipynb +++ /dev/null @@ -1,45 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "import param\n", - "import panel as pn\n", - "import app.app as app\n", - "import importlib\n", - "importlib.reload(app)\n", - "\n", - "pn.extension()\n", - "\n", - "a = app.App()\n", - "a.ui()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.2" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/testplans/composer/composer.sh b/testplans/composer/composer.sh deleted file mode 100755 index 0d8bc8eb9..000000000 --- a/testplans/composer/composer.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/bin/bash - -# this script runs jupyter inside a docker container and copies -# plan manifests from the user's local filesystem into a temporary -# directory that's bind-mounted into the container. - -set -o errexit -set -o pipefail - -set -e - -err_report() { - echo "Error on line $1" -} - -trap 'err_report $LINENO' ERR - - -image_name="iptestground/composer" -image_tag="latest" -image_full_name="$image_name:$image_tag" -tg_home=${TESTGROUND_HOME:-$HOME/testground} -container_plans_dir="/testground/plans" -jupyter_port=${JUPYTER_PORT:-8888} -panel_port=${PANEL_PORT:-5006} - -poll_interval=30 - -exists() { - command -v "$1" >/dev/null 2>&1 -} - -require_cmds() { - for cmd in $@; do - exists $cmd || { echo "This script requires the $cmd command. Please install it and try again." >&2; exit 1; } - done -} - -update_plans() { - local dest_dir=$1 - rsync -avzh --quiet --copy-links "${tg_home}/plans/" ${dest_dir} -} - -watch_plans() { - local plans_dest=$1 - while true; do - update_plans ${plans_dest} - sleep $poll_interval - done -} - -open_url() { - local url=$1 - if exists cmd.exe; then - cmd.exe /c start ${url} >/dev/null 2>&1 - elif exists xdg-open; then - xdg-open ${url} >/dev/null 2>&1 & - elif exists open; then - open ${url} - else - echo "unable to automatically open url. copy/paste this into a browser: $url" - fi -} - -# delete temp dir and stop docker container -cleanup () { - if [[ "$container_id" != "" ]]; then - docker stop ${container_id} >/dev/null - fi - - if [[ -d "$temp_plans_dir" ]]; then - rm -rf ${temp_plans_dir} - fi -} - -get_host_ip() { - # get interface of default route - local net_if=$(netstat -rn | awk '/^0.0.0.0/ {thif=substr($0,74,10); print thif;} /^default.*UG/ {thif=substr($0,65,10); print thif;}') - # use ifconfig to get addr of that interface - detected_host_ip=`ifconfig ${net_if} | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'` - - if [ -z "$detected_host_ip" ] - then - detected_host_ip="host.docker.internal" - fi - - echo $detected_host_ip -} - -# run cleanup on exit -trap "{ cleanup; }" EXIT - -# make sure we have the commands we need -require_cmds jq docker rsync - -if [[ "$SKIP_BUILD" == "" ]]; then - echo "Building latest docker image. Set SKIP_BUILD env var to any value to bypass." - require_cmds make - make docker -fi - -# make temp dir for manifests -temp_base="/tmp" -if [[ "$TEMP" != "" ]]; then - temp_base=$TEMP -fi - -temp_plans_dir="$(mktemp -d ${temp_base}/testground-composer-XXXX)" -echo "temp plans dir: $temp_plans_dir" - -# copy testplans from $TESTGROUND_HOME/plans to the temp dir -update_plans ${temp_plans_dir} - -# run the container in detached mode and grab the id -container_id=$(docker run -d \ - -e TESTGROUND_DAEMON_HOST=$(get_host_ip) \ - --user $(id -u):$(id -g) \ - -p ${panel_port}:5006 \ - -v ${temp_plans_dir}:${container_plans_dir}:ro \ - $image_full_name) - -echo "container $container_id started" -# print the log output -docker logs -f ${container_id} & - -# sleep for a couple seconds to let the server start up -sleep 2 - -# open a browser to the app url -panel_url="http://localhost:${panel_port}" -open_url $panel_url - -# poll & sync testplan changes every few seconds -watch_plans ${temp_plans_dir} diff --git a/testplans/composer/fixtures/all-both-k8s.toml b/testplans/composer/fixtures/all-both-k8s.toml deleted file mode 100644 index ab9e0864e..000000000 --- a/testplans/composer/fixtures/all-both-k8s.toml +++ /dev/null @@ -1,214 +0,0 @@ -[metadata] - name = "all-both" - author = "adin" - -[global] - plan = "dht" - case = "all" - total_instances = 1000 - builder = "docker:go" - runner = "cluster:k8s" - [global.build_config] - push_registry = true - registry_type = "aws" - -[[groups]] - id = "balsam-undialable-provider" - [groups.instances] - count = 5 - percentage = 0.0 - [groups.build] - selectors = ["balsam"] - [groups.run] - artifact = "909427826938.dkr.ecr.us-east-1.amazonaws.com/testground-us-east-1-dht:701251a63b92" - [groups.run.test_params] - bs_strategy = "7" - bucket_size = "10" - expect_dht = "false" - group_order = "4" - latency = "100" - record_count = "1" - timeout_secs = "600" - undialable = "true" - -[[groups]] - id = "balsam-undialable-searcher" - [groups.instances] - count = 5 - percentage = 0.0 - [groups.build] - selectors = ["balsam"] - [groups.run] - artifact = "909427826938.dkr.ecr.us-east-1.amazonaws.com/testground-us-east-1-dht:701251a63b92" - [groups.run.test_params] - bs_strategy = "7" - bucket_size = "10" - expect_dht = "false" - group_order = "5" - latency = "100" - search_records = "true" - timeout_secs = "600" - undialable = "true" - -[[groups]] - id = "balsam-dialable-passive" - [groups.instances] - count = 780 - percentage = 0.0 - [groups.build] - selectors = ["balsam"] - [groups.run] - artifact = "909427826938.dkr.ecr.us-east-1.amazonaws.com/testground-us-east-1-dht:701251a63b92" - [groups.run.test_params] - bs_strategy = "7" - bucket_size = "10" - expect_dht = "false" - group_order = "6" - latency = "100" - timeout_secs = "600" - undialable = "false" - -[[groups]] - id = "balsam-dialable-provider" - [groups.instances] - count = 5 - percentage = 0.0 - [groups.build] - selectors = ["balsam"] - [groups.run] - artifact = "909427826938.dkr.ecr.us-east-1.amazonaws.com/testground-us-east-1-dht:701251a63b92" - [groups.run.test_params] - bs_strategy = "7" - bucket_size = "10" - expect_dht = "false" - group_order = "7" - latency = "100" - record_count = "1" - timeout_secs = "600" - undialable = "false" - -[[groups]] - id = "balsam-dialable-searcher" - [groups.instances] - count = 5 - percentage = 0.0 - [groups.build] - selectors = ["balsam"] - [groups.run] - artifact = "909427826938.dkr.ecr.us-east-1.amazonaws.com/testground-us-east-1-dht:701251a63b92" - [groups.run.test_params] - bs_strategy = "7" - bucket_size = "10" - expect_dht = "false" - group_order = "8" - latency = "100" - search_records = "true" - timeout_secs = "600" - undialable = "false" - -[[groups]] - id = "cypress-passive" - [groups.instances] - count = 185 - percentage = 0.0 - [groups.build] - selectors = ["cypress"] - - [[groups.build.dependencies]] - module = "github.com/libp2p/go-libp2p-kad-dht" - version = "180be07b8303d536e39809bc39c58be5407fedd9" - - [[groups.build.dependencies]] - module = "github.com/libp2p/go-libp2p-xor" - version = "df24f5b04bcbdc0059b27989163a6090f4f6dc7a" - [groups.run] - artifact = "909427826938.dkr.ecr.us-east-1.amazonaws.com/testground-us-east-1-dht:ca78473d669d" - [groups.run.test_params] - alpha = "6" - beta = "3" - bs_strategy = "7" - bucket_size = "10" - group_order = "1" - latency = "100" - timeout_secs = "600" - -[[groups]] - id = "cypress-provider" - [groups.instances] - count = 5 - percentage = 0.0 - [groups.build] - selectors = ["cypress"] - - [[groups.build.dependencies]] - module = "github.com/libp2p/go-libp2p-kad-dht" - version = "180be07b8303d536e39809bc39c58be5407fedd9" - - [[groups.build.dependencies]] - module = "github.com/libp2p/go-libp2p-xor" - version = "df24f5b04bcbdc0059b27989163a6090f4f6dc7a" - [groups.run] - artifact = "909427826938.dkr.ecr.us-east-1.amazonaws.com/testground-us-east-1-dht:ca78473d669d" - [groups.run.test_params] - alpha = "6" - beta = "3" - bs_strategy = "7" - bucket_size = "10" - group_order = "2" - latency = "100" - record_count = "1" - timeout_secs = "600" - -[[groups]] - id = "cypress-searcher" - [groups.instances] - count = 5 - percentage = 0.0 - [groups.build] - selectors = ["cypress"] - - [[groups.build.dependencies]] - module = "github.com/libp2p/go-libp2p-kad-dht" - version = "180be07b8303d536e39809bc39c58be5407fedd9" - - [[groups.build.dependencies]] - module = "github.com/libp2p/go-libp2p-xor" - version = "df24f5b04bcbdc0059b27989163a6090f4f6dc7a" - [groups.run] - artifact = "909427826938.dkr.ecr.us-east-1.amazonaws.com/testground-us-east-1-dht:ca78473d669d" - [groups.run.test_params] - alpha = "6" - beta = "3" - bs_strategy = "7" - bucket_size = "10" - group_order = "3" - latency = "100" - search_records = "true" - timeout_secs = "600" - -[[groups]] - id = "cypress-bs" - [groups.instances] - count = 5 - percentage = 0.0 - [groups.build] - selectors = ["cypress"] - - [[groups.build.dependencies]] - module = "github.com/libp2p/go-libp2p-kad-dht" - version = "180be07b8303d536e39809bc39c58be5407fedd9" - - [[groups.build.dependencies]] - module = "github.com/libp2p/go-libp2p-xor" - version = "df24f5b04bcbdc0059b27989163a6090f4f6dc7a" - [groups.run] - artifact = "909427826938.dkr.ecr.us-east-1.amazonaws.com/testground-us-east-1-dht:ca78473d669d" - [groups.run.test_params] - alpha = "6" - beta = "3" - bootstrapper = "true" - bs_strategy = "7" - bucket_size = "10" - group_order = "0" - latency = "100" - timeout_secs = "600" diff --git a/testplans/composer/fixtures/ping-pong-local.toml b/testplans/composer/fixtures/ping-pong-local.toml deleted file mode 100644 index d845daafd..000000000 --- a/testplans/composer/fixtures/ping-pong-local.toml +++ /dev/null @@ -1,14 +0,0 @@ -[metadata] -name = "ping-pong-local" -author = "yusef" - -[global] -plan = "network" -case = "ping-pong" -total_instances = 2 -builder = "docker:go" -runner = "local:docker" - -[[groups]] -id = "nodes" -instances = { count = 2 } \ No newline at end of file diff --git a/testplans/composer/requirements.txt b/testplans/composer/requirements.txt deleted file mode 100644 index cfdfaa463..000000000 --- a/testplans/composer/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -param -toml -jupyter -panel -holoviews -ansi2html -matplotlib -hvplot diff --git a/testplans/dashboards/baseline.json b/testplans/dashboards/baseline.json deleted file mode 100644 index 0678594ac..000000000 --- a/testplans/dashboards/baseline.json +++ /dev/null @@ -1,2106 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "id": 15, - "iteration": 1595335476624, - "links": [], - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 0 - }, - "hiddenSeries": false, - "id": 21, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "$tag_instance", - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "instance" - ], - "type": "tag" - }, - { - "params": [ - "previous" - ], - "type": "fill" - } - ], - "measurement": "message/received", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "count" - ], - "type": "field" - }, - { - "params": [], - "type": "last" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "message/received", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 0 - }, - "hiddenSeries": false, - "id": 22, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "$tag_instance", - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "instance" - ], - "type": "tag" - }, - { - "params": [ - "previous" - ], - "type": "fill" - } - ], - "measurement": "message/success", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "count" - ], - "type": "field" - }, - { - "params": [], - "type": "last" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "message/success", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 8 - }, - "hiddenSeries": false, - "id": 18, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "$tag_instance", - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "instance" - ], - "type": "tag" - }, - { - "params": [ - "none" - ], - "type": "fill" - } - ], - "measurement": "chain/node_height", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "last" - ], - "type": "field" - }, - { - "params": [], - "type": "last" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "chain/node_height", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 8 - }, - "hiddenSeries": false, - "id": 19, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "$tag_instance", - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "instance" - ], - "type": "tag" - }, - { - "params": [ - "none" - ], - "type": "fill" - } - ], - "measurement": "peer/count", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "last" - ], - "type": "field" - }, - { - "params": [], - "type": "last" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "peer/count", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "collapsed": false, - "datasource": null, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 16 - }, - "id": 10, - "panels": [], - "title": "Blocks", - "type": "row" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 17 - }, - "hiddenSeries": false, - "id": 15, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "total", - "sortDesc": false, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "$tag_instance", - "groupBy": [ - { - "params": [ - "$myinterval" - ], - "type": "time" - }, - { - "params": [ - "instance" - ], - "type": "tag" - }, - { - "params": [ - "null" - ], - "type": "fill" - } - ], - "measurement": "block/received", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "count" - ], - "type": "field" - }, - { - "params": [], - "type": "last" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "block/received", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 17 - }, - "hiddenSeries": false, - "id": 16, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "total", - "sortDesc": false, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "$tag_instance", - "groupBy": [ - { - "params": [ - "$myinterval" - ], - "type": "time" - }, - { - "params": [ - "instance" - ], - "type": "tag" - }, - { - "params": [ - "null" - ], - "type": "fill" - } - ], - "measurement": "block/success", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "count" - ], - "type": "field" - }, - { - "params": [], - "type": "last" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "block/success", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 25 - }, - "hiddenSeries": false, - "id": 13, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "total", - "sortDesc": false, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "$tag_miner ($tag_run)", - "groupBy": [ - { - "params": [ - "$myinterval" - ], - "type": "time" - }, - { - "params": [ - "run" - ], - "type": "tag" - }, - { - "params": [ - "miner" - ], - "type": "tag" - }, - { - "params": [ - "0" - ], - "type": "fill" - } - ], - "measurement": "diagnostics.block.mine.counter", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "count" - ], - "type": "field" - }, - { - "params": [], - "type": "sum" - } - ] - ], - "tags": [ - { - "key": "run", - "operator": "=~", - "value": "/^$runid$/" - } - ] - }, - { - "alias": "all ($tag_run)", - "groupBy": [ - { - "params": [ - "$myinterval" - ], - "type": "time" - }, - { - "params": [ - "run" - ], - "type": "tag" - }, - { - "params": [ - "0" - ], - "type": "fill" - } - ], - "measurement": "diagnostics.block.mine.counter", - "orderByTime": "ASC", - "policy": "default", - "refId": "B", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "count" - ], - "type": "field" - }, - { - "params": [], - "type": "sum" - } - ] - ], - "tags": [ - { - "key": "run", - "operator": "=~", - "value": "/^$runid$/" - } - ] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "mined blocks from testplan", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "collapsed": false, - "datasource": null, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 33 - }, - "id": 8, - "panels": [], - "title": "Data", - "type": "row" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 34 - }, - "hiddenSeries": false, - "id": 2, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "find-data - 95% max", - "groupBy": [ - { - "params": [ - "$myinterval" - ], - "type": "time" - }, - { - "params": [ - "run" - ], - "type": "tag" - }, - { - "params": [ - "0" - ], - "type": "fill" - } - ], - "measurement": "diagnostics.find-data.histogram", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "p95" - ], - "type": "field" - }, - { - "params": [], - "type": "max" - } - ] - ], - "tags": [ - { - "key": "run", - "operator": "=~", - "value": "/^$runid$/" - } - ] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "find data", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "ns", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 34 - }, - "hiddenSeries": false, - "id": 14, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "total", - "sortDesc": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "send-data-to - $tag_miner ($tag_run)", - "groupBy": [ - { - "params": [ - "$myinterval" - ], - "type": "time" - }, - { - "params": [ - "miner" - ], - "type": "tag" - }, - { - "params": [ - "run" - ], - "type": "tag" - }, - { - "params": [ - "0" - ], - "type": "fill" - } - ], - "measurement": "diagnostics.send-data-to.counter", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "count" - ], - "type": "field" - }, - { - "params": [], - "type": "sum" - } - ] - ], - "tags": [ - { - "key": "run", - "operator": "=~", - "value": "/^$runid$/" - } - ] - }, - { - "alias": "find-data.offer - $tag_miner ($tag_run)", - "groupBy": [ - { - "params": [ - "$myinterval" - ], - "type": "time" - }, - { - "params": [ - "miner" - ], - "type": "tag" - }, - { - "params": [ - "run" - ], - "type": "tag" - }, - { - "params": [ - "0" - ], - "type": "fill" - } - ], - "measurement": "diagnostics.find-data.offer.counter", - "orderByTime": "ASC", - "policy": "default", - "refId": "D", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "count" - ], - "type": "field" - }, - { - "params": [], - "type": "sum" - } - ] - ], - "tags": [ - { - "key": "run", - "operator": "=~", - "value": "/^$runid$/" - } - ] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "send data to ; got retrieve offers from", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "collapsed": false, - "datasource": null, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 43 - }, - "id": 6, - "panels": [], - "title": "Deals", - "type": "row" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 44 - }, - "hiddenSeries": false, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "deal.sealed - 95% max", - "groupBy": [ - { - "params": [ - "$myinterval" - ], - "type": "time" - }, - { - "params": [ - "run" - ], - "type": "tag" - }, - { - "params": [ - "0" - ], - "type": "fill" - } - ], - "measurement": "diagnostics.deal.sealed.histogram", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "p95" - ], - "type": "field" - }, - { - "params": [], - "type": "max" - } - ] - ], - "tags": [ - { - "key": "run", - "operator": "=~", - "value": "/^$runid$/" - } - ] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "started -> sealed", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "ns", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 44 - }, - "hiddenSeries": false, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "deal.retrieved - 95% max ($tag_run)", - "groupBy": [ - { - "params": [ - "$myinterval" - ], - "type": "time" - }, - { - "params": [ - "run" - ], - "type": "tag" - }, - { - "params": [ - "run" - ], - "type": "tag" - }, - { - "params": [ - "0" - ], - "type": "fill" - } - ], - "measurement": "diagnostics.deal.retrieved.histogram", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "p95" - ], - "type": "field" - }, - { - "params": [], - "type": "max" - } - ] - ], - "tags": [ - { - "key": "run", - "operator": "=~", - "value": "/^$runid$/" - } - ] - }, - { - "alias": "deal.retrieved - min ($tag_run)", - "groupBy": [ - { - "params": [ - "$myinterval" - ], - "type": "time" - }, - { - "params": [ - "run" - ], - "type": "tag" - }, - { - "params": [ - "run" - ], - "type": "tag" - }, - { - "params": [ - "0" - ], - "type": "fill" - } - ], - "measurement": "diagnostics.deal.retrieved.histogram", - "orderByTime": "ASC", - "policy": "default", - "refId": "B", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "min" - ], - "type": "field" - }, - { - "params": [], - "type": "min" - } - ] - ], - "tags": [ - { - "key": "run", - "operator": "=~", - "value": "/^$runid$/" - } - ] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "started -> retrieved", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "ns", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 53 - }, - "hiddenSeries": false, - "id": 23, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "deal.sealed - count", - "groupBy": [ - { - "params": [ - "$myinterval" - ], - "type": "time" - }, - { - "params": [ - "run" - ], - "type": "tag" - }, - { - "params": [ - "0" - ], - "type": "fill" - } - ], - "measurement": "diagnostics.deal.sealed.histogram", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "count" - ], - "type": "field" - }, - { - "params": [], - "type": "sum" - } - ] - ], - "tags": [ - { - "key": "run", - "operator": "=~", - "value": "/^$runid$/" - } - ] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "started -> sealed", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 53 - }, - "hiddenSeries": false, - "id": 24, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "deal.retrieved - count", - "groupBy": [ - { - "params": [ - "$myinterval" - ], - "type": "time" - }, - { - "params": [ - "run" - ], - "type": "tag" - }, - { - "params": [ - "0" - ], - "type": "fill" - } - ], - "measurement": "diagnostics.deal.retrieved.histogram", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "count" - ], - "type": "field" - }, - { - "params": [], - "type": "sum" - } - ] - ], - "tags": [ - { - "key": "run", - "operator": "=~", - "value": "/^$runid$/" - } - ] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "started -> retrieved", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "refresh": "5s", - "schemaVersion": 25, - "style": "dark", - "tags": [], - "templating": { - "list": [ - { - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "selected": false, - "text": "10s", - "value": "10s" - }, - "hide": 0, - "label": null, - "name": "myinterval", - "options": [ - { - "selected": true, - "text": "10s", - "value": "10s" - }, - { - "selected": false, - "text": "100s", - "value": "100s" - } - ], - "query": "10s,100s", - "queryValue": "", - "refresh": 2, - "skipUrlSync": false, - "type": "interval" - }, - { - "allValue": null, - "current": { - "selected": false, - "text": "All", - "value": "$__all" - }, - "datasource": "influxdb", - "definition": "SHOW TAG VALUES WITH KEY = run", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "runid", - "options": [], - "query": "SHOW TAG VALUES WITH KEY = run", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] - }, - "timezone": "", - "title": "Project Oni - Baseline test", - "uid": "8em8RXWMz", - "version": 1 -} diff --git a/testplans/dashboards/chain.json b/testplans/dashboards/chain.json deleted file mode 100644 index c708c61cc..000000000 --- a/testplans/dashboards/chain.json +++ /dev/null @@ -1,2748 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "id": 15, - "links": [], - "panels": [ - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "decimals": 2, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 3, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 0 - }, - "hiddenSeries": false, - "hideTimeOverride": false, - "id": 38, - "interval": "", - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "avg", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "alias": "$tag_miner", - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "miner" - ], - "type": "tag" - }, - { - "params": [ - "null" - ], - "type": "fill" - } - ], - "measurement": "chain.election", - "orderByTime": "ASC", - "policy": "default", - "query": "SELECT count(\"value\") FROM \"chain.election\" WHERE $timeFilter -10m GROUP BY time($__interval), \"miner\" fill(null)", - "rawQuery": true, - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "count" - }, - { - "params": [ - "20" - ], - "type": "moving_average" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Blocks Won", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 2, - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "decimals": null, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "cacheTimeout": null, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 4, - "w": 8, - "x": 0, - "y": 9 - }, - "hiddenSeries": false, - "id": 22, - "interval": "", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "/.*/", - "color": "rgb(31, 120, 193)" - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "groupBy": [], - "measurement": "chain.power", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": "4h", - "timeRegions": [], - "timeShift": null, - "title": "Total Power", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "format": "s", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 8, - "y": 9 - }, - "id": 12, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true, - "ymax": null, - "ymin": 0 - }, - "tableColumn": "", - "targets": [ - { - "groupBy": [], - "measurement": "chain.blocktime", - "orderByTime": "ASC", - "policy": "default", - "query": "SELECT difference(mean(\"value\")) FROM \"chain.blocktime\" WHERE $timeFilter GROUP BY time($__interval) fill(null)", - "rawQuery": false, - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "difference" - } - ] - ], - "tags": [] - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Avg Blocktime", - "type": "singlestat", - "valueFontSize": "100%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "format": "bytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 12, - "y": 9 - }, - "id": 42, - "interval": "", - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true, - "ymax": null, - "ymin": 0 - }, - "tableColumn": "", - "targets": [ - { - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "null" - ], - "type": "fill" - } - ], - "orderByTime": "ASC", - "policy": "default", - "query": "SELECT sum(\"value\") FROM \"chain.miner_power\" WHERE $timeFilter GROUP BY time(2s)", - "rawQuery": true, - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "mean" - } - ] - ], - "tags": [] - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Network Storage", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 8, - "x": 16, - "y": 9 - }, - "id": 6, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true, - "ymax": null, - "ymin": 0 - }, - "tableColumn": "", - "targets": [ - { - "groupBy": [ - { - "params": [ - "$interval" - ], - "type": "time" - } - ], - "measurement": "chain.election", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "sum" - } - ] - ], - "tags": [] - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Blocks In Tipset", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorPostfix": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 3, - "w": 4, - "x": 0, - "y": 13 - }, - "id": 4, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": true, - "lineColor": "rgb(31, 120, 193)", - "show": true, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "groupBy": [], - "measurement": "chain.height", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - } - ] - ], - "tags": [] - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Block Height", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "format": "s", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 3, - "w": 4, - "x": 4, - "y": 13 - }, - "id": 14, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true, - "ymax": null, - "ymin": 0 - }, - "tableColumn": "", - "targets": [ - { - "groupBy": [], - "measurement": "chain.blocktime", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "difference" - } - ] - ], - "tags": [] - } - ], - "thresholds": "30,90", - "timeFrom": null, - "timeShift": null, - "title": "Last Blocktime", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 3, - "w": 4, - "x": 8, - "y": 13 - }, - "id": 32, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "null" - ], - "type": "fill" - } - ], - "measurement": "chain.message_gasprice", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "mean" - } - ] - ], - "tags": [] - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Avg Gas Price", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "format": "decbytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 3, - "w": 4, - "x": 12, - "y": 13 - }, - "id": 20, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "null" - ], - "type": "fill" - } - ], - "measurement": "chain.message_size", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "mean" - } - ] - ], - "tags": [] - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Avg Message Size", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "format": "bytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 3, - "w": 4, - "x": 16, - "y": 13 - }, - "id": 8, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true, - "ymax": null, - "ymin": 0 - }, - "tableColumn": "", - "targets": [ - { - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "null" - ], - "type": "fill" - } - ], - "measurement": "chain.blockheader_size", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "mean" - } - ] - ], - "tags": [] - } - ], - "thresholds": "1024,2048", - "timeFrom": null, - "timeShift": null, - "title": "Avg Blockheader Size", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 3, - "w": 4, - "x": 20, - "y": 13 - }, - "id": 10, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "pluginVersion": "6.4.2", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true, - "ymax": null, - "ymin": 0 - }, - "tableColumn": "", - "targets": [ - { - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "null" - ], - "type": "fill" - } - ], - "measurement": "chain.message_count", - "orderByTime": "ASC", - "policy": "default", - "query": "SELECT \"value\" FROM \"chain.message_count\" WHERE $timeFilter ", - "rawQuery": false, - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "sum" - } - ] - ], - "tags": [] - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Avg Messages in Tipset", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "influxdb", - "decimals": 0, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "format": "dateTimeFromNow", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 3, - "w": 4, - "x": 0, - "y": 16 - }, - "id": 16, - "interval": "", - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "groupBy": [], - "measurement": "chain.blocktime", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [ - "*1000" - ], - "type": "math" - } - ] - ], - "tags": [] - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Head Updated", - "type": "singlestat", - "valueFontSize": "50%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "aliasColors": {}, - "bars": false, - "cacheTimeout": null, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 3, - "w": 16, - "x": 4, - "y": 16 - }, - "hiddenSeries": false, - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": false, - "hideZero": false, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Null Blocks", - "yaxis": 2 - }, - { - "alias": "Block Time", - "color": "rgb(31, 120, 193)" - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "Block Time", - "groupBy": [], - "measurement": "chain.blocktime", - "orderByTime": "ASC", - "policy": "default", - "query": "SELECT difference(\"value\") FROM \"chain.blocktime\" WHERE $timeFilter", - "rawQuery": true, - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "difference" - } - ] - ], - "tags": [] - }, - { - "alias": "Null Blocks", - "groupBy": [], - "measurement": "chain.height", - "orderByTime": "ASC", - "policy": "default", - "refId": "B", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "difference" - }, - { - "params": [ - "-1" - ], - "type": "math" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Tipsets", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "label": "Time between tipsets", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "decimals": 0, - "format": "short", - "label": "Number of Null blocks", - "logBase": 1, - "max": null, - "min": "0", - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 3, - "w": 4, - "x": 20, - "y": 16 - }, - "id": 30, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "FIL", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "groupBy": [], - "measurement": "chain.pledge_collateral", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - } - ] - ], - "tags": [] - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Pledge Collateral", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "columns": [], - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fontSize": "100%", - "gridPos": { - "h": 21, - "w": 4, - "x": 0, - "y": 19 - }, - "id": 28, - "pageSize": null, - "showHeader": true, - "sort": { - "col": 1, - "desc": true - }, - "styles": [ - { - "alias": "Time", - "align": "auto", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "", - "align": "auto", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "mappingType": 1, - "pattern": "power", - "thresholds": [], - "type": "number", - "unit": "bytes" - }, - { - "alias": "", - "align": "auto", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "decimals": 2, - "pattern": "/.*/", - "thresholds": [], - "type": "number", - "unit": "short" - } - ], - "targets": [ - { - "groupBy": [], - "measurement": "chain.miner_power", - "orderByTime": "ASC", - "policy": "default", - "query": "SELECT top(\"value\", \"miner\", 20) as \"power\" FROM \"chain.miner_power\" WHERE $timeFilter", - "rawQuery": true, - "refId": "A", - "resultFormat": "table", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - } - ] - ], - "tags": [] - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Top Power Table", - "transform": "table", - "type": "table-old" - }, - { - "aliasColors": {}, - "bars": false, - "cacheTimeout": null, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 5, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 4, - "y": 19 - }, - "hiddenSeries": false, - "id": 40, - "interval": "", - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": true, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "alias": "$tag_miner", - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "miner" - ], - "type": "tag" - }, - { - "params": [ - "previous" - ], - "type": "fill" - } - ], - "limit": "", - "measurement": "chain.miner_power", - "orderByTime": "ASC", - "policy": "default", - "query": "SELECT mean(\"value\") FROM \"chain.miner_power\" WHERE $timeFilter GROUP BY time($__interval), \"miner\" fill(previous)", - "rawQuery": true, - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [ - "\"miner\",20" - ], - "type": "top" - } - ] - ], - "slimit": "", - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Top Miner Power", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 2, - "format": "bytes", - "label": "Power", - "logBase": 1, - "max": "100", - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "columns": [], - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fontSize": "100%", - "gridPos": { - "h": 21, - "w": 8, - "x": 16, - "y": 19 - }, - "id": 18, - "pageSize": null, - "showHeader": true, - "sort": { - "col": 0, - "desc": true - }, - "styles": [ - { - "alias": "Height", - "align": "auto", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "link": false, - "mappingType": 1, - "pattern": "chain.height", - "preserveFormat": false, - "sanitize": false, - "type": "string" - }, - { - "alias": "Tipset", - "align": "auto", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "decimals": 2, - "pattern": "chain.height.tipset", - "preserveFormat": false, - "sanitize": false, - "thresholds": [], - "type": "string", - "unit": "short" - }, - { - "alias": "", - "align": "auto", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "mappingType": 1, - "pattern": "Time", - "thresholds": [], - "type": "hidden", - "unit": "short" - } - ], - "targets": [ - { - "groupBy": [], - "measurement": "chain.height", - "orderByTime": "ASC", - "policy": "default", - "query": "SELECT \"value\", \"tipset\" FROM \"chain.height\" WHERE $timeFilter", - "rawQuery": true, - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - } - ] - ], - "tags": [] - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Chain Table", - "transform": "timeseries_to_columns", - "type": "table-old" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 4, - "y": 27 - }, - "hiddenSeries": false, - "id": 46, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "$tag_miner", - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "null" - ], - "type": "fill" - } - ], - "orderByTime": "ASC", - "policy": "default", - "query": "SELECT top(\"value\", \"miner\",20) FROM \"chain.miner_power\" WHERE $timeFilter GROUP BY time($__interval), \"miner\"", - "rawQuery": true, - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "mean" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Chain / Miner Power", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "cacheTimeout": null, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 6, - "w": 12, - "x": 4, - "y": 35 - }, - "hiddenSeries": false, - "id": 24, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "/.*/", - "color": "rgb(31, 120, 193)" - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "previous" - ], - "type": "fill" - } - ], - "measurement": "chain.pledge_collateral", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "mean" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Pledge Collateral", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "FIL", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "cacheTimeout": null, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 12, - "x": 4, - "y": 41 - }, - "hiddenSeries": false, - "id": 44, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "previous" - ], - "type": "fill" - } - ], - "measurement": "chain.miner_power", - "orderByTime": "ASC", - "policy": "default", - "query": "SELECT count(\"value\") FROM \"chain.miner_power\" WHERE $timeFilter GROUP BY time($__interval)", - "rawQuery": false, - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "count" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Miners on Chain", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 48 - }, - "hiddenSeries": false, - "id": 34, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": false, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "alias": "Adr $tag_actor | Md $tag_method", - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "actor" - ], - "type": "tag" - }, - { - "params": [ - "method" - ], - "type": "tag" - }, - { - "params": [ - "null" - ], - "type": "fill" - } - ], - "measurement": "chain.message_count", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "sum" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Actor Messages Method", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "influxdb", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 48 - }, - "hiddenSeries": false, - "id": 36, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "avg", - "sortDesc": false, - "total": false, - "values": false - }, - "lines": false, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "alias": "Adr $tag_actor | Md $tag_method | Ex $tag_exitcode", - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "method" - ], - "type": "tag" - }, - { - "params": [ - "exitcode" - ], - "type": "tag" - }, - { - "params": [ - "actor" - ], - "type": "tag" - }, - { - "params": [ - "null" - ], - "type": "fill" - } - ], - "measurement": "chain.message_count", - "orderByTime": "ASC", - "policy": "default", - "query": "SELECT sum(\"value\") FROM \"chain.message_count\" WHERE $timeFilter GROUP BY time($__interval), \"method\", \"exitcode\", \"actor\" fill(null)", - "rawQuery": true, - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "count" - } - ] - ], - "tags": [] - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Actor Messages Method With Exitcode", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "refresh": "5s", - "schemaVersion": 25, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-30m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "10s", - "30s", - "45s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] - }, - "timezone": "", - "title": "Chain", - "uid": "z6FtI92Zz", - "version": 3 -} diff --git a/testplans/docker-images/Dockerfile.oni-buildbase b/testplans/docker-images/Dockerfile.oni-buildbase deleted file mode 100644 index 33420f4a6..000000000 --- a/testplans/docker-images/Dockerfile.oni-buildbase +++ /dev/null @@ -1,16 +0,0 @@ -ARG GO_VERSION=1.18.1 - -FROM golang:${GO_VERSION}-buster - -RUN apt-get update && apt-get install -y ca-certificates llvm clang mesa-opencl-icd ocl-icd-opencl-dev jq gcc git pkg-config bzr libhwloc-dev - -ARG FILECOIN_FFI_COMMIT=8b97bd8230b77bd32f4f27e4766a6d8a03b4e801 -ARG FFI_DIR=/extern/filecoin-ffi - -RUN mkdir -p ${FFI_DIR} \ - && git clone https://github.com/filecoin-project/filecoin-ffi.git ${FFI_DIR} \ - && cd ${FFI_DIR} \ - && git checkout ${FILECOIN_FFI_COMMIT} \ - && make - -RUN ldconfig diff --git a/testplans/docker-images/Dockerfile.oni-runtime b/testplans/docker-images/Dockerfile.oni-runtime deleted file mode 100644 index e18ca3bbc..000000000 --- a/testplans/docker-images/Dockerfile.oni-runtime +++ /dev/null @@ -1,23 +0,0 @@ -ARG GO_VERSION=1.18.1 - -FROM golang:${GO_VERSION}-buster as downloader - -## Fetch the proof parameters. -## 1. Install the paramfetch binary first, so it can be cached over builds. -## 2. Then copy over the parameters (which could change). -## 3. Trigger the download. -## Output will be in /var/tmp/filecoin-proof-parameters. - -RUN go get github.com/filecoin-project/go-paramfetch/paramfetch@master -COPY /proof-parameters.json / -RUN paramfetch 8388608 /proof-parameters.json - -FROM ubuntu:18.04 - -RUN apt-get update && apt-get install -y ca-certificates llvm clang mesa-opencl-icd ocl-icd-opencl-dev gcc pkg-config libhwloc-dev - -RUN apt-get install -y jq net-tools netcat traceroute iputils-ping wget vim curl telnet iproute2 dnsutils - -COPY --from=downloader /var/tmp/filecoin-proof-parameters /var/tmp/filecoin-proof-parameters - -RUN ldconfig diff --git a/testplans/docker-images/Dockerfile.oni-runtime-debug b/testplans/docker-images/Dockerfile.oni-runtime-debug deleted file mode 100644 index 33954c92f..000000000 --- a/testplans/docker-images/Dockerfile.oni-runtime-debug +++ /dev/null @@ -1,30 +0,0 @@ -ARG GO_VERSION=1.18.1 - -FROM golang:${GO_VERSION}-buster as downloader - -## Fetch the proof parameters. -## 1. Install the paramfetch binary first, so it can be cached over builds. -## 2. Then copy over the parameters (which could change). -## 3. Trigger the download. -## Output will be in /var/tmp/filecoin-proof-parameters. - -RUN go get github.com/filecoin-project/go-paramfetch/paramfetch@master -COPY /proof-parameters.json / -RUN paramfetch 8388608 /proof-parameters.json - -ARG LOTUS_COMMIT=b8deee048eaf850113e8626a73f64b17ba69a9f6 - -## for debug purposes -RUN apt update && apt install -y mesa-opencl-icd ocl-icd-opencl-dev gcc git bzr jq pkg-config libhwloc-dev curl && git clone https://github.com/filecoin-project/lotus.git && cd lotus/ && git checkout ${LOTUS_COMMIT} && make clean && make all && make install - -FROM ubuntu:18.04 - -RUN apt-get update && apt-get install -y ca-certificates llvm clang mesa-opencl-icd ocl-icd-opencl-dev jq gcc pkg-config libhwloc-dev net-tools netcat traceroute iputils-ping wget vim curl telnet iproute2 dnsutils -COPY --from=downloader /var/tmp/filecoin-proof-parameters /var/tmp/filecoin-proof-parameters - -## for debug purposes -COPY --from=downloader /usr/local/bin/lotus /usr/local/bin/lll -COPY --from=downloader /usr/local/bin/lotus-miner /usr/local/bin/lm - -ENV FULLNODE_API_INFO="/ip4/127.0.0.1/tcp/1234/http" -ENV MINER_API_INFO="/ip4/127.0.0.1/tcp/2345/http" diff --git a/testplans/docker-images/proof-parameters.json b/testplans/docker-images/proof-parameters.json deleted file mode 100644 index 88bb0bfa3..000000000 --- a/testplans/docker-images/proof-parameters.json +++ /dev/null @@ -1,202 +0,0 @@ -{ - "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": { - "cid": "QmVxjFRyhmyQaZEtCh7nk2abc7LhFkzhnRX4rcHqCCpikR", - "digest": "7610b9f82bfc88405b7a832b651ce2f6", - "sector_size": 2048 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-0170db1f394b35d995252228ee359194b13199d259380541dc529fb0099096b0.vk": { - "cid": "QmcS5JZs8X3TdtkEBpHAdUYjdNDqcL7fWQFtQz69mpnu2X", - "digest": "0e0958009936b9d5e515ec97b8cb792d", - "sector_size": 2048 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-0cfb4f178bbb71cf2ecfcd42accce558b27199ab4fb59cb78f2483fe21ef36d9.params": { - "cid": "QmUiRx71uxfmUE8V3H9sWAsAXoM88KR4eo1ByvvcFNeTLR", - "digest": "1a7d4a9c8a502a497ed92a54366af33f", - "sector_size": 536870912 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-0cfb4f178bbb71cf2ecfcd42accce558b27199ab4fb59cb78f2483fe21ef36d9.vk": { - "cid": "QmfCeddjFpWtavzfEzZpJfzSajGNwfL4RjFXWAvA9TSnTV", - "digest": "4dae975de4f011f101f5a2f86d1daaba", - "sector_size": 536870912 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-3ea05428c9d11689f23529cde32fd30aabd50f7d2c93657c1d3650bca3e8ea9e.params": { - "cid": "QmcSTqDcFVLGGVYz1njhUZ7B6fkKtBumsLUwx4nkh22TzS", - "digest": "82c88066be968bb550a05e30ff6c2413", - "sector_size": 2048 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-3ea05428c9d11689f23529cde32fd30aabd50f7d2c93657c1d3650bca3e8ea9e.vk": { - "cid": "QmSTCXF2ipGA3f6muVo6kHc2URSx6PzZxGUqu7uykaH5KU", - "digest": "ffd79788d614d27919ae5bd2d94eacb6", - "sector_size": 2048 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-50c7368dea9593ed0989e70974d28024efa9d156d585b7eea1be22b2e753f331.params": { - "cid": "QmU9SBzJNrcjRFDiFc4GcApqdApN6z9X7MpUr66mJ2kAJP", - "digest": "700171ecf7334e3199437c930676af82", - "sector_size": 8388608 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-50c7368dea9593ed0989e70974d28024efa9d156d585b7eea1be22b2e753f331.vk": { - "cid": "QmbmUMa3TbbW3X5kFhExs6WgC4KeWT18YivaVmXDkB6ANG", - "digest": "79ebb55f56fda427743e35053edad8fc", - "sector_size": 8388608 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-5294475db5237a2e83c3e52fd6c2b03859a1831d45ed08c4f35dbf9a803165a9.params": { - "cid": "QmdNEL2RtqL52GQNuj8uz6mVj5Z34NVnbaJ1yMyh1oXtBx", - "digest": "c49499bb76a0762884896f9683403f55", - "sector_size": 8388608 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-5294475db5237a2e83c3e52fd6c2b03859a1831d45ed08c4f35dbf9a803165a9.vk": { - "cid": "QmUiVYCQUgr6Y13pZFr8acWpSM4xvTXUdcvGmxyuHbKhsc", - "digest": "34d4feeacd9abf788d69ef1bb4d8fd00", - "sector_size": 8388608 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-7d739b8cf60f1b0709eeebee7730e297683552e4b69cab6984ec0285663c5781.params": { - "cid": "QmVgCsJFRXKLuuUhT3aMYwKVGNA9rDeR6DCrs7cAe8riBT", - "digest": "827359440349fe8f5a016e7598993b79", - "sector_size": 536870912 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-0-0-7d739b8cf60f1b0709eeebee7730e297683552e4b69cab6984ec0285663c5781.vk": { - "cid": "QmfA31fbCWojSmhSGvvfxmxaYCpMoXP95zEQ9sLvBGHNaN", - "digest": "bd2cd62f65c1ab84f19ca27e97b7c731", - "sector_size": 536870912 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-0-0377ded656c6f524f1618760bffe4e0a1c51d5a70c4509eedae8a27555733edc.params": { - "cid": "QmaUmfcJt6pozn8ndq1JVBzLRjRJdHMTPd4foa8iw5sjBZ", - "digest": "2cf49eb26f1fee94c85781a390ddb4c8", - "sector_size": 34359738368 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-0-0377ded656c6f524f1618760bffe4e0a1c51d5a70c4509eedae8a27555733edc.vk": { - "cid": "QmR9i9KL3vhhAqTBGj1bPPC7LvkptxrH9RvxJxLN1vvsBE", - "digest": "0f8ec542485568fa3468c066e9fed82b", - "sector_size": 34359738368 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-0-559e581f022bb4e4ec6e719e563bf0e026ad6de42e56c18714a2c692b1b88d7e.params": { - "cid": "Qmdtczp7p4wrbDofmHdGhiixn9irAcN77mV9AEHZBaTt1i", - "digest": "d84f79a16fe40e9e25a36e2107bb1ba0", - "sector_size": 34359738368 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-0-559e581f022bb4e4ec6e719e563bf0e026ad6de42e56c18714a2c692b1b88d7e.vk": { - "cid": "QmZCvxKcKP97vDAk8Nxs9R1fWtqpjQrAhhfXPoCi1nkDoF", - "digest": "fc02943678dd119e69e7fab8420e8819", - "sector_size": 34359738368 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-2-2627e4006b67f99cef990c0a47d5426cb7ab0a0ad58fc1061547bf2d28b09def.params": { - "cid": "QmeAN4vuANhXsF8xP2Lx5j2L6yMSdogLzpcvqCJThRGK1V", - "digest": "3810b7780ac0e299b22ae70f1f94c9bc", - "sector_size": 68719476736 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-2-2627e4006b67f99cef990c0a47d5426cb7ab0a0ad58fc1061547bf2d28b09def.vk": { - "cid": "QmWV8rqZLxs1oQN9jxNWmnT1YdgLwCcscv94VARrhHf1T7", - "digest": "59d2bf1857adc59a4f08fcf2afaa916b", - "sector_size": 68719476736 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-2-b62098629d07946e9028127e70295ed996fe3ed25b0f9f88eb610a0ab4385a3c.params": { - "cid": "QmVkrXc1SLcpgcudK5J25HH93QvR9tNsVhVTYHm5UymXAz", - "digest": "2170a91ad5bae22ea61f2ea766630322", - "sector_size": 68719476736 - }, - "v28-proof-of-spacetime-fallback-merkletree-poseidon_hasher-8-8-2-b62098629d07946e9028127e70295ed996fe3ed25b0f9f88eb610a0ab4385a3c.vk": { - "cid": "QmbfQjPD7EpzjhWGmvWAsyN2mAZ4PcYhsf3ujuhU9CSuBm", - "digest": "6d3789148fb6466d07ee1e24d6292fd6", - "sector_size": 68719476736 - }, - "v28-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-032d3138d22506ec0082ed72b2dcba18df18477904e35bafee82b3793b06832f.params": { - "cid": "QmWceMgnWYLopMuM4AoGMvGEau7tNe5UK83XFjH5V9B17h", - "digest": "434fb1338ecfaf0f59256f30dde4968f", - "sector_size": 2048 - }, - "v28-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-032d3138d22506ec0082ed72b2dcba18df18477904e35bafee82b3793b06832f.vk": { - "cid": "QmamahpFCstMUqHi2qGtVoDnRrsXhid86qsfvoyCTKJqHr", - "digest": "dc1ade9929ade1708238f155343044ac", - "sector_size": 2048 - }, - "v28-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-6babf46ce344ae495d558e7770a585b2382d54f225af8ed0397b8be7c3fcd472.params": { - "cid": "QmYBpTt7LWNAWr1JXThV5VxX7wsQFLd1PHrGYVbrU1EZjC", - "digest": "6c77597eb91ab936c1cef4cf19eba1b3", - "sector_size": 536870912 - }, - "v28-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-6babf46ce344ae495d558e7770a585b2382d54f225af8ed0397b8be7c3fcd472.vk": { - "cid": "QmWionkqH2B6TXivzBSQeSyBxojaiAFbzhjtwYRrfwd8nH", - "digest": "065179da19fbe515507267677f02823e", - "sector_size": 536870912 - }, - "v28-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-ecd683648512ab1765faa2a5f14bab48f676e633467f0aa8aad4b55dcb0652bb.params": { - "cid": "QmPXAPPuQtuQz7Zz3MHMAMEtsYwqM1o9H1csPLeiMUQwZH", - "digest": "09e612e4eeb7a0eb95679a88404f960c", - "sector_size": 8388608 - }, - "v28-stacked-proof-of-replication-merkletree-poseidon_hasher-8-0-0-sha256_hasher-ecd683648512ab1765faa2a5f14bab48f676e633467f0aa8aad4b55dcb0652bb.vk": { - "cid": "QmYCuipFyvVW1GojdMrjK1JnMobXtT4zRCZs1CGxjizs99", - "digest": "b687beb9adbd9dabe265a7e3620813e4", - "sector_size": 8388608 - }, - "v28-stacked-proof-of-replication-merkletree-poseidon_hasher-8-8-0-sha256_hasher-82a357d2f2ca81dc61bb45f4a762807aedee1b0a53fd6c4e77b46a01bfef7820.params": { - "cid": "QmengpM684XLQfG8754ToonszgEg2bQeAGUan5uXTHUQzJ", - "digest": "6a388072a518cf46ebd661f5cc46900a", - "sector_size": 34359738368 - }, - "v28-stacked-proof-of-replication-merkletree-poseidon_hasher-8-8-0-sha256_hasher-82a357d2f2ca81dc61bb45f4a762807aedee1b0a53fd6c4e77b46a01bfef7820.vk": { - "cid": "Qmf93EMrADXAK6CyiSfE8xx45fkMfR3uzKEPCvZC1n2kzb", - "digest": "0c7b4aac1c40fdb7eb82bc355b41addf", - "sector_size": 34359738368 - }, - "v28-stacked-proof-of-replication-merkletree-poseidon_hasher-8-8-2-sha256_hasher-96f1b4a04c5c51e4759bbf224bbc2ef5a42c7100f16ec0637123f16a845ddfb2.params": { - "cid": "QmS7ye6Ri2MfFzCkcUJ7FQ6zxDKuJ6J6B8k5PN7wzSR9sX", - "digest": "1801f8a6e1b00bceb00cc27314bb5ce3", - "sector_size": 68719476736 - }, - "v28-stacked-proof-of-replication-merkletree-poseidon_hasher-8-8-2-sha256_hasher-96f1b4a04c5c51e4759bbf224bbc2ef5a42c7100f16ec0637123f16a845ddfb2.vk": { - "cid": "QmehSmC6BhrgRZakPDta2ewoH9nosNzdjCqQRXsNFNUkLN", - "digest": "a89884252c04c298d0b3c81bfd884164", - "sector_size": 68719476736 - } -} diff --git a/testplans/lotus-soup/.gitignore b/testplans/lotus-soup/.gitignore deleted file mode 100644 index 001a5837b..000000000 --- a/testplans/lotus-soup/.gitignore +++ /dev/null @@ -1 +0,0 @@ -lotus-soup diff --git a/testplans/lotus-soup/_compositions/baseline-docker-1-1-with-restarts.toml b/testplans/lotus-soup/_compositions/baseline-docker-1-1-with-restarts.toml deleted file mode 100644 index 28865a03b..000000000 --- a/testplans/lotus-soup/_compositions/baseline-docker-1-1-with-restarts.toml +++ /dev/null @@ -1,59 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 3 - builder = "docker:go" - runner = "local:docker" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "1" - miners = "1" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "3" - random_beacon_type = "mock" - mining_mode = "natural" - bandwidth = "4MB" - - -[[groups]] - id = "bootstrapper" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" - # Bounce the connection during push and pull requests - bounce_conn_data_transfers = "true" diff --git a/testplans/lotus-soup/_compositions/baseline-docker-1-1.toml b/testplans/lotus-soup/_compositions/baseline-docker-1-1.toml deleted file mode 100644 index 25a31f9ec..000000000 --- a/testplans/lotus-soup/_compositions/baseline-docker-1-1.toml +++ /dev/null @@ -1,55 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 3 - builder = "docker:go" - runner = "local:docker" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "1" - miners = "1" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "3" - random_beacon_type = "mock" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/baseline-docker-5-1.toml b/testplans/lotus-soup/_compositions/baseline-docker-5-1.toml deleted file mode 100644 index 001a02434..000000000 --- a/testplans/lotus-soup/_compositions/baseline-docker-5-1.toml +++ /dev/null @@ -1,55 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 7 - builder = "docker:go" - runner = "local:docker" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "5" - miners = "1" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "5" - random_beacon_type = "mock" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.instances] - count = 5 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/baseline-k8s-1-1-versions.toml b/testplans/lotus-soup/_compositions/baseline-k8s-1-1-versions.toml deleted file mode 100644 index 051d8e0c6..000000000 --- a/testplans/lotus-soup/_compositions/baseline-k8s-1-1-versions.toml +++ /dev/null @@ -1,74 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 3 - builder = "docker:go" - runner = "cluster:k8s" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - push_registry=true - go_proxy_mode="remote" - go_proxy_url="http://localhost:8081" - registry_type="aws" - -[global.run.test_params] - clients = "1" - miners = "1" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "10" - random_beacon_type = "mock" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "512Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.resources] - memory = "4096Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - [groups.build] - dependencies = [ - { module = "github.com/filecoin-project/lotus", version = "{{.Env.LOTUS_VERSION_MINER}}"}, - ] -[[groups]] - id = "clients" - [groups.resources] - memory = "1024Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" - [groups.build] - dependencies = [ - { module = "github.com/filecoin-project/lotus", version = "{{.Env.LOTUS_VERSION_CLIENT}}"}, - ] diff --git a/testplans/lotus-soup/_compositions/baseline-k8s-1-1.toml b/testplans/lotus-soup/_compositions/baseline-k8s-1-1.toml deleted file mode 100644 index 754d12797..000000000 --- a/testplans/lotus-soup/_compositions/baseline-k8s-1-1.toml +++ /dev/null @@ -1,67 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 3 - builder = "docker:go" - runner = "cluster:k8s" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - push_registry=true - go_proxy_mode="remote" - go_proxy_url="http://localhost:8081" - registry_type="aws" - -[global.run.test_params] - clients = "1" - miners = "1" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "10" - random_beacon_type = "mock" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "512Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.resources] - memory = "4096Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.resources] - memory = "1024Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/baseline-k8s-10-3.toml b/testplans/lotus-soup/_compositions/baseline-k8s-10-3.toml deleted file mode 100644 index 4afd3375e..000000000 --- a/testplans/lotus-soup/_compositions/baseline-k8s-10-3.toml +++ /dev/null @@ -1,80 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 14 - builder = "docker:go" - runner = "cluster:k8s" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - push_registry=true - go_proxy_mode="remote" - go_proxy_url="http://localhost:8081" - registry_type="aws" - -[global.run.test_params] - clients = "10" - miners = "3" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - random_beacon_type = "mock" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "512Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners-weak" - [groups.resources] - memory = "8192Mi" - cpu = "1000m" - [groups.instances] - count = 2 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - sectors = "8" - -[[groups]] - id = "miners-strong" - [groups.resources] - memory = "8192Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - sectors = "24" - -[[groups]] - id = "clients" - [groups.resources] - memory = "1024Mi" - cpu = "1000m" - [groups.instances] - count = 10 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/baseline-k8s-2-1.toml b/testplans/lotus-soup/_compositions/baseline-k8s-2-1.toml deleted file mode 100644 index 6258adf40..000000000 --- a/testplans/lotus-soup/_compositions/baseline-k8s-2-1.toml +++ /dev/null @@ -1,67 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 4 - builder = "docker:go" - runner = "cluster:k8s" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - push_registry=true - go_proxy_mode="remote" - go_proxy_url="http://localhost:8081" - registry_type="aws" - -[global.run.test_params] - clients = "2" - miners = "1" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "10" - random_beacon_type = "mock" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "512Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.resources] - memory = "4096Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.resources] - memory = "1024Mi" - cpu = "1000m" - [groups.instances] - count = 2 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/baseline-k8s-3-1.toml b/testplans/lotus-soup/_compositions/baseline-k8s-3-1.toml deleted file mode 100644 index dc6519656..000000000 --- a/testplans/lotus-soup/_compositions/baseline-k8s-3-1.toml +++ /dev/null @@ -1,67 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 5 - builder = "docker:go" - runner = "cluster:k8s" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - push_registry=true - go_proxy_mode="remote" - go_proxy_url="http://localhost:8081" - registry_type="aws" - -[global.run.test_params] - clients = "3" - miners = "1" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "10" - random_beacon_type = "mock" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "512Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.resources] - memory = "8192Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.resources] - memory = "1024Mi" - cpu = "1000m" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/baseline-k8s-3-2.toml b/testplans/lotus-soup/_compositions/baseline-k8s-3-2.toml deleted file mode 100644 index a1c130c31..000000000 --- a/testplans/lotus-soup/_compositions/baseline-k8s-3-2.toml +++ /dev/null @@ -1,67 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 6 - builder = "docker:go" - runner = "cluster:k8s" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - push_registry=true - go_proxy_mode="remote" - go_proxy_url="http://localhost:8081" - registry_type="aws" - -[global.run.test_params] - clients = "3" - miners = "2" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "4" - random_beacon_type = "mock" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "512Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.resources] - memory = "4096Mi" - cpu = "1000m" - [groups.instances] - count = 2 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.resources] - memory = "1024Mi" - cpu = "1000m" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/baseline-k8s-3-3.toml b/testplans/lotus-soup/_compositions/baseline-k8s-3-3.toml deleted file mode 100644 index d8ab629db..000000000 --- a/testplans/lotus-soup/_compositions/baseline-k8s-3-3.toml +++ /dev/null @@ -1,67 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 7 - builder = "docker:go" - runner = "cluster:k8s" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - push_registry=true - go_proxy_mode="remote" - go_proxy_url="http://localhost:8081" - registry_type="aws" - -[global.run.test_params] - clients = "3" - miners = "3" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "10" - random_beacon_type = "mock" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "512Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.resources] - memory = "4096Mi" - cpu = "1000m" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.resources] - memory = "1024Mi" - cpu = "1000m" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/baseline.toml b/testplans/lotus-soup/_compositions/baseline.toml deleted file mode 100644 index be035b6eb..000000000 --- a/testplans/lotus-soup/_compositions/baseline.toml +++ /dev/null @@ -1,55 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 6 - builder = "exec:go" - runner = "local:exec" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "3" - miners = "2" - genesis_timestamp_offset = "0" - balance = "20000000.5" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "10" - random_beacon_type = "mock" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.instances] - count = 2 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/deals-stress-concurrent-natural-k8s.toml b/testplans/lotus-soup/_compositions/deals-stress-concurrent-natural-k8s.toml deleted file mode 100644 index 18f14407f..000000000 --- a/testplans/lotus-soup/_compositions/deals-stress-concurrent-natural-k8s.toml +++ /dev/null @@ -1,69 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-stress" - total_instances = 6 - builder = "docker:go" - runner = "cluster:k8s" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - push_registry=true - go_proxy_mode="remote" - go_proxy_url="http://localhost:8081" - registry_type="aws" - -[global.run.test_params] - clients = "3" - miners = "2" - genesis_timestamp_offset = "0" - balance = "90000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "10" - random_beacon_type = "mock" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "512Mi" - cpu = "100m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.resources] - memory = "14000Mi" - cpu = "1000m" - [groups.instances] - count = 2 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.resources] - memory = "2048Mi" - cpu = "100m" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" - deals = "3" - deal_mode = "concurrent" diff --git a/testplans/lotus-soup/_compositions/deals-stress-concurrent-natural.toml b/testplans/lotus-soup/_compositions/deals-stress-concurrent-natural.toml deleted file mode 100644 index cc3ab45fc..000000000 --- a/testplans/lotus-soup/_compositions/deals-stress-concurrent-natural.toml +++ /dev/null @@ -1,57 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-stress" - total_instances = 6 - builder = "docker:go" - runner = "local:docker" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "3" - miners = "2" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "1000" - random_beacon_type = "mock" - -[[groups]] - id = "bootstrapper" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.instances] - count = 2 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - mining_mode = "natural" - -[[groups]] - id = "clients" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" - deals = "300" - deal_mode = "concurrent" diff --git a/testplans/lotus-soup/_compositions/deals-stress-concurrent.toml b/testplans/lotus-soup/_compositions/deals-stress-concurrent.toml deleted file mode 100644 index bec530c42..000000000 --- a/testplans/lotus-soup/_compositions/deals-stress-concurrent.toml +++ /dev/null @@ -1,56 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-stress" - total_instances = 6 - builder = "docker:go" - runner = "local:docker" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "3" - miners = "2" - genesis_timestamp_offset = "100000" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "1000" - random_beacon_type = "mock" - -[[groups]] - id = "bootstrapper" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.instances] - count = 2 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" - deals = "300" - deal_mode = "concurrent" diff --git a/testplans/lotus-soup/_compositions/deals-stress-serial-natural.toml b/testplans/lotus-soup/_compositions/deals-stress-serial-natural.toml deleted file mode 100644 index c5611a3e8..000000000 --- a/testplans/lotus-soup/_compositions/deals-stress-serial-natural.toml +++ /dev/null @@ -1,57 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-stress" - total_instances = 6 - builder = "docker:go" - runner = "local:docker" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "3" - miners = "2" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "1000" - random_beacon_type = "mock" - -[[groups]] - id = "bootstrapper" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.instances] - count = 2 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - mining_mode = "natural" - -[[groups]] - id = "clients" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" - deals = "300" - deal_mode = "serial" diff --git a/testplans/lotus-soup/_compositions/deals-stress-serial.toml b/testplans/lotus-soup/_compositions/deals-stress-serial.toml deleted file mode 100644 index 5317fecb9..000000000 --- a/testplans/lotus-soup/_compositions/deals-stress-serial.toml +++ /dev/null @@ -1,56 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-stress" - total_instances = 6 - builder = "docker:go" - runner = "local:docker" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "3" - miners = "2" - genesis_timestamp_offset = "100000" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "1000" - random_beacon_type = "mock" - -[[groups]] - id = "bootstrapper" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.instances] - count = 2 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" - deals = "300" - deal_mode = "serial" diff --git a/testplans/lotus-soup/_compositions/drand-halt.toml b/testplans/lotus-soup/_compositions/drand-halt.toml deleted file mode 100644 index ce2610dc1..000000000 --- a/testplans/lotus-soup/_compositions/drand-halt.toml +++ /dev/null @@ -1,79 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "drand-halting" - total_instances = 6 - builder = "docker:go" - runner = "local:docker" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "1" - miners = "1" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "10" - random_beacon_type = "local-drand" - genesis_timestamp_offset = "0" -# mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "120Mi" - cpu = "10m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - - -[[groups]] - id = "miners" - [groups.resources] - memory = "120Mi" - cpu = "10m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - - -[[groups]] - id = "clients" - [groups.resources] - memory = "120Mi" - cpu = "10m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" - - -[[groups]] - id = "drand" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "drand" - drand_period = "1s" - drand_log_level = "none" - suspend_events = "wait 20s -> halt -> wait 1m -> resume -> wait 2s -> halt -> wait 1m -> resume" diff --git a/testplans/lotus-soup/_compositions/drand-outage-k8s.toml b/testplans/lotus-soup/_compositions/drand-outage-k8s.toml deleted file mode 100644 index 0588adb0b..000000000 --- a/testplans/lotus-soup/_compositions/drand-outage-k8s.toml +++ /dev/null @@ -1,71 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "drand-outage" - total_instances = 7 - builder = "docker:go" - runner = "cluster:k8s" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - push_registry=true - go_proxy_mode="remote" - go_proxy_url="http://localhost:8081" - registry_type="aws" - -[global.run.test_params] - clients = "0" - miners = "3" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "100" - random_beacon_type = "local-drand" - genesis_timestamp_offset = "0" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "1024Mi" - cpu = "10m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.resources] - memory = "1024Mi" - cpu = "10m" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "drand" - [groups.resources] - memory = "1024Mi" - cpu = "10m" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "drand" - drand_period = "30s" - drand_catchup_period = "10s" - drand_log_level = "debug" - suspend_events = "wait 5m -> halt -> wait 45m -> resume -> wait 15m -> halt -> wait 5m -> resume" diff --git a/testplans/lotus-soup/_compositions/drand-outage-local.toml b/testplans/lotus-soup/_compositions/drand-outage-local.toml deleted file mode 100644 index dad81a203..000000000 --- a/testplans/lotus-soup/_compositions/drand-outage-local.toml +++ /dev/null @@ -1,59 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "drand-outage" - total_instances = 7 - builder = "docker:go" - runner = "local:docker" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "0" - miners = "3" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "10" - random_beacon_type = "local-drand" - genesis_timestamp_offset = "0" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "drand" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "drand" - drand_period = "30s" - drand_catchup_period = "10s" - drand_log_level = "debug" - suspend_events = "wait 3m -> halt -> wait 3m -> resume -> wait 3m -> halt -> wait 3m -> resume" diff --git a/testplans/lotus-soup/_compositions/fast-k8s-3-1.toml b/testplans/lotus-soup/_compositions/fast-k8s-3-1.toml deleted file mode 100644 index d77bfbc3e..000000000 --- a/testplans/lotus-soup/_compositions/fast-k8s-3-1.toml +++ /dev/null @@ -1,68 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 5 - builder = "docker:go" - runner = "cluster:k8s" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - push_registry=true - go_proxy_mode="remote" - go_proxy_url="http://localhost:8081" - registry_type="aws" - -[global.run.test_params] - clients = "3" - miners = "1" - fast_retrieval = "true" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "10" - random_beacon_type = "mock" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "512Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.resources] - memory = "4096Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.resources] - memory = "1024Mi" - cpu = "1000m" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/local-drand.toml b/testplans/lotus-soup/_compositions/local-drand.toml deleted file mode 100644 index e942ed072..000000000 --- a/testplans/lotus-soup/_compositions/local-drand.toml +++ /dev/null @@ -1,72 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 6 - builder = "docker:go" - runner = "local:docker" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "1" - miners = "1" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "10" - random_beacon_type = "local-drand" - genesis_timestamp_offset = "0" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "120Mi" - cpu = "10m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.resources] - memory = "120Mi" - cpu = "10m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.resources] - memory = "120Mi" - cpu = "10m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" - -[[groups]] - id = "drand" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "drand" diff --git a/testplans/lotus-soup/_compositions/natural.toml b/testplans/lotus-soup/_compositions/natural.toml deleted file mode 100644 index bfef6b844..000000000 --- a/testplans/lotus-soup/_compositions/natural.toml +++ /dev/null @@ -1,55 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 6 - builder = "docker:go" - runner = "local:docker" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "3" - miners = "2" - genesis_timestamp_offset = "100000" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "10" - random_beacon_type = "mock" - -[[groups]] - id = "bootstrapper" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.instances] - count = 2 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - mining_mode = "natural" - -[[groups]] - id = "clients" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/net-chaos/latency.toml b/testplans/lotus-soup/_compositions/net-chaos/latency.toml deleted file mode 100644 index fb5f5f544..000000000 --- a/testplans/lotus-soup/_compositions/net-chaos/latency.toml +++ /dev/null @@ -1,57 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 7 - builder = "docker:go" - runner = "local:docker" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "5" - miners = "1" - genesis_timestamp_offset = "0" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "5" - random_beacon_type = "mock" - mining_mode = "natural" - -[[groups]] - id = "bootstrapper" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - latency_range = '["20ms", "300ms"]' - -[[groups]] - id = "clients" - [groups.instances] - count = 5 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" - latency_range = '["100ms", "1500ms"]' diff --git a/testplans/lotus-soup/_compositions/paych-stress-k8s.toml b/testplans/lotus-soup/_compositions/paych-stress-k8s.toml deleted file mode 100644 index b5d7f9bd4..000000000 --- a/testplans/lotus-soup/_compositions/paych-stress-k8s.toml +++ /dev/null @@ -1,62 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "raulk" - -[global] - plan = "lotus-soup" - case = "paych-stress" - total_instances = 4 # 2 clients + 1 miners + 1 bootstrapper - builder = "docker:go" - runner = "cluster:k8s" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - push_registry=true - go_proxy_mode="remote" - go_proxy_url="http://localhost:8081" - registry_type="aws" - -[global.run.test_params] - clients = "2" - miners = "1" - genesis_timestamp_offset = "0" - balance = "100" ## be careful, this is in FIL. - sectors = "10" - random_beacon_type = "mock" - mining_mode = "natural" - # number of lanes to send vouchers on - lane_count = "8" - # number of vouchers on each lane - vouchers_per_lane = "3" - # amount to increase voucher by each time (per lane) - increments = "3" ## in FIL - -[[groups]] - id = "bootstrapper" - instances = { count = 1 } - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - instances = { count = 1 } - [groups.run.test_params] - role = "miner" - [groups.resources] - memory = "2048Mi" - cpu = "100m" - -[[groups]] - id = "clients" - # the first client will be on the receiving end; all others will be on the sending end. - instances = { count = 2 } - [groups.run.test_params] - role = "client" - [groups.resources] - memory = "1024Mi" - cpu = "100m" diff --git a/testplans/lotus-soup/_compositions/paych-stress.toml b/testplans/lotus-soup/_compositions/paych-stress.toml deleted file mode 100644 index b42721a7b..000000000 --- a/testplans/lotus-soup/_compositions/paych-stress.toml +++ /dev/null @@ -1,53 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "raulk" - -[global] - plan = "lotus-soup" - case = "paych-stress" - total_instances = 5 # 2 clients + 2 miners + 1 bootstrapper - builder = "exec:go" - runner = "local:exec" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "2" - miners = "2" - genesis_timestamp_offset = "0" - balance = "100" ## be careful, this is in FIL. - sectors = "10" - random_beacon_type = "mock" - mining_mode = "natural" - # number of lanes to send vouchers on - lane_count = "8" - # number of vouchers on each lane - vouchers_per_lane = "3" - # amount to increase voucher by each time (per lane) - increments = "3" ## in FIL - -[[groups]] - id = "bootstrapper" - instances = { count = 1 } - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - instances = { count = 2 } - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - # the first client will be on the receiving end; all others will be on the sending end. - instances = { count = 2 } - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/pubsub-tracer.toml b/testplans/lotus-soup/_compositions/pubsub-tracer.toml deleted file mode 100644 index db9f111d1..000000000 --- a/testplans/lotus-soup/_compositions/pubsub-tracer.toml +++ /dev/null @@ -1,64 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "deals-e2e" - total_instances = 7 - builder = "docker:go" - runner = "local:docker" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - enable_go_build_cache = true - -[global.run.test_params] - clients = "3" - miners = "2" - genesis_timestamp_offset = "100000" - balance = "20000000" # These balances will work for maximum 100 nodes, as TotalFilecoin is 2B - sectors = "10" - random_beacon_type = "mock" - enable_pubsub_tracer = "true" - -[[groups]] - id = "pubsub-tracer" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "pubsub-tracer" - -[[groups]] - id = "bootstrapper" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.instances] - count = 2 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - -[[groups]] - id = "clients" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/recovery-exec.toml b/testplans/lotus-soup/_compositions/recovery-exec.toml deleted file mode 100644 index 8e9ef9d6e..000000000 --- a/testplans/lotus-soup/_compositions/recovery-exec.toml +++ /dev/null @@ -1,80 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "recovery-failed-windowed-post" - total_instances = 7 - builder = "exec:go" - runner = "local:exec" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - -[global.build_config] - push_registry=true - go_proxy_mode="remote" - go_proxy_url="http://localhost:8081" - registry_type="aws" - -[global.run.test_params] - clients = "3" - miners = "3" - genesis_timestamp_offset = "0" - balance = "20000000" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "512Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.resources] - memory = "4096Mi" - cpu = "1000m" - [groups.instances] - count = 2 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - sectors = "10" - mining_mode = "natural" - -[[groups]] - id = "miners-biserk" - [groups.resources] - memory = "4096Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner-biserk" - sectors = "5" - mining_mode = "natural" - -[[groups]] - id = "clients" - [groups.resources] - memory = "1024Mi" - cpu = "1000m" - [groups.instances] - count = 3 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/_compositions/recovery-k8s.toml b/testplans/lotus-soup/_compositions/recovery-k8s.toml deleted file mode 100644 index 5b7037e01..000000000 --- a/testplans/lotus-soup/_compositions/recovery-k8s.toml +++ /dev/null @@ -1,95 +0,0 @@ -[metadata] - name = "lotus-soup" - author = "" - -[global] - plan = "lotus-soup" - case = "recovery-failed-windowed-post" - total_instances = 9 - builder = "docker:go" - runner = "cluster:k8s" - -[global.build] - selectors = ["testground"] - -[global.run_config] - exposed_ports = { pprof = "6060", node_rpc = "1234", miner_rpc = "2345" } - keep_service=true - -[global.build_config] - push_registry=true - go_proxy_mode="remote" - go_proxy_url="http://localhost:8081" - registry_type="aws" - -[global.run.test_params] - clients = "4" - miners = "4" - genesis_timestamp_offset = "0" - balance = "20000000" - -[[groups]] - id = "bootstrapper" - [groups.resources] - memory = "512Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "bootstrapper" - -[[groups]] - id = "miners" - [groups.resources] - memory = "4096Mi" - cpu = "1000m" - [groups.instances] - count = 2 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner" - sectors = "10" - mining_mode = "natural" - -[[groups]] - id = "miners-full-slash" - [groups.resources] - memory = "4096Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner-full-slash" - sectors = "10" - mining_mode = "natural" - -[[groups]] - id = "miners-partial-slash" - [groups.resources] - memory = "4096Mi" - cpu = "1000m" - [groups.instances] - count = 1 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "miner-partial-slash" - sectors = "10" - mining_mode = "natural" - -[[groups]] - id = "clients" - [groups.resources] - memory = "1024Mi" - cpu = "1000m" - [groups.instances] - count = 4 - percentage = 0.0 - [groups.run] - [groups.run.test_params] - role = "client" diff --git a/testplans/lotus-soup/deals_e2e.go b/testplans/lotus-soup/deals_e2e.go deleted file mode 100644 index d650bb444..000000000 --- a/testplans/lotus-soup/deals_e2e.go +++ /dev/null @@ -1,246 +0,0 @@ -package main - -import ( - "context" - "fmt" - "io/ioutil" - mbig "math/big" - "math/rand" - "os" - "time" - - "github.com/libp2p/go-libp2p/core/peer" - "github.com/testground/sdk-go/sync" - - "github.com/filecoin-project/go-address" - datatransfer "github.com/filecoin-project/go-data-transfer" - "github.com/filecoin-project/go-state-types/big" - - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/testplans/lotus-soup/testkit" -) - -// This is the baseline test; Filecoin 101. -// -// A network with a bootstrapper, a number of miners, and a number of clients/full nodes -// is constructed and connected through the bootstrapper. -// Some funds are allocated to each node and a number of sectors are presealed in the genesis block. -// -// The test plan: -// One or more clients store content to one or more miners, testing storage deals. -// The plan ensures that the storage deals hit the blockchain and measure the time it took. -// Verification: one or more clients retrieve and verify the hashes of stored content. -// The plan ensures that all (previously) published content can be correctly retrieved -// and measures the time it took. -// -// Preparation of the genesis block: this is the responsibility of the bootstrapper. -// In order to compute the genesis block, we need to collect identities and presealed -// sectors from each node. -// Then we create a genesis block that allocates some funds to each node and collects -// the presealed sectors. -func dealsE2E(t *testkit.TestEnvironment) error { - t.RecordMessage("running node with role '%s'", t.Role) - - // Dispatch/forward non-client roles to defaults. - if t.Role != "client" { - return testkit.HandleDefaultRole(t) - } - - // This is a client role - fastRetrieval := t.BooleanParam("fast_retrieval") - t.RecordMessage("running client, with fast retrieval set to: %v", fastRetrieval) - - cl, err := testkit.PrepareClient(t) - if err != nil { - return err - } - - ctx := context.Background() - client := cl.FullApi - - // select a random miner - minerAddr := cl.MinerAddrs[rand.Intn(len(cl.MinerAddrs))] - if err := client.NetConnect(ctx, minerAddr.MinerNetAddrs); err != nil { - return err - } - t.D().Counter(fmt.Sprintf("send-data-to,miner=%s", minerAddr.MinerActorAddr)).Inc(1) - - t.RecordMessage("selected %s as the miner", minerAddr.MinerActorAddr) - - if fastRetrieval { - err = initPaymentChannel(t, ctx, cl, minerAddr) - if err != nil { - return err - } - } - - // give some time to the miner, otherwise, we get errors like: - // deal errored deal failed: (State=26) error calling node: publishing deal: GasEstimateMessageGas - // error: estimating gas used: message execution failed: exit 19, reason: failed to lock balance: failed to lock client funds: not enough balance to lock for addr t0102: escrow balance 0 < locked 0 + required 640297000 (RetCode=19) - time.Sleep(40 * time.Second) - - time.Sleep(time.Duration(t.GlobalSeq) * 5 * time.Second) - - // generate 5000000 bytes of random data - data := make([]byte, 5000000) - rand.New(rand.NewSource(time.Now().UnixNano())).Read(data) - - file, err := ioutil.TempFile("/tmp", "data") - if err != nil { - return err - } - defer os.Remove(file.Name()) - - _, err = file.Write(data) - if err != nil { - return err - } - - fcid, err := client.ClientImport(ctx, api.FileRef{Path: file.Name(), IsCAR: false}) - if err != nil { - return err - } - t.RecordMessage("file cid: %s", fcid) - - // Check if we should bounce the connection during data transfers - if t.BooleanParam("bounce_conn_data_transfers") { - t.RecordMessage("Will bounce connection during push and pull data-transfers") - err = bounceConnInTransfers(ctx, t, client, minerAddr.MinerNetAddrs.ID) - if err != nil { - return err - } - } - - // start deal - t1 := time.Now() - deal := testkit.StartDeal(ctx, minerAddr.MinerActorAddr, client, fcid.Root, fastRetrieval) - t.RecordMessage("started deal: %s", deal) - - // TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this - time.Sleep(2 * time.Second) - - t.RecordMessage("waiting for deal to be sealed") - testkit.WaitDealSealed(t, ctx, client, deal) - t.D().ResettingHistogram("deal.sealed").Update(int64(time.Since(t1))) - - // wait for all client deals to be sealed before trying to retrieve - t.SyncClient.MustSignalAndWait(ctx, sync.State("done-sealing"), t.IntParam("clients")) - - carExport := true - - t.RecordMessage("trying to retrieve %s", fcid) - t1 = time.Now() - _ = testkit.RetrieveData(t, ctx, client, fcid.Root, nil, carExport, data) - t.D().ResettingHistogram("deal.retrieved").Update(int64(time.Since(t1))) - - t.SyncClient.MustSignalEntry(ctx, testkit.StateStopMining) - - time.Sleep(10 * time.Second) // wait for metrics to be emitted - - // TODO broadcast published content CIDs to other clients - // TODO select a random piece of content published by some other client and retrieve it - - t.SyncClient.MustSignalAndWait(ctx, testkit.StateDone, t.TestInstanceCount) - return nil -} - -func bounceConnInTransfers(ctx context.Context, t *testkit.TestEnvironment, client api.FullNode, minerPeerID peer.ID) error { - storageConnBroken := false - retrievalConnBroken := false - upds, err := client.ClientDataTransferUpdates(ctx) - if err != nil { - return err - } - - go func() { - for upd := range upds { - dir := "push" - if !upd.IsSender { - dir = "pull" - } - - t.RecordMessage("%s data transfer status: %s, transferred: %d", dir, datatransfer.Statuses[upd.Status], upd.Transferred) - - // Bounce the connection after the first block is sent for the storage deal - if upd.IsSender && upd.Transferred > 0 && !storageConnBroken { - storageConnBroken = true - bounceConnection(ctx, t, client, minerPeerID) - } - - // Bounce the connection after the first block is received for the retrieval deal - if !upd.IsSender && upd.Transferred > 0 && !retrievalConnBroken { - retrievalConnBroken = true - bounceConnection(ctx, t, client, minerPeerID) - } - } - }() - - return nil -} - -func bounceConnection(ctx context.Context, t *testkit.TestEnvironment, client api.FullNode, minerPeerID peer.ID) { - t.RecordMessage("disconnecting peer %s", minerPeerID) - client.NetBlockAdd(ctx, api.NetBlockList{ - Peers: []peer.ID{minerPeerID}, - }) - - go func() { - time.Sleep(3 * time.Second) - t.RecordMessage("reconnecting to peer %s", minerPeerID) - client.NetBlockRemove(ctx, api.NetBlockList{ - Peers: []peer.ID{minerPeerID}, - }) - }() -} - -// filToAttoFil converts a fractional filecoin value into AttoFIL, rounding if necessary -func filToAttoFil(f float64) big.Int { - a := mbig.NewFloat(f) - a.Mul(a, mbig.NewFloat(float64(build.FilecoinPrecision))) - i, _ := a.Int(nil) - return big.Int{Int: i} -} - -func initPaymentChannel(t *testkit.TestEnvironment, ctx context.Context, cl *testkit.LotusClient, minerAddr testkit.MinerAddressesMsg) error { - recv := minerAddr - balance := filToAttoFil(10) - t.RecordMessage("my balance: %d", balance) - t.RecordMessage("creating payment channel; from=%s, to=%s, funds=%d", cl.Wallet.Address, recv.WalletAddr, balance) - - channel, err := cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, balance, api.PaychGetOpts{ - OffChain: false, - }) - if err != nil { - return fmt.Errorf("failed to create payment channel: %w", err) - } - - if addr := channel.Channel; addr != address.Undef { - return fmt.Errorf("expected an Undef channel address, got: %s", addr) - } - - t.RecordMessage("payment channel created; msg_cid=%s", channel.WaitSentinel) - t.RecordMessage("waiting for payment channel message to appear on chain") - - // wait for the channel creation message to appear on chain. - _, err = cl.FullApi.StateWaitMsg(ctx, channel.WaitSentinel, 2, api.LookbackNoLimit, true) - if err != nil { - return fmt.Errorf("failed while waiting for payment channel creation msg to appear on chain: %w", err) - } - - // need to wait so that the channel is tracked. - // the full API waits for build.MessageConfidence (=1 in tests) before tracking the channel. - // we wait for 2 confirmations, so we have the assurance the channel is tracked. - - t.RecordMessage("reloading paych; now it should have an address") - channel, err = cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, big.Zero(), api.PaychGetOpts{ - OffChain: false, - }) - if err != nil { - return fmt.Errorf("failed to reload payment channel: %w", err) - } - - t.RecordMessage("channel address: %s", channel.Channel) - - return nil -} diff --git a/testplans/lotus-soup/deals_stress.go b/testplans/lotus-soup/deals_stress.go deleted file mode 100644 index 39eea8d0d..000000000 --- a/testplans/lotus-soup/deals_stress.go +++ /dev/null @@ -1,147 +0,0 @@ -package main - -import ( - "context" - "fmt" - "io/ioutil" - "math/rand" - "os" - "sync" - "time" - - "github.com/ipfs/go-cid" - - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/testplans/lotus-soup/testkit" -) - -func dealsStress(t *testkit.TestEnvironment) error { - // Dispatch/forward non-client roles to defaults. - if t.Role != "client" { - return testkit.HandleDefaultRole(t) - } - - t.RecordMessage("running client") - - cl, err := testkit.PrepareClient(t) - if err != nil { - return err - } - - ctx := context.Background() - client := cl.FullApi - - // select a random miner - minerAddr := cl.MinerAddrs[rand.Intn(len(cl.MinerAddrs))] - if err := client.NetConnect(ctx, minerAddr.MinerNetAddrs); err != nil { - return err - } - - t.RecordMessage("selected %s as the miner", minerAddr.MinerActorAddr) - - time.Sleep(12 * time.Second) - - // prepare a number of concurrent data points - deals := t.IntParam("deals") - data := make([][]byte, 0, deals) - files := make([]*os.File, 0, deals) - cids := make([]cid.Cid, 0, deals) - rng := rand.NewSource(time.Now().UnixNano()) - - for i := 0; i < deals; i++ { - dealData := make([]byte, 1600) - rand.New(rng).Read(dealData) - - dealFile, err := ioutil.TempFile("/tmp", "data") - if err != nil { - return err - } - defer os.Remove(dealFile.Name()) - - _, err = dealFile.Write(dealData) - if err != nil { - return err - } - - dealCid, err := client.ClientImport(ctx, api.FileRef{Path: dealFile.Name(), IsCAR: false}) - if err != nil { - return err - } - - t.RecordMessage("deal %d file cid: %s", i, dealCid) - - data = append(data, dealData) - files = append(files, dealFile) - cids = append(cids, dealCid.Root) - } - - concurrentDeals := true - if t.StringParam("deal_mode") == "serial" { - concurrentDeals = false - } - - // this to avoid failure to get block - time.Sleep(2 * time.Second) - - t.RecordMessage("starting storage deals") - if concurrentDeals { - - var wg1 sync.WaitGroup - for i := 0; i < deals; i++ { - wg1.Add(1) - go func(i int) { - defer wg1.Done() - t1 := time.Now() - deal := testkit.StartDeal(ctx, minerAddr.MinerActorAddr, client, cids[i], false) - t.RecordMessage("started storage deal %d -> %s", i, deal) - time.Sleep(2 * time.Second) - t.RecordMessage("waiting for deal %d to be sealed", i) - testkit.WaitDealSealed(t, ctx, client, deal) - t.D().ResettingHistogram(fmt.Sprintf("deal.sealed,miner=%s", minerAddr.MinerActorAddr)).Update(int64(time.Since(t1))) - }(i) - } - t.RecordMessage("waiting for all deals to be sealed") - wg1.Wait() - t.RecordMessage("all deals sealed; starting retrieval") - - var wg2 sync.WaitGroup - for i := 0; i < deals; i++ { - wg2.Add(1) - go func(i int) { - defer wg2.Done() - t.RecordMessage("retrieving data for deal %d", i) - t1 := time.Now() - _ = testkit.RetrieveData(t, ctx, client, cids[i], nil, true, data[i]) - - t.RecordMessage("retrieved data for deal %d", i) - t.D().ResettingHistogram("deal.retrieved").Update(int64(time.Since(t1))) - }(i) - } - t.RecordMessage("waiting for all retrieval deals to complete") - wg2.Wait() - t.RecordMessage("all retrieval deals successful") - - } else { - - for i := 0; i < deals; i++ { - deal := testkit.StartDeal(ctx, minerAddr.MinerActorAddr, client, cids[i], false) - t.RecordMessage("started storage deal %d -> %s", i, deal) - time.Sleep(2 * time.Second) - t.RecordMessage("waiting for deal %d to be sealed", i) - testkit.WaitDealSealed(t, ctx, client, deal) - } - - for i := 0; i < deals; i++ { - t.RecordMessage("retrieving data for deal %d", i) - _ = testkit.RetrieveData(t, ctx, client, cids[i], nil, true, data[i]) - t.RecordMessage("retrieved data for deal %d", i) - } - } - - t.SyncClient.MustSignalEntry(ctx, testkit.StateStopMining) - t.SyncClient.MustSignalAndWait(ctx, testkit.StateDone, t.TestInstanceCount) - - time.Sleep(15 * time.Second) // wait for metrics to be emitted - - return nil -} diff --git a/testplans/lotus-soup/env-ci.toml b/testplans/lotus-soup/env-ci.toml deleted file mode 100644 index bd651c465..000000000 --- a/testplans/lotus-soup/env-ci.toml +++ /dev/null @@ -1 +0,0 @@ -[client] diff --git a/testplans/lotus-soup/go.mod b/testplans/lotus-soup/go.mod deleted file mode 100644 index 657ff2a4c..000000000 --- a/testplans/lotus-soup/go.mod +++ /dev/null @@ -1,337 +0,0 @@ -module github.com/filecoin-project/lotus/testplans/lotus-soup - -go 1.18 - -require ( - contrib.go.opencensus.io/exporter/prometheus v0.4.0 - github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe - github.com/davecgh/go-spew v1.1.1 - github.com/drand/drand v1.3.0 - github.com/filecoin-project/go-address v1.0.0 - github.com/filecoin-project/go-data-transfer v1.15.2 - github.com/filecoin-project/go-fil-markets v1.24.1-0.20220926170416-a19d1b3b2cb2 - github.com/filecoin-project/go-jsonrpc v0.1.8 - github.com/filecoin-project/go-state-types v0.1.12-beta.0.20220926152009-c481def1ce73 - github.com/filecoin-project/go-storedcounter v0.1.0 - github.com/filecoin-project/lotus v0.0.0-00010101000000-000000000000 - github.com/filecoin-project/specs-actors v0.9.15 - github.com/google/uuid v1.3.0 - github.com/gorilla/mux v1.8.0 - github.com/hashicorp/go-multierror v1.1.1 - github.com/ipfs/go-cid v0.2.0 - github.com/ipfs/go-datastore v0.5.1 - github.com/ipfs/go-ipfs-files v0.1.1 - github.com/ipfs/go-ipld-format v0.4.0 - github.com/ipfs/go-log/v2 v2.5.1 - github.com/ipfs/go-merkledag v0.6.0 - github.com/ipfs/go-unixfs v0.3.1 - github.com/ipld/go-car v0.4.0 - github.com/kpacha/opencensus-influxdb v0.0.0-20181102202715-663e2683a27c - github.com/libp2p/go-libp2p v0.22.0 - github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6 - github.com/multiformats/go-multiaddr v0.6.0 - github.com/testground/sdk-go v0.2.6 - go.opencensus.io v0.23.0 - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 -) - -require ( - github.com/BurntSushi/toml v1.1.0 // indirect - github.com/DataDog/zstd v1.4.1 // indirect - github.com/GeertJohan/go.incremental v1.0.0 // indirect - github.com/GeertJohan/go.rice v1.0.2 // indirect - github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee // indirect - github.com/Kubuxu/imtui v0.0.0-20210401140320-41663d68d0fa // indirect - github.com/StackExchange/wmi v1.2.1 // indirect - github.com/Stebalien/go-bitfield v0.0.1 // indirect - github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect - github.com/akavel/rsrc v0.8.0 // indirect - github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a // indirect - github.com/avast/retry-go v2.6.0+incompatible // indirect - github.com/benbjohnson/clock v1.3.0 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/bep/debounce v1.2.0 // indirect - github.com/buger/goterm v1.0.3 // indirect - github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/cheekybits/genny v1.0.0 // indirect - github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect - github.com/cilium/ebpf v0.4.0 // indirect - github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect - github.com/containerd/cgroups v1.0.4 // indirect - github.com/coreos/go-systemd/v22 v22.3.2 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect - github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect - github.com/cskr/pubsub v1.0.2 // indirect - github.com/daaku/go.zipexe v1.0.0 // indirect - github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect - github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e // indirect - github.com/dgraph-io/badger/v2 v2.2007.3 // indirect - github.com/dgraph-io/ristretto v0.1.0 // indirect - github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 // indirect - github.com/docker/go-units v0.4.0 // indirect - github.com/drand/kyber v1.1.7 // indirect - github.com/drand/kyber-bls12381 v0.2.1 // indirect - github.com/dustin/go-humanize v1.0.0 // indirect - github.com/elastic/go-sysinfo v1.7.0 // indirect - github.com/elastic/go-windows v1.0.0 // indirect - github.com/elastic/gosigar v0.14.2 // indirect - github.com/fatih/color v1.13.0 // indirect - github.com/filecoin-project/dagstore v0.5.2 // indirect - github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f // indirect - github.com/filecoin-project/go-amt-ipld/v2 v2.1.0 // indirect - github.com/filecoin-project/go-amt-ipld/v3 v3.1.0 // indirect - github.com/filecoin-project/go-amt-ipld/v4 v4.0.0 // indirect - github.com/filecoin-project/go-bitfield v0.2.4 // indirect - github.com/filecoin-project/go-cbor-util v0.0.1 // indirect - github.com/filecoin-project/go-commp-utils v0.1.3 // indirect - github.com/filecoin-project/go-commp-utils/nonffi v0.0.0-20220905160352-62059082a837 // indirect - github.com/filecoin-project/go-crypto v0.0.1 // indirect - github.com/filecoin-project/go-ds-versioning v0.1.1 // indirect - github.com/filecoin-project/go-fil-commcid v0.1.0 // indirect - github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 // indirect - github.com/filecoin-project/go-hamt-ipld v0.1.5 // indirect - github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 // indirect - github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 // indirect - github.com/filecoin-project/go-legs v0.4.4 // indirect - github.com/filecoin-project/go-padreader v0.0.1 // indirect - github.com/filecoin-project/go-paramfetch v0.0.4 // indirect - github.com/filecoin-project/go-statemachine v1.0.2 // indirect - github.com/filecoin-project/go-statestore v0.2.0 // indirect - github.com/filecoin-project/index-provider v0.8.1 // indirect - github.com/filecoin-project/pubsub v1.0.0 // indirect - github.com/filecoin-project/specs-actors/v2 v2.3.6 // indirect - github.com/filecoin-project/specs-actors/v3 v3.1.2 // indirect - github.com/filecoin-project/specs-actors/v4 v4.0.2 // indirect - github.com/filecoin-project/specs-actors/v5 v5.0.6 // indirect - github.com/filecoin-project/specs-actors/v6 v6.0.2 // indirect - github.com/filecoin-project/specs-actors/v7 v7.0.1 // indirect - github.com/filecoin-project/specs-actors/v8 v8.0.1 // indirect - github.com/filecoin-project/storetheindex v0.4.17 // indirect - github.com/flynn/noise v1.0.0 // indirect - github.com/francoispqt/gojay v1.2.13 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect - github.com/gbrlsnchs/jwt/v3 v3.0.1 // indirect - github.com/gdamore/encoding v1.0.0 // indirect - github.com/gdamore/tcell/v2 v2.2.0 // indirect - github.com/go-kit/kit v0.12.0 // indirect - github.com/go-kit/log v0.2.0 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.2.3 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.5 // indirect - github.com/go-redis/redis/v7 v7.4.0 // indirect - github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/gogo/googleapis v1.4.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/gogo/status v1.1.0 // indirect - github.com/golang/glog v1.0.0 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/mock v1.6.0 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/google/gopacket v1.1.19 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 // indirect - github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect - github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 // indirect - github.com/hannahhoward/cbor-gen-for v0.0.0-20200817222906-ea96cece81f1 // indirect - github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/huin/goupnp v1.0.3 // indirect - github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94 // indirect - github.com/influxdata/influxdb v1.9.4 // indirect - github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab // indirect - github.com/ipfs/bbloom v0.0.4 // indirect - github.com/ipfs/go-bitfield v1.0.0 // indirect - github.com/ipfs/go-bitswap v0.10.2 // indirect - github.com/ipfs/go-block-format v0.0.3 // indirect - github.com/ipfs/go-blockservice v0.4.0 // indirect - github.com/ipfs/go-cidutil v0.1.0 // indirect - github.com/ipfs/go-ds-badger2 v0.1.2 // indirect - github.com/ipfs/go-ds-leveldb v0.5.0 // indirect - github.com/ipfs/go-ds-measure v0.2.0 // indirect - github.com/ipfs/go-filestore v1.2.0 // indirect - github.com/ipfs/go-fs-lock v0.0.7 // indirect - github.com/ipfs/go-graphsync v0.13.1 // indirect - github.com/ipfs/go-ipfs-blockstore v1.2.0 // indirect - github.com/ipfs/go-ipfs-chunker v0.0.5 // indirect - github.com/ipfs/go-ipfs-cmds v0.7.0 // indirect - github.com/ipfs/go-ipfs-delay v0.0.1 // indirect - github.com/ipfs/go-ipfs-ds-help v1.1.0 // indirect - github.com/ipfs/go-ipfs-exchange-interface v0.2.0 // indirect - github.com/ipfs/go-ipfs-exchange-offline v0.3.0 // indirect - github.com/ipfs/go-ipfs-http-client v0.4.0 // indirect - github.com/ipfs/go-ipfs-posinfo v0.0.1 // indirect - github.com/ipfs/go-ipfs-pq v0.0.2 // indirect - github.com/ipfs/go-ipfs-routing v0.2.1 // indirect - github.com/ipfs/go-ipfs-util v0.0.2 // indirect - github.com/ipfs/go-ipld-cbor v0.0.6 // indirect - github.com/ipfs/go-ipld-legacy v0.1.1 // indirect - github.com/ipfs/go-ipns v0.2.0 // indirect - github.com/ipfs/go-log v1.0.5 // indirect - github.com/ipfs/go-metrics-interface v0.0.1 // indirect - github.com/ipfs/go-path v0.3.0 // indirect - github.com/ipfs/go-peertaskqueue v0.7.1 // indirect - github.com/ipfs/go-unixfsnode v1.4.0 // indirect - github.com/ipfs/go-verifcid v0.0.1 // indirect - github.com/ipfs/interface-go-ipfs-core v0.7.0 // indirect - github.com/ipld/go-car/v2 v2.4.1 // indirect - github.com/ipld/go-codec-dagpb v1.3.2 // indirect - github.com/ipld/go-ipld-prime v0.17.0 // indirect - github.com/ipld/go-ipld-selector-text-lite v0.0.1 // indirect - github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 // indirect - github.com/jackpal/go-nat-pmp v1.0.2 // indirect - github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/jbenet/goprocess v0.1.4 // indirect - github.com/jessevdk/go-flags v1.4.0 // indirect - github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 // indirect - github.com/jonboulle/clockwork v0.2.2 // indirect - github.com/jpillora/backoff v1.0.0 // indirect - github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/kilic/bls12-381 v0.0.0-20200820230200-6b2c19996391 // indirect - github.com/klauspost/compress v1.15.1 // indirect - github.com/klauspost/cpuid/v2 v2.1.0 // indirect - github.com/koron/go-ssdp v0.0.3 // indirect - github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/libp2p/go-cidranger v1.1.0 // indirect - github.com/libp2p/go-flow-metrics v0.1.0 // indirect - github.com/libp2p/go-libp2p-asn-util v0.2.0 // indirect - github.com/libp2p/go-libp2p-connmgr v0.4.0 // indirect - github.com/libp2p/go-libp2p-core v0.20.0 // indirect - github.com/libp2p/go-libp2p-gostream v0.4.0 // indirect - github.com/libp2p/go-libp2p-kad-dht v0.18.0 // indirect - github.com/libp2p/go-libp2p-kbucket v0.5.0 // indirect - github.com/libp2p/go-libp2p-noise v0.5.0 // indirect - github.com/libp2p/go-libp2p-peerstore v0.8.0 // indirect - github.com/libp2p/go-libp2p-pubsub v0.8.0 // indirect - github.com/libp2p/go-libp2p-record v0.2.0 // indirect - github.com/libp2p/go-libp2p-routing-helpers v0.2.3 // indirect - github.com/libp2p/go-libp2p-tls v0.5.0 // indirect - github.com/libp2p/go-maddr-filter v0.1.0 // indirect - github.com/libp2p/go-msgio v0.2.0 // indirect - github.com/libp2p/go-nat v0.1.0 // indirect - github.com/libp2p/go-netroute v0.2.0 // indirect - github.com/libp2p/go-openssl v0.1.0 // indirect - github.com/libp2p/go-reuseport v0.2.0 // indirect - github.com/libp2p/go-yamux/v3 v3.1.2 // indirect - github.com/lucas-clemente/quic-go v0.28.1 // indirect - github.com/lucasb-eyer/go-colorful v1.0.3 // indirect - github.com/magefile/mage v1.9.0 // indirect - github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect - github.com/marten-seemann/qtls-go1-17 v0.1.2 // indirect - github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect - github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect - github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect - github.com/mattn/go-colorable v0.1.9 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-pointer v0.0.1 // indirect - github.com/mattn/go-runewidth v0.0.10 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/miekg/dns v1.1.50 // indirect - github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect - github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect - github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect - github.com/minio/sha256-simd v1.0.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mr-tron/base58 v1.2.0 // indirect - github.com/multiformats/go-base32 v0.0.4 // indirect - github.com/multiformats/go-base36 v0.1.0 // indirect - github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect - github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect - github.com/multiformats/go-multibase v0.1.1 // indirect - github.com/multiformats/go-multicodec v0.5.0 // indirect - github.com/multiformats/go-multihash v0.2.1 // indirect - github.com/multiformats/go-multistream v0.3.3 // indirect - github.com/multiformats/go-varint v0.0.6 // indirect - github.com/nikkolasg/hexjson v0.0.0-20181101101858-78e39397e00c // indirect - github.com/nkovacs/streamquote v1.0.0 // indirect - github.com/nxadm/tail v1.4.8 // indirect - github.com/onsi/ginkgo v1.16.5 // indirect - github.com/opencontainers/runtime-spec v1.0.2 // indirect - github.com/opentracing-contrib/go-grpc v0.0.0-20191001143057-db30781987df // indirect - github.com/opentracing-contrib/go-stdlib v1.0.0 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect - github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e // indirect - github.com/prometheus/client_golang v1.12.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect - github.com/prometheus/statsd_exporter v0.21.0 // indirect - github.com/raulk/clock v1.1.0 // indirect - github.com/raulk/go-watchdog v1.3.0 // indirect - github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect - github.com/rivo/uniseg v0.1.0 // indirect - github.com/rs/cors v1.7.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sercand/kuberesolver v2.4.0+incompatible // indirect - github.com/shirou/gopsutil v2.18.12+incompatible // indirect - github.com/sirupsen/logrus v1.8.1 // indirect - github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect - github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/stretchr/testify v1.8.0 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect - github.com/uber/jaeger-client-go v2.28.0+incompatible // indirect - github.com/uber/jaeger-lib v2.4.1+incompatible // indirect - github.com/urfave/cli/v2 v2.8.1 // indirect - github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasttemplate v1.2.1 // indirect - github.com/weaveworks/common v0.0.0-20200512154658-384f10054ec5 // indirect - github.com/weaveworks/promrus v1.2.0 // indirect - github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba // indirect - github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 // indirect - github.com/whyrusleeping/cbor-gen v0.0.0-20220514204315-f29c37e9c44c // indirect - github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect - github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect - github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 // indirect - github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect - github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - github.com/zondax/hid v0.9.0 // indirect - github.com/zondax/ledger-go v0.12.1 // indirect - go.dedis.ch/fixbuf v1.0.3 // indirect - go.dedis.ch/protobuf v1.0.11 // indirect - go.etcd.io/bbolt v1.3.4 // indirect - go.opentelemetry.io/otel v1.7.0 // indirect - go.opentelemetry.io/otel/trace v1.7.0 // indirect - go.uber.org/atomic v1.10.0 // indirect - go.uber.org/dig v1.12.0 // indirect - go.uber.org/fx v1.15.0 // indirect - go.uber.org/multierr v1.8.0 // indirect - go.uber.org/zap v1.22.0 // indirect - go4.org v0.0.0-20200411211856-f5505b9728dd // indirect - golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect - golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect - golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect - golang.org/x/tools v0.1.12 // indirect - golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect - google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 // indirect - google.golang.org/grpc v1.45.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect - gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect - gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect - lukechampine.com/blake3 v1.1.7 // indirect -) - -// This will work in all build modes: docker:go, exec:go, and local go build. -// On docker:go and exec:go, it maps to /extra/filecoin-ffi, as it's picked up -// as an "extra source" in the manifest. -replace github.com/filecoin-project/filecoin-ffi => ../../extern/filecoin-ffi - -replace github.com/filecoin-project/lotus => ../.. diff --git a/testplans/lotus-soup/go.sum b/testplans/lotus-soup/go.sum deleted file mode 100644 index 328384afa..000000000 --- a/testplans/lotus-soup/go.sum +++ /dev/null @@ -1,2762 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= -cloud.google.com/go/bigtable v1.3.0/go.mod h1:z5EyKrPE8OQmeg4h5MNdKvuSnI9CCT49Ki3f23aBzio= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= -contrib.go.opencensus.io/exporter/prometheus v0.4.0 h1:0QfIkj9z/iVZgK31D9H9ohjjIDApI2GOPScCKwxedbs= -contrib.go.opencensus.io/exporter/prometheus v0.4.0/go.mod h1:o7cosnyfuPVK0tB8q0QmaQNhGnptITnPQB+z1+qeFB0= -dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= -dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= -dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= -github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= -github.com/Azure/azure-sdk-for-go v41.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-storage-blob-go v0.13.0/go.mod h1:pA9kNqtjUeQF2zOSu4s//nUdBD+e64lEuc4sVnuOfNs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest v0.10.0/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= -github.com/Azure/go-autorest/autorest v0.11.9/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= -github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= -github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= -github.com/Azure/go-autorest/autorest/adal v0.9.2/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.3/go.mod h1:4bJZhUhcq8LB20TruwHbAQsmUs2Xh+QR7utuJpLXX3A= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM= -github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= -github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= -github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= -github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM= -github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg= -github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= -github.com/GeertJohan/go.rice v1.0.2 h1:PtRw+Tg3oa3HYwiDBZyvOJ8LdIyf6lAovJJtr7YOAYk= -github.com/GeertJohan/go.rice v1.0.2/go.mod h1:af5vUNlDNkCjOZeSGFgIJxDje9qdjsO6hshx0gTmZt4= -github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee h1:8doiS7ib3zi6/K172oDhSKU0dJ/miJramo9NITOMyZQ= -github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee/go.mod h1:W0GbEAA4uFNYOGG2cJpmFJ04E6SD1NLELPYZB57/7AY= -github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= -github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= -github.com/Kubuxu/imtui v0.0.0-20210401140320-41663d68d0fa h1:1PPxEyGdIGVkX/kqMvLJ95a1dGS1Sz7tpNEgehEYYt0= -github.com/Kubuxu/imtui v0.0.0-20210401140320-41663d68d0fa/go.mod h1:WUmMvh9wMtqj1Xhf1hf3kp9RvL+y6odtdYxpyZjb90U= -github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/sprig v2.16.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/SAP/go-hdb v0.14.1/go.mod h1:7fdQLVC2lER3urZLjZCm0AuMQfApof92n3aylBPEkMo= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/Stebalien/go-bitfield v0.0.1 h1:X3kbSSPUaJK60wV2hjOPZwmpljr6VGCqdq4cBLhbQBo= -github.com/Stebalien/go-bitfield v0.0.1/go.mod h1:GNjFpasyUVkHMsfEOk8EFLJ9syQ6SI+XWrX9Wf2XH0s= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= -github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= -github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a h1:E/8AP5dFtMhl5KPJz66Kt9G0n+7Sn41Fy1wv9/jHOrc= -github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= -github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= -github.com/apache/arrow/go/arrow v0.0.0-20200601151325-b2287a20f230/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0= -github.com/apache/arrow/go/arrow v0.0.0-20200923215132-ac86123a3f01/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= -github.com/avast/retry-go v2.6.0+incompatible h1:FelcMrm7Bxacr1/RM8+/eqkDkmVN7tjlsy51dOzB3LI= -github.com/avast/retry-go v2.6.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.29.16/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= -github.com/aws/aws-sdk-go v1.30.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.32.11/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/aws/aws-sdk-go-v2 v1.3.2/go.mod h1:7OaACgj2SX3XGWnrIjGlJM22h6yD6MEWKvm7levnnM8= -github.com/aws/aws-sdk-go-v2/config v1.1.5/go.mod h1:P3F1hku7qzC81txjwXnwOM6Ex6ezkU6+/557Teyb64E= -github.com/aws/aws-sdk-go-v2/credentials v1.1.5/go.mod h1:Ir1R6tPiR1/2y1hes8yOijFMz54hzSmgcmCDo6F45Qc= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.6/go.mod h1:0+fWMitrmIpENiY8/1DyhdYPUCAPvd9UNz9mtCsEoLQ= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.1.2/go.mod h1:Azf567f5wBUfUbwpyJJnLM/geFFIzEulGR30L+nQZOE= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.4/go.mod h1:BCfU3Uo2fhKcMZFp9zU5QQGQxqWCOYmZ/27Dju3S/do= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.6/go.mod h1:L0KWr0ASo83PRZu9NaZaDsw3koS6PspKv137DMDZjHo= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.2.2/go.mod h1:nnutjMLuna0s3GVY/MAkpLX03thyNER06gXvnMAPj5g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.5.0/go.mod h1:uwA7gs93Qcss43astPUb1eq4RyceNmYWAQjZFDOAMLo= -github.com/aws/aws-sdk-go-v2/service/sso v1.1.5/go.mod h1:bpGz0tidC4y39sZkQSkpO/J0tzWCMXHbw6FZ0j1GkWM= -github.com/aws/aws-sdk-go-v2/service/sts v1.2.2/go.mod h1:ssRzzJ2RZOVuKj2Vx1YE7ypfil/BIlgmQnCSW4DistU= -github.com/aws/smithy-go v1.3.1/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= -github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= -github.com/benbjohnson/clock v1.0.2/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/immutable v0.2.1/go.mod h1:uc6OHo6PN2++n98KHLxW8ef4W42ylHiQSENghE1ezxI= -github.com/benbjohnson/tmpl v1.0.0/go.mod h1:igT620JFIi44B6awvU9IsDhR77IXWtFigTLil/RPdps= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bep/debounce v1.2.0 h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo= -github.com/bep/debounce v1.2.0/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/bonitoo-io/go-sql-bigquery v0.3.4-1.4.0/go.mod h1:J4Y6YJm0qTWB9aFziB7cPeSyc6dOZFyJdteSeybVpXQ= -github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/briandowns/spinner v1.11.1/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= -github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= -github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= -github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= -github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= -github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= -github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/buger/goterm v1.0.3 h1:7V/HeAQHrzPk/U4BvyH2g9u+xbUW9nr4yRPyG59W4fM= -github.com/buger/goterm v1.0.3/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE= -github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= -github.com/cactus/go-statsd-client/statsd v0.0.0-20191106001114-12b4e2b38748/go.mod h1:l/bIBLeOl9eX+wxJAzxS4TveKRtAqlyDpHjhkfO0MEI= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v0.0.0-20181003080854-62661b46c409/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= -github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= -github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/cilium/ebpf v0.4.0 h1:QlHdikaxALkqWasW8hAC1mfR0jdmvbfaBdBPFmRSglA= -github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q= -github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= -github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe h1:69JI97HlzP+PH5Mi1thcGlDoBr6PS2Oe+l3mNmAkbs4= -github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE= -github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= -github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= -github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= -github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis= -github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= -github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY= -github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= -github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= -github.com/davidlazar/go-crypto v0.0.0-20190912175916-7055855a373f/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= -github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e h1:lj77EKYUpYXTd8CD/+QMIf8b6OIOTsfEBSXiAzuEHTU= -github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e/go.mod h1:3ZQK6DMPSz/QZ73jlWxBtUhNA8xZx7LzUFSq/OfP8vk= -github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= -github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= -github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= -github.com/dgraph-io/badger v1.6.1/go.mod h1:FRmFw3uxvcpa8zG3Rxs0th+hCLIuaQg8HlNV5bjgnuU= -github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= -github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= -github.com/dgraph-io/badger/v2 v2.2007.3 h1:Sl9tQWz92WCbVSe8pj04Tkqlm2boW+KAxd+XSs58SQI= -github.com/dgraph-io/badger/v2 v2.2007.3/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= -github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= -github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= -github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI= -github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= -github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= -github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/drand/bls12-381 v0.3.2/go.mod h1:dtcLgPtYT38L3NO6mPDYH0nbpc5tjPassDqiniuAt4Y= -github.com/drand/drand v1.3.0 h1:k/w/PtHzmlU6OmfoAqgirWyrJ4FZH8ESlJrsKF20UkM= -github.com/drand/drand v1.3.0/go.mod h1:D6kAVlxufq1gi71YCGfzN455JrXF4Q272ZJEG975fzo= -github.com/drand/kyber v1.0.1-0.20200110225416-8de27ed8c0e2/go.mod h1:UpXoA0Upd1N9l4TvRPHr1qAUBBERj6JQ/mnKI3BPEmw= -github.com/drand/kyber v1.0.2/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw= -github.com/drand/kyber v1.1.4/go.mod h1:9+IgTq7kadePhZg7eRwSD7+bA+bmvqRK+8DtmoV5a3U= -github.com/drand/kyber v1.1.7 h1:YnOshFoGYSOdhf4K8BiDw4XL/l6caL92vsodAsVQbJI= -github.com/drand/kyber v1.1.7/go.mod h1:UkHLsI4W6+jT5PvNxmc0cvQAgppjTUpX+XCsN9TXmRo= -github.com/drand/kyber-bls12381 v0.2.0/go.mod h1:zQip/bHdeEB6HFZSU3v+d3cQE0GaBVQw9aR2E7AdoeI= -github.com/drand/kyber-bls12381 v0.2.1 h1:/d5/YAdaCmHpYjF1NZevOEcKGaq6LBbyvkCTIdGqDjs= -github.com/drand/kyber-bls12381 v0.2.1/go.mod h1:JwWn4nHO9Mp4F5qCie5sVIPQZ0X6cw8XAeMRvc/GXBE= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/elastic/go-sysinfo v1.7.0 h1:4vVvcfi255+8+TyQ7TYUTEK3A+G8v5FLE+ZKYL1z1Dg= -github.com/elastic/go-sysinfo v1.7.0/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6eh0ikPT9F0= -github.com/elastic/go-windows v1.0.0 h1:qLURgZFkkrYyTTkvYpsZIgf83AUsdIHfvlJaqaZ7aSY= -github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6CcloAxnPgU= -github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= -github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/ema/qdisc v0.0.0-20190904071900-b82c76788043/go.mod h1:ix4kG2zvdUd8kEKSW0ZTr1XLks0epFpI4j745DXxlNE= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.8.0/go.mod h1:3l45GVGkyrnYNl9HoIjnp2NnNWvh6hLAqD8yTfGjnw8= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/filecoin-project/dagstore v0.5.2 h1:Nd6oXdnolbbVhpMpkYT5PJHOjQp4OBSntHpMV5pxj3c= -github.com/filecoin-project/dagstore v0.5.2/go.mod h1:mdqKzYrRBHf1pRMthYfMv3n37oOw0Tkx7+TxPt240M0= -github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= -github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= -github.com/filecoin-project/go-address v0.0.6/go.mod h1:7B0/5DA13n6nHkB8bbGx1gWzG/dbTsZ0fgOJVGsM3TE= -github.com/filecoin-project/go-address v1.0.0 h1:IrexI0kpADLaPP+CdmU3CVAUqnW/FQC0KTmz4lVKiFU= -github.com/filecoin-project/go-address v1.0.0/go.mod h1:5t3z6qPmIADZBtuE9EIzi0EwzcRy2nVhpo0I/c1r0OA= -github.com/filecoin-project/go-amt-ipld/v2 v2.1.0 h1:t6qDiuGYYngDqaLc2ZUvdtAg4UNxPeOYaXhBWSNsVaM= -github.com/filecoin-project/go-amt-ipld/v2 v2.1.0/go.mod h1:nfFPoGyX0CU9SkXX8EoCcSuHN1XcbN0c6KBh7yvP5fs= -github.com/filecoin-project/go-amt-ipld/v3 v3.0.0/go.mod h1:Qa95YNAbtoVCTSVtX38aAC1ptBnJfPma1R/zZsKmx4o= -github.com/filecoin-project/go-amt-ipld/v3 v3.1.0 h1:ZNJ9tEG5bE72vBWYiuh5bkxJVM3ViHNOmQ7qew9n6RE= -github.com/filecoin-project/go-amt-ipld/v3 v3.1.0/go.mod h1:UjM2QhDFrrjD5s1CdnkJkat4ga+LqZBZgTMniypABRo= -github.com/filecoin-project/go-amt-ipld/v4 v4.0.0 h1:XM81BJ4/6h3FV0WfFjh74cIDIgqMbJsMBLM0fIuLUUk= -github.com/filecoin-project/go-amt-ipld/v4 v4.0.0/go.mod h1:gF053YQ4BIpzTNDoEwHZas7U3oAwncDVGvOHyY8oDpE= -github.com/filecoin-project/go-bitfield v0.2.0/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM= -github.com/filecoin-project/go-bitfield v0.2.3/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM= -github.com/filecoin-project/go-bitfield v0.2.4 h1:uZ7MeE+XfM5lqrHJZ93OnhQKc/rveW8p9au0C68JPgk= -github.com/filecoin-project/go-bitfield v0.2.4/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM= -github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg= -github.com/filecoin-project/go-cbor-util v0.0.1 h1:E1LYZYTtjfAQwCReho0VXvbu8t3CYAVPiMx8EiV/VAs= -github.com/filecoin-project/go-cbor-util v0.0.1/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg= -github.com/filecoin-project/go-commp-utils v0.1.3 h1:rTxbkNXZU7FLgdkBk8RsQIEOuPONHykEoX3xGk41Fkw= -github.com/filecoin-project/go-commp-utils v0.1.3/go.mod h1:3ENlD1pZySaUout0p9ANQrY3fDFoXdqyX04J+dWpK30= -github.com/filecoin-project/go-commp-utils/nonffi v0.0.0-20220905160352-62059082a837 h1:4cITW0pwgvqLs86Q9bWQa34+jBfR1V687bDkmv2DgnA= -github.com/filecoin-project/go-commp-utils/nonffi v0.0.0-20220905160352-62059082a837/go.mod h1:e2YBjSblNVoBckkbv3PPqsq71q98oFkFqL7s1etViGo= -github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= -github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2JJGLl6gCq6o= -github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= -github.com/filecoin-project/go-data-transfer v1.15.2 h1:PzqsFr2Q/onMGKrGh7TtRT0dKsJcVJrioJJnjnKmxlk= -github.com/filecoin-project/go-data-transfer v1.15.2/go.mod h1:qXOJ3IF5dEJQHykXXTwcaRxu17bXAxr+LglXzkL6bZQ= -github.com/filecoin-project/go-ds-versioning v0.1.1 h1:JiyBqaQlwC+UM0WhcBtVEeT3XrX59mQhT8U3p7nu86o= -github.com/filecoin-project/go-ds-versioning v0.1.1/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= -github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= -github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88OqLYEo6roi+GiIeOh8= -github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= -github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= -github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.24.1-0.20220926170416-a19d1b3b2cb2 h1:KykqGi/2M6dxPTbXBaGBwtbIUzBfq6vQis/2OrRWnoI= -github.com/filecoin-project/go-fil-markets v1.24.1-0.20220926170416-a19d1b3b2cb2/go.mod h1:1HOXAYcGyWZdFD0ko1pPfPNXwYV8VVuhLUlKYV0OVhI= -github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= -github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= -github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= -github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0/go.mod h1:7aWZdaQ1b16BVoQUYR+eEvrDCGJoPLxFpDynFjYfBjI= -github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGyDjJjYSRX7hp/FGOStdqrWyDI= -github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= -github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= -github.com/filecoin-project/go-jsonrpc v0.1.8 h1:uXX/ikAk3Q4f/k8DRd9Zw+fWnfiYb5I+UI1tzlQgHog= -github.com/filecoin-project/go-jsonrpc v0.1.8/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= -github.com/filecoin-project/go-legs v0.4.4 h1:mpMmAOOnamaz0CV9rgeKhEWA8j9kMC+f+UGCGrxKaZo= -github.com/filecoin-project/go-legs v0.4.4/go.mod h1:JQ3hA6xpJdbR8euZ2rO0jkxaMxeidXf0LDnVuqPAe9s= -github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= -github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= -github.com/filecoin-project/go-padreader v0.0.1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= -github.com/filecoin-project/go-paramfetch v0.0.4 h1:H+Me8EL8T5+79z/KHYQQcT8NVOzYVqXIi7nhb48tdm8= -github.com/filecoin-project/go-paramfetch v0.0.4/go.mod h1:1FH85P8U+DUEmWk1Jkw3Bw7FrwTVUNHk/95PSPG+dts= -github.com/filecoin-project/go-state-types v0.0.0-20200903145444-247639ffa6ad/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= -github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= -github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= -github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= -github.com/filecoin-project/go-state-types v0.1.6/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= -github.com/filecoin-project/go-state-types v0.1.8/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= -github.com/filecoin-project/go-state-types v0.1.10/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= -github.com/filecoin-project/go-state-types v0.1.12-beta.0.20220926152009-c481def1ce73 h1:XciR+g0KrQu/gkRy5i5xFOWz85xNBbPrLfl0PRxdoz8= -github.com/filecoin-project/go-state-types v0.1.12-beta.0.20220926152009-c481def1ce73/go.mod h1:n/kujdC9JphvYTrmaD1+vJpvDPy/DwzckoMzP0nBKWI= -github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= -github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc= -github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= -github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= -github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNdofHZoGPjfNaAo5Q= -github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= -github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= -github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= -github.com/filecoin-project/index-provider v0.8.1 h1:ggoBWvMSWR91HZQCWfv8SZjoTGNyJBwNMLuN9bJZrbU= -github.com/filecoin-project/index-provider v0.8.1/go.mod h1:c/Ym5HtWPp9NQgNc9dgSBMpSNsZ/DE9FEi9qVubl5RM= -github.com/filecoin-project/pubsub v1.0.0 h1:ZTmT27U07e54qV1mMiQo4HDr0buo8I1LDHBYLXlsNXM= -github.com/filecoin-project/pubsub v1.0.0/go.mod h1:GkpB33CcUtUNrLPhJgfdy4FDx4OMNR9k+46DHx/Lqrg= -github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= -github.com/filecoin-project/specs-actors v0.9.15-0.20220514164640-94e0d5e123bd/go.mod h1:pjGEe3QlWtK20ju/aFRsiArbMX6Cn8rqEhhsiCM9xYE= -github.com/filecoin-project/specs-actors v0.9.15 h1:3VpKP5/KaDUHQKAMOg4s35g/syDaEBueKLws0vbsjMc= -github.com/filecoin-project/specs-actors v0.9.15/go.mod h1:pjGEe3QlWtK20ju/aFRsiArbMX6Cn8rqEhhsiCM9xYE= -github.com/filecoin-project/specs-actors/v2 v2.3.6 h1:UxnWTfQd7JsOae39/aHCK0m1IBjdcyymCJfqxuSkn+g= -github.com/filecoin-project/specs-actors/v2 v2.3.6/go.mod h1:DJMpxVRXvev9t8P0XWA26RmTzN+MHiL9IlItVLT0zUc= -github.com/filecoin-project/specs-actors/v3 v3.1.2 h1:Gq3gAbvdGLA/D0GKz1IJfewt9Fh7gA32TPt46Xv+1Cw= -github.com/filecoin-project/specs-actors/v3 v3.1.2/go.mod h1:uOJn+m6W8OW/1mdWMEvxeM1cjQPxmps7s1Z4bJ9V4kY= -github.com/filecoin-project/specs-actors/v4 v4.0.2 h1:VTsv30kIf1Keo8Jlu6Omco+2Ud0pG4EN5UAzyYCibh8= -github.com/filecoin-project/specs-actors/v4 v4.0.2/go.mod h1:zT0GVFxwFS93prGK0b/rMd1sePjRQKfAuodQ9DFAd6Y= -github.com/filecoin-project/specs-actors/v5 v5.0.6 h1:TLtA9hT3pHQF5vB83GmB+m6anw9u6MjdT+VVn/lyC+c= -github.com/filecoin-project/specs-actors/v5 v5.0.6/go.mod h1:myb/UGwESp0V1f1BACXSUrFgTWLvGUoG0ZZH7eqriFM= -github.com/filecoin-project/specs-actors/v6 v6.0.2 h1:K1xPRJoW5PBvb08QF9+4w1AjcnqwR6BjTmeltQFCvWo= -github.com/filecoin-project/specs-actors/v6 v6.0.2/go.mod h1:wnfVvPnYmzPZilNvSqCSSA/ZQX3rdV/U/Vf9EIoQhrI= -github.com/filecoin-project/specs-actors/v7 v7.0.1 h1:w72xCxijK7xs1qzmJiw+WYJaVt2EPHN8oiwpA1Ay3/4= -github.com/filecoin-project/specs-actors/v7 v7.0.1/go.mod h1:tPLEYXoXhcpyLh69Ccq91SOuLXsPWjHiY27CzawjUEk= -github.com/filecoin-project/specs-actors/v8 v8.0.1 h1:4u0tIRJeT5G7F05lwLRIsDnsrN+bJ5Ixj6h49Q7uE2Y= -github.com/filecoin-project/specs-actors/v8 v8.0.1/go.mod h1:UYIPg65iPWoFw5NEftREdJwv9b/5yaLKdCgTvNI/2FA= -github.com/filecoin-project/storetheindex v0.4.17 h1:w0dVc954TGPukoVbidlYvn9Xt+wVhk5vBvrqeJiRo8I= -github.com/filecoin-project/storetheindex v0.4.17/go.mod h1:y2dL8C5D3PXi183hdxgGtM8vVYOZ1lg515tpl/D3tN8= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= -github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/foxcpp/go-mockdns v0.0.0-20201212160233-ede2f9158d15/go.mod h1:tPg4cp4nseejPd+UKxtCVQ2hUxNTZ7qQZJa7CLriIeo= -github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= -github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= -github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/gbrlsnchs/jwt/v3 v3.0.1 h1:lbUmgAKpxnClrKloyIwpxm4OuWeDl5wLk52G91ODPw4= -github.com/gbrlsnchs/jwt/v3 v3.0.1/go.mod h1:AncDcjXz18xetI3A6STfXq2w+LuTx8pQ8bGEwRN8zVM= -github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= -github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= -github.com/gdamore/tcell/v2 v2.2.0 h1:vSyEgKwraXPSOkvCk7IwOSyX+Pv3V2cV9CikJMXg4U4= -github.com/gdamore/tcell/v2 v2.2.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU= -github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= -github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= -github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= -github.com/go-chi/chi v4.1.0+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= -github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= -github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0 h1:7i2K3eKTos3Vc0enKCfnVcgHh2olr/MyfboYq7cAcFw= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= -github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= -github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= -github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= -github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= -github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ= -github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= -github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= -github.com/go-openapi/errors v0.19.4/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= -github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= -github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI= -github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= -github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY= -github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= -github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= -github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= -github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo= -github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= -github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= -github.com/go-openapi/spec v0.19.7/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= -github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= -github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= -github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= -github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= -github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= -github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= -github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= -github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= -github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= -github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo= -github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= -github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4= -github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= -github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= -github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= -github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/googleapis v1.4.0 h1:zgVt4UpGxcqVOw97aRGxT4svlcmdK35fynLNctY32zI= -github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/gogo/status v1.0.3/go.mod h1:SavQ51ycCLnc7dGyJxp8YAmudx8xqiVrRf+6IXRsugc= -github.com/gogo/status v1.1.0 h1:+eIkrewn5q6b30y+g/BJINVVdi2xH7je5MPJ3ZPK3JA= -github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= -github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= -github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200417002340-c6e0a841f49a/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.4.0/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= -github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= -github.com/gophercloud/gophercloud v0.10.0/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f h1:KMlcu9X58lhTA/KrfX8Bi1LQSO4pzoVjTiL3h4Jk+Zk= -github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= -github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 h1:0IKlLyQ3Hs9nDaiK5cSHAGmcQEIC8l2Ts1u6x5Dfrqg= -github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.14.4/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= -github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= -github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 h1:BpJ2o0OR5FV7vrkDYfXYVJQeMNWa8RhklZOpW2ITAIQ= -github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE= -github.com/hannahhoward/cbor-gen-for v0.0.0-20200817222906-ea96cece81f1 h1:F9k+7wv5OIk1zcq23QpdiL0hfDuXPjuOmMNaC6fgQ0Q= -github.com/hannahhoward/cbor-gen-for v0.0.0-20200817222906-ea96cece81f1/go.mod h1:jvfsLIxk0fY/2BKSQ1xf2406AKA5dwMmKKv0ADcOfN8= -github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e h1:3YKHER4nmd7b5qy5t0GWDTwSn4OyRgfAXSmo6VnryBY= -github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e/go.mod h1:I8h3MITA53gN9OnWGCgaMa0JWVRdXthWw4M3CPM54OY= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/api v1.4.0/go.mod h1:xc8u05kyMa3Wjr9eEAsIAo3dg8+LywT5E/Cl7cNS5nU= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.4.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v0.12.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.2.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/memberlist v0.2.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/serf v0.9.0/go.mod h1:YL0HO+FifKOW2u1ke99DGVu1zhcpZzNwrLIqBC7vbYU= -github.com/hodgesds/perf-utils v0.0.8/go.mod h1:F6TfvsbtrF88i++hou29dTXlI2sfsJv+gRZDtmTJkAs= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= -github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= -github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= -github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94 h1:9tcYMdi+7Rb1y0E9Del1DRHui7Ne3za5lLw6CjMJv/M= -github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94/go.mod h1:GYeBD1CF7AqnKZK+UCytLcY3G+UKo0ByXX/3xfdNyqQ= -github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6 h1:8UsGZ2rr2ksmEru6lToqnXgA8Mz1DP11X4zSJ159C3k= -github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA= -github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/flux v0.65.0/go.mod h1:BwN2XG2lMszOoquQaFdPET8FRQfrXiZsWmcMO9rkaVY= -github.com/influxdata/flux v0.127.3/go.mod h1:Zc0P/HNnJnhBlm4QsmsBbAeAdtccKo4Eu0OfkP3RCk0= -github.com/influxdata/httprouter v1.3.1-0.20191122104820-ee83e2772f69/go.mod h1:pwymjR6SrP3gD3pRj9RJwdl1j5s3doEEV8gS4X9qSzA= -github.com/influxdata/influxdb v1.8.0/go.mod h1:SIzcnsjaHRFpmlxpJ4S3NT64qtEKYweNTUMb/vh0OMQ= -github.com/influxdata/influxdb v1.9.4 h1:hZMq5fd4enVnruYHd7qCHsqG7kWQ/msA6x+kCvGFsRY= -github.com/influxdata/influxdb v1.9.4/go.mod h1:dR0WCHqaHPpJLaqWnRSl/QHsbXJR+QpofbZXyTc8ccw= -github.com/influxdata/influxdb-client-go/v2 v2.3.1-0.20210518120617-5d1fff431040/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/influxdata/influxdb1-client v0.0.0-20200515024757-02f0bf5dbca3/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab h1:HqW4xhhynfjrtEiiSGcQUd6vrK23iMam1FO8rI7mwig= -github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/influxdata/influxql v1.1.0/go.mod h1:KpVI7okXjK6PRi3Z5B+mtKZli+R1DnZgb3N+tzevNgo= -github.com/influxdata/influxql v1.1.1-0.20210223160523-b6ab99450c93/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= -github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= -github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/influxdata/pkg-config v0.2.8/go.mod h1:EMS7Ll0S4qkzDk53XS3Z72/egBsPInt+BeRxb0WeSwk= -github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8= -github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= -github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= -github.com/influxdata/tdigest v0.0.2-0.20210216194612-fc98d27c9e8b/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y= -github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/ipfs/bbloom v0.0.1/go.mod h1:oqo8CVWsJFMOZqTglBG4wydCE4IQA/G2/SEofB0rjUI= -github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= -github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/go-bitfield v1.0.0 h1:y/XHm2GEmD9wKngheWNNCNL0pzrWXZwCdQGv1ikXknQ= -github.com/ipfs/go-bitfield v1.0.0/go.mod h1:N/UiujQy+K+ceU1EF5EkVd1TNqevLrCQMIcAEPrdtus= -github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= -github.com/ipfs/go-bitswap v0.1.2/go.mod h1:qxSWS4NXGs7jQ6zQvoPY3+NmOfHHG47mhkiLzBpJQIs= -github.com/ipfs/go-bitswap v0.5.1/go.mod h1:P+ckC87ri1xFLvk74NlXdP0Kj9RmWAh4+H78sC6Qopo= -github.com/ipfs/go-bitswap v0.6.0/go.mod h1:Hj3ZXdOC5wBJvENtdqsixmzzRukqd8EHLxZLZc3mzRA= -github.com/ipfs/go-bitswap v0.10.2 h1:B81RIwkTnIvSYT1ZCzxjYTeF0Ek88xa9r1AMpTfk+9Q= -github.com/ipfs/go-bitswap v0.10.2/go.mod h1:+fZEvycxviZ7c+5KlKwTzLm0M28g2ukCPqiuLfJk4KA= -github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= -github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= -github.com/ipfs/go-block-format v0.0.3 h1:r8t66QstRp/pd/or4dpnbVfXT5Gt7lOqRvC+/dDTpMc= -github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= -github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= -github.com/ipfs/go-blockservice v0.2.1/go.mod h1:k6SiwmgyYgs4M/qt+ww6amPeUH9EISLRBnvUurKJhi8= -github.com/ipfs/go-blockservice v0.3.0/go.mod h1:P5ppi8IHDC7O+pA0AlGTF09jruB2h+oP3wVVaZl8sfk= -github.com/ipfs/go-blockservice v0.4.0 h1:7MUijAW5SqdsqEW/EhnNFRJXVF8mGU5aGhZ3CQaCWbY= -github.com/ipfs/go-blockservice v0.4.0/go.mod h1:kRjO3wlGW9mS1aKuiCeGhx9K1DagQ10ACpVO59qgAx4= -github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.4-0.20191112011718-79e75dffeb10/go.mod h1:/BYOuUoxkE+0f6tGzlzMvycuN+5l35VOR4Bpg2sCmds= -github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= -github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= -github.com/ipfs/go-cid v0.0.6-0.20200501230655-7c82f3b81c00/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= -github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= -github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= -github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o= -github.com/ipfs/go-cid v0.2.0 h1:01JTiihFq9en9Vz0lc0VDWvZe/uBonGpzo4THP0vcQ0= -github.com/ipfs/go-cid v0.2.0/go.mod h1:P+HXFDF4CVhaVayiEb4wkAy7zBHxBwsJyt0Y5U6MLro= -github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q= -github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA= -github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-datastore v0.0.5/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= -github.com/ipfs/go-datastore v0.3.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= -github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= -github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= -github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= -github.com/ipfs/go-datastore v0.4.5/go.mod h1:eXTcaaiN6uOlVCLS9GjJUJtlvJfM3xk23w3fyfrmmJs= -github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= -github.com/ipfs/go-datastore v0.5.1 h1:WkRhLuISI+XPD0uk3OskB0fYFSyqK8Ob5ZYew9Qa1nQ= -github.com/ipfs/go-datastore v0.5.1/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= -github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= -github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= -github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= -github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= -github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= -github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= -github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= -github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= -github.com/ipfs/go-ds-badger2 v0.1.2 h1:sQc2q1gaXrv8YFNeUtxil0neuyDf9hnVHfLsi7lpXfE= -github.com/ipfs/go-ds-badger2 v0.1.2/go.mod h1:3FtQmDv6fMubygEfU43bsFelYpIiXX/XEYA54l9eCwg= -github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= -github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= -github.com/ipfs/go-ds-leveldb v0.4.2/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= -github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= -github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= -github.com/ipfs/go-ds-measure v0.2.0 h1:sG4goQe0KDTccHMyT45CY1XyUbxe5VwTKpg2LjApYyQ= -github.com/ipfs/go-ds-measure v0.2.0/go.mod h1:SEUD/rE2PwRa4IQEC5FuNAmjJCyYObZr9UvVh8V3JxE= -github.com/ipfs/go-fetcher v1.6.1/go.mod h1:27d/xMV8bodjVs9pugh/RCjjK2OZ68UgAMspMdingNo= -github.com/ipfs/go-filestore v1.2.0 h1:O2wg7wdibwxkEDcl7xkuQsPvJFRBVgVSsOJ/GP6z3yU= -github.com/ipfs/go-filestore v1.2.0/go.mod h1:HLJrCxRXquTeEEpde4lTLMaE/MYJZD7WHLkp9z6+FF8= -github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM= -github.com/ipfs/go-fs-lock v0.0.7 h1:6BR3dajORFrFTkb5EpCUFIAypsoxpGpDSVUdFwzgL9U= -github.com/ipfs/go-fs-lock v0.0.7/go.mod h1:Js8ka+FNYmgQRLrRXzU3CB/+Csr1BwrRilEcvYrHhhc= -github.com/ipfs/go-graphsync v0.13.1 h1:lWiP/WLycoPUYyj3IDEi1GJNP30kFuYOvimcfeuZyQs= -github.com/ipfs/go-graphsync v0.13.1/go.mod h1:y8e8G6CmZeL9Srvx1l15CtGiRdf3h5JdQuqPz/iYL0A= -github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= -github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= -github.com/ipfs/go-ipfs-blockstore v0.2.1/go.mod h1:jGesd8EtCM3/zPgx+qr0/feTXGUeRai6adgwC+Q+JvE= -github.com/ipfs/go-ipfs-blockstore v1.1.2/go.mod h1:w51tNR9y5+QXB0wkNcHt4O2aSZjTdqaEWaQdSxEyUOY= -github.com/ipfs/go-ipfs-blockstore v1.2.0 h1:n3WTeJ4LdICWs/0VSfjHrlqpPpl6MZ+ySd3j8qz0ykw= -github.com/ipfs/go-ipfs-blockstore v1.2.0/go.mod h1:eh8eTFLiINYNSNawfZOC7HOxNTxpB1PFuA5E1m/7exE= -github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= -github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk= -github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= -github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8= -github.com/ipfs/go-ipfs-chunker v0.0.5/go.mod h1:jhgdF8vxRHycr00k13FM8Y0E+6BoalYeobXmUyTreP8= -github.com/ipfs/go-ipfs-cmds v0.7.0 h1:0lEldmB7C83RxIOer38Sv1ob6wIoCAIEOaxiYgcv7wA= -github.com/ipfs/go-ipfs-cmds v0.7.0/go.mod h1:y0bflH6m4g6ary4HniYt98UqbrVnRxmRarzeMdLIUn0= -github.com/ipfs/go-ipfs-config v0.18.0 h1:Ta1aNGNEq6RIvzbw7dqzCVZJKb7j+Dd35JFnAOCpT8g= -github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= -github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= -github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= -github.com/ipfs/go-ipfs-ds-help v0.0.1/go.mod h1:gtP9xRaZXqIQRh1HRpp595KbBEdgqWFxefeVKOV8sxo= -github.com/ipfs/go-ipfs-ds-help v0.1.1/go.mod h1:SbBafGJuGsPI/QL3j9Fc5YPLeAu+SzOkI0gFwAg+mOs= -github.com/ipfs/go-ipfs-ds-help v1.1.0 h1:yLE2w9RAsl31LtfMt91tRZcrx+e61O5mDxFRR994w4Q= -github.com/ipfs/go-ipfs-ds-help v1.1.0/go.mod h1:YR5+6EaebOhfcqVCyqemItCLthrpVNot+rsOU/5IatU= -github.com/ipfs/go-ipfs-exchange-interface v0.0.1/go.mod h1:c8MwfHjtQjPoDyiy9cFquVtVHkO9b9Ob3FG91qJnWCM= -github.com/ipfs/go-ipfs-exchange-interface v0.1.0/go.mod h1:ych7WPlyHqFvCi/uQI48zLZuAWVP5iTQPXEfVaw5WEI= -github.com/ipfs/go-ipfs-exchange-interface v0.2.0 h1:8lMSJmKogZYNo2jjhUs0izT+dck05pqUw4mWNW9Pw6Y= -github.com/ipfs/go-ipfs-exchange-interface v0.2.0/go.mod h1:z6+RhJuDQbqKguVyslSOuVDhqF9JtTrO3eptSAiW2/Y= -github.com/ipfs/go-ipfs-exchange-offline v0.0.1/go.mod h1:WhHSFCVYX36H/anEKQboAzpUws3x7UeEGkzQc3iNkM0= -github.com/ipfs/go-ipfs-exchange-offline v0.1.1/go.mod h1:vTiBRIbzSwDD0OWm+i3xeT0mO7jG2cbJYatp3HPk5XY= -github.com/ipfs/go-ipfs-exchange-offline v0.2.0/go.mod h1:HjwBeW0dvZvfOMwDP0TSKXIHf2s+ksdP4E3MLDRtLKY= -github.com/ipfs/go-ipfs-exchange-offline v0.3.0 h1:c/Dg8GDPzixGd0MC8Jh6mjOwU57uYokgWRFidfvEkuA= -github.com/ipfs/go-ipfs-exchange-offline v0.3.0/go.mod h1:MOdJ9DChbb5u37M1IcbrRB02e++Z7521fMxqCNRrz9s= -github.com/ipfs/go-ipfs-files v0.0.3/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= -github.com/ipfs/go-ipfs-files v0.0.4/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= -github.com/ipfs/go-ipfs-files v0.0.8/go.mod h1:wiN/jSG8FKyk7N0WyctKSvq3ljIa2NNTiZB55kpTdOs= -github.com/ipfs/go-ipfs-files v0.1.1 h1:/MbEowmpLo9PJTEQk16m9rKzUHjeP4KRU9nWJyJO324= -github.com/ipfs/go-ipfs-files v0.1.1/go.mod h1:8xkIrMWH+Y5P7HvJ4Yc5XWwIW2e52dyXUiC0tZyjDbM= -github.com/ipfs/go-ipfs-http-client v0.4.0 h1:LNuVbFoKfCohCmcNImml3byM3PpTxTT7RPrv/UoDFkI= -github.com/ipfs/go-ipfs-http-client v0.4.0/go.mod h1:NXzPUKt/QVCuR74a8angJCGOSLPImNi5LqaTxIep/70= -github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= -github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= -github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= -github.com/ipfs/go-ipfs-pq v0.0.2 h1:e1vOOW6MuOwG2lqxcLA+wEn93i/9laCY8sXAw76jFOY= -github.com/ipfs/go-ipfs-pq v0.0.2/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= -github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= -github.com/ipfs/go-ipfs-routing v0.2.1 h1:E+whHWhJkdN9YeoHZNj5itzc+OR292AJ2uE9FFiW0BY= -github.com/ipfs/go-ipfs-routing v0.2.1/go.mod h1:xiNNiwgjmLqPS1cimvAw6EyB9rkVDbiocA4yY+wRNLM= -github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= -github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= -github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= -github.com/ipfs/go-ipld-cbor v0.0.2/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc= -github.com/ipfs/go-ipld-cbor v0.0.3/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc= -github.com/ipfs/go-ipld-cbor v0.0.4/go.mod h1:BkCduEx3XBCO6t2Sfo5BaHzuok7hbhdMm9Oh8B2Ftq4= -github.com/ipfs/go-ipld-cbor v0.0.5/go.mod h1:BkCduEx3XBCO6t2Sfo5BaHzuok7hbhdMm9Oh8B2Ftq4= -github.com/ipfs/go-ipld-cbor v0.0.6-0.20211211231443-5d9b9e1f6fa8/go.mod h1:ssdxxaLJPXH7OjF5V4NSjBbcfh+evoR4ukuru0oPXMA= -github.com/ipfs/go-ipld-cbor v0.0.6 h1:pYuWHyvSpIsOOLw4Jy7NbBkCyzLDcl64Bf/LZW7eBQ0= -github.com/ipfs/go-ipld-cbor v0.0.6/go.mod h1:ssdxxaLJPXH7OjF5V4NSjBbcfh+evoR4ukuru0oPXMA= -github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms= -github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k= -github.com/ipfs/go-ipld-format v0.2.0/go.mod h1:3l3C1uKoadTPbeNfrDi+xMInYKlx2Cvg1BuydPSdzQs= -github.com/ipfs/go-ipld-format v0.3.0/go.mod h1:co/SdBE8h99968X0hViiw1MNlh6fvxxnHpvVLnH7jSM= -github.com/ipfs/go-ipld-format v0.4.0 h1:yqJSaJftjmjc9jEOFYlpkwOLVKv68OD27jFLlSghBlQ= -github.com/ipfs/go-ipld-format v0.4.0/go.mod h1:co/SdBE8h99968X0hViiw1MNlh6fvxxnHpvVLnH7jSM= -github.com/ipfs/go-ipld-legacy v0.1.0/go.mod h1:86f5P/srAmh9GcIcWQR9lfFLZPrIyyXQeVlOWeeWEuI= -github.com/ipfs/go-ipld-legacy v0.1.1 h1:BvD8PEuqwBHLTKqlGFTHSwrwFOMkVESEvwIYwR2cdcc= -github.com/ipfs/go-ipld-legacy v0.1.1/go.mod h1:8AyKFCjgRPsQFf15ZQgDB8Din4DML/fOmKZkkFkrIEg= -github.com/ipfs/go-ipns v0.2.0 h1:BgmNtQhqOw5XEZ8RAfWEpK4DhqaYiuP6h71MhIp7xXU= -github.com/ipfs/go-ipns v0.2.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24= -github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= -github.com/ipfs/go-log v1.0.0/go.mod h1:JO7RzlMK6rA+CIxFMLOuB6Wf5b81GDiKElL7UPSIKjA= -github.com/ipfs/go-log v1.0.1/go.mod h1:HuWlQttfN6FWNHRhlY5yMk/lW7evQC0HHGOxEwMRR8I= -github.com/ipfs/go-log v1.0.2/go.mod h1:1MNjMxe0u6xvJZgeqbJ8vdo2TKaGwZ1a0Bpza+sr2Sk= -github.com/ipfs/go-log v1.0.3/go.mod h1:OsLySYkwIbiSUR/yBTdv1qPtcE4FW3WPWk/ewz9Ru+A= -github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= -github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= -github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= -github.com/ipfs/go-log/v2 v2.0.1/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= -github.com/ipfs/go-log/v2 v2.0.2/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= -github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= -github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= -github.com/ipfs/go-log/v2 v2.0.8/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= -github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= -github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= -github.com/ipfs/go-log/v2 v2.1.2/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= -github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= -github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g= -github.com/ipfs/go-log/v2 v2.4.0/go.mod h1:nPZnh7Cj7lwS3LpRU5Mwr2ol1c2gXIEXuF6aywqrtmo= -github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= -github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= -github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= -github.com/ipfs/go-merkledag v0.2.4/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= -github.com/ipfs/go-merkledag v0.3.2/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= -github.com/ipfs/go-merkledag v0.5.1/go.mod h1:cLMZXx8J08idkp5+id62iVftUQV+HlYJ3PIhDfZsjA4= -github.com/ipfs/go-merkledag v0.6.0 h1:oV5WT2321tS4YQVOPgIrWHvJ0lJobRTerU+i9nmUCuA= -github.com/ipfs/go-merkledag v0.6.0/go.mod h1:9HSEwRd5sV+lbykiYP+2NC/3o6MZbKNaa4hfNcH5iH0= -github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= -github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= -github.com/ipfs/go-path v0.3.0 h1:tkjga3MtpXyM5v+3EbRvOHEoo+frwi4oumw5K+KYWyA= -github.com/ipfs/go-path v0.3.0/go.mod h1:NOScsVgxfC/eIw4nz6OiGwK42PjaSJ4Y/ZFPn1Xe07I= -github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= -github.com/ipfs/go-peertaskqueue v0.7.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= -github.com/ipfs/go-peertaskqueue v0.7.1 h1:7PLjon3RZwRQMgOTvYccZ+mjzkmds/7YzSWKFlBAypE= -github.com/ipfs/go-peertaskqueue v0.7.1/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= -github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb/go.mod h1:IwAAgul1UQIcNZzKPYZWOCijryFBeCV79cNubPzol+k= -github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= -github.com/ipfs/go-unixfs v0.3.1 h1:LrfED0OGfG98ZEegO4/xiprx2O+yS+krCMQSp7zLVv8= -github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= -github.com/ipfs/go-unixfsnode v1.1.2/go.mod h1:5dcE2x03pyjHk4JjamXmunTMzz+VUtqvPwZjIEkfV6s= -github.com/ipfs/go-unixfsnode v1.4.0 h1:9BUxHBXrbNi8mWHc6j+5C580WJqtVw9uoeEKn4tMhwA= -github.com/ipfs/go-unixfsnode v1.4.0/go.mod h1:qc7YFFZ8tABc58p62HnIYbUMwj9chhUuFWmxSokfePo= -github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= -github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= -github.com/ipfs/interface-go-ipfs-core v0.7.0 h1:7tb+2upz8oCcjIyjo1atdMk+P+u7wPmI+GksBlLE8js= -github.com/ipfs/interface-go-ipfs-core v0.7.0/go.mod h1:lF27E/nnSPbylPqKVXGZghal2hzifs3MmjyiEjnc9FY= -github.com/ipfs/iptb v1.4.0 h1:YFYTrCkLMRwk/35IMyC6+yjoQSHTEcNcefBStLJzgvo= -github.com/ipfs/iptb-plugins v0.3.0 h1:C1rpq1o5lUZtaAOkLIox5akh6ba4uk/3RwWc6ttVxw0= -github.com/ipld/go-car v0.1.0/go.mod h1:RCWzaUh2i4mOEkB3W45Vc+9jnS/M6Qay5ooytiBHl3g= -github.com/ipld/go-car v0.4.0 h1:U6W7F1aKF/OJMHovnOVdst2cpQE5GhmHibQkAixgNcQ= -github.com/ipld/go-car v0.4.0/go.mod h1:Uslcn4O9cBKK9wqHm/cLTFacg6RAPv6LZx2mxd2Ypl4= -github.com/ipld/go-car/v2 v2.1.1/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= -github.com/ipld/go-car/v2 v2.4.1 h1:9S+FYbQzQJ/XzsdiOV13W5Iu/i+gUnr6csbSD9laFEg= -github.com/ipld/go-car/v2 v2.4.1/go.mod h1:zjpRf0Jew9gHqSvjsKVyoq9OY9SWoEKdYCQUKVaaPT0= -github.com/ipld/go-codec-dagpb v1.2.0/go.mod h1:6nBN7X7h8EOsEejZGqC7tej5drsdBAXbMHyBT+Fne5s= -github.com/ipld/go-codec-dagpb v1.3.0/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= -github.com/ipld/go-codec-dagpb v1.3.1/go.mod h1:ErNNglIi5KMur/MfFE/svtgQthzVvf+43MrzLbpcIZY= -github.com/ipld/go-codec-dagpb v1.3.2 h1:MZQUIjanHXXfDuYmtWYT8nFbqfFsZuyHClj6VDmSXr4= -github.com/ipld/go-codec-dagpb v1.3.2/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= -github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= -github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= -github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= -github.com/ipld/go-ipld-prime v0.10.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= -github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8= -github.com/ipld/go-ipld-prime v0.14.0/go.mod h1:9ASQLwUFLptCov6lIYc70GRB4V7UTyLD0IJtrDJe6ZM= -github.com/ipld/go-ipld-prime v0.16.0/go.mod h1:axSCuOCBPqrH+gvXr2w9uAOulJqBPhHPT2PjoiiU1qA= -github.com/ipld/go-ipld-prime v0.17.0 h1:+U2peiA3aQsE7mrXjD2nYZaZrCcakoz2Wge8K42Ld8g= -github.com/ipld/go-ipld-prime v0.17.0/go.mod h1:aYcKm5TIvGfY8P3QBKz/2gKcLxzJ1zDaD+o0bOowhgs= -github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU= -github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73 h1:TsyATB2ZRRQGTwafJdgEUQkmjOExRV0DNokcihZxbnQ= -github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73/go.mod h1:2PJ0JgxyB08t0b2WKrcuqI3di0V+5n6RS/LTUJhkoxY= -github.com/ipld/go-ipld-selector-text-lite v0.0.1 h1:lNqFsQpBHc3p5xHob2KvEg/iM5dIFn6iw4L/Hh+kS1Y= -github.com/ipld/go-ipld-selector-text-lite v0.0.1/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM= -github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= -github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= -github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= -github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= -github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs= -github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= -github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c h1:uUx61FiAa1GI6ZmVd2wf2vULeQZIKG66eybjNXKYCz4= -github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c/go.mod h1:sdx1xVM9UuLw1tXnhJWN3piypTUO3vCIHYmG15KE/dU= -github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs= -github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= -github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= -github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= -github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= -github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4= -github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.1.1-0.20190114141812-62fb9bc030d1/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= -github.com/jsimonetti/rtnetlink v0.0.0-20190830100107-3784a6c7c552/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= -github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= -github.com/jsternberg/zap-logfmt v1.2.0/go.mod h1:kz+1CUmCutPWABnNkOu9hOHKdT2q3TDYCcsFy9hpqb0= -github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= -github.com/kabukky/httpscerts v0.0.0-20150320125433-617593d7dcb3 h1:Iy7Ifq2ysilWU4QlCx/97OoI4xT1IV7i8byT/EyIT/M= -github.com/kabukky/httpscerts v0.0.0-20150320125433-617593d7dcb3/go.mod h1:BYpt4ufZiIGv2nXn4gMxnfKV306n3mWXgNu/d2TqdTU= -github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= -github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= -github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= -github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= -github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= -github.com/kilic/bls12-381 v0.0.0-20200607163746-32e1441c8a9f/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s= -github.com/kilic/bls12-381 v0.0.0-20200731194930-64c428e1bff5/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s= -github.com/kilic/bls12-381 v0.0.0-20200820230200-6b2c19996391 h1:51kHw7l/dUDdOdW06AlUGT5jnpj6nqQSILebcsikSjA= -github.com/kilic/bls12-381 v0.0.0-20200820230200-6b2c19996391/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= -github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0= -github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= -github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= -github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= -github.com/koron/go-ssdp v0.0.2/go.mod h1:XoLfkAiA2KeZsYh4DbHxD7h3nR2AZNqVQOa+LJuqPYs= -github.com/koron/go-ssdp v0.0.3 h1:JivLMY45N76b4p/vsWGOKewBQu6uf39y8l+AQ7sDKx8= -github.com/koron/go-ssdp v0.0.3/go.mod h1:b2MxI6yh02pKrsyNoQUsk4+YNikaGhe4894J+Q5lDvA= -github.com/kpacha/opencensus-influxdb v0.0.0-20181102202715-663e2683a27c h1:3pM6OrLfkfe0rKZjE6MHdcTaI0ohcHbRUZJeJqkvPb4= -github.com/kpacha/opencensus-influxdb v0.0.0-20181102202715-663e2683a27c/go.mod h1:ESXZSm2iaF+1P5o6VFEWpeARTQpcil4e1DwumnTopdg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20160406211939-eadb3ce320cb/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= -github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ= -github.com/libp2p/go-addr-util v0.0.2/go.mod h1:Ecd6Fb3yIuLzq4bD7VcywcVSBtefcAwnUISBM3WG15E= -github.com/libp2p/go-addr-util v0.1.0/go.mod h1:6I3ZYuFr2O/9D+SoyM0zEw0EF3YkldtTX406BpdQMqw= -github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= -github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= -github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= -github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= -github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= -github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= -github.com/libp2p/go-conn-security-multistream v0.2.0/go.mod h1:hZN4MjlNetKD3Rq5Jb/P5ohUnFLNzEAR4DLSzpn2QLU= -github.com/libp2p/go-conn-security-multistream v0.2.1/go.mod h1:cR1d8gA0Hr59Fj6NhaTpFhJZrjSYuNmhpT2r25zYR70= -github.com/libp2p/go-conn-security-multistream v0.3.0/go.mod h1:EEP47t4fw/bTelVmEzIDqSe69hO/ip52xBEhZMLWAHM= -github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= -github.com/libp2p/go-eventbus v0.2.1/go.mod h1:jc2S4SoEVPP48H9Wpzm5aiGwUCBMfGhVhhBjyhhCJs8= -github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= -github.com/libp2p/go-flow-metrics v0.0.2/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= -github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= -github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= -github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= -github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM= -github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8= -github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZkfEI5sT54= -github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= -github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= -github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= -github.com/libp2p/go-libp2p v0.8.3/go.mod h1:EsH1A+8yoWK+L4iKcbPYu6MPluZ+CHWI9El8cTaefiM= -github.com/libp2p/go-libp2p v0.10.0/go.mod h1:yBJNpb+mGJdgrwbKAKrhPU0u3ogyNFTfjJ6bdM+Q/G8= -github.com/libp2p/go-libp2p v0.14.3/go.mod h1:d12V4PdKbpL0T1/gsUNN8DfgMuRPDX8bS2QxCZlwRH0= -github.com/libp2p/go-libp2p v0.16.0/go.mod h1:ump42BsirwAWxKzsCiFnTtN1Yc+DuPu76fyMX364/O4= -github.com/libp2p/go-libp2p v0.17.0/go.mod h1:Fkin50rsGdv5mm5BshBUtPRZknt9esfmYXBOYcwOTgw= -github.com/libp2p/go-libp2p v0.22.0 h1:2Tce0kHOp5zASFKJbNzRElvh0iZwdtG5uZheNW8chIw= -github.com/libp2p/go-libp2p v0.22.0/go.mod h1:UDolmweypBSjQb2f7xutPnwZ/fxioLbMBxSjRksxxU4= -github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= -github.com/libp2p/go-libp2p-asn-util v0.2.0 h1:rg3+Os8jbnO5DxkC7K/Utdi+DkY3q/d1/1q+8WeNAsw= -github.com/libp2p/go-libp2p-asn-util v0.2.0/go.mod h1:WoaWxbHKBymSN41hWSq/lGKJEca7TNm58+gGJi2WsLI= -github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= -github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= -github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= -github.com/libp2p/go-libp2p-autonat v0.2.1/go.mod h1:MWtAhV5Ko1l6QBsHQNSuM6b1sRkXrpk0/LqCr+vCVxI= -github.com/libp2p/go-libp2p-autonat v0.2.2/go.mod h1:HsM62HkqZmHR2k1xgX34WuWDzk/nBwNHoeyyT4IWV6A= -github.com/libp2p/go-libp2p-autonat v0.2.3/go.mod h1:2U6bNWCNsAG9LEbwccBDQbjzQ8Krdjge1jLTE9rdoMM= -github.com/libp2p/go-libp2p-autonat v0.4.2/go.mod h1:YxaJlpr81FhdOv3W3BTconZPfhaYivRdf53g+S2wobk= -github.com/libp2p/go-libp2p-autonat v0.6.0/go.mod h1:bFC6kY8jwzNNWoqc8iGE57vsfwyJ/lP4O4DOV1e0B2o= -github.com/libp2p/go-libp2p-autonat v0.7.0/go.mod h1:uPvPn6J7cN+LCfFwW5tpOYvAz5NvPTc4iBamTV/WDMg= -github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= -github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU= -github.com/libp2p/go-libp2p-blankhost v0.1.6/go.mod h1:jONCAJqEP+Z8T6EQviGL4JsQcLx1LgTGtVqFNY8EMfQ= -github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= -github.com/libp2p/go-libp2p-blankhost v0.3.0/go.mod h1:urPC+7U01nCGgJ3ZsV8jdwTp6Ji9ID0dMTvq+aJ+nZU= -github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= -github.com/libp2p/go-libp2p-circuit v0.1.4/go.mod h1:CY67BrEjKNDhdTk8UgBX1Y/H5c3xkAcs3gnksxY7osU= -github.com/libp2p/go-libp2p-circuit v0.2.1/go.mod h1:BXPwYDN5A8z4OEY9sOfr2DUQMLQvKt/6oku45YUmjIo= -github.com/libp2p/go-libp2p-circuit v0.2.2/go.mod h1:nkG3iE01tR3FoQ2nMm06IUrCpCyJp1Eo4A1xYdpjfs4= -github.com/libp2p/go-libp2p-circuit v0.2.3/go.mod h1:nkG3iE01tR3FoQ2nMm06IUrCpCyJp1Eo4A1xYdpjfs4= -github.com/libp2p/go-libp2p-circuit v0.4.0/go.mod h1:t/ktoFIUzM6uLQ+o1G6NuBl2ANhBKN9Bc8jRIk31MoA= -github.com/libp2p/go-libp2p-connmgr v0.2.4/go.mod h1:YV0b/RIm8NGPnnNWM7hG9Q38OeQiQfKhHCCs1++ufn0= -github.com/libp2p/go-libp2p-connmgr v0.3.0/go.mod h1:RVoyPjJm0J9Vd1m6qUN2Tn7kJm4rL1Ml20pFsFgPGik= -github.com/libp2p/go-libp2p-connmgr v0.4.0 h1:q/KZUS1iMDIQckMZarMYwhQisJqiFPHAVC1c4DR3hDE= -github.com/libp2p/go-libp2p-connmgr v0.4.0/go.mod h1:exFQQm19PFAx+QuJmBPw4MM58QejzPJRFFFYnNmgi2w= -github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= -github.com/libp2p/go-libp2p-core v0.0.2/go.mod h1:9dAcntw/n46XycV4RnlBq3BpgrmyUi9LuoTNdPrbUco= -github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE= -github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= -github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= -github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= -github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g= -github.com/libp2p/go-libp2p-core v0.2.5/go.mod h1:6+5zJmKhsf7yHn1RbmYDu08qDUpIUxGdqHuEZckmZOA= -github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= -github.com/libp2p/go-libp2p-core v0.3.1/go.mod h1:thvWy0hvaSBhnVBaW37BvzgVV68OUhgJJLAa6almrII= -github.com/libp2p/go-libp2p-core v0.4.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= -github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= -github.com/libp2p/go-libp2p-core v0.5.1/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= -github.com/libp2p/go-libp2p-core v0.5.2/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= -github.com/libp2p/go-libp2p-core v0.5.3/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= -github.com/libp2p/go-libp2p-core v0.5.4/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= -github.com/libp2p/go-libp2p-core v0.5.5/go.mod h1:vj3awlOr9+GMZJFH9s4mpt9RHHgGqeHCopzbYKZdRjM= -github.com/libp2p/go-libp2p-core v0.5.6/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= -github.com/libp2p/go-libp2p-core v0.5.7/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= -github.com/libp2p/go-libp2p-core v0.6.0/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= -github.com/libp2p/go-libp2p-core v0.7.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= -github.com/libp2p/go-libp2p-core v0.8.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= -github.com/libp2p/go-libp2p-core v0.8.1/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= -github.com/libp2p/go-libp2p-core v0.8.2/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= -github.com/libp2p/go-libp2p-core v0.8.5/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= -github.com/libp2p/go-libp2p-core v0.8.6/go.mod h1:dgHr0l0hIKfWpGpqAMbpo19pen9wJfdCGv51mTmdpmM= -github.com/libp2p/go-libp2p-core v0.9.0/go.mod h1:ESsbz31oC3C1AvMJoGx26RTuCkNhmkSRCqZ0kQtJ2/8= -github.com/libp2p/go-libp2p-core v0.10.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= -github.com/libp2p/go-libp2p-core v0.11.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= -github.com/libp2p/go-libp2p-core v0.12.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= -github.com/libp2p/go-libp2p-core v0.13.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= -github.com/libp2p/go-libp2p-core v0.20.0 h1:PGKM74+T+O/FaZNARNW32i90RMBHCcgd/hkum2UQ5eY= -github.com/libp2p/go-libp2p-core v0.20.0/go.mod h1:6zR8H7CvQWgYLsbG4on6oLNSGcyKaYFSEYyDt51+bIY= -github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= -github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g= -github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg= -github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw= -github.com/libp2p/go-libp2p-discovery v0.4.0/go.mod h1:bZ0aJSrFc/eX2llP0ryhb1kpgkPyTo23SJ5b7UQCMh4= -github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= -github.com/libp2p/go-libp2p-discovery v0.6.0/go.mod h1:/u1voHt0tKIe5oIA1RHBKQLVCWPna2dXmPNHc2zR9S8= -github.com/libp2p/go-libp2p-gostream v0.4.0 h1:heduMMEB78yBqeEQv+P7Fn5X926MHC2jDIC7/7yLpYA= -github.com/libp2p/go-libp2p-gostream v0.4.0/go.mod h1:21DVGBcCQwRfEXZpCnZ2kG24QiEkBpEQvG53gYXE4u0= -github.com/libp2p/go-libp2p-kad-dht v0.18.0 h1:akqO3gPMwixR7qFSFq70ezRun97g5hrA/lBW9jrjUYM= -github.com/libp2p/go-libp2p-kad-dht v0.18.0/go.mod h1:Gb92MYIPm3K2pJLGn8wl0m8wiKDvHrYpg+rOd0GzzPA= -github.com/libp2p/go-libp2p-kbucket v0.5.0 h1:g/7tVm8ACHDxH29BGrpsQlnNeu+6OF1A9bno/4/U1oA= -github.com/libp2p/go-libp2p-kbucket v0.5.0/go.mod h1:zGzGCpQd78b5BNTDGHNDLaTt9aDK/A02xeZp9QeFC4U= -github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= -github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= -github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= -github.com/libp2p/go-libp2p-mplex v0.2.2/go.mod h1:74S9eum0tVQdAfFiKxAyKzNdSuLqw5oadDq7+L/FELo= -github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxWDkm+dVvjfuG3ek= -github.com/libp2p/go-libp2p-mplex v0.4.0/go.mod h1:yCyWJE2sc6TBTnFpjvLuEJgTSw/u+MamvzILKdX7asw= -github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= -github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= -github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= -github.com/libp2p/go-libp2p-nat v0.0.6/go.mod h1:iV59LVhB3IkFvS6S6sauVTSOrNEANnINbI/fkaLimiw= -github.com/libp2p/go-libp2p-nat v0.1.0/go.mod h1:DQzAG+QbDYjN1/C3B6vXucLtz3u9rEonLVPtZVzQqks= -github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= -github.com/libp2p/go-libp2p-noise v0.2.0/go.mod h1:IEbYhBBzGyvdLBoxxULL/SGbJARhUeqlO8lVSREYu2Q= -github.com/libp2p/go-libp2p-noise v0.3.0/go.mod h1:JNjHbociDJKHD64KTkzGnzqJ0FEV5gHJa6AB00kbCNQ= -github.com/libp2p/go-libp2p-noise v0.5.0 h1:gwJZ/3iH3MRnBrLIyr/YLdCOnmqfJMptlsFFUIc3j0Y= -github.com/libp2p/go-libp2p-noise v0.5.0/go.mod h1:CYYpJ+T4pox1d1J/hhUVxuMf6b2s3c41hFUgS8/yFQw= -github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= -github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= -github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= -github.com/libp2p/go-libp2p-peerstore v0.2.0/go.mod h1:N2l3eVIeAitSg3Pi2ipSrJYnqhVnMNQZo9nkSCuAbnQ= -github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= -github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= -github.com/libp2p/go-libp2p-peerstore v0.2.3/go.mod h1:K8ljLdFn590GMttg/luh4caB/3g0vKuY01psze0upRw= -github.com/libp2p/go-libp2p-peerstore v0.2.4/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s= -github.com/libp2p/go-libp2p-peerstore v0.2.6/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s= -github.com/libp2p/go-libp2p-peerstore v0.2.7/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s= -github.com/libp2p/go-libp2p-peerstore v0.4.0/go.mod h1:rDJUFyzEWPpXpEwywkcTYYzDHlwza8riYMaUzaN6hX0= -github.com/libp2p/go-libp2p-peerstore v0.6.0/go.mod h1:DGEmKdXrcYpK9Jha3sS7MhqYdInxJy84bIPtSu65bKc= -github.com/libp2p/go-libp2p-peerstore v0.8.0 h1:bzTG693TA1Ju/zKmUCQzDLSqiJnyRFVwPpuloZ/OZtI= -github.com/libp2p/go-libp2p-peerstore v0.8.0/go.mod h1:9geHWmNA3YDlQBjL/uPEJD6vpDK12aDNlUNHJ6kio/s= -github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= -github.com/libp2p/go-libp2p-pubsub v0.3.2/go.mod h1:Uss7/Cfz872KggNb+doCVPHeCDmXB7z500m/R8DaAUk= -github.com/libp2p/go-libp2p-pubsub v0.6.0/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= -github.com/libp2p/go-libp2p-pubsub v0.8.0 h1:KygfDpaa9AeUPGCVcpVenpXNFauDn+5kBYu3EjcL3Tg= -github.com/libp2p/go-libp2p-pubsub v0.8.0/go.mod h1:e4kT+DYjzPUYGZeWk4I+oxCSYTXizzXii5LDRRhjKSw= -github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6 h1:2lH7rMlvDPSvXeOR+g7FE6aqiEwxtpxWKQL8uigk5fQ= -github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6/go.mod h1:8ZodgKS4qRLayfw9FDKDd9DX4C16/GMofDxSldG8QPI= -github.com/libp2p/go-libp2p-quic-transport v0.5.0/go.mod h1:IEcuC5MLxvZ5KuHKjRu+dr3LjCT1Be3rcD/4d8JrX8M= -github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= -github.com/libp2p/go-libp2p-quic-transport v0.13.0/go.mod h1:39/ZWJ1TW/jx1iFkKzzUg00W6tDJh73FC0xYudjr7Hc= -github.com/libp2p/go-libp2p-quic-transport v0.15.0/go.mod h1:wv4uGwjcqe8Mhjj7N/Ic0aKjA+/10UnMlSzLO0yRpYQ= -github.com/libp2p/go-libp2p-quic-transport v0.15.2/go.mod h1:wv4uGwjcqe8Mhjj7N/Ic0aKjA+/10UnMlSzLO0yRpYQ= -github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q= -github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGdsU/9W//C8dqjQDk= -github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0= -github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk= -github.com/libp2p/go-libp2p-routing-helpers v0.2.3 h1:xY61alxJ6PurSi+MXbywZpelvuU4U4p/gPTxjqCqTzY= -github.com/libp2p/go-libp2p-routing-helpers v0.2.3/go.mod h1:795bh+9YeoFl99rMASoiVgHdi5bjack0N1+AFAdbvBw= -github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= -github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= -github.com/libp2p/go-libp2p-secio v0.2.1/go.mod h1:cWtZpILJqkqrSkiYcDBh5lA3wbT2Q+hz3rJQq3iftD8= -github.com/libp2p/go-libp2p-secio v0.2.2/go.mod h1:wP3bS+m5AUnFA+OFO7Er03uO1mncHG0uVwGrwvjYlNY= -github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= -github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU= -github.com/libp2p/go-libp2p-swarm v0.2.3/go.mod h1:P2VO/EpxRyDxtChXz/VPVXyTnszHvokHKRhfkEgFKNM= -github.com/libp2p/go-libp2p-swarm v0.2.4/go.mod h1:/xIpHFPPh3wmSthtxdGbkHZ0OET1h/GGZes8Wku/M5Y= -github.com/libp2p/go-libp2p-swarm v0.2.7/go.mod h1:ZSJ0Q+oq/B1JgfPHJAT2HTall+xYRNYp1xs4S2FBWKA= -github.com/libp2p/go-libp2p-swarm v0.2.8/go.mod h1:JQKMGSth4SMqonruY0a8yjlPVIkb0mdNSwckW7OYziM= -github.com/libp2p/go-libp2p-swarm v0.3.0/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= -github.com/libp2p/go-libp2p-swarm v0.5.0/go.mod h1:sU9i6BoHE0Ve5SKz3y9WfKrh8dUat6JknzUehFx8xW4= -github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= -github.com/libp2p/go-libp2p-swarm v0.9.0/go.mod h1:2f8d8uxTJmpeqHF/1ujjdXZp+98nNIbujVOMEZxCbZ8= -github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= -github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= -github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= -github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= -github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= -github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= -github.com/libp2p/go-libp2p-testing v0.3.0/go.mod h1:efZkql4UZ7OVsEfaxNHZPzIehtsBXMrXnCfJIgDti5g= -github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= -github.com/libp2p/go-libp2p-testing v0.4.2/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= -github.com/libp2p/go-libp2p-testing v0.5.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= -github.com/libp2p/go-libp2p-testing v0.6.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= -github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= -github.com/libp2p/go-libp2p-tls v0.1.3/go.mod h1:wZfuewxOndz5RTnCAxFliGjvYSDA40sKitV4c50uI1M= -github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= -github.com/libp2p/go-libp2p-tls v0.3.1/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= -github.com/libp2p/go-libp2p-tls v0.5.0 h1:aRNTeOI8Ljm1r4L2uMGxkMsVnyZoPwaqQqMw23qAsQs= -github.com/libp2p/go-libp2p-tls v0.5.0/go.mod h1:1a4tq0xQSZ0kAkDkZVAppuP3SAIUHcnzi2djJ/2EN4I= -github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= -github.com/libp2p/go-libp2p-transport-upgrader v0.2.0/go.mod h1:mQcrHj4asu6ArfSoMuyojOdjx73Q47cYD7s5+gZOlns= -github.com/libp2p/go-libp2p-transport-upgrader v0.3.0/go.mod h1:i+SKzbRnvXdVbU3D1dwydnTmKRPXiAR/fyvi1dXuL4o= -github.com/libp2p/go-libp2p-transport-upgrader v0.4.2/go.mod h1:NR8ne1VwfreD5VIWIU62Agt/J18ekORFU/j1i2y8zvk= -github.com/libp2p/go-libp2p-transport-upgrader v0.4.3/go.mod h1:bpkldbOWXMrXhpZbSV1mQxTrefOg2Fi+k1ClDSA4ppw= -github.com/libp2p/go-libp2p-transport-upgrader v0.5.0/go.mod h1:Rc+XODlB3yce7dvFV4q/RmyJGsFcCZRkeZMu/Zdg0mo= -github.com/libp2p/go-libp2p-transport-upgrader v0.6.0/go.mod h1:1e07y1ZSZdHo9HPbuU8IztM1Cj+DR5twgycb4pnRzRo= -github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= -github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZKkAQzZbkSQt5fI= -github.com/libp2p/go-libp2p-yamux v0.2.2/go.mod h1:lIohaR0pT6mOt0AZ0L2dFze9hds9Req3OfS+B+dv4qw= -github.com/libp2p/go-libp2p-yamux v0.2.5/go.mod h1:Zpgj6arbyQrmZ3wxSZxfBmbdnWtbZ48OpsfmQVTErwA= -github.com/libp2p/go-libp2p-yamux v0.2.7/go.mod h1:X28ENrBMU/nm4I3Nx4sZ4dgjZ6VhLEn0XhIoZ5viCwU= -github.com/libp2p/go-libp2p-yamux v0.2.8/go.mod h1:/t6tDqeuZf0INZMTgd0WxIRbtK2EzI2h7HbFm9eAKI4= -github.com/libp2p/go-libp2p-yamux v0.4.0/go.mod h1:+DWDjtFMzoAwYLVkNZftoucn7PelNoy5nm3tZ3/Zw30= -github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= -github.com/libp2p/go-libp2p-yamux v0.5.4/go.mod h1:tfrXbyaTqqSU654GTvK3ocnSZL3BuHoeTSqhcel1wsE= -github.com/libp2p/go-libp2p-yamux v0.6.0/go.mod h1:MRhd6mAYnFRnSISp4M8i0ClV/j+mWHo2mYLifWGw33k= -github.com/libp2p/go-libp2p-yamux v0.7.0/go.mod h1:fMyA0CsPfHkIuBU0wjRGrCjTBFiXTXxG0k5M4ETv+08= -github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= -github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M= -github.com/libp2p/go-maddr-filter v0.1.0 h1:4ACqZKw8AqiuJfwFGq1CYDFugfXTOos+qQ3DETkhtCE= -github.com/libp2p/go-maddr-filter v0.1.0/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= -github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= -github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= -github.com/libp2p/go-mplex v0.1.1/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= -github.com/libp2p/go-mplex v0.1.2/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= -github.com/libp2p/go-mplex v0.2.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= -github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= -github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= -github.com/libp2p/go-msgio v0.0.3/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= -github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= -github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA= -github.com/libp2p/go-msgio v0.1.0/go.mod h1:eNlv2vy9V2X/kNldcZ+SShFE++o2Yjxwx6RAYsmgJnE= -github.com/libp2p/go-msgio v0.2.0 h1:W6shmB+FeynDrUVl2dgFQvzfBZcXiyqY4VmpQLu9FqU= -github.com/libp2p/go-msgio v0.2.0/go.mod h1:dBVM1gW3Jk9XqHkU4eKdGvVHdLa51hoGfll6jMJMSlY= -github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI= -github.com/libp2p/go-nat v0.0.4/go.mod h1:Nmw50VAvKuk38jUBcmNh6p9lUJLoODbJRvYAa/+KSDo= -github.com/libp2p/go-nat v0.0.5/go.mod h1:B7NxsVNPZmRLvMOwiEO1scOSyjA56zxYAGv1yQgRkEU= -github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= -github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM= -github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= -github.com/libp2p/go-netroute v0.1.3/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= -github.com/libp2p/go-netroute v0.1.5/go.mod h1:V1SR3AaECRkEQCoFFzYwVYWvYIEtlxx89+O3qcpCl4A= -github.com/libp2p/go-netroute v0.1.6/go.mod h1:AqhkMh0VuWmfgtxKPp3Oc1LdU5QSWS7wl0QLhSZqXxQ= -github.com/libp2p/go-netroute v0.2.0 h1:0FpsbsvuSnAhXFnCY0VLFbJOzaK0VnP0r1QT/o4nWRE= -github.com/libp2p/go-netroute v0.2.0/go.mod h1:Vio7LTzZ+6hoT4CMZi5/6CpY3Snzh2vgZhWgxMNwlQI= -github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= -github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= -github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= -github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= -github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= -github.com/libp2p/go-openssl v0.1.0 h1:LBkKEcUv6vtZIQLVTegAil8jbNpJErQ9AnT+bWV+Ooo= -github.com/libp2p/go-openssl v0.1.0/go.mod h1:OiOxwPpL3n4xlenjx2h7AwSGaFSC/KZvf6gNdOBQMtc= -github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= -github.com/libp2p/go-reuseport v0.0.2/go.mod h1:SPD+5RwGC7rcnzngoYC86GjPzjSywuQyMVAheVBD9nQ= -github.com/libp2p/go-reuseport v0.1.0/go.mod h1:bQVn9hmfcTaoo0c9v5pBhOarsU1eNOBZdaAd2hzXRKU= -github.com/libp2p/go-reuseport v0.2.0 h1:18PRvIMlpY6ZK85nIAicSBuXXvrYoSw3dsBAR7zc560= -github.com/libp2p/go-reuseport v0.2.0/go.mod h1:bvVho6eLMm6Bz5hmU0LYN3ixd3nPPvtIlaURZZgOY4k= -github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= -github.com/libp2p/go-reuseport-transport v0.0.3/go.mod h1:Spv+MPft1exxARzP2Sruj2Wb5JSyHNncjf1Oi2dEbzM= -github.com/libp2p/go-reuseport-transport v0.0.4/go.mod h1:trPa7r/7TJK/d+0hdBLOCGvpQQVOU74OXbNCIMkufGw= -github.com/libp2p/go-reuseport-transport v0.1.0/go.mod h1:vev0C0uMkzriDY59yFHD9v+ujJvYmDQVLowvAjEOmfw= -github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-sockaddr v0.1.1/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= -github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc= -github.com/libp2p/go-stream-muxer-multistream v0.3.0/go.mod h1:yDh8abSIzmZtqtOt64gFJUXEryejzNb0lisTt+fAMJA= -github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= -github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= -github.com/libp2p/go-tcp-transport v0.2.0/go.mod h1:vX2U0CnWimU4h0SGSEsg++AzvBcroCGYw28kh94oLe0= -github.com/libp2p/go-tcp-transport v0.2.3/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyPFvl1S/igQ5QD1SU= -github.com/libp2p/go-tcp-transport v0.4.0/go.mod h1:0y52Rwrn4076xdJYu/51/qJIdxz+EWDAOG2S45sV3VI= -github.com/libp2p/go-testutil v0.1.0/go.mod h1:81b2n5HypcVyrCg/MJx4Wgfp/VHojytjVe/gLzZ2Ehc= -github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo= -github.com/libp2p/go-ws-transport v0.2.0/go.mod h1:9BHJz/4Q5A9ludYWKoGCFC5gUElzlHoKzu0yY9p/klM= -github.com/libp2p/go-ws-transport v0.3.0/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= -github.com/libp2p/go-ws-transport v0.3.1/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= -github.com/libp2p/go-ws-transport v0.4.0/go.mod h1:EcIEKqf/7GDjth6ksuS/6p7R49V4CBY6/E7R/iyhYUA= -github.com/libp2p/go-ws-transport v0.5.0/go.mod h1:I2juo1dNTbl8BKSBYo98XY85kU2xds1iamArLvl8kNg= -github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.3.0/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= -github.com/libp2p/go-yamux v1.4.0/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= -github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= -github.com/libp2p/go-yamux/v2 v2.2.0/go.mod h1:3So6P6TV6r75R9jiBpiIKgU/66lOarCZjqROGxzPpPQ= -github.com/libp2p/go-yamux/v2 v2.3.0/go.mod h1:iTU+lOIn/2h0AgKcL49clNTwfEw+WSfDYrXe05EyKIs= -github.com/libp2p/go-yamux/v3 v3.1.2 h1:lNEy28MBk1HavUAlzKgShp+F6mn/ea1nDYWftZhFW9Q= -github.com/libp2p/go-yamux/v3 v3.1.2/go.mod h1:jeLEQgLXqE2YqX1ilAClIfCMDY+0uXQUKmmb/qp0gT4= -github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lucas-clemente/quic-go v0.16.0/go.mod h1:I0+fcNTdb9eS1ZcjQZbDVPGchJ86chcIxPALn9lEJqE= -github.com/lucas-clemente/quic-go v0.19.3/go.mod h1:ADXpNbTQjq1hIzCpB+y/k5iz4n4z4IwqoLb94Kh5Hu8= -github.com/lucas-clemente/quic-go v0.23.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= -github.com/lucas-clemente/quic-go v0.24.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= -github.com/lucas-clemente/quic-go v0.28.1 h1:Uo0lvVxWg5la9gflIF9lwa39ONq85Xq2D91YNEIslzU= -github.com/lucas-clemente/quic-go v0.28.1/go.mod h1:oGz5DKK41cJt5+773+BSO9BXDsREY4HLf7+0odGAPO0= -github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac= -github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/lufia/iostat v1.1.0/go.mod h1:rEPNA0xXgjHQjuI5Cy05sLlS2oRcSlWHRLrvh/AQ+Pg= -github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magefile/mage v1.9.0 h1:t3AU2wNwehMCW97vuqQLtw6puppWXHO+O2MHo5a50XE= -github.com/magefile/mage v1.9.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= -github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= -github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= -github.com/marten-seemann/qtls v0.9.1/go.mod h1:T1MmAdDPyISzxlK6kjRr0pcZFBVd1OZbBb/j3cvzHhk= -github.com/marten-seemann/qtls v0.10.0/go.mod h1:UvMd1oaYDACI99/oZUYLzMCkBXQVT0aGm99sJhbT8hs= -github.com/marten-seemann/qtls-go1-15 v0.1.1/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= -github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= -github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= -github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ= -github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= -github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= -github.com/marten-seemann/qtls-go1-17 v0.1.2 h1:JADBlm0LYiVbuSySCHeY863dNkcpMmDR7s0bLKJeYlQ= -github.com/marten-seemann/qtls-go1-17 v0.1.2/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s= -github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM= -github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= -github.com/marten-seemann/qtls-go1-19 v0.1.0-beta.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI= -github.com/marten-seemann/qtls-go1-19 v0.1.0 h1:rLFKD/9mp/uq1SYGYuVZhm83wkmU95pK5df3GufyYYU= -github.com/marten-seemann/qtls-go1-19 v0.1.0/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= -github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= -github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= -github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= -github.com/mattn/go-xmlrpc v0.0.3/go.mod h1:mqc2dz7tP5x5BKlCahN/n+hs7OSZKJkS9JsHNBRlrxA= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc= -github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= -github.com/mdlayher/netlink v0.0.0-20190828143259-340058475d09/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= -github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= -github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY= -github.com/mdlayher/wifi v0.0.0-20190303161829-b1436901ddee/go.mod h1:Evt/EIne46u9PtQbeTx2NTcqURpr5K4SvKtGmBuDPN8= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.22/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= -github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= -github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= -github.com/mileusna/useragent v0.0.0-20190129205925-3e331f0949a5/go.mod h1:JWhYAp2EXqUtsxTKdeGlY8Wp44M7VxThC9FEoNGi2IE= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.2.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= -github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= -github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= -github.com/multiformats/go-base32 v0.0.4 h1:+qMh4a2f37b4xTNs6mqitDinryCI+tfO2dRVMN9mjSE= -github.com/multiformats/go-base32 v0.0.4/go.mod h1:jNLFzjPZtp3aIARHbJRZIaPuspdH0J6q39uUM5pnABM= -github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= -github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= -github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= -github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y= -github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= -github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= -github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= -github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc= -github.com/multiformats/go-multiaddr v0.6.0 h1:qMnoOPj2s8xxPU5kZ57Cqdr0hHhARz7mFsPMIiYNqzg= -github.com/multiformats/go-multiaddr v0.6.0/go.mod h1:F4IpaKZuPP360tOMn2Tpyu0At8w23aRyVqeK0DbFeGM= -github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= -github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= -github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= -github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= -github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= -github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= -github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= -github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= -github.com/multiformats/go-multiaddr-net v0.1.1/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= -github.com/multiformats/go-multiaddr-net v0.1.2/go.mod h1:QsWt3XK/3hwvNxZJp92iMQKME1qHfpYmyIjFVsSOY6Y= -github.com/multiformats/go-multiaddr-net v0.1.3/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= -github.com/multiformats/go-multiaddr-net v0.1.4/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= -github.com/multiformats/go-multiaddr-net v0.1.5/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= -github.com/multiformats/go-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= -github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= -github.com/multiformats/go-multibase v0.0.2/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= -github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= -github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI= -github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8= -github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= -github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= -github.com/multiformats/go-multicodec v0.3.1-0.20211210143421-a526f306ed2c/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= -github.com/multiformats/go-multicodec v0.5.0 h1:EgU6cBe/D7WRwQb1KmnBvU7lrcFGMggZVTPtOW9dDHs= -github.com/multiformats/go-multicodec v0.5.0/go.mod h1:DiY2HFaEp5EhEXb/iYzVAunmyX/aSFMxq2KMKfWEues= -github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= -github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= -github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.0.9/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= -github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= -github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= -github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84= -github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= -github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= -github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= -github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= -github.com/multiformats/go-multistream v0.2.1/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= -github.com/multiformats/go-multistream v0.2.2/go.mod h1:UIcnm7Zuo8HKG+HkWgfQsGL+/MIEhyTqbODbIUwSXKs= -github.com/multiformats/go-multistream v0.3.3 h1:d5PZpjwRgVlbwfdTDjife7XszfZd8KYWfROYFlGcR8o= -github.com/multiformats/go-multistream v0.3.3/go.mod h1:ODRoqamLUsETKS9BNcII4gcRsJBU5VAwRIv7O39cEXg= -github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= -github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nikkolasg/hexjson v0.0.0-20181101101858-78e39397e00c h1:5bFTChQxSKNwy8ALwOebjekYExl9HTT9urdawqC95tA= -github.com/nikkolasg/hexjson v0.0.0-20181101101858-78e39397e00c/go.mod h1:7qN3Y0BvzRUf4LofcoJplQL10lsFDb4PYlePTVwrP28= -github.com/nkovacs/streamquote v1.0.0 h1:PmVIV08Zlx2lZK5fFZlMZ04eHcDTIFJCv/5/0twVUow= -github.com/nkovacs/streamquote v1.0.0/go.mod h1:BN+NaZ2CmdKqUuTUXUEm9j95B2TRbpOWpxbJYzzgUsc= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= -github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opentracing-contrib/go-grpc v0.0.0-20180928155321-4b5a12d3ff02/go.mod h1:JNdpVEzCpXBgIiv4ds+TzhN1hrtxq6ClLrTlT9OQRSc= -github.com/opentracing-contrib/go-grpc v0.0.0-20191001143057-db30781987df h1:vdYtBU6zvL7v+Tr+0xFM/qhahw/EvY8DMMunZHKH6eE= -github.com/opentracing-contrib/go-grpc v0.0.0-20191001143057-db30781987df/go.mod h1:DYR5Eij8rJl8h7gblRrOZ8g0kW1umSpKqYIBTgeDtLo= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing-contrib/go-stdlib v0.0.0-20190519235532-cf7a6c988dc9/go.mod h1:PLldrQSroqzH70Xl+1DQcGnefIbqsKR7UDaiux3zV+w= -github.com/opentracing-contrib/go-stdlib v1.0.0 h1:TBS7YuVotp8myLon4Pv7BtCBzOTo1DeZCld0Z63mW2w= -github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk= -github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= -github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= -github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= -github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= -github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= -github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e h1:ZOcivgkkFRnjfoTcGsDq3UQYiBmekwLA+qg0OjyB/ls= -github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/alertmanager v0.20.0/go.mod h1:9g2i48FAyZW6BtbsnvHtMHQXl2aVtrORKwKVCQ+nbrg= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= -github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/node_exporter v1.0.0-rc.0.0.20200428091818-01054558c289/go.mod h1:FGbBv5OPKjch+jNUJmEQpMZytIdyW0NdBtWFcfSKusc= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190425082905-87a4384529e0/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/prometheus v0.0.0-20200609090129-a6600f564e3c/go.mod h1:S5n0C6tSgdnwWshBUceRx5G1OsjLv/EeZ9t3wIfEtsY= -github.com/prometheus/statsd_exporter v0.21.0 h1:hA05Q5RFeIjgwKIYEdFd59xu5Wwaznf33yKI+pyX6T8= -github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= -github.com/raulk/clock v1.1.0 h1:dpb29+UKMbLqiU/jqIJptgLR1nn23HLgMY0sTCDza5Y= -github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0= -github.com/raulk/go-watchdog v1.2.0/go.mod h1:lzSbAl5sh4rtI8tYHU01BWIDzgzqaQLj6RcA1i4mlqI= -github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= -github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= -github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= -github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= -github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= -github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/satori/go.uuid v0.0.0-20160603004225-b111a074d5ef/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= -github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= -github.com/sercand/kuberesolver v2.1.0+incompatible/go.mod h1:lWF3GL0xptCB/vCiJPl/ZshwPsX/n4Y7u0CW9E7aQIQ= -github.com/sercand/kuberesolver v2.4.0+incompatible h1:WE2OlRf6wjLxHwNkkFLQGaZcVLEXjMjBPjjEU5vksH8= -github.com/sercand/kuberesolver v2.4.0+incompatible/go.mod h1:lWF3GL0xptCB/vCiJPl/ZshwPsX/n4Y7u0CW9E7aQIQ= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM= -github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= -github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= -github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= -github.com/siebenmann/go-kstat v0.0.0-20160321171754-d34789b79745/go.mod h1:G81aIFAMS9ECrwBYR9YxhlPjWgrItd+Kje78O6+uqm8= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= -github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= -github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= -github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= -github.com/snowflakedb/gosnowflake v1.6.1/go.mod h1:1kyg2XEduwti88V11PKRHImhXLK5WpGiayY6lFNYb98= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a/go.mod h1:LeFCbQYJ3KJlPs/FvPz2dy1tkpxyeNESVyCNNzRXFR0= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/testground/sdk-go v0.2.6 h1:sMwv0/caNNODKfdPigNqmSSIZLcse7pZX6fgrjCGBIs= -github.com/testground/sdk-go v0.2.6/go.mod h1:Q4dnWsUBH+dZ1u7aEGDBHWGUaLfhitjUq3UJQqxeTmk= -github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/uber-go/tally v3.3.15+incompatible/go.mod h1:YDTIBxdXyOU/sCWilKB4bgyufu1cEi0jdVnRdxvjnmU= -github.com/uber/athenadriver v1.1.4/go.mod h1:tQjho4NzXw55LGfSZEcETuYydpY1vtmixUabHkC1K/E= -github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-client-go v2.23.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-client-go v2.23.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-client-go v2.28.0+incompatible h1:G4QSBfvPKvg5ZM2j9MrJFdfI5iSljY/WnJqOGFao6HI= -github.com/uber/jaeger-client-go v2.28.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-lib v1.5.1-0.20181102163054-1fc5c315e03c/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= -github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -github.com/urfave/cli/v2 v2.8.1 h1:CGuYNZF9IKZY/rfBe3lJpccSoIY1ytfvmgQT90cNOl4= -github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= -github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= -github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= -github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0= -github.com/warpfork/go-testmark v0.10.0 h1:E86YlUMYfwIacEsQGlnTvjk1IgYkyTGjPhF0RnwTCmw= -github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= -github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= -github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w= -github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= -github.com/weaveworks/common v0.0.0-20200512154658-384f10054ec5 h1:EYxr08r8x6r/5fLEAMMkida1BVgxVXE4LfZv/XV+znU= -github.com/weaveworks/common v0.0.0-20200512154658-384f10054ec5/go.mod h1:c98fKi5B9u8OsKGiWHLRKus6ToQ1Tubeow44ECO1uxY= -github.com/weaveworks/promrus v1.2.0 h1:jOLf6pe6/vss4qGHjXmGz4oDJQA+AOCqEL3FvvZGz7M= -github.com/weaveworks/promrus v1.2.0/go.mod h1:SaE82+OJ91yqjrE1rsvBWVzNZKcHYFtMUyS1+Ogs/KA= -github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba h1:X4n8JG2e2biEZZXdBKt9HX7DN3bYGFUqljqqy0DqgnY= -github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba/go.mod h1:CHQnYnQUEPydYCwuy8lmTHfGmdw9TKrhWV0xLx8l0oM= -github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0= -github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20191216205031-b047b6acb3c0/go.mod h1:xdlJQaiqipF0HW+Mzpg7XRM3fWbGvfgFlcppuvlkIvY= -github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= -github.com/whyrusleeping/cbor-gen v0.0.0-20200414195334-429a0b5e922e/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= -github.com/whyrusleeping/cbor-gen v0.0.0-20200504204219-64967432584d/go.mod h1:W5MvapuoHRP8rz4vxjwCK1pDqF1aQcWsV5PZ+AHbqdg= -github.com/whyrusleeping/cbor-gen v0.0.0-20200710004633-5379fc63235d/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20200715143311-227fab5a2377/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20200723185710-6a3894a6352b/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20200806213330-63aa96ca5488/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20200810223238-211df3b9e24c/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20200812213548-958ddffe352c/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20220323183124-98fa8256a799/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20220514204315-f29c37e9c44c h1:6VPKXBDRt7mDUyiHx9X8ROnPYFDf3L7OfEuKCI5dZDI= -github.com/whyrusleeping/cbor-gen v0.0.0-20220514204315-f29c37e9c44c/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= -github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= -github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= -github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= -github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= -github.com/whyrusleeping/go-logging v0.0.1/go.mod h1:lDPYj54zutzG1XYfHAhcc7oNXEburHQBn+Iqd4yS4vE= -github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8= -github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 h1:NwiwjQDB3CzQ5XH0rdMh1oQqzJH7O2PSLWxif/w3zsY= -github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4/go.mod h1:K+EVq8d5QcQ2At5VECsA+SNZvWefyBXh8TnIsxo1OvQ= -github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= -github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= -github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= -github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= -github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= -github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= -github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= -github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= -github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= -github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= -github.com/xorcare/golden v0.6.0/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ= -github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZDpfMfWg7xk29yEOZiXmo/wZl+utTI8= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= -github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.12.1 h1:hYRcyznPRJp+5mzF2sazTLP2nGvGjYDD2VzhHhFomLU= -github.com/zondax/ledger-go v0.12.1/go.mod h1:KatxXrVDzgWwbssUWsF5+cOJHXPvzQ09YSlzGNuhOEo= -go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= -go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= -go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= -go.dedis.ch/kyber/v3 v3.0.9 h1:i0ZbOQocHUjfFasBiUql5zVeC7u/vahFd96DFA8UOWk= -go.dedis.ch/kyber/v3 v3.0.9/go.mod h1:rhNjUUg6ahf8HEg5HUvVBYoWY4boAafX8tYxX+PS+qg= -go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= -go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= -go.dedis.ch/protobuf v1.0.11 h1:FTYVIEzY/bfl37lu3pR4lIj+F9Vp1jE8oh91VmxKgLo= -go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg= -go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= -go.mongodb.org/mongo-driver v1.3.2/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= -go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I= -go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM= -go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk v1.2.0 h1:wKN260u4DesJYhyjxDa7LRFkuhH7ncEVKU37LWcyNIo= -go.opentelemetry.io/otel/sdk v1.2.0/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/otel/trace v1.2.0/go.mod h1:N5FLswTubnxKxOJHM7XZC074qpeEdLy3CgAVsdMucK0= -go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o= -go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/dig v1.12.0 h1:l1GQeZpEbss0/M4l/ZotuBndCrkMdjnygzgcuOjAdaY= -go.uber.org/dig v1.12.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= -go.uber.org/fx v1.15.0 h1:kcfBpAm98n0ksanyyZLFE/Q3T7yPi13Ge2liu3TxR+A= -go.uber.org/fx v1.15.0/go.mod h1:jI3RazQUhGv5KkpZIRv+kuP4CcgX3fnc0qX8bLnzbx8= -go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= -go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.22.0 h1:Zcye5DUgBloQ9BaT4qc9BnjOFog5TvBSAGkJ3Nf70c0= -go.uber.org/zap v1.22.0/go.mod h1:H4siCOZOrAolnUPJEkfaSjDqyP+BDS0DdDWzwcgt3+U= -go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= -go4.org v0.0.0-20200411211856-f5505b9728dd h1:BNJlw5kRTzdmyfh5U8F93HA2OwkP7ZGwA51eJ/0wKOU= -go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg= -golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180505025534-4ec37c66abab/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= -golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200422194213-44a606286825/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20210615023648-acb5c1269671/go.mod h1:DVyR6MI7P4kEQgvZJSj1fQGrWIi2RzIrfYWycwheUAc= -golang.org/x/exp v0.0.0-20210714144626-1041f73d31d8/go.mod h1:DVyR6MI7P4kEQgvZJSj1fQGrWIi2RzIrfYWycwheUAc= -golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 h1:rxKZ2gOnYxjfmakvUUqh9Gyb6KXfrj7JWTxORTYqb0E= -golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E= -golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180202135801-37707fdb30a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190524122548-abf6ff778158/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211209171907-798191bca915/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190813034749-528a2984e271/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191030062658-86caa796c7ab/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191203134012-c197fd4bf371/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200216192241-b320d3a0f5a2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304024140-c4206d458c3f/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200422205258-72e4a01eba43/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200721032237-77f530d86f9a/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= -google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200420144010-e5e8543f8aeb/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 h1:ysnBoUyeL/H6RCvNRhWHjKoDEmguI+mPU+qHgK8qv/w= -google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= -gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= -gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M= -howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= -k8s.io/api v0.17.5/go.mod h1:0zV5/ungglgy2Rlm3QK8fbxkXVs+BSJWpJP/+8gUVLY= -k8s.io/apimachinery v0.17.5/go.mod h1:ioIo1G/a+uONV7Tv+ZmCbMG1/a3kVw5YcDdncd8ugQ0= -k8s.io/client-go v0.17.5/go.mod h1:S8uZpBpjJJdEH/fEyxcqg7Rn0P5jH+ilkgBHjriSmNo= -k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/kube-openapi v0.0.0-20200316234421-82d701f24f9d/go.mod h1:F+5wygcW0wmRTnM3cOgIqGivxkwSWIWT5YdsDbeAOaU= -k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -k8s.io/utils v0.0.0-20200414100711-2df71ebbae66/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= -lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= -lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/structured-merge-diff/v2 v2.0.1/go.mod h1:Wb7vfKAodbKgf6tn1Kl0VvGj7mRH6DGaRcixXEJXTsE= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= -sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/testplans/lotus-soup/init.go b/testplans/lotus-soup/init.go deleted file mode 100644 index bd9367a61..000000000 --- a/testplans/lotus-soup/init.go +++ /dev/null @@ -1,63 +0,0 @@ -package main - -import ( - "os" - - "github.com/ipfs/go-log/v2" - - "github.com/filecoin-project/go-state-types/abi" - - "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/chain/actors/policy" -) - -func init() { - build.BlockDelaySecs = 3 - build.PropagationDelaySecs = 1 - - _ = log.SetLogLevel("*", "DEBUG") - _ = log.SetLogLevel("dht", "WARN") - _ = log.SetLogLevel("swarm2", "WARN") - _ = log.SetLogLevel("addrutil", "WARN") - _ = log.SetLogLevel("stats", "WARN") - _ = log.SetLogLevel("dht/RtRefreshManager", "ERROR") // noisy - _ = log.SetLogLevel("bitswap", "ERROR") // noisy - _ = log.SetLogLevel("badgerbs", "ERROR") // noisy - _ = log.SetLogLevel("sub", "ERROR") // noisy - _ = log.SetLogLevel("pubsub", "ERROR") // noisy - _ = log.SetLogLevel("chain", "ERROR") // noisy - _ = log.SetLogLevel("chainstore", "ERROR") // noisy - _ = log.SetLogLevel("basichost", "ERROR") // noisy - - _ = os.Setenv("BELLMAN_NO_GPU", "1") - - build.InsecurePoStValidation = true - build.DisableBuiltinAssets = true - - // MessageConfidence is the amount of tipsets we wait after a message is - // mined, e.g. payment channel creation, to be considered committed. - build.MessageConfidence = 1 - - // The duration of a deadline's challenge window, the period before a - // deadline when the challenge is available. - // - // This will auto-scale the proving period. - // policy.SetWPoStChallengeWindow(abi.ChainEpoch(5)) // commented-out until we enable PoSt faults tests - - // Number of epochs between publishing the precommit and when the challenge for interactive PoRep is drawn - // used to ensure it is not predictable by miner. - policy.SetPreCommitChallengeDelay(abi.ChainEpoch(10)) - - policy.SetConsensusMinerMinPower(abi.NewTokenAmount(2048)) - policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg8MiBV1) - - policy.SetMinVerifiedDealSize(abi.NewTokenAmount(256)) - - // Disable upgrades. - build.UpgradeSmokeHeight = -1 - build.UpgradeIgnitionHeight = -2 - build.UpgradeLiftoffHeight = -3 - // We need to _run_ this upgrade because genesis doesn't support v2, so - // we run it at height 0. - build.UpgradeAssemblyHeight = 0 -} diff --git a/testplans/lotus-soup/main.go b/testplans/lotus-soup/main.go deleted file mode 100644 index b1d17f018..000000000 --- a/testplans/lotus-soup/main.go +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "github.com/testground/sdk-go/run" - - "github.com/filecoin-project/lotus/testplans/lotus-soup/paych" - "github.com/filecoin-project/lotus/testplans/lotus-soup/rfwp" - "github.com/filecoin-project/lotus/testplans/lotus-soup/testkit" -) - -var cases = map[string]interface{}{ - "deals-e2e": testkit.WrapTestEnvironment(dealsE2E), - "recovery-failed-windowed-post": testkit.WrapTestEnvironment(rfwp.RecoveryFromFailedWindowedPoStE2E), - "deals-stress": testkit.WrapTestEnvironment(dealsStress), - "drand-halting": testkit.WrapTestEnvironment(dealsE2E), - "drand-outage": testkit.WrapTestEnvironment(dealsE2E), - "paych-stress": testkit.WrapTestEnvironment(paych.Stress), -} - -func main() { - sanityCheck() - - run.InvokeMap(cases) -} diff --git a/testplans/lotus-soup/manifest.toml b/testplans/lotus-soup/manifest.toml deleted file mode 100644 index 9f5a57444..000000000 --- a/testplans/lotus-soup/manifest.toml +++ /dev/null @@ -1,218 +0,0 @@ -name = "lotus-soup" - -[defaults] -builder = "docker:go" -runner = "local:docker" - -[builders."exec:go"] -enabled = true - -[builders."docker:go"] -enabled = true -build_base_image = "iptestground/oni-buildbase:v15-lotus" -runtime_image = "iptestground/oni-runtime:v10-debug" - -[runners."local:exec"] -enabled = true - -[runners."local:docker"] -enabled = true - -[runners."cluster:k8s"] -enabled = true - -###################### -## -## Testcases -## -###################### - -[[testcases]] -name = "deals-e2e" -instances = { min = 1, max = 100, default = 5 } - - [testcases.params] - clients = { type = "int", default = 1 } - miners = { type = "int", default = 1 } - balance = { type = "float", default = 1 } - sectors = { type = "int", default = 1 } - role = { type = "string" } - - genesis_timestamp_offset = { type = "int", default = 0 } - - random_beacon_type = { type = "enum", default = "mock", options = ["mock", "local-drand", "external-drand"] } - - # Params relevant to drand nodes. drand nodes should have role="drand", and must all be - # in the same composition group. There must be at least threshold drand nodes. - # To get lotus nodes to actually use the drand nodes, you must set random_beacon_type="local-drand" - # for the lotus node groups. - drand_period = { type = "duration", default="10s" } - drand_threshold = { type = "int", default = 2 } - drand_gossip_relay = { type = "bool", default = true } - drand_log_level = { type = "string", default="info" } - - # Params relevant to pubsub tracing - enable_pubsub_tracer = { type = "bool", default = false } - mining_mode = { type = "enum", default = "synchronized", options = ["synchronized", "natural"] } - - # Fast retrieval - fast_retrieval = { type = "bool", default = false } - - # Bounce connection during push and pull data transfers - bounce_conn_data_transfers = { type = "bool", default = false } - - -[[testcases]] -name = "drand-halting" -instances = { min = 1, max = 100, default = 5 } - - [testcases.params] - clients = { type = "int", default = 1 } - miners = { type = "int", default = 1 } - balance = { type = "float", default = 1 } - sectors = { type = "int", default = 1 } - role = { type = "string" } - genesis_timestamp_offset = { type = "int", default = 0 } - - - random_beacon_type = { type = "enum", default = "local-drand", options = ["mock", "local-drand", "external-drand"] } - - # Params relevant to drand nodes. drand nodes should have role="drand", and must all be - # in the same composition group. There must be at least threshold drand nodes. - # To get lotus nodes to actually use the drand nodes, you must set random_beacon_type="local-drand" - # for the lotus node groups. - drand_period = { type = "duration", default="10s" } - drand_threshold = { type = "int", default = 2 } - drand_gossip_relay = { type = "bool", default = true } - drand_log_level = { type = "string", default="info" } - suspend_events = { type = "string", default="", desc = "a sequence of halt/resume/wait events separated by '->'" } - - # Params relevant to pubsub tracing - enable_pubsub_tracer = { type = "bool", default = false } # Mining Mode: synchronized -vs- natural time - mining_mode = { type = "enum", default = "synchronized", options = ["synchronized", "natural"] } - - -[[testcases]] -name = "drand-outage" -instances = { min = 1, max = 100, default = 5 } - - [testcases.params] - clients = { type = "int", default = 0 } - miners = { type = "int", default = 3 } - balance = { type = "float", default = 1 } - sectors = { type = "int", default = 1 } - role = { type = "string" } - genesis_timestamp_offset = { type = "int", default = 0 } - - - random_beacon_type = { type = "enum", default = "local-drand", options = ["mock", "local-drand", "external-drand"] } - - # Params relevant to drand nodes. drand nodes should have role="drand", and must all be - # in the same composition group. There must be at least threshold drand nodes. - # To get lotus nodes to actually use the drand nodes, you must set random_beacon_type="local-drand" - # for the lotus node groups. - drand_period = { type = "duration", default="30s" } - drand_catchup_period = { type = "duration", default="10s" } - drand_threshold = { type = "int", default = 2 } - drand_gossip_relay = { type = "bool", default = true } - drand_log_level = { type = "string", default="info" } - suspend_events = { type = "string", default="", desc = "a sequence of halt/resume/wait events separated by '->'" } - - # Params relevant to pubsub tracing - enable_pubsub_tracer = { type = "bool", default = false } # Mining Mode: synchronized -vs- natural time - mining_mode = { type = "enum", default = "synchronized", options = ["synchronized", "natural"] } - - -[[testcases]] -name = "deals-stress" -instances = { min = 1, max = 100, default = 5 } - - [testcases.params] - clients = { type = "int", default = 1 } - miners = { type = "int", default = 1 } - balance = { type = "float", default = 1 } - sectors = { type = "int", default = 1 } - role = { type = "string" } - - genesis_timestamp_offset = { type = "int", default = 0 } - - random_beacon_type = { type = "enum", default = "mock", options = ["mock", "local-drand", "external-drand"] } - - # Params relevant to drand nodes. drand nodes should have role="drand", and must all be - # in the same composition group. There must be at least threshold drand nodes. - # To get lotus nodes to actually use the drand nodes, you must set random_beacon_type="local-drand" - # for the lotus node groups. - drand_period = { type = "duration", default="10s" } - drand_threshold = { type = "int", default = 2 } - drand_gossip_relay = { type = "bool", default = true } - - # Params relevant to pubsub tracing - enable_pubsub_tracer = { type = "bool", default = false } - - # Mining Mode: synchronized -vs- natural time - mining_mode = { type = "enum", default = "synchronized", options = ["synchronized", "natural"] } - - deals = { type = "int", default = 1 } - deal_mode = { type = "enum", default = "serial", options = ["serial", "concurrent"] } - - -[[testcases]] -name = "paych-stress" -instances = { min = 1, max = 100, default = 5 } - - [testcases.params] - clients = { type = "int", default = 1 } - miners = { type = "int", default = 1 } - balance = { type = "float", default = 1 } - sectors = { type = "int", default = 1 } - role = { type = "string" } - genesis_timestamp_offset = { type = "int", default = 0 } - - random_beacon_type = { type = "enum", default = "local-drand", options = ["mock", "local-drand", "external-drand"] } - - # Params relevant to drand nodes. drand nodes should have role="drand", and must all be - # in the same composition group. There must be at least threshold drand nodes. - # To get lotus nodes to actually use the drand nodes, you must set random_beacon_type="local-drand" - # for the lotus node groups. - drand_period = { type = "duration", default="10s" } - drand_threshold = { type = "int", default = 2 } - drand_gossip_relay = { type = "bool", default = true } - drand_log_level = { type = "string", default="info" } - suspend_events = { type = "string", default="", desc = "a sequence of halt/resume/wait events separated by '->'" } - - # Params relevant to pubsub tracing - enable_pubsub_tracer = { type = "bool", default = false } # Mining Mode: synchronized -vs- natural time - mining_mode = { type = "enum", default = "synchronized", options = ["synchronized", "natural"] } - - # ********** Test-case specific ********** - increments = { type = "int", default = "100", desc = "increments in which to send payment vouchers" } - lane_count = { type = "int", default = "256", desc = "lanes to open; vouchers will be distributed across these lanes in round-robin fashion" } - - -[[testcases]] -name = "recovery-failed-windowed-post" -instances = { min = 1, max = 100, default = 5 } - - [testcases.params] - clients = { type = "int", default = 1 } - miners = { type = "int", default = 1 } - balance = { type = "int", default = 1 } - sectors = { type = "int", default = 1 } - role = { type = "string" } - - genesis_timestamp_offset = { type = "int", default = 0 } - - random_beacon_type = { type = "enum", default = "mock", options = ["mock", "local-drand", "external-drand"] } - - # Params relevant to drand nodes. drand nodes should have role="drand", and must all be - # in the same composition group. There must be at least threshold drand nodes. - # To get lotus nodes to actually use the drand nodes, you must set random_beacon_type="local-drand" - # for the lotus node groups. - drand_period = { type = "duration", default="10s" } - drand_threshold = { type = "int", default = 2 } - drand_gossip_relay = { type = "bool", default = true } - drand_log_level = { type = "string", default="info" } - - # Params relevant to pubsub tracing - enable_pubsub_tracer = { type = "bool", default = false } - mining_mode = { type = "enum", default = "synchronized", options = ["synchronized", "natural"] } diff --git a/testplans/lotus-soup/paych/README.md b/testplans/lotus-soup/paych/README.md deleted file mode 100644 index dbd5879ed..000000000 --- a/testplans/lotus-soup/paych/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Payment channels end-to-end tests - -This package contains the following test cases, each of which is described -further below. - -- Payment channels stress test case (`stress.go`). - -## Payment channels stress test case (`stress.go`) - -***WIP | blocked due to https://github.com/filecoin-project/lotus/issues/2297*** - -This test case turns all clients into payment receivers and senders. -The first member to start in the group becomes the _receiver_. -All other members become _senders_. - -The _senders_ will open a single payment channel to the _receiver_, and will -wait for the message to be posted on-chain. We are setting -`build.MessageConfidence=1`, in order to accelerate the test. So we'll only wait -for a single tipset confirmation once we witness the message. - -Once the message is posted, we load the payment channel actor address and create -as many lanes as the `lane_count` test parameter dictates. - -When then fetch our total balance, and start sending it on the payment channel, -round-robinning across all lanes, until our balance is extinguished. - -**TODO:** - -- [ ] Assertions, metrics, etc. Actually gather statistics. Right now this is - just a smoke test, and it fails. -- [ ] Implement the _receiver_ logic. -- [ ] Model test lifetime by signalling end. \ No newline at end of file diff --git a/testplans/lotus-soup/paych/stress.go b/testplans/lotus-soup/paych/stress.go deleted file mode 100644 index 36862ac7e..000000000 --- a/testplans/lotus-soup/paych/stress.go +++ /dev/null @@ -1,316 +0,0 @@ -package paych - -import ( - "context" - "fmt" - "os" - "time" - - "github.com/ipfs/go-cid" - "github.com/testground/sdk-go/sync" - - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/big" - "github.com/filecoin-project/go-state-types/builtin/v8/paych" - - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/testplans/lotus-soup/testkit" -) - -var SendersDoneState = sync.State("senders-done") -var ReceiverReadyState = sync.State("receiver-ready") -var ReceiverAddedVouchersState = sync.State("receiver-added-vouchers") - -var VoucherTopic = sync.NewTopic("voucher", &paych.SignedVoucher{}) -var SettleTopic = sync.NewTopic("settle", cid.Cid{}) - -type ClientMode uint64 - -const ( - ModeSender ClientMode = iota - ModeReceiver -) - -func (cm ClientMode) String() string { - return [...]string{"Sender", "Receiver"}[cm] -} - -func getClientMode(groupSeq int64) ClientMode { - if groupSeq == 1 { - return ModeReceiver - } - return ModeSender -} - -// TODO Stress is currently WIP. We found blockers in Lotus that prevent us from -// -// making progress. See https://github.com/filecoin-project/lotus/issues/2297. -func Stress(t *testkit.TestEnvironment) error { - // Dispatch/forward non-client roles to defaults. - if t.Role != "client" { - return testkit.HandleDefaultRole(t) - } - - // This is a client role. - t.RecordMessage("running payments client") - - ctx := context.Background() - cl, err := testkit.PrepareClient(t) - if err != nil { - return err - } - - // are we the receiver or a sender? - mode := getClientMode(t.GroupSeq) - t.RecordMessage("acting as %s", mode) - - var clients []*testkit.ClientAddressesMsg - sctx, cancel := context.WithCancel(ctx) - clientsCh := make(chan *testkit.ClientAddressesMsg) - t.SyncClient.MustSubscribe(sctx, testkit.ClientsAddrsTopic, clientsCh) - for i := 0; i < t.TestGroupInstanceCount; i++ { - clients = append(clients, <-clientsCh) - } - cancel() - - switch mode { - case ModeReceiver: - err := runReceiver(t, ctx, cl) - if err != nil { - return err - } - - case ModeSender: - err := runSender(ctx, t, clients, cl) - if err != nil { - return err - } - } - - // Signal that the client is done - t.SyncClient.MustSignalEntry(ctx, testkit.StateDone) - - // Signal to the miners to stop mining - t.SyncClient.MustSignalEntry(ctx, testkit.StateStopMining) - - return nil -} - -func runSender(ctx context.Context, t *testkit.TestEnvironment, clients []*testkit.ClientAddressesMsg, cl *testkit.LotusClient) error { - var ( - // lanes to open; vouchers will be distributed across these lanes in round-robin fashion - laneCount = t.IntParam("lane_count") - // number of vouchers to send on each lane - vouchersPerLane = t.IntParam("vouchers_per_lane") - // increments in which to send payment vouchers - increments = big.Mul(big.NewInt(int64(t.IntParam("increments"))), big.NewInt(int64(build.FilecoinPrecision))) - // channel amount should be enough to cover all vouchers - channelAmt = big.Mul(big.NewInt(int64(laneCount*vouchersPerLane)), increments) - ) - - // Lock up funds in the payment channel. - recv := findReceiver(clients) - balance, err := cl.FullApi.WalletBalance(ctx, cl.Wallet.Address) - if err != nil { - return fmt.Errorf("failed to acquire wallet balance: %w", err) - } - - t.RecordMessage("my balance: %d", balance) - t.RecordMessage("creating payment channel; from=%s, to=%s, funds=%d", cl.Wallet.Address, recv.WalletAddr, channelAmt) - - pid := os.Getpid() - t.RecordMessage("sender pid: %d", pid) - - time.Sleep(20 * time.Second) - - channel, err := cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, channelAmt, api.PaychGetOpts{ - OffChain: false, - }) - if err != nil { - return fmt.Errorf("failed to create payment channel: %w", err) - } - - if addr := channel.Channel; addr != address.Undef { - return fmt.Errorf("expected an Undef channel address, got: %s", addr) - } - - t.RecordMessage("payment channel created; msg_cid=%s", channel.WaitSentinel) - t.RecordMessage("waiting for payment channel message to appear on chain") - - // wait for the channel creation message to appear on chain. - _, err = cl.FullApi.StateWaitMsg(ctx, channel.WaitSentinel, 2, api.LookbackNoLimit, true) - if err != nil { - return fmt.Errorf("failed while waiting for payment channel creation msg to appear on chain: %w", err) - } - - // need to wait so that the channel is tracked. - // the full API waits for build.MessageConfidence (=1 in tests) before tracking the channel. - // we wait for 2 confirmations, so we have the assurance the channel is tracked. - - t.RecordMessage("get payment channel address") - channelAddr, err := cl.FullApi.PaychGetWaitReady(ctx, channel.WaitSentinel) - if err != nil { - return fmt.Errorf("failed to get payment channel address: %w", err) - } - - t.RecordMessage("channel address: %s", channelAddr) - t.RecordMessage("allocating lanes; count=%d", laneCount) - - // allocate as many lanes as required - var lanes []uint64 - for i := 0; i < laneCount; i++ { - lane, err := cl.FullApi.PaychAllocateLane(ctx, channelAddr) - if err != nil { - return fmt.Errorf("failed to allocate lane: %w", err) - } - lanes = append(lanes, lane) - } - - t.RecordMessage("lanes allocated; count=%d", laneCount) - - <-t.SyncClient.MustBarrier(ctx, ReceiverReadyState, 1).C - - t.RecordMessage("sending payments in round-robin fashion across lanes; increments=%d", increments) - - // create vouchers - remaining := channelAmt - for i := 0; i < vouchersPerLane; i++ { - for _, lane := range lanes { - voucherAmt := big.Mul(big.NewInt(int64(i+1)), increments) - voucher, err := cl.FullApi.PaychVoucherCreate(ctx, channelAddr, voucherAmt, lane) - if err != nil { - return fmt.Errorf("failed to create voucher: %w", err) - } - t.RecordMessage("payment voucher created; lane=%d, nonce=%d, amount=%d", voucher.Voucher.Lane, voucher.Voucher.Nonce, voucher.Voucher.Amount) - - _, err = t.SyncClient.Publish(ctx, VoucherTopic, voucher.Voucher) - if err != nil { - return fmt.Errorf("failed to publish voucher: %w", err) - } - - remaining = big.Sub(remaining, increments) - t.RecordMessage("remaining balance: %d", remaining) - } - } - - t.RecordMessage("finished sending all payment vouchers") - - // Inform the receiver that all vouchers have been created - t.SyncClient.MustSignalEntry(ctx, SendersDoneState) - - // Wait for the receiver to add all vouchers - <-t.SyncClient.MustBarrier(ctx, ReceiverAddedVouchersState, 1).C - - t.RecordMessage("settle channel") - - // Settle the channel. When the receiver sees the settle message, they - // should automatically submit all vouchers. - settleMsgCid, err := cl.FullApi.PaychSettle(ctx, channelAddr) - if err != nil { - return fmt.Errorf("failed to settle payment channel: %w", err) - } - - _, err = t.SyncClient.Publish(ctx, SettleTopic, settleMsgCid) - if err != nil { - return fmt.Errorf("failed to publish settle message cid: %w", err) - } - - return nil -} - -func findReceiver(clients []*testkit.ClientAddressesMsg) *testkit.ClientAddressesMsg { - for _, c := range clients { - if getClientMode(c.GroupSeq) == ModeReceiver { - return c - } - } - return nil -} - -func runReceiver(t *testkit.TestEnvironment, ctx context.Context, cl *testkit.LotusClient) error { - // lanes to open; vouchers will be distributed across these lanes in round-robin fashion - laneCount := t.IntParam("lane_count") - // number of vouchers to send on each lane - vouchersPerLane := t.IntParam("vouchers_per_lane") - totalVouchers := laneCount * vouchersPerLane - - vouchers := make(chan *paych.SignedVoucher) - vouchersSub, err := t.SyncClient.Subscribe(ctx, VoucherTopic, vouchers) - if err != nil { - return fmt.Errorf("failed to subscribe to voucher topic: %w", err) - } - - settleMsgChan := make(chan cid.Cid) - settleSub, err := t.SyncClient.Subscribe(ctx, SettleTopic, settleMsgChan) - if err != nil { - return fmt.Errorf("failed to subscribe to settle topic: %w", err) - } - - // inform the clients that the receiver is ready for incoming vouchers - t.SyncClient.MustSignalEntry(ctx, ReceiverReadyState) - - t.RecordMessage("adding %d payment vouchers", totalVouchers) - - // Add each of the vouchers - var addedVouchers []*paych.SignedVoucher - for i := 0; i < totalVouchers; i++ { - v := <-vouchers - addedVouchers = append(addedVouchers, v) - - _, err := cl.FullApi.PaychVoucherAdd(ctx, v.ChannelAddr, v, nil, big.NewInt(0)) - if err != nil { - return fmt.Errorf("failed to add voucher: %w", err) - } - spendable, err := cl.FullApi.PaychVoucherCheckSpendable(ctx, v.ChannelAddr, v, nil, nil) - if err != nil { - return fmt.Errorf("failed to check voucher spendable: %w", err) - } - if !spendable { - return fmt.Errorf("expected voucher %d to be spendable", i) - } - - t.RecordMessage("payment voucher added; lane=%d, nonce=%d, amount=%d", v.Lane, v.Nonce, v.Amount) - } - - vouchersSub.Done() - - t.RecordMessage("finished adding all payment vouchers") - - // Inform the clients that the receiver has added all vouchers - t.SyncClient.MustSignalEntry(ctx, ReceiverAddedVouchersState) - - // Wait for the settle message (put on chain by the sender) - t.RecordMessage("waiting for client to put settle message on chain") - settleMsgCid := <-settleMsgChan - settleSub.Done() - - time.Sleep(5 * time.Second) - - t.RecordMessage("waiting for confirmation of settle message on chain: %s", settleMsgCid) - _, err = cl.FullApi.StateWaitMsg(ctx, settleMsgCid, 10, api.LookbackNoLimit, true) - if err != nil { - return fmt.Errorf("failed to wait for settle message: %w", err) - } - - // Note: Once the receiver sees the settle message on chain, it will - // automatically call submit voucher with the best vouchers - - // TODO: Uncomment this section once this PR is merged: - // https://github.com/filecoin-project/lotus/pull/3197 - //t.RecordMessage("checking that all %d vouchers are no longer spendable", len(addedVouchers)) - //for i, v := range addedVouchers { - // spendable, err := cl.FullApi.PaychVoucherCheckSpendable(ctx, v.ChannelAddr, v, nil, nil) - // if err != nil { - // return fmt.Errorf("failed to check voucher spendable: %w", err) - // } - // // Should no longer be spendable because the best voucher has been submitted - // if spendable { - // return fmt.Errorf("expected voucher %d to no longer be spendable", i) - // } - //} - - t.RecordMessage("all vouchers were submitted successfully") - - return nil -} diff --git a/testplans/lotus-soup/rfwp/chain_state.go b/testplans/lotus-soup/rfwp/chain_state.go deleted file mode 100644 index 96ad91743..000000000 --- a/testplans/lotus-soup/rfwp/chain_state.go +++ /dev/null @@ -1,837 +0,0 @@ -package rfwp - -import ( - "bufio" - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "math" - corebig "math/big" - "os" - "sort" - "text/tabwriter" - "time" - - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/big" - - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/api/v0api" - "github.com/filecoin-project/lotus/blockstore" - "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/chain/actors/builtin" - "github.com/filecoin-project/lotus/chain/actors/builtin/miner" - "github.com/filecoin-project/lotus/chain/store" - "github.com/filecoin-project/lotus/chain/types" - sealing "github.com/filecoin-project/lotus/storage/pipeline" - "github.com/filecoin-project/lotus/testplans/lotus-soup/testkit" - tsync "github.com/filecoin-project/lotus/tools/stats/sync" -) - -func UpdateChainState(t *testkit.TestEnvironment, m *testkit.LotusMiner) error { - height := 0 - headlag := 3 - - ctx := context.Background() - - tipsetsCh, err := tsync.BufferedTipsetChannel(ctx, &v0api.WrapperV1Full{FullNode: m.FullApi}, abi.ChainEpoch(height), headlag) - if err != nil { - return err - } - - jsonFilename := fmt.Sprintf("%s%cchain-state.ndjson", t.TestOutputsPath, os.PathSeparator) - jsonFile, err := os.Create(jsonFilename) - if err != nil { - return err - } - defer jsonFile.Close() - jsonEncoder := json.NewEncoder(jsonFile) - - for tipset := range tipsetsCh { - maddrs, err := m.FullApi.StateListMiners(ctx, tipset.Key()) - if err != nil { - return err - } - - snapshot := ChainSnapshot{ - Height: tipset.Height(), - MinerStates: make(map[string]*MinerStateSnapshot), - } - - err = func() error { - cs.Lock() - defer cs.Unlock() - - for _, maddr := range maddrs { - err := func() error { - filename := fmt.Sprintf("%s%cstate-%s-%d", t.TestOutputsPath, os.PathSeparator, maddr, tipset.Height()) - - f, err := os.Create(filename) - if err != nil { - return err - } - defer f.Close() - - w := bufio.NewWriter(f) - defer w.Flush() - - minerInfo, err := info(t, m, maddr, w, tipset.Height()) - if err != nil { - return err - } - writeText(w, minerInfo) - - if tipset.Height()%100 == 0 { - printDiff(t, minerInfo, tipset.Height()) - } - - faultState, err := provingFaults(t, m, maddr, tipset.Height()) - if err != nil { - return err - } - writeText(w, faultState) - - provState, err := provingInfo(t, m, maddr, tipset.Height()) - if err != nil { - return err - } - writeText(w, provState) - - // record diff - recordDiff(minerInfo, provState, tipset.Height()) - - deadlines, err := provingDeadlines(t, m, maddr, tipset.Height()) - if err != nil { - return err - } - writeText(w, deadlines) - - sectorInfo, err := sectorsList(t, m, maddr, w, tipset.Height()) - if err != nil { - return err - } - writeText(w, sectorInfo) - - snapshot.MinerStates[maddr.String()] = &MinerStateSnapshot{ - Info: minerInfo, - Faults: faultState, - ProvingInfo: provState, - Deadlines: deadlines, - Sectors: sectorInfo, - } - - return jsonEncoder.Encode(snapshot) - }() - if err != nil { - return err - } - } - - cs.PrevHeight = tipset.Height() - - return nil - }() - if err != nil { - return err - } - } - - return nil -} - -type ChainSnapshot struct { - Height abi.ChainEpoch - - MinerStates map[string]*MinerStateSnapshot -} - -type MinerStateSnapshot struct { - Info *MinerInfo - Faults *ProvingFaultState - ProvingInfo *ProvingInfoState - Deadlines *ProvingDeadlines - Sectors *SectorInfo -} - -// writeText marshals m to text and writes to w, swallowing any errors along the way. -func writeText(w io.Writer, m plainTextMarshaler) { - b, err := m.MarshalPlainText() - if err != nil { - return - } - _, _ = w.Write(b) -} - -// if we make our structs `encoding.TextMarshaler`s, they all get stringified when marshaling to JSON -// instead of just using the default struct marshaler. -// so here's encoding.TextMarshaler with a different name, so that doesn't happen. -type plainTextMarshaler interface { - MarshalPlainText() ([]byte, error) -} - -type ProvingFaultState struct { - // FaultedSectors is a slice per-deadline faulty sectors. If the miner - // has no faulty sectors, this will be nil. - FaultedSectors [][]uint64 -} - -func (s *ProvingFaultState) MarshalPlainText() ([]byte, error) { - w := &bytes.Buffer{} - - if len(s.FaultedSectors) == 0 { - fmt.Fprintf(w, "no faulty sectors\n") - return w.Bytes(), nil - } - - tw := tabwriter.NewWriter(w, 2, 4, 2, ' ', 0) - _, _ = fmt.Fprintf(tw, "deadline\tsectors") - for deadline, sectors := range s.FaultedSectors { - for _, num := range sectors { - _, _ = fmt.Fprintf(tw, "%d\t%d\n", deadline, num) - } - } - - return w.Bytes(), nil -} - -func provingFaults(t *testkit.TestEnvironment, m *testkit.LotusMiner, maddr address.Address, height abi.ChainEpoch) (*ProvingFaultState, error) { - api := m.FullApi - ctx := context.Background() - - head, err := api.ChainHead(ctx) - if err != nil { - return nil, err - } - deadlines, err := api.StateMinerDeadlines(ctx, maddr, head.Key()) - if err != nil { - return nil, err - } - faultedSectors := make([][]uint64, len(deadlines)) - hasFaults := false - for dlIdx := range deadlines { - partitions, err := api.StateMinerPartitions(ctx, maddr, uint64(dlIdx), types.EmptyTSK) - if err != nil { - return nil, err - } - - for _, partition := range partitions { - faulty, err := partition.FaultySectors.All(10000000) - if err != nil { - return nil, err - } - - if len(faulty) > 0 { - hasFaults = true - } - - faultedSectors[dlIdx] = append(faultedSectors[dlIdx], faulty...) - } - } - result := new(ProvingFaultState) - if hasFaults { - result.FaultedSectors = faultedSectors - } - - return result, nil -} - -type ProvingInfoState struct { - CurrentEpoch abi.ChainEpoch - - ProvingPeriodStart abi.ChainEpoch - - Faults uint64 - ProvenSectors uint64 - FaultPercent float64 - Recoveries uint64 - - DeadlineIndex uint64 - DeadlineSectors uint64 - DeadlineOpen abi.ChainEpoch - DeadlineClose abi.ChainEpoch - DeadlineChallenge abi.ChainEpoch - DeadlineFaultCutoff abi.ChainEpoch - - WPoStProvingPeriod abi.ChainEpoch -} - -func (s *ProvingInfoState) MarshalPlainText() ([]byte, error) { - w := &bytes.Buffer{} - fmt.Fprintf(w, "Current Epoch: %d\n", s.CurrentEpoch) - fmt.Fprintf(w, "Chain Period: %d\n", s.CurrentEpoch/s.WPoStProvingPeriod) - fmt.Fprintf(w, "Chain Period Start: %s\n", epochTime(s.CurrentEpoch, (s.CurrentEpoch/s.WPoStProvingPeriod)*s.WPoStProvingPeriod)) - fmt.Fprintf(w, "Chain Period End: %s\n\n", epochTime(s.CurrentEpoch, (s.CurrentEpoch/s.WPoStProvingPeriod+1)*s.WPoStProvingPeriod)) - - fmt.Fprintf(w, "Proving Period Boundary: %d\n", s.ProvingPeriodStart%s.WPoStProvingPeriod) - fmt.Fprintf(w, "Proving Period Start: %s\n", epochTime(s.CurrentEpoch, s.ProvingPeriodStart)) - fmt.Fprintf(w, "Next Period Start: %s\n\n", epochTime(s.CurrentEpoch, s.ProvingPeriodStart+s.WPoStProvingPeriod)) - - fmt.Fprintf(w, "Faults: %d (%.2f%%)\n", s.Faults, s.FaultPercent) - fmt.Fprintf(w, "Recovering: %d\n", s.Recoveries) - //fmt.Fprintf(w, "New Sectors: %d\n\n", s.NewSectors) - - fmt.Fprintf(w, "Deadline Index: %d\n", s.DeadlineIndex) - fmt.Fprintf(w, "Deadline Sectors: %d\n", s.DeadlineSectors) - - fmt.Fprintf(w, "Deadline Open: %s\n", epochTime(s.CurrentEpoch, s.DeadlineOpen)) - fmt.Fprintf(w, "Deadline Close: %s\n", epochTime(s.CurrentEpoch, s.DeadlineClose)) - fmt.Fprintf(w, "Deadline Challenge: %s\n", epochTime(s.CurrentEpoch, s.DeadlineChallenge)) - fmt.Fprintf(w, "Deadline FaultCutoff: %s\n", epochTime(s.CurrentEpoch, s.DeadlineFaultCutoff)) - - return w.Bytes(), nil -} - -func provingInfo(t *testkit.TestEnvironment, m *testkit.LotusMiner, maddr address.Address, height abi.ChainEpoch) (*ProvingInfoState, error) { - lapi := m.FullApi - ctx := context.Background() - - head, err := lapi.ChainHead(ctx) - if err != nil { - return nil, err - } - - cd, err := lapi.StateMinerProvingDeadline(ctx, maddr, head.Key()) - if err != nil { - return nil, err - } - - deadlines, err := lapi.StateMinerDeadlines(ctx, maddr, head.Key()) - if err != nil { - return nil, err - } - - parts := map[uint64][]api.Partition{} - for dlIdx := range deadlines { - part, err := lapi.StateMinerPartitions(ctx, maddr, uint64(dlIdx), types.EmptyTSK) - if err != nil { - return nil, err - } - - parts[uint64(dlIdx)] = part - } - - proving := uint64(0) - faults := uint64(0) - recovering := uint64(0) - - for _, partitions := range parts { - for _, partition := range partitions { - sc, err := partition.LiveSectors.Count() - if err != nil { - return nil, err - } - proving += sc - - fc, err := partition.FaultySectors.Count() - if err != nil { - return nil, err - } - faults += fc - - rc, err := partition.RecoveringSectors.Count() - if err != nil { - return nil, err - } - recovering += rc - } - } - - var faultPerc float64 - if proving > 0 { - faultPerc = float64(faults*10000/proving) / 100 - } - - s := ProvingInfoState{ - CurrentEpoch: cd.CurrentEpoch, - ProvingPeriodStart: cd.PeriodStart, - Faults: faults, - ProvenSectors: proving, - FaultPercent: faultPerc, - Recoveries: recovering, - DeadlineIndex: cd.Index, - DeadlineOpen: cd.Open, - DeadlineClose: cd.Close, - DeadlineChallenge: cd.Challenge, - DeadlineFaultCutoff: cd.FaultCutoff, - WPoStProvingPeriod: cd.WPoStProvingPeriod, - } - - if cd.Index < cd.WPoStPeriodDeadlines { - for _, partition := range parts[cd.Index] { - sc, err := partition.LiveSectors.Count() - if err != nil { - return nil, err - } - s.DeadlineSectors += sc - } - } - - return &s, nil -} - -func epochTime(curr, e abi.ChainEpoch) string { - switch { - case curr > e: - return fmt.Sprintf("%d (%s ago)", e, time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(curr-e))) - case curr == e: - return fmt.Sprintf("%d (now)", e) - case curr < e: - return fmt.Sprintf("%d (in %s)", e, time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(e-curr))) - } - - panic("math broke") -} - -type ProvingDeadlines struct { - Deadlines []DeadlineInfo -} - -type DeadlineInfo struct { - Sectors uint64 - Partitions int - Proven uint64 - Current bool -} - -func (d *ProvingDeadlines) MarshalPlainText() ([]byte, error) { - w := new(bytes.Buffer) - tw := tabwriter.NewWriter(w, 2, 4, 2, ' ', 0) - _, _ = fmt.Fprintln(tw, "deadline\tsectors\tpartitions\tproven") - - for i, di := range d.Deadlines { - var cur string - if di.Current { - cur += "\t(current)" - } - _, _ = fmt.Fprintf(tw, "%d\t%d\t%d\t%d%s\n", i, di.Sectors, di.Partitions, di.Proven, cur) - } - tw.Flush() - return w.Bytes(), nil -} - -func provingDeadlines(t *testkit.TestEnvironment, m *testkit.LotusMiner, maddr address.Address, height abi.ChainEpoch) (*ProvingDeadlines, error) { - lapi := m.FullApi - ctx := context.Background() - - deadlines, err := lapi.StateMinerDeadlines(ctx, maddr, types.EmptyTSK) - if err != nil { - return nil, err - } - - di, err := lapi.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK) - if err != nil { - return nil, err - } - - infos := make([]DeadlineInfo, 0, len(deadlines)) - for dlIdx, deadline := range deadlines { - partitions, err := lapi.StateMinerPartitions(ctx, maddr, uint64(dlIdx), types.EmptyTSK) - if err != nil { - return nil, err - } - - provenPartitions, err := deadline.PostSubmissions.Count() - if err != nil { - return nil, err - } - - var cur string - if di.Index == uint64(dlIdx) { - cur += "\t(current)" - } - - outInfo := DeadlineInfo{ - //Sectors: c, - Partitions: len(partitions), - Proven: provenPartitions, - Current: di.Index == uint64(dlIdx), - } - infos = append(infos, outInfo) - //_, _ = fmt.Fprintf(tw, "%d\t%d\t%d%s\n", dlIdx, len(partitions), provenPartitions, cur) - } - - return &ProvingDeadlines{Deadlines: infos}, nil -} - -type SectorInfo struct { - Sectors []abi.SectorNumber - SectorStates map[abi.SectorNumber]api.SectorInfo - Committed []abi.SectorNumber - Proving []abi.SectorNumber -} - -func (i *SectorInfo) MarshalPlainText() ([]byte, error) { - provingIDs := make(map[abi.SectorNumber]struct{}, len(i.Proving)) - for _, id := range i.Proving { - provingIDs[id] = struct{}{} - } - commitedIDs := make(map[abi.SectorNumber]struct{}, len(i.Committed)) - for _, id := range i.Committed { - commitedIDs[id] = struct{}{} - } - - w := new(bytes.Buffer) - tw := tabwriter.NewWriter(w, 8, 4, 1, ' ', 0) - - for _, s := range i.Sectors { - _, inSSet := commitedIDs[s] - _, inPSet := provingIDs[s] - - st, ok := i.SectorStates[s] - if !ok { - continue - } - - fmt.Fprintf(tw, "%d: %s\tsSet: %s\tpSet: %s\ttktH: %d\tseedH: %d\tdeals: %v\n", - s, - st.State, - yesno(inSSet), - yesno(inPSet), - st.Ticket.Epoch, - st.Seed.Epoch, - st.Deals, - ) - } - - if err := tw.Flush(); err != nil { - return nil, err - } - return w.Bytes(), nil -} - -func sectorsList(t *testkit.TestEnvironment, m *testkit.LotusMiner, maddr address.Address, w io.Writer, height abi.ChainEpoch) (*SectorInfo, error) { - node := m.FullApi - ctx := context.Background() - - list, err := m.MinerApi.SectorsList(ctx) - if err != nil { - return nil, err - } - - activeSet, err := node.StateMinerActiveSectors(ctx, maddr, types.EmptyTSK) - if err != nil { - return nil, err - } - activeIDs := make(map[abi.SectorNumber]struct{}, len(activeSet)) - for _, info := range activeSet { - activeIDs[info.SectorNumber] = struct{}{} - } - - sset, err := node.StateMinerSectors(ctx, maddr, nil, types.EmptyTSK) - if err != nil { - return nil, err - } - commitedIDs := make(map[abi.SectorNumber]struct{}, len(activeSet)) - for _, info := range sset { - commitedIDs[info.SectorNumber] = struct{}{} - } - - sort.Slice(list, func(i, j int) bool { - return list[i] < list[j] - }) - - i := SectorInfo{Sectors: list, SectorStates: make(map[abi.SectorNumber]api.SectorInfo, len(list))} - - for _, s := range list { - st, err := m.MinerApi.SectorsStatus(ctx, s, true) - if err != nil { - fmt.Fprintf(w, "%d:\tError: %s\n", s, err) - continue - } - i.SectorStates[s] = st - } - return &i, nil -} - -func yesno(b bool) string { - if b { - return "YES" - } - return "NO" -} - -type MinerInfo struct { - MinerAddr address.Address - SectorSize string - - MinerPower *api.MinerPower - - CommittedBytes big.Int - ProvingBytes big.Int - FaultyBytes big.Int - FaultyPercentage float64 - - Balance big.Int - PreCommitDeposits big.Int - LockedFunds big.Int - AvailableFunds big.Int - WorkerBalance big.Int - MarketEscrow big.Int - MarketLocked big.Int - - SectorStateCounts map[sealing.SectorState]int -} - -func (i *MinerInfo) MarshalPlainText() ([]byte, error) { - w := new(bytes.Buffer) - fmt.Fprintf(w, "Miner: %s\n", i.MinerAddr) - fmt.Fprintf(w, "Sector Size: %s\n", i.SectorSize) - - pow := i.MinerPower - - fmt.Fprintf(w, "Byte Power: %s / %s (%0.4f%%)\n", - types.SizeStr(pow.MinerPower.RawBytePower), - types.SizeStr(pow.TotalPower.RawBytePower), - types.BigDivFloat( - types.BigMul(pow.MinerPower.RawBytePower, big.NewInt(100)), - pow.TotalPower.RawBytePower, - ), - ) - - fmt.Fprintf(w, "Actual Power: %s / %s (%0.4f%%)\n", - types.DeciStr(pow.MinerPower.QualityAdjPower), - types.DeciStr(pow.TotalPower.QualityAdjPower), - types.BigDivFloat( - types.BigMul(pow.MinerPower.QualityAdjPower, big.NewInt(100)), - pow.TotalPower.QualityAdjPower, - ), - ) - - fmt.Fprintf(w, "\tCommitted: %s\n", types.SizeStr(i.CommittedBytes)) - - if i.FaultyBytes.Int == nil || i.FaultyBytes.IsZero() { - fmt.Fprintf(w, "\tProving: %s\n", types.SizeStr(i.ProvingBytes)) - } else { - fmt.Fprintf(w, "\tProving: %s (%s Faulty, %.2f%%)\n", - types.SizeStr(i.ProvingBytes), - types.SizeStr(i.FaultyBytes), - i.FaultyPercentage) - } - - if !i.MinerPower.HasMinPower { - fmt.Fprintf(w, "Below minimum power threshold, no blocks will be won\n") - } else { - - winRatio := new(corebig.Rat).SetFrac( - types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(build.BlocksPerEpoch)).Int, - pow.TotalPower.QualityAdjPower.Int, - ) - - if winRatioFloat, _ := winRatio.Float64(); winRatioFloat > 0 { - - // if the corresponding poisson distribution isn't infinitely small then - // throw it into the mix as well, accounting for multi-wins - winRationWithPoissonFloat := -math.Expm1(-winRatioFloat) - winRationWithPoisson := new(corebig.Rat).SetFloat64(winRationWithPoissonFloat) - if winRationWithPoisson != nil { - winRatio = winRationWithPoisson - winRatioFloat = winRationWithPoissonFloat - } - - weekly, _ := new(corebig.Rat).Mul( - winRatio, - new(corebig.Rat).SetInt64(7*builtin.EpochsInDay), - ).Float64() - - avgDuration, _ := new(corebig.Rat).Mul( - new(corebig.Rat).SetInt64(builtin.EpochDurationSeconds), - new(corebig.Rat).Inv(winRatio), - ).Float64() - - fmt.Fprintf(w, "Projected average block win rate: %.02f/week (every %s)\n", - weekly, - (time.Second * time.Duration(avgDuration)).Truncate(time.Second).String(), - ) - - // Geometric distribution of P(Y < k) calculated as described in https://en.wikipedia.org/wiki/Geometric_distribution#Probability_Outcomes_Examples - // https://www.wolframalpha.com/input/?i=t+%3E+0%3B+p+%3E+0%3B+p+%3C+1%3B+c+%3E+0%3B+c+%3C1%3B+1-%281-p%29%5E%28t%29%3Dc%3B+solve+t - // t == how many dice-rolls (epochs) before win - // p == winRate == ( minerPower / netPower ) - // c == target probability of win ( 99.9% in this case ) - fmt.Fprintf(w, "Projected block win with 99.9%% probability every %s\n", - (time.Second * time.Duration( - builtin.EpochDurationSeconds*math.Log(1-0.999)/ - math.Log(1-winRatioFloat), - )).Truncate(time.Second).String(), - ) - fmt.Fprintln(w, "(projections DO NOT account for future network and miner growth)") - } - } - - fmt.Fprintf(w, "Miner Balance: %s\n", types.FIL(i.Balance)) - fmt.Fprintf(w, "\tPreCommit: %s\n", types.FIL(i.PreCommitDeposits)) - fmt.Fprintf(w, "\tLocked: %s\n", types.FIL(i.LockedFunds)) - fmt.Fprintf(w, "\tAvailable: %s\n", types.FIL(i.AvailableFunds)) - fmt.Fprintf(w, "Worker Balance: %s\n", types.FIL(i.WorkerBalance)) - fmt.Fprintf(w, "Market (Escrow): %s\n", types.FIL(i.MarketEscrow)) - fmt.Fprintf(w, "Market (Locked): %s\n\n", types.FIL(i.MarketLocked)) - - buckets := i.SectorStateCounts - - var sorted []stateMeta - for state, i := range buckets { - sorted = append(sorted, stateMeta{i: i, state: state}) - } - - sort.Slice(sorted, func(i, j int) bool { - return stateOrder[sorted[i].state].i < stateOrder[sorted[j].state].i - }) - - for _, s := range sorted { - _, _ = fmt.Fprintf(w, "\t%s: %d\n", s.state, s.i) - } - - return w.Bytes(), nil -} - -func info(t *testkit.TestEnvironment, m *testkit.LotusMiner, maddr address.Address, w io.Writer, height abi.ChainEpoch) (*MinerInfo, error) { - api := m.FullApi - ctx := context.Background() - - ts, err := api.ChainHead(ctx) - if err != nil { - return nil, err - } - - mact, err := api.StateGetActor(ctx, maddr, ts.Key()) - if err != nil { - return nil, err - } - - i := MinerInfo{MinerAddr: maddr} - - // Sector size - mi, err := api.StateMinerInfo(ctx, maddr, ts.Key()) - if err != nil { - return nil, err - } - - i.SectorSize = types.SizeStr(types.NewInt(uint64(mi.SectorSize))) - - i.MinerPower, err = api.StateMinerPower(ctx, maddr, ts.Key()) - if err != nil { - return nil, err - } - - secCounts, err := api.StateMinerSectorCount(ctx, maddr, ts.Key()) - if err != nil { - return nil, err - } - faults, err := api.StateMinerFaults(ctx, maddr, ts.Key()) - if err != nil { - return nil, err - } - - nfaults, err := faults.Count() - if err != nil { - return nil, err - } - - i.CommittedBytes = types.BigMul(types.NewInt(secCounts.Live), types.NewInt(uint64(mi.SectorSize))) - i.ProvingBytes = types.BigMul(types.NewInt(secCounts.Active), types.NewInt(uint64(mi.SectorSize))) - - if nfaults != 0 { - if secCounts.Live != 0 { - i.FaultyPercentage = float64(10000*nfaults/secCounts.Live) / 100. - } - i.FaultyBytes = types.BigMul(types.NewInt(nfaults), types.NewInt(uint64(mi.SectorSize))) - } - - stor := store.ActorStore(ctx, blockstore.NewAPIBlockstore(api)) - mas, err := miner.Load(stor, mact) - if err != nil { - return nil, err - } - - funds, err := mas.LockedFunds() - if err != nil { - return nil, err - } - - i.Balance = mact.Balance - i.PreCommitDeposits = funds.PreCommitDeposits - i.LockedFunds = funds.VestingFunds - i.AvailableFunds, err = mas.AvailableBalance(mact.Balance) - if err != nil { - return nil, err - } - - wb, err := api.WalletBalance(ctx, mi.Worker) - if err != nil { - return nil, err - } - i.WorkerBalance = wb - - mb, err := api.StateMarketBalance(ctx, maddr, types.EmptyTSK) - if err != nil { - return nil, err - } - i.MarketEscrow = mb.Escrow - i.MarketLocked = mb.Locked - - sectors, err := m.MinerApi.SectorsList(ctx) - if err != nil { - return nil, err - } - - buckets := map[sealing.SectorState]int{ - "Total": len(sectors), - } - for _, s := range sectors { - st, err := m.MinerApi.SectorsStatus(ctx, s, true) - if err != nil { - return nil, err - } - - buckets[sealing.SectorState(st.State)]++ - } - i.SectorStateCounts = buckets - - return &i, nil -} - -type stateMeta struct { - i int - state sealing.SectorState -} - -var stateOrder = map[sealing.SectorState]stateMeta{} -var stateList = []stateMeta{ - {state: "Total"}, - {state: sealing.Proving}, - - {state: sealing.UndefinedSectorState}, - {state: sealing.Empty}, - {state: sealing.Packing}, - {state: sealing.PreCommit1}, - {state: sealing.PreCommit2}, - {state: sealing.PreCommitting}, - {state: sealing.PreCommitWait}, - {state: sealing.WaitSeed}, - {state: sealing.Committing}, - {state: sealing.CommitWait}, - {state: sealing.FinalizeSector}, - - {state: sealing.FailedUnrecoverable}, - {state: sealing.SealPreCommit1Failed}, - {state: sealing.SealPreCommit2Failed}, - {state: sealing.PreCommitFailed}, - {state: sealing.ComputeProofFailed}, - {state: sealing.CommitFailed}, - {state: sealing.PackingFailed}, - {state: sealing.FinalizeFailed}, - {state: sealing.Faulty}, - {state: sealing.FaultReported}, - {state: sealing.FaultedFinal}, -} - -func init() { - for i, state := range stateList { - stateOrder[state.state] = stateMeta{ - i: i, - } - } -} diff --git a/testplans/lotus-soup/rfwp/diffs.go b/testplans/lotus-soup/rfwp/diffs.go deleted file mode 100644 index fed1148e8..000000000 --- a/testplans/lotus-soup/rfwp/diffs.go +++ /dev/null @@ -1,296 +0,0 @@ -package rfwp - -import ( - "bufio" - "fmt" - "os" - "sort" - "sync" - - "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/big" - - "github.com/filecoin-project/lotus/testplans/lotus-soup/testkit" -) - -type ChainState struct { - sync.Mutex - - PrevHeight abi.ChainEpoch - DiffHeight map[string]map[string]map[abi.ChainEpoch]big.Int // height -> value - DiffValue map[string]map[string]map[string][]abi.ChainEpoch // value -> []height - DiffCmp map[string]map[string]map[string][]abi.ChainEpoch // difference (height, height-1) -> []height - valueTypes []string -} - -func NewChainState() *ChainState { - cs := &ChainState{} - cs.PrevHeight = abi.ChainEpoch(-1) - cs.DiffHeight = make(map[string]map[string]map[abi.ChainEpoch]big.Int) // height -> value - cs.DiffValue = make(map[string]map[string]map[string][]abi.ChainEpoch) // value -> []height - cs.DiffCmp = make(map[string]map[string]map[string][]abi.ChainEpoch) // difference (height, height-1) -> []height - cs.valueTypes = []string{"MinerPower", "CommittedBytes", "ProvingBytes", "Balance", "PreCommitDeposits", "LockedFunds", "AvailableFunds", "WorkerBalance", "MarketEscrow", "MarketLocked", "Faults", "ProvenSectors", "Recoveries"} - return cs -} - -var ( - cs *ChainState -) - -func init() { - cs = NewChainState() -} - -func printDiff(t *testkit.TestEnvironment, mi *MinerInfo, height abi.ChainEpoch) { - maddr := mi.MinerAddr.String() - filename := fmt.Sprintf("%s%cdiff-%s-%d", t.TestOutputsPath, os.PathSeparator, maddr, height) - - f, err := os.Create(filename) - if err != nil { - panic(err) - } - defer f.Close() - - w := bufio.NewWriter(f) - defer w.Flush() - - keys := make([]string, 0, len(cs.DiffCmp[maddr])) - for k := range cs.DiffCmp[maddr] { - keys = append(keys, k) - } - sort.Strings(keys) - - fmt.Fprintln(w, "=====", maddr, "=====") - for i, valueName := range keys { - fmt.Fprintln(w, toCharStr(i), "=====", valueName, "=====") - if len(cs.DiffCmp[maddr][valueName]) > 0 { - fmt.Fprintf(w, "%s diff of |\n", toCharStr(i)) - } - - for difference, heights := range cs.DiffCmp[maddr][valueName] { - fmt.Fprintf(w, "%s diff of %30v at heights %v\n", toCharStr(i), difference, heights) - } - } -} - -func recordDiff(mi *MinerInfo, ps *ProvingInfoState, height abi.ChainEpoch) { - maddr := mi.MinerAddr.String() - if _, ok := cs.DiffHeight[maddr]; !ok { - cs.DiffHeight[maddr] = make(map[string]map[abi.ChainEpoch]big.Int) - cs.DiffValue[maddr] = make(map[string]map[string][]abi.ChainEpoch) - cs.DiffCmp[maddr] = make(map[string]map[string][]abi.ChainEpoch) - - for _, v := range cs.valueTypes { - cs.DiffHeight[maddr][v] = make(map[abi.ChainEpoch]big.Int) - cs.DiffValue[maddr][v] = make(map[string][]abi.ChainEpoch) - cs.DiffCmp[maddr][v] = make(map[string][]abi.ChainEpoch) - } - } - - { - value := big.Int(mi.MinerPower.MinerPower.RawBytePower) - cs.DiffHeight[maddr]["MinerPower"][height] = value - cs.DiffValue[maddr]["MinerPower"][value.String()] = append(cs.DiffValue[maddr]["MinerPower"][value.String()], height) - - if cs.PrevHeight != -1 { - prevValue := cs.DiffHeight[maddr]["MinerPower"][cs.PrevHeight] - cmp := big.Zero() - cmp.Sub(value.Int, prevValue.Int) // value - prevValue - if big.Cmp(cmp, big.Zero()) != 0 { - cs.DiffCmp[maddr]["MinerPower"][cmp.String()] = append(cs.DiffCmp[maddr]["MinerPower"][cmp.String()], height) - } - } - } - - { - value := big.Int(mi.CommittedBytes) - cs.DiffHeight[maddr]["CommittedBytes"][height] = value - cs.DiffValue[maddr]["CommittedBytes"][value.String()] = append(cs.DiffValue[maddr]["CommittedBytes"][value.String()], height) - - if cs.PrevHeight != -1 { - prevValue := cs.DiffHeight[maddr]["CommittedBytes"][cs.PrevHeight] - cmp := big.Zero() - cmp.Sub(value.Int, prevValue.Int) // value - prevValue - if big.Cmp(cmp, big.Zero()) != 0 { - cs.DiffCmp[maddr]["CommittedBytes"][cmp.String()] = append(cs.DiffCmp[maddr]["CommittedBytes"][cmp.String()], height) - } - } - } - - { - value := big.Int(mi.ProvingBytes) - cs.DiffHeight[maddr]["ProvingBytes"][height] = value - cs.DiffValue[maddr]["ProvingBytes"][value.String()] = append(cs.DiffValue[maddr]["ProvingBytes"][value.String()], height) - - if cs.PrevHeight != -1 { - prevValue := cs.DiffHeight[maddr]["ProvingBytes"][cs.PrevHeight] - cmp := big.Zero() - cmp.Sub(value.Int, prevValue.Int) // value - prevValue - if big.Cmp(cmp, big.Zero()) != 0 { - cs.DiffCmp[maddr]["ProvingBytes"][cmp.String()] = append(cs.DiffCmp[maddr]["ProvingBytes"][cmp.String()], height) - } - } - } - - { - value := big.Int(mi.Balance) - roundBalance(&value) - cs.DiffHeight[maddr]["Balance"][height] = value - cs.DiffValue[maddr]["Balance"][value.String()] = append(cs.DiffValue[maddr]["Balance"][value.String()], height) - - if cs.PrevHeight != -1 { - prevValue := cs.DiffHeight[maddr]["Balance"][cs.PrevHeight] - cmp := big.Zero() - cmp.Sub(value.Int, prevValue.Int) // value - prevValue - if big.Cmp(cmp, big.Zero()) != 0 { - cs.DiffCmp[maddr]["Balance"][cmp.String()] = append(cs.DiffCmp[maddr]["Balance"][cmp.String()], height) - } - } - } - - { - value := big.Int(mi.PreCommitDeposits) - cs.DiffHeight[maddr]["PreCommitDeposits"][height] = value - cs.DiffValue[maddr]["PreCommitDeposits"][value.String()] = append(cs.DiffValue[maddr]["PreCommitDeposits"][value.String()], height) - - if cs.PrevHeight != -1 { - prevValue := cs.DiffHeight[maddr]["PreCommitDeposits"][cs.PrevHeight] - cmp := big.Zero() - cmp.Sub(value.Int, prevValue.Int) // value - prevValue - if big.Cmp(cmp, big.Zero()) != 0 { - cs.DiffCmp[maddr]["PreCommitDeposits"][cmp.String()] = append(cs.DiffCmp[maddr]["PreCommitDeposits"][cmp.String()], height) - } - } - } - - { - value := big.Int(mi.LockedFunds) - roundBalance(&value) - cs.DiffHeight[maddr]["LockedFunds"][height] = value - cs.DiffValue[maddr]["LockedFunds"][value.String()] = append(cs.DiffValue[maddr]["LockedFunds"][value.String()], height) - - if cs.PrevHeight != -1 { - prevValue := cs.DiffHeight[maddr]["LockedFunds"][cs.PrevHeight] - cmp := big.Zero() - cmp.Sub(value.Int, prevValue.Int) // value - prevValue - if big.Cmp(cmp, big.Zero()) != 0 { - cs.DiffCmp[maddr]["LockedFunds"][cmp.String()] = append(cs.DiffCmp[maddr]["LockedFunds"][cmp.String()], height) - } - } - } - - { - value := big.Int(mi.AvailableFunds) - roundBalance(&value) - cs.DiffHeight[maddr]["AvailableFunds"][height] = value - cs.DiffValue[maddr]["AvailableFunds"][value.String()] = append(cs.DiffValue[maddr]["AvailableFunds"][value.String()], height) - - if cs.PrevHeight != -1 { - prevValue := cs.DiffHeight[maddr]["AvailableFunds"][cs.PrevHeight] - cmp := big.Zero() - cmp.Sub(value.Int, prevValue.Int) // value - prevValue - if big.Cmp(cmp, big.Zero()) != 0 { - cs.DiffCmp[maddr]["AvailableFunds"][cmp.String()] = append(cs.DiffCmp[maddr]["AvailableFunds"][cmp.String()], height) - } - } - } - - { - value := big.Int(mi.WorkerBalance) - cs.DiffHeight[maddr]["WorkerBalance"][height] = value - cs.DiffValue[maddr]["WorkerBalance"][value.String()] = append(cs.DiffValue[maddr]["WorkerBalance"][value.String()], height) - - if cs.PrevHeight != -1 { - prevValue := cs.DiffHeight[maddr]["WorkerBalance"][cs.PrevHeight] - cmp := big.Zero() - cmp.Sub(value.Int, prevValue.Int) // value - prevValue - if big.Cmp(cmp, big.Zero()) != 0 { - cs.DiffCmp[maddr]["WorkerBalance"][cmp.String()] = append(cs.DiffCmp[maddr]["WorkerBalance"][cmp.String()], height) - } - } - } - - { - value := big.Int(mi.MarketEscrow) - cs.DiffHeight[maddr]["MarketEscrow"][height] = value - cs.DiffValue[maddr]["MarketEscrow"][value.String()] = append(cs.DiffValue[maddr]["MarketEscrow"][value.String()], height) - - if cs.PrevHeight != -1 { - prevValue := cs.DiffHeight[maddr]["MarketEscrow"][cs.PrevHeight] - cmp := big.Zero() - cmp.Sub(value.Int, prevValue.Int) // value - prevValue - if big.Cmp(cmp, big.Zero()) != 0 { - cs.DiffCmp[maddr]["MarketEscrow"][cmp.String()] = append(cs.DiffCmp[maddr]["MarketEscrow"][cmp.String()], height) - } - } - } - - { - value := big.Int(mi.MarketLocked) - cs.DiffHeight[maddr]["MarketLocked"][height] = value - cs.DiffValue[maddr]["MarketLocked"][value.String()] = append(cs.DiffValue[maddr]["MarketLocked"][value.String()], height) - - if cs.PrevHeight != -1 { - prevValue := cs.DiffHeight[maddr]["MarketLocked"][cs.PrevHeight] - cmp := big.Zero() - cmp.Sub(value.Int, prevValue.Int) // value - prevValue - if big.Cmp(cmp, big.Zero()) != 0 { - cs.DiffCmp[maddr]["MarketLocked"][cmp.String()] = append(cs.DiffCmp[maddr]["MarketLocked"][cmp.String()], height) - } - } - } - - { - value := big.NewInt(int64(ps.Faults)) - cs.DiffHeight[maddr]["Faults"][height] = value - cs.DiffValue[maddr]["Faults"][value.String()] = append(cs.DiffValue[maddr]["Faults"][value.String()], height) - - if cs.PrevHeight != -1 { - prevValue := cs.DiffHeight[maddr]["Faults"][cs.PrevHeight] - cmp := big.Zero() - cmp.Sub(value.Int, prevValue.Int) // value - prevValue - if big.Cmp(cmp, big.Zero()) != 0 { - cs.DiffCmp[maddr]["Faults"][cmp.String()] = append(cs.DiffCmp[maddr]["Faults"][cmp.String()], height) - } - } - } - - { - value := big.NewInt(int64(ps.ProvenSectors)) - cs.DiffHeight[maddr]["ProvenSectors"][height] = value - cs.DiffValue[maddr]["ProvenSectors"][value.String()] = append(cs.DiffValue[maddr]["ProvenSectors"][value.String()], height) - - if cs.PrevHeight != -1 { - prevValue := cs.DiffHeight[maddr]["ProvenSectors"][cs.PrevHeight] - cmp := big.Zero() - cmp.Sub(value.Int, prevValue.Int) // value - prevValue - if big.Cmp(cmp, big.Zero()) != 0 { - cs.DiffCmp[maddr]["ProvenSectors"][cmp.String()] = append(cs.DiffCmp[maddr]["ProvenSectors"][cmp.String()], height) - } - } - } - - { - value := big.NewInt(int64(ps.Recoveries)) - cs.DiffHeight[maddr]["Recoveries"][height] = value - cs.DiffValue[maddr]["Recoveries"][value.String()] = append(cs.DiffValue[maddr]["Recoveries"][value.String()], height) - - if cs.PrevHeight != -1 { - prevValue := cs.DiffHeight[maddr]["Recoveries"][cs.PrevHeight] - cmp := big.Zero() - cmp.Sub(value.Int, prevValue.Int) // value - prevValue - if big.Cmp(cmp, big.Zero()) != 0 { - cs.DiffCmp[maddr]["Recoveries"][cmp.String()] = append(cs.DiffCmp[maddr]["Recoveries"][cmp.String()], height) - } - } - } -} - -func roundBalance(i *big.Int) { - *i = big.Div(*i, big.NewInt(1000000000000000)) - *i = big.Mul(*i, big.NewInt(1000000000000000)) -} - -func toCharStr(i int) string { - return string('a' + i) -} diff --git a/testplans/lotus-soup/rfwp/e2e.go b/testplans/lotus-soup/rfwp/e2e.go deleted file mode 100644 index 29832c4f8..000000000 --- a/testplans/lotus-soup/rfwp/e2e.go +++ /dev/null @@ -1,349 +0,0 @@ -package rfwp - -import ( - "context" - "errors" - "fmt" - "io/ioutil" - "math/rand" - "os" - "sort" - "strings" - "time" - - "golang.org/x/sync/errgroup" - - "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/big" - - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/testplans/lotus-soup/testkit" -) - -func RecoveryFromFailedWindowedPoStE2E(t *testkit.TestEnvironment) error { - switch t.Role { - case "bootstrapper": - return testkit.HandleDefaultRole(t) - case "client": - return handleClient(t) - case "miner": - return handleMiner(t) - case "miner-full-slash": - return handleMinerFullSlash(t) - case "miner-partial-slash": - return handleMinerPartialSlash(t) - } - - return fmt.Errorf("unknown role: %s", t.Role) -} - -func handleMiner(t *testkit.TestEnvironment) error { - m, err := testkit.PrepareMiner(t) - if err != nil { - return err - } - - ctx := context.Background() - myActorAddr, err := m.MinerApi.ActorAddress(ctx) - if err != nil { - return err - } - - t.RecordMessage("running miner: %s", myActorAddr) - - if t.GroupSeq == 1 { - go FetchChainState(t, m) - } - - go UpdateChainState(t, m) - - minersToBeSlashed := 2 - ch := make(chan testkit.SlashedMinerMsg) - sub := t.SyncClient.MustSubscribe(ctx, testkit.SlashedMinerTopic, ch) - var eg errgroup.Group - - for i := 0; i < minersToBeSlashed; i++ { - select { - case slashedMiner := <-ch: - // wait for slash - eg.Go(func() error { - select { - case <-waitForSlash(t, slashedMiner): - case err = <-t.SyncClient.MustBarrier(ctx, testkit.StateAbortTest, 1).C: - if err != nil { - return err - } - return errors.New("got abort signal, exitting") - } - return nil - }) - case err := <-sub.Done(): - return fmt.Errorf("got error while waiting for slashed miners: %w", err) - case err := <-t.SyncClient.MustBarrier(ctx, testkit.StateAbortTest, 1).C: - if err != nil { - return err - } - return errors.New("got abort signal, exitting") - } - } - - errc := make(chan error) - go func() { - errc <- eg.Wait() - }() - - select { - case err := <-errc: - if err != nil { - return err - } - case err := <-t.SyncClient.MustBarrier(ctx, testkit.StateAbortTest, 1).C: - if err != nil { - return err - } - return errors.New("got abort signal, exitting") - } - - t.SyncClient.MustSignalAndWait(ctx, testkit.StateDone, t.TestInstanceCount) - return nil -} - -func waitForSlash(t *testkit.TestEnvironment, msg testkit.SlashedMinerMsg) chan error { - // assert that balance got reduced with that much 5 times (sector fee) - // assert that balance got reduced with that much 2 times (termination fee) - // assert that balance got increased with that much 10 times (block reward) - // assert that power got increased with that much 1 times (after sector is sealed) - // assert that power got reduced with that much 1 times (after sector is announced faulty) - slashedMiner := msg.MinerActorAddr - - errc := make(chan error) - go func() { - foundSlashConditions := false - for range time.Tick(10 * time.Second) { - if foundSlashConditions { - close(errc) - return - } - t.RecordMessage("wait for slashing, tick") - func() { - cs.Lock() - defer cs.Unlock() - - negativeAmounts := []big.Int{} - negativeDiffs := make(map[big.Int][]abi.ChainEpoch) - - for am, heights := range cs.DiffCmp[slashedMiner.String()]["LockedFunds"] { - amount, err := big.FromString(am) - if err != nil { - errc <- fmt.Errorf("cannot parse LockedFunds amount: %w:", err) - return - } - - // amount is negative => slash condition - if big.Cmp(amount, big.Zero()) < 0 { - negativeDiffs[amount] = heights - negativeAmounts = append(negativeAmounts, amount) - } - } - - t.RecordMessage("negative diffs: %d", len(negativeDiffs)) - if len(negativeDiffs) < 3 { - return - } - - sort.Slice(negativeAmounts, func(i, j int) bool { return big.Cmp(negativeAmounts[i], negativeAmounts[j]) > 0 }) - - // TODO: confirm the largest is > 18 filecoin - // TODO: confirm the next largest is > 9 filecoin - foundSlashConditions = true - }() - } - }() - - return errc -} - -func handleMinerFullSlash(t *testkit.TestEnvironment) error { - m, err := testkit.PrepareMiner(t) - if err != nil { - return err - } - - ctx := context.Background() - myActorAddr, err := m.MinerApi.ActorAddress(ctx) - if err != nil { - return err - } - - t.RecordMessage("running miner, full slash: %s", myActorAddr) - - // TODO: wait until we have sealed a deal for a client - time.Sleep(240 * time.Second) - - t.RecordMessage("shutting down miner, full slash: %s", myActorAddr) - - ctxt, cancel := context.WithTimeout(ctx, 10*time.Second) - defer cancel() - err = m.StopFn(ctxt) - if err != nil { - //return err - t.RecordMessage("err from StopFn: %s", err.Error()) // TODO: expect this to be fixed on Lotus - } - - t.RecordMessage("shutdown miner, full slash: %s", myActorAddr) - - t.SyncClient.MustPublish(ctx, testkit.SlashedMinerTopic, testkit.SlashedMinerMsg{ - MinerActorAddr: myActorAddr, - }) - - t.SyncClient.MustSignalAndWait(ctx, testkit.StateDone, t.TestInstanceCount) - return nil -} - -func handleMinerPartialSlash(t *testkit.TestEnvironment) error { - m, err := testkit.PrepareMiner(t) - if err != nil { - return err - } - - ctx := context.Background() - myActorAddr, err := m.MinerApi.ActorAddress(ctx) - if err != nil { - return err - } - - t.RecordMessage("running miner, partial slash: %s", myActorAddr) - - // TODO: wait until we have sealed a deal for a client - time.Sleep(185 * time.Second) - - t.RecordMessage("shutting down miner, partial slash: %s", myActorAddr) - - ctxt, cancel := context.WithTimeout(ctx, 10*time.Second) - defer cancel() - err = m.StopFn(ctxt) - if err != nil { - //return err - t.RecordMessage("err from StopFn: %s", err.Error()) // TODO: expect this to be fixed on Lotus - } - - t.RecordMessage("shutdown miner, partial slash: %s", myActorAddr) - - t.SyncClient.MustPublish(ctx, testkit.SlashedMinerTopic, testkit.SlashedMinerMsg{ - MinerActorAddr: myActorAddr, - }) - - time.Sleep(300 * time.Second) - - rm, err := testkit.RestoreMiner(t, m) - if err != nil { - t.RecordMessage("got err: %s", err.Error()) - return err - } - - myActorAddr, err = rm.MinerApi.ActorAddress(ctx) - if err != nil { - t.RecordMessage("got err: %s", err.Error()) - return err - } - - t.RecordMessage("running miner again, partial slash: %s", myActorAddr) - - time.Sleep(3600 * time.Second) - - //t.SyncClient.MustSignalAndWait(ctx, testkit.StateDone, t.TestInstanceCount) - return nil -} - -func handleClient(t *testkit.TestEnvironment) error { - cl, err := testkit.PrepareClient(t) - if err != nil { - return err - } - - // This is a client role - t.RecordMessage("running client") - - ctx := context.Background() - client := cl.FullApi - - time.Sleep(10 * time.Second) - - // select a miner based on our GroupSeq (client 1 -> miner 1 ; client 2 -> miner 2) - // this assumes that all miner instances receive the same sorted MinerAddrs slice - minerAddr := cl.MinerAddrs[t.InitContext.GroupSeq-1] - if err := client.NetConnect(ctx, minerAddr.MinerNetAddrs); err != nil { - return err - } - t.D().Counter(fmt.Sprintf("send-data-to,miner=%s", minerAddr.MinerActorAddr)).Inc(1) - - t.RecordMessage("selected %s as the miner", minerAddr.MinerActorAddr) - - time.Sleep(2 * time.Second) - - // generate 1800 bytes of random data - data := make([]byte, 1800) - rand.New(rand.NewSource(time.Now().UnixNano())).Read(data) - - file, err := ioutil.TempFile("/tmp", "data") - if err != nil { - return err - } - defer os.Remove(file.Name()) - - _, err = file.Write(data) - if err != nil { - return err - } - - fcid, err := client.ClientImport(ctx, api.FileRef{Path: file.Name(), IsCAR: false}) - if err != nil { - return err - } - t.RecordMessage("file cid: %s", fcid) - - // start deal - t1 := time.Now() - fastRetrieval := false - deal := testkit.StartDeal(ctx, minerAddr.MinerActorAddr, client, fcid.Root, fastRetrieval) - t.RecordMessage("started deal: %s", deal) - - // this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this - time.Sleep(2 * time.Second) - - t.RecordMessage("waiting for deal to be sealed") - testkit.WaitDealSealed(t, ctx, client, deal) - t.D().ResettingHistogram("deal.sealed").Update(int64(time.Since(t1))) - - // TODO: wait to stop miner (ideally get a signal, rather than sleep) - time.Sleep(180 * time.Second) - - t.RecordMessage("trying to retrieve %s", fcid) - info, err := client.ClientGetDealInfo(ctx, *deal) - if err != nil { - return err - } - - carExport := true - err = testkit.RetrieveData(t, ctx, client, fcid.Root, &info.PieceCID, carExport, data) - if err != nil && strings.Contains(err.Error(), "cannot make retrieval deal for zero bytes") { - t.D().Counter("deal.expect-slashing").Inc(1) - } else if err != nil { - // unknown error => fail test - t.RecordFailure(err) - - // send signal to abort test - t.SyncClient.MustSignalEntry(ctx, testkit.StateAbortTest) - - t.D().ResettingHistogram("deal.retrieved.err").Update(int64(time.Since(t1))) - time.Sleep(10 * time.Second) // wait for metrics to be emitted - - return nil - } - - t.D().ResettingHistogram("deal.retrieved").Update(int64(time.Since(t1))) - time.Sleep(10 * time.Second) // wait for metrics to be emitted - - t.SyncClient.MustSignalAndWait(ctx, testkit.StateDone, t.TestInstanceCount) // TODO: not sure about this - return nil -} diff --git a/testplans/lotus-soup/rfwp/html_chain_state.go b/testplans/lotus-soup/rfwp/html_chain_state.go deleted file mode 100644 index 9dbd271a3..000000000 --- a/testplans/lotus-soup/rfwp/html_chain_state.go +++ /dev/null @@ -1,69 +0,0 @@ -package rfwp - -import ( - "context" - "fmt" - "os" - - "github.com/ipfs/go-cid" - - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" - - "github.com/filecoin-project/lotus/api/v0api" - "github.com/filecoin-project/lotus/cli" - "github.com/filecoin-project/lotus/testplans/lotus-soup/testkit" - tsync "github.com/filecoin-project/lotus/tools/stats/sync" -) - -func FetchChainState(t *testkit.TestEnvironment, m *testkit.LotusMiner) error { - height := 0 - headlag := 3 - - ctx := context.Background() - api := m.FullApi - - tipsetsCh, err := tsync.BufferedTipsetChannel(ctx, &v0api.WrapperV1Full{FullNode: m.FullApi}, abi.ChainEpoch(height), headlag) - if err != nil { - - return err - } - - for tipset := range tipsetsCh { - err := func() error { - filename := fmt.Sprintf("%s%cchain-state-%d.html", t.TestOutputsPath, os.PathSeparator, tipset.Height()) - file, err := os.Create(filename) - defer file.Close() - if err != nil { - return err - } - - stout, err := api.StateCompute(ctx, tipset.Height(), nil, tipset.Key()) - if err != nil { - return err - } - - codeCache := map[address.Address]cid.Cid{} - getCode := func(addr address.Address) (cid.Cid, error) { - if c, found := codeCache[addr]; found { - return c, nil - } - - c, err := api.StateGetActor(ctx, addr, tipset.Key()) - if err != nil { - return cid.Cid{}, err - } - - codeCache[addr] = c.Code - return c.Code, nil - } - - return cli.ComputeStateHTMLTempl(file, tipset, stout, true, getCode) - }() - if err != nil { - return err - } - } - - return nil -} diff --git a/testplans/lotus-soup/runner/main.go b/testplans/lotus-soup/runner/main.go deleted file mode 100644 index e867533f0..000000000 --- a/testplans/lotus-soup/runner/main.go +++ /dev/null @@ -1,120 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "io" - "io/ioutil" - "log" - "os" - "path" - - "github.com/codeskyblue/go-sh" -) - -type jobDefinition struct { - runNumber int - compositionPath string - outputDir string - skipStdout bool -} - -type jobResult struct { - job jobDefinition - runError error -} - -func runComposition(job jobDefinition) jobResult { - outputArchive := path.Join(job.outputDir, "test-outputs.tgz") - cmd := sh.Command("testground", "run", "composition", "-f", job.compositionPath, "--collect", "-o", outputArchive) - if err := os.MkdirAll(job.outputDir, os.ModePerm); err != nil { - return jobResult{runError: fmt.Errorf("unable to make output directory: %w", err)} - } - - outPath := path.Join(job.outputDir, "run.out") - outFile, err := os.Create(outPath) - if err != nil { - return jobResult{runError: fmt.Errorf("unable to create output file %s: %w", outPath, err)} - } - if job.skipStdout { - cmd.Stdout = outFile - } else { - cmd.Stdout = io.MultiWriter(os.Stdout, outFile) - } - log.Printf("starting test run %d. writing testground client output to %s\n", job.runNumber, outPath) - if err = cmd.Run(); err != nil { - return jobResult{job: job, runError: err} - } - return jobResult{job: job} -} - -func worker(id int, jobs <-chan jobDefinition, results chan<- jobResult) { - log.Printf("started worker %d\n", id) - for j := range jobs { - log.Printf("worker %d started test run %d\n", id, j.runNumber) - results <- runComposition(j) - } -} - -func buildComposition(compositionPath string, outputDir string) (string, error) { - outComp := path.Join(outputDir, "composition.toml") - err := sh.Command("cp", compositionPath, outComp).Run() - if err != nil { - return "", err - } - - return outComp, sh.Command("testground", "build", "composition", "-w", "-f", outComp).Run() -} - -func main() { - runs := flag.Int("runs", 1, "number of times to run composition") - parallelism := flag.Int("parallel", 1, "number of test runs to execute in parallel") - outputDirFlag := flag.String("output", "", "path to output directory (will use temp dir if unset)") - flag.Parse() - - if len(flag.Args()) != 1 { - log.Fatal("must provide a single composition file path argument") - } - - outdir := *outputDirFlag - if outdir == "" { - var err error - outdir, err = ioutil.TempDir(os.TempDir(), "oni-batch-run-") - if err != nil { - log.Fatal(err) - } - } - if err := os.MkdirAll(outdir, os.ModePerm); err != nil { - log.Fatal(err) - } - - compositionPath := flag.Args()[0] - - // first build the composition and write out the artifacts. - // we copy to a temp file first to avoid modifying the original - log.Printf("building composition %s\n", compositionPath) - compositionPath, err := buildComposition(compositionPath, outdir) - if err != nil { - log.Fatal(err) - } - - jobs := make(chan jobDefinition, *runs) - results := make(chan jobResult, *runs) - for w := 1; w <= *parallelism; w++ { - go worker(w, jobs, results) - } - - for j := 1; j <= *runs; j++ { - dir := path.Join(outdir, fmt.Sprintf("run-%d", j)) - skipStdout := *parallelism != 1 - jobs <- jobDefinition{runNumber: j, compositionPath: compositionPath, outputDir: dir, skipStdout: skipStdout} - } - close(jobs) - - for i := 0; i < *runs; i++ { - r := <-results - if r.runError != nil { - log.Printf("error running job %d: %s\n", r.job.runNumber, r.runError) - } - } -} diff --git a/testplans/lotus-soup/sanity.go b/testplans/lotus-soup/sanity.go deleted file mode 100644 index ca9799a50..000000000 --- a/testplans/lotus-soup/sanity.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "fmt" - "os" -) - -func sanityCheck() { - enhanceMsg := func(msg string, a ...interface{}) string { - return fmt.Sprintf("sanity check: "+msg+"; if running on local:exec, make sure to run `make` from the root of the oni repo", a...) - } - - dir := "/var/tmp/filecoin-proof-parameters" - stat, err := os.Stat(dir) - if os.IsNotExist(err) { - panic(enhanceMsg("proofs parameters not available in /var/tmp/filecoin-proof-parameters")) - } - if err != nil { - panic(enhanceMsg("failed to stat /var/tmp/filecoin-proof-parameters: %s", err)) - } - - if !stat.IsDir() { - panic(enhanceMsg("/var/tmp/filecoin-proof-parameters is not a directory; aborting")) - } - - files, err := os.ReadDir(dir) - if err != nil { - panic(enhanceMsg("failed list directory /var/tmp/filecoin-proof-parameters: %s", err)) - } - - if len(files) == 0 { - panic(enhanceMsg("no files in /var/tmp/filecoin-proof-parameters")) - } -} diff --git a/testplans/lotus-soup/statemachine/statemachine.go b/testplans/lotus-soup/statemachine/statemachine.go deleted file mode 100644 index 17de614db..000000000 --- a/testplans/lotus-soup/statemachine/statemachine.go +++ /dev/null @@ -1,108 +0,0 @@ -package statemachine - -import ( - "errors" - "sync" -) - -// This code has been shamelessly lifted from this blog post: -// https://venilnoronha.io/a-simple-state-machine-framework-in-go -// Many thanks to the author, Venil Norohnha - -// ErrEventRejected is the error returned when the state machine cannot process -// an event in the state that it is in. -var ErrEventRejected = errors.New("event rejected") - -const ( - // Default represents the default state of the system. - Default StateType = "" - - // NoOp represents a no-op event. - NoOp EventType = "NoOp" -) - -// StateType represents an extensible state type in the state machine. -type StateType string - -// EventType represents an extensible event type in the state machine. -type EventType string - -// EventContext represents the context to be passed to the action implementation. -type EventContext interface{} - -// Action represents the action to be executed in a given state. -type Action interface { - Execute(eventCtx EventContext) EventType -} - -// Events represents a mapping of events and states. -type Events map[EventType]StateType - -// State binds a state with an action and a set of events it can handle. -type State struct { - Action Action - Events Events -} - -// States represents a mapping of states and their implementations. -type States map[StateType]State - -// StateMachine represents the state machine. -type StateMachine struct { - // Previous represents the previous state. - Previous StateType - - // Current represents the current state. - Current StateType - - // States holds the configuration of states and events handled by the state machine. - States States - - // mutex ensures that only 1 event is processed by the state machine at any given time. - mutex sync.Mutex -} - -// getNextState returns the next state for the event given the machine's current -// state, or an error if the event can't be handled in the given state. -func (s *StateMachine) getNextState(event EventType) (StateType, error) { - if state, ok := s.States[s.Current]; ok { - if state.Events != nil { - if next, ok := state.Events[event]; ok { - return next, nil - } - } - } - return Default, ErrEventRejected -} - -// SendEvent sends an event to the state machine. -func (s *StateMachine) SendEvent(event EventType, eventCtx EventContext) error { - s.mutex.Lock() - defer s.mutex.Unlock() - - for { - // Determine the next state for the event given the machine's current state. - nextState, err := s.getNextState(event) - if err != nil { - return ErrEventRejected - } - - // Identify the state definition for the next state. - state, ok := s.States[nextState] - if !ok || state.Action == nil { - // configuration error - } - - // Transition over to the next state. - s.Previous = s.Current - s.Current = nextState - - // Execute the next state's action and loop over again if the event returned - // is not a no-op. - nextEvent := state.Action.Execute(eventCtx) - if nextEvent == NoOp { - return nil - } - event = nextEvent - } -} diff --git a/testplans/lotus-soup/statemachine/suspend.go b/testplans/lotus-soup/statemachine/suspend.go deleted file mode 100644 index 11bade7c1..000000000 --- a/testplans/lotus-soup/statemachine/suspend.go +++ /dev/null @@ -1,128 +0,0 @@ -package statemachine - -import ( - "fmt" - "strings" - "time" -) - -const ( - Running StateType = "running" - Suspended StateType = "suspended" - - Halt EventType = "halt" - Resume EventType = "resume" -) - -type Suspendable interface { - Halt() - Resume() -} - -type HaltAction struct{} - -func (a *HaltAction) Execute(ctx EventContext) EventType { - s, ok := ctx.(*Suspender) - if !ok { - fmt.Println("unable to halt, event context is not Suspendable") - return NoOp - } - s.target.Halt() - return NoOp -} - -type ResumeAction struct{} - -func (a *ResumeAction) Execute(ctx EventContext) EventType { - s, ok := ctx.(*Suspender) - if !ok { - fmt.Println("unable to resume, event context is not Suspendable") - return NoOp - } - s.target.Resume() - return NoOp -} - -type Suspender struct { - StateMachine - target Suspendable - log LogFn -} - -type LogFn func(fmt string, args ...interface{}) - -func NewSuspender(target Suspendable, log LogFn) *Suspender { - return &Suspender{ - target: target, - log: log, - StateMachine: StateMachine{ - Current: Running, - States: States{ - Running: State{ - Action: &ResumeAction{}, - Events: Events{ - Halt: Suspended, - }, - }, - - Suspended: State{ - Action: &HaltAction{}, - Events: Events{ - Resume: Running, - }, - }, - }, - }, - } -} - -func (s *Suspender) RunEvents(eventSpec string) { - s.log("running event spec: %s", eventSpec) - for _, et := range parseEventSpec(eventSpec, s.log) { - if et.delay != 0 { - //s.log("waiting %s", et.delay.String()) - time.Sleep(et.delay) - continue - } - if et.event == "" { - s.log("ignoring empty event") - continue - } - s.log("sending event %s", et.event) - err := s.SendEvent(et.event, s) - if err != nil { - s.log("error sending event %s: %s", et.event, err) - } - } -} - -type eventTiming struct { - delay time.Duration - event EventType -} - -func parseEventSpec(spec string, log LogFn) []eventTiming { - fields := strings.Split(spec, "->") - out := make([]eventTiming, 0, len(fields)) - for _, f := range fields { - f = strings.TrimSpace(f) - words := strings.Split(f, " ") - - // TODO: try to implement a "waiting" state instead of special casing like this - if words[0] == "wait" { - if len(words) != 2 { - log("expected 'wait' to be followed by duration, e.g. 'wait 30s'. ignoring.") - continue - } - d, err := time.ParseDuration(words[1]) - if err != nil { - log("bad argument for 'wait': %s", err) - continue - } - out = append(out, eventTiming{delay: d}) - } else { - out = append(out, eventTiming{event: EventType(words[0])}) - } - } - return out -} diff --git a/testplans/lotus-soup/testkit/deals.go b/testplans/lotus-soup/testkit/deals.go deleted file mode 100644 index b65517c4d..000000000 --- a/testplans/lotus-soup/testkit/deals.go +++ /dev/null @@ -1,76 +0,0 @@ -package testkit - -import ( - "context" - "fmt" - - "github.com/ipfs/go-cid" - - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-fil-markets/storagemarket" - "github.com/filecoin-project/go-state-types/abi" - - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/api/v0api" - "github.com/filecoin-project/lotus/chain/types" - tsync "github.com/filecoin-project/lotus/tools/stats/sync" -) - -func StartDeal(ctx context.Context, minerActorAddr address.Address, client api.FullNode, fcid cid.Cid, fastRetrieval bool) *cid.Cid { - addr, err := client.WalletDefaultAddress(ctx) - if err != nil { - panic(err) - } - - deal, err := client.ClientStartDeal(ctx, &api.StartDealParams{ - Data: &storagemarket.DataRef{ - TransferType: storagemarket.TTGraphsync, - Root: fcid, - }, - Wallet: addr, - Miner: minerActorAddr, - EpochPrice: types.NewInt(4000000), - MinBlocksDuration: 640000, - DealStartEpoch: 200, - FastRetrieval: fastRetrieval, - }) - if err != nil { - panic(err) - } - return deal -} - -func WaitDealSealed(t *TestEnvironment, ctx context.Context, client api.FullNode, deal *cid.Cid) { - height := 0 - headlag := 3 - - cctx, cancel := context.WithCancel(ctx) - defer cancel() - - tipsetsCh, err := tsync.BufferedTipsetChannel(cctx, &v0api.WrapperV1Full{FullNode: client}, abi.ChainEpoch(height), headlag) - if err != nil { - panic(err) - } - - for tipset := range tipsetsCh { - t.RecordMessage("got tipset: height %d", tipset.Height()) - - di, err := client.ClientGetDealInfo(ctx, *deal) - if err != nil { - panic(err) - } - switch di.State { - case storagemarket.StorageDealProposalRejected: - panic("deal rejected") - case storagemarket.StorageDealFailing: - panic("deal failed") - case storagemarket.StorageDealError: - panic(fmt.Sprintf("deal errored %s", di.Message)) - case storagemarket.StorageDealActive: - t.RecordMessage("completed deal: %s", di) - return - } - - t.RecordMessage("deal state: %s", storagemarket.DealStates[di.State]) - } -} diff --git a/testplans/lotus-soup/testkit/defaults.go b/testplans/lotus-soup/testkit/defaults.go deleted file mode 100644 index a0681f37c..000000000 --- a/testplans/lotus-soup/testkit/defaults.go +++ /dev/null @@ -1,55 +0,0 @@ -package testkit - -import "fmt" - -type RoleName = string - -var DefaultRoles = map[RoleName]func(*TestEnvironment) error{ - "bootstrapper": func(t *TestEnvironment) error { - b, err := PrepareBootstrapper(t) - if err != nil { - return err - } - return b.RunDefault() - }, - "miner": func(t *TestEnvironment) error { - m, err := PrepareMiner(t) - if err != nil { - return err - } - return m.RunDefault() - }, - "client": func(t *TestEnvironment) error { - c, err := PrepareClient(t) - if err != nil { - return err - } - return c.RunDefault() - }, - "drand": func(t *TestEnvironment) error { - d, err := PrepareDrandInstance(t) - if err != nil { - return err - } - return d.RunDefault() - }, - "pubsub-tracer": func(t *TestEnvironment) error { - tr, err := PreparePubsubTracer(t) - if err != nil { - return err - } - return tr.RunDefault() - }, -} - -// HandleDefaultRole handles a role by running its default behaviour. -// -// This function is suitable to forward to when a test case doesn't need to -// explicitly handle/alter a role. -func HandleDefaultRole(t *TestEnvironment) error { - f, ok := DefaultRoles[t.Role] - if !ok { - panic(fmt.Sprintf("unrecognized role: %s", t.Role)) - } - return f(t) -} diff --git a/testplans/lotus-soup/testkit/lotus_opts.go b/testplans/lotus-soup/testkit/lotus_opts.go deleted file mode 100644 index 768c6d0d3..000000000 --- a/testplans/lotus-soup/testkit/lotus_opts.go +++ /dev/null @@ -1,67 +0,0 @@ -package testkit - -import ( - "fmt" - - "github.com/libp2p/go-libp2p/core/peer" - ma "github.com/multiformats/go-multiaddr" - - "github.com/filecoin-project/lotus/node" - "github.com/filecoin-project/lotus/node/config" - "github.com/filecoin-project/lotus/node/modules" - "github.com/filecoin-project/lotus/node/modules/dtypes" - "github.com/filecoin-project/lotus/node/modules/lp2p" - "github.com/filecoin-project/lotus/node/repo" -) - -func withGenesis(gb []byte) node.Option { - return node.Override(new(modules.Genesis), modules.LoadGenesis(gb)) -} - -func withBootstrapper(ab []byte) node.Option { - return node.Override(new(dtypes.BootstrapPeers), - func() (dtypes.BootstrapPeers, error) { - if ab == nil { - return dtypes.BootstrapPeers{}, nil - } - - a, err := ma.NewMultiaddrBytes(ab) - if err != nil { - return nil, err - } - ai, err := peer.AddrInfoFromP2pAddr(a) - if err != nil { - return nil, err - } - return dtypes.BootstrapPeers{*ai}, nil - }) -} - -func withPubsubConfig(bootstrapper bool, pubsubTracer string) node.Option { - return node.Override(new(*config.Pubsub), func() *config.Pubsub { - return &config.Pubsub{ - Bootstrapper: bootstrapper, - RemoteTracer: pubsubTracer, - } - }) -} - -func withListenAddress(ip string) node.Option { - addrs := []string{fmt.Sprintf("/ip4/%s/tcp/0", ip)} - return node.Override(node.StartListeningKey, lp2p.StartListening(addrs)) -} - -func withMinerListenAddress(ip string) node.Option { - addrs := []string{fmt.Sprintf("/ip4/%s/tcp/0", ip)} - return node.Override(node.StartListeningKey, lp2p.StartListening(addrs)) -} - -func withApiEndpoint(addr string) node.Option { - return node.Override(node.SetApiEndpointKey, func(lr repo.LockedRepo) error { - apima, err := ma.NewMultiaddr(addr) - if err != nil { - return err - } - return lr.SetAPIEndpoint(apima) - }) -} diff --git a/testplans/lotus-soup/testkit/net.go b/testplans/lotus-soup/testkit/net.go deleted file mode 100644 index d2dbc2ae6..000000000 --- a/testplans/lotus-soup/testkit/net.go +++ /dev/null @@ -1,92 +0,0 @@ -package testkit - -import ( - "context" - "fmt" - "time" - - "github.com/testground/sdk-go/network" - "github.com/testground/sdk-go/sync" -) - -func ApplyNetworkParameters(t *TestEnvironment) { - if !t.TestSidecar { - t.RecordMessage("no test sidecar, skipping network config") - return - } - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - ls := network.LinkShape{} - - if t.IsParamSet("latency_range") { - r := t.DurationRangeParam("latency_range") - ls.Latency = r.ChooseRandom() - t.D().RecordPoint("latency_ms", float64(ls.Latency.Milliseconds())) - } - - if t.IsParamSet("jitter_range") { - r := t.DurationRangeParam("jitter_range") - ls.Jitter = r.ChooseRandom() - t.D().RecordPoint("jitter_ms", float64(ls.Jitter.Milliseconds())) - } - - if t.IsParamSet("loss_range") { - r := t.FloatRangeParam("loss_range") - ls.Loss = r.ChooseRandom() - t.D().RecordPoint("packet_loss", float64(ls.Loss)) - } - - if t.IsParamSet("corrupt_range") { - r := t.FloatRangeParam("corrupt_range") - ls.Corrupt = r.ChooseRandom() - t.D().RecordPoint("corrupt_packet_probability", float64(ls.Corrupt)) - } - - if t.IsParamSet("corrupt_corr_range") { - r := t.FloatRangeParam("corrupt_corr_range") - ls.CorruptCorr = r.ChooseRandom() - t.D().RecordPoint("corrupt_packet_correlation", float64(ls.CorruptCorr)) - } - - if t.IsParamSet("reorder_range") { - r := t.FloatRangeParam("reorder_range") - ls.Reorder = r.ChooseRandom() - t.D().RecordPoint("reordered_packet_probability", float64(ls.Reorder)) - } - - if t.IsParamSet("reorder_corr_range") { - r := t.FloatRangeParam("reorder_corr_range") - ls.ReorderCorr = r.ChooseRandom() - t.D().RecordPoint("reordered_packet_correlation", float64(ls.ReorderCorr)) - } - - if t.IsParamSet("duplicate_range") { - r := t.FloatRangeParam("duplicate_range") - ls.Duplicate = r.ChooseRandom() - t.D().RecordPoint("duplicate_packet_probability", float64(ls.Duplicate)) - } - - if t.IsParamSet("duplicate_corr_range") { - r := t.FloatRangeParam("duplicate_corr_range") - ls.DuplicateCorr = r.ChooseRandom() - t.D().RecordPoint("duplicate_packet_correlation", float64(ls.DuplicateCorr)) - } - - if t.IsParamSet("bandwidth") { - ls.Bandwidth = t.SizeParam("bandwidth") - t.D().RecordPoint("bandwidth_bytes", float64(ls.Bandwidth)) - } - - t.NetClient.MustConfigureNetwork(ctx, &network.Config{ - Network: "default", - Enable: true, - Default: ls, - CallbackState: sync.State(fmt.Sprintf("latency-configured-%s", t.TestGroupID)), - CallbackTarget: t.TestGroupInstanceCount, - RoutingPolicy: network.AllowAll, - }) - - t.DumpJSON("network-link-shape.json", ls) -} diff --git a/testplans/lotus-soup/testkit/node.go b/testplans/lotus-soup/testkit/node.go deleted file mode 100644 index 4d8d04aeb..000000000 --- a/testplans/lotus-soup/testkit/node.go +++ /dev/null @@ -1,288 +0,0 @@ -package testkit - -import ( - "context" - "fmt" - "net/http" - "os" - "sort" - "time" - - influxdb "github.com/kpacha/opencensus-influxdb" - ma "github.com/multiformats/go-multiaddr" - manet "github.com/multiformats/go-multiaddr/net" - "go.opencensus.io/stats" - "go.opencensus.io/stats/view" - - "github.com/filecoin-project/go-state-types/abi" - - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/chain/beacon" - "github.com/filecoin-project/lotus/chain/wallet/key" - "github.com/filecoin-project/lotus/metrics" - "github.com/filecoin-project/lotus/miner" - "github.com/filecoin-project/lotus/node" - "github.com/filecoin-project/lotus/node/modules/dtypes" - modtest "github.com/filecoin-project/lotus/node/modules/testing" - tinflux "github.com/filecoin-project/lotus/tools/stats/influx" - tipldstore "github.com/filecoin-project/lotus/tools/stats/ipldstore" - tpoints "github.com/filecoin-project/lotus/tools/stats/points" - tsync "github.com/filecoin-project/lotus/tools/stats/sync" -) - -var PrepareNodeTimeout = 3 * time.Minute - -type LotusNode struct { - FullApi api.FullNode - MinerApi api.StorageMiner - StopFn node.StopFunc - Wallet *key.Key - MineOne func(context.Context, miner.MineReq) error -} - -func (n *LotusNode) setWallet(ctx context.Context, walletKey *key.Key) error { - _, err := n.FullApi.WalletImport(ctx, &walletKey.KeyInfo) - if err != nil { - return err - } - - err = n.FullApi.WalletSetDefault(ctx, walletKey.Address) - if err != nil { - return err - } - - n.Wallet = walletKey - - return nil -} - -func WaitForBalances(t *TestEnvironment, ctx context.Context, nodes int) ([]*InitialBalanceMsg, error) { - ch := make(chan *InitialBalanceMsg) - sub := t.SyncClient.MustSubscribe(ctx, BalanceTopic, ch) - - balances := make([]*InitialBalanceMsg, 0, nodes) - for i := 0; i < nodes; i++ { - select { - case m := <-ch: - balances = append(balances, m) - case err := <-sub.Done(): - return nil, fmt.Errorf("got error while waiting for balances: %w", err) - } - } - - return balances, nil -} - -func CollectPreseals(t *TestEnvironment, ctx context.Context, miners int) ([]*PresealMsg, error) { - ch := make(chan *PresealMsg) - sub := t.SyncClient.MustSubscribe(ctx, PresealTopic, ch) - - preseals := make([]*PresealMsg, 0, miners) - for i := 0; i < miners; i++ { - select { - case m := <-ch: - preseals = append(preseals, m) - case err := <-sub.Done(): - return nil, fmt.Errorf("got error while waiting for preseals: %w", err) - } - } - - sort.Slice(preseals, func(i, j int) bool { - return preseals[i].Seqno < preseals[j].Seqno - }) - - return preseals, nil -} - -func WaitForGenesis(t *TestEnvironment, ctx context.Context) (*GenesisMsg, error) { - genesisCh := make(chan *GenesisMsg) - sub := t.SyncClient.MustSubscribe(ctx, GenesisTopic, genesisCh) - - select { - case genesisMsg := <-genesisCh: - return genesisMsg, nil - case err := <-sub.Done(): - return nil, fmt.Errorf("error while waiting for genesis msg: %w", err) - } -} - -func CollectMinerAddrs(t *TestEnvironment, ctx context.Context, miners int) ([]MinerAddressesMsg, error) { - ch := make(chan MinerAddressesMsg) - sub := t.SyncClient.MustSubscribe(ctx, MinersAddrsTopic, ch) - - addrs := make([]MinerAddressesMsg, 0, miners) - for i := 0; i < miners; i++ { - select { - case a := <-ch: - addrs = append(addrs, a) - case err := <-sub.Done(): - return nil, fmt.Errorf("got error while waiting for miners addrs: %w", err) - } - } - - return addrs, nil -} - -func CollectClientAddrs(t *TestEnvironment, ctx context.Context, clients int) ([]*ClientAddressesMsg, error) { - ch := make(chan *ClientAddressesMsg) - sub := t.SyncClient.MustSubscribe(ctx, ClientsAddrsTopic, ch) - - addrs := make([]*ClientAddressesMsg, 0, clients) - for i := 0; i < clients; i++ { - select { - case a := <-ch: - addrs = append(addrs, a) - case err := <-sub.Done(): - return nil, fmt.Errorf("got error while waiting for clients addrs: %w", err) - } - } - - return addrs, nil -} - -func GetPubsubTracerMaddr(ctx context.Context, t *TestEnvironment) (string, error) { - if !t.BooleanParam("enable_pubsub_tracer") { - return "", nil - } - - ch := make(chan *PubsubTracerMsg) - sub := t.SyncClient.MustSubscribe(ctx, PubsubTracerTopic, ch) - - select { - case m := <-ch: - return m.Multiaddr, nil - case err := <-sub.Done(): - return "", fmt.Errorf("got error while waiting for pubsub tracer config: %w", err) - } -} - -func GetRandomBeaconOpts(ctx context.Context, t *TestEnvironment) (node.Option, error) { - beaconType := t.StringParam("random_beacon_type") - switch beaconType { - case "external-drand": - noop := func(settings *node.Settings) error { - return nil - } - return noop, nil - - case "local-drand": - cfg, err := waitForDrandConfig(ctx, t.SyncClient) - if err != nil { - t.RecordMessage("error getting drand config: %w", err) - return nil, err - - } - t.RecordMessage("setting drand config: %v", cfg) - return node.Options( - node.Override(new(dtypes.DrandConfig), cfg.Config), - node.Override(new(dtypes.DrandBootstrap), cfg.GossipBootstrap), - ), nil - - case "mock": - return node.Options( - node.Override(new(beacon.RandomBeacon), modtest.RandomBeacon), - node.Override(new(dtypes.DrandConfig), dtypes.DrandConfig{ - ChainInfoJSON: "{\"Hash\":\"wtf\"}", - }), - node.Override(new(dtypes.DrandBootstrap), dtypes.DrandBootstrap{}), - ), nil - - default: - return nil, fmt.Errorf("unknown random_beacon_type: %s", beaconType) - } -} - -func startServer(endpoint ma.Multiaddr, srv *http.Server) (listenAddr string, err error) { - lst, err := manet.Listen(endpoint) - if err != nil { - return "", fmt.Errorf("could not listen: %w", err) - } - - go func() { - _ = srv.Serve(manet.NetListener(lst)) - }() - - return lst.Addr().String(), nil -} - -func registerAndExportMetrics(instanceName string) { - // Register all Lotus metric views - err := view.Register(metrics.DefaultViews...) - if err != nil { - panic(err) - } - - // Set the metric to one so it is published to the exporter - stats.Record(context.Background(), metrics.LotusInfo.M(1)) - - // Register our custom exporter to opencensus - e, err := influxdb.NewExporter(context.Background(), influxdb.Options{ - Database: "testground", - Address: os.Getenv("INFLUXDB_URL"), - Username: "", - Password: "", - InstanceName: instanceName, - }) - if err != nil { - panic(err) - } - view.RegisterExporter(e) - view.SetReportingPeriod(5 * time.Second) -} - -func collectStats(t *TestEnvironment, ctx context.Context, api api.FullNode) error { - t.RecordMessage("collecting blockchain stats") - - influxAddr := os.Getenv("INFLUXDB_URL") - influxUser := "" - influxPass := "" - influxDb := "testground" - - influxClient, err := tinflux.NewClient(influxAddr, influxUser, influxPass) - if err != nil { - t.RecordMessage(err.Error()) - return err - } - - height := int64(0) - headlag := 1 - - go func() { - time.Sleep(15 * time.Second) - t.RecordMessage("calling tstats.Collect") - - store, err := tipldstore.NewApiIpldStore(ctx, api, 1024) - if err != nil { - t.RecordMessage(err.Error()) - return - } - - collector, err := tpoints.NewChainPointCollector(ctx, store, api) - if err != nil { - t.RecordMessage(err.Error()) - return - } - - tipsets, err := tsync.BufferedTipsetChannel(ctx, api, abi.ChainEpoch(height), headlag) - if err != nil { - t.RecordMessage(err.Error()) - return - } - - wq := tinflux.NewWriteQueue(ctx, influxClient) - defer wq.Close() - - for tipset := range tipsets { - if nb, err := collector.Collect(ctx, tipset); err != nil { - t.RecordMessage(err.Error()) - return - } else { - nb.SetDatabase(influxDb) - wq.AddBatch(nb) - } - } - - }() - - return nil -} diff --git a/testplans/lotus-soup/testkit/retrieval.go b/testplans/lotus-soup/testkit/retrieval.go deleted file mode 100644 index 0182b0907..000000000 --- a/testplans/lotus-soup/testkit/retrieval.go +++ /dev/null @@ -1,108 +0,0 @@ -package testkit - -import ( - "bytes" - "context" - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "time" - - "github.com/ipfs/go-cid" - files "github.com/ipfs/go-ipfs-files" - ipld "github.com/ipfs/go-ipld-format" - dag "github.com/ipfs/go-merkledag" - dstest "github.com/ipfs/go-merkledag/test" - unixfile "github.com/ipfs/go-unixfs/file" - "github.com/ipld/go-car" - - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/api/v0api" -) - -func RetrieveData(t *TestEnvironment, ctx context.Context, client api.FullNode, fcid cid.Cid, _ *cid.Cid, carExport bool, data []byte) error { - t1 := time.Now() - offers, err := client.ClientFindData(ctx, fcid, nil) - if err != nil { - panic(err) - } - for _, o := range offers { - t.D().Counter(fmt.Sprintf("find-data.offer,miner=%s", o.Miner)).Inc(1) - } - t.D().ResettingHistogram("find-data").Update(int64(time.Since(t1))) - - if len(offers) < 1 { - panic("no offers") - } - - rpath, err := ioutil.TempDir("", "lotus-retrieve-test-") - if err != nil { - panic(err) - } - defer os.RemoveAll(rpath) - - caddr, err := client.WalletDefaultAddress(ctx) - if err != nil { - return err - } - - ref := &api.FileRef{ - Path: filepath.Join(rpath, "ret"), - IsCAR: carExport, - } - t1 = time.Now() - err = (&v0api.WrapperV1Full{FullNode: client}).ClientRetrieve(ctx, v0api.OfferOrder(offers[0], caddr), ref) - if err != nil { - return err - } - t.D().ResettingHistogram("retrieve-data").Update(int64(time.Since(t1))) - - rdata, err := ioutil.ReadFile(filepath.Join(rpath, "ret")) - if err != nil { - return err - } - - if carExport { - rdata = ExtractCarData(ctx, rdata, rpath) - } - - if !bytes.Equal(rdata, data) { - return errors.New("wrong data retrieved") - } - - t.RecordMessage("retrieved successfully") - - return nil -} - -func ExtractCarData(ctx context.Context, rdata []byte, rpath string) []byte { - bserv := dstest.Bserv() - ch, err := car.LoadCar(ctx, bserv.Blockstore(), bytes.NewReader(rdata)) - if err != nil { - panic(err) - } - b, err := bserv.GetBlock(ctx, ch.Roots[0]) - if err != nil { - panic(err) - } - nd, err := ipld.Decode(b) - if err != nil { - panic(err) - } - dserv := dag.NewDAGService(bserv) - fil, err := unixfile.NewUnixfsFile(ctx, dserv, nd) - if err != nil { - panic(err) - } - outPath := filepath.Join(rpath, "retLoadedCAR") - if err := files.WriteTo(fil, outPath); err != nil { - panic(err) - } - rdata, err = ioutil.ReadFile(outPath) - if err != nil { - panic(err) - } - return rdata -} diff --git a/testplans/lotus-soup/testkit/role_bootstrapper.go b/testplans/lotus-soup/testkit/role_bootstrapper.go deleted file mode 100644 index 6c19f26f1..000000000 --- a/testplans/lotus-soup/testkit/role_bootstrapper.go +++ /dev/null @@ -1,203 +0,0 @@ -package testkit - -import ( - "bytes" - "context" - "fmt" - mbig "math/big" - "time" - - "github.com/google/uuid" - "github.com/libp2p/go-libp2p/core/peer" - ma "github.com/multiformats/go-multiaddr" - - "github.com/filecoin-project/go-state-types/big" - - "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/chain/gen" - "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/genesis" - "github.com/filecoin-project/lotus/node" - "github.com/filecoin-project/lotus/node/modules" - modtest "github.com/filecoin-project/lotus/node/modules/testing" - "github.com/filecoin-project/lotus/node/repo" -) - -// Bootstrapper is a special kind of process that produces a genesis block with -// the initial wallet balances and preseals for all enlisted miners and clients. -type Bootstrapper struct { - *LotusNode - - t *TestEnvironment -} - -func PrepareBootstrapper(t *TestEnvironment) (*Bootstrapper, error) { - var ( - clients = t.IntParam("clients") - miners = t.IntParam("miners") - nodes = clients + miners - ) - - ctx, cancel := context.WithTimeout(context.Background(), PrepareNodeTimeout) - defer cancel() - - pubsubTracerMaddr, err := GetPubsubTracerMaddr(ctx, t) - if err != nil { - return nil, err - } - - randomBeaconOpt, err := GetRandomBeaconOpts(ctx, t) - if err != nil { - return nil, err - } - - // the first duty of the boostrapper is to construct the genesis block - // first collect all client and miner balances to assign initial funds - balances, err := WaitForBalances(t, ctx, nodes) - if err != nil { - return nil, err - } - - totalBalance := big.Zero() - for _, b := range balances { - totalBalance = big.Add(filToAttoFil(b.Balance), totalBalance) - } - - totalBalanceFil := attoFilToFil(totalBalance) - t.RecordMessage("TOTAL BALANCE: %s AttoFIL (%s FIL)", totalBalance, totalBalanceFil) - if max := types.TotalFilecoinInt; totalBalanceFil.GreaterThanEqual(max) { - panic(fmt.Sprintf("total sum of balances is greater than max Filecoin ever; sum=%s, max=%s", totalBalance, max)) - } - - // then collect all preseals from miners - preseals, err := CollectPreseals(t, ctx, miners) - if err != nil { - return nil, err - } - - // now construct the genesis block - var genesisActors []genesis.Actor - var genesisMiners []genesis.Miner - - for _, bm := range balances { - balance := filToAttoFil(bm.Balance) - t.RecordMessage("balance assigned to actor %s: %s AttoFIL", bm.Addr, balance) - genesisActors = append(genesisActors, - genesis.Actor{ - Type: genesis.TAccount, - Balance: balance, - Meta: (&genesis.AccountMeta{Owner: bm.Addr}).ActorMeta(), - }) - } - - for _, pm := range preseals { - genesisMiners = append(genesisMiners, pm.Miner) - } - - genesisTemplate := genesis.Template{ - Accounts: genesisActors, - Miners: genesisMiners, - Timestamp: uint64(time.Now().Unix()) - uint64(t.IntParam("genesis_timestamp_offset")), - VerifregRootKey: gen.DefaultVerifregRootkeyActor, - RemainderAccount: gen.DefaultRemainderAccountActor, - NetworkName: "testground-local-" + uuid.New().String(), - } - - // dump the genesis block - // var jsonBuf bytes.Buffer - // jsonEnc := json.NewEncoder(&jsonBuf) - // err := jsonEnc.Encode(genesisTemplate) - // if err != nil { - // panic(err) - // } - // runenv.RecordMessage(fmt.Sprintf("Genesis template: %s", string(jsonBuf.Bytes()))) - - // this is horrendously disgusting, we use this contraption to side effect the construction - // of the genesis block in the buffer -- yes, a side effect of dependency injection. - // I remember when software was straightforward... - var genesisBuffer bytes.Buffer - - bootstrapperIP := t.NetClient.MustGetDataNetworkIP().String() - - n := &LotusNode{} - r := repo.NewMemory(nil) - stop, err := node.New(context.Background(), - node.FullAPI(&n.FullApi), - node.Base(), - node.Repo(r), - node.Override(new(modules.Genesis), modtest.MakeGenesisMem(&genesisBuffer, genesisTemplate)), - withApiEndpoint(fmt.Sprintf("/ip4/0.0.0.0/tcp/%s", t.PortNumber("node_rpc", "0"))), - withListenAddress(bootstrapperIP), - withBootstrapper(nil), - withPubsubConfig(true, pubsubTracerMaddr), - randomBeaconOpt, - ) - if err != nil { - return nil, err - } - n.StopFn = stop - - var bootstrapperAddr ma.Multiaddr - - bootstrapperAddrs, err := n.FullApi.NetAddrsListen(ctx) - if err != nil { - stop(context.TODO()) - return nil, err - } - for _, a := range bootstrapperAddrs.Addrs { - ip, err := a.ValueForProtocol(ma.P_IP4) - if err != nil { - continue - } - if ip != bootstrapperIP { - continue - } - addrs, err := peer.AddrInfoToP2pAddrs(&peer.AddrInfo{ - ID: bootstrapperAddrs.ID, - Addrs: []ma.Multiaddr{a}, - }) - if err != nil { - panic(err) - } - bootstrapperAddr = addrs[0] - break - } - - if bootstrapperAddr == nil { - panic("failed to determine bootstrapper address") - } - - genesisMsg := &GenesisMsg{ - Genesis: genesisBuffer.Bytes(), - Bootstrapper: bootstrapperAddr.Bytes(), - } - t.SyncClient.MustPublish(ctx, GenesisTopic, genesisMsg) - - t.RecordMessage("waiting for all nodes to be ready") - t.SyncClient.MustSignalAndWait(ctx, StateReady, t.TestInstanceCount) - - return &Bootstrapper{n, t}, nil -} - -// RunDefault runs a default bootstrapper. -func (b *Bootstrapper) RunDefault() error { - b.t.RecordMessage("running bootstrapper") - ctx := context.Background() - b.t.SyncClient.MustSignalAndWait(ctx, StateDone, b.t.TestInstanceCount) - return nil -} - -// filToAttoFil converts a fractional filecoin value into AttoFIL, rounding if necessary -func filToAttoFil(f float64) big.Int { - a := mbig.NewFloat(f) - a.Mul(a, mbig.NewFloat(float64(build.FilecoinPrecision))) - i, _ := a.Int(nil) - return big.Int{Int: i} -} - -func attoFilToFil(atto big.Int) big.Int { - i := big.NewInt(0) - i.Add(i.Int, atto.Int) - i.Div(i.Int, big.NewIntUnsigned(build.FilecoinPrecision).Int) - return i -} diff --git a/testplans/lotus-soup/testkit/role_client.go b/testplans/lotus-soup/testkit/role_client.go deleted file mode 100644 index afde27420..000000000 --- a/testplans/lotus-soup/testkit/role_client.go +++ /dev/null @@ -1,199 +0,0 @@ -package testkit - -import ( - "context" - "fmt" - "net/http" - "time" - - "contrib.go.opencensus.io/exporter/prometheus" - "github.com/gorilla/mux" - "github.com/hashicorp/go-multierror" - - "github.com/filecoin-project/go-jsonrpc" - "github.com/filecoin-project/go-jsonrpc/auth" - - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/chain/wallet/key" - "github.com/filecoin-project/lotus/node" - "github.com/filecoin-project/lotus/node/repo" -) - -type LotusClient struct { - *LotusNode - - t *TestEnvironment - MinerAddrs []MinerAddressesMsg -} - -func PrepareClient(t *TestEnvironment) (*LotusClient, error) { - ctx, cancel := context.WithTimeout(context.Background(), PrepareNodeTimeout) - defer cancel() - - ApplyNetworkParameters(t) - - pubsubTracer, err := GetPubsubTracerMaddr(ctx, t) - if err != nil { - return nil, err - } - - drandOpt, err := GetRandomBeaconOpts(ctx, t) - if err != nil { - return nil, err - } - - // first create a wallet - walletKey, err := key.GenerateKey(types.KTBLS) - if err != nil { - return nil, err - } - - // publish the account ID/balance - balance := t.FloatParam("balance") - balanceMsg := &InitialBalanceMsg{Addr: walletKey.Address, Balance: balance} - t.SyncClient.Publish(ctx, BalanceTopic, balanceMsg) - - // then collect the genesis block and bootstrapper address - genesisMsg, err := WaitForGenesis(t, ctx) - if err != nil { - return nil, err - } - - clientIP := t.NetClient.MustGetDataNetworkIP().String() - - nodeRepo := repo.NewMemory(nil) - - // create the node - n := &LotusNode{} - stop, err := node.New(context.Background(), - node.FullAPI(&n.FullApi), - node.Base(), - node.Repo(nodeRepo), - withApiEndpoint(fmt.Sprintf("/ip4/0.0.0.0/tcp/%s", t.PortNumber("node_rpc", "0"))), - withGenesis(genesisMsg.Genesis), - withListenAddress(clientIP), - withBootstrapper(genesisMsg.Bootstrapper), - withPubsubConfig(false, pubsubTracer), - drandOpt, - ) - if err != nil { - return nil, err - } - - // set the wallet - err = n.setWallet(ctx, walletKey) - if err != nil { - _ = stop(context.TODO()) - return nil, err - } - - fullSrv, err := startFullNodeAPIServer(t, nodeRepo, n.FullApi) - if err != nil { - return nil, err - } - - n.StopFn = func(ctx context.Context) error { - var err *multierror.Error - err = multierror.Append(fullSrv.Shutdown(ctx)) - err = multierror.Append(stop(ctx)) - return err.ErrorOrNil() - } - - registerAndExportMetrics(fmt.Sprintf("client_%d", t.GroupSeq)) - - t.RecordMessage("publish our address to the clients addr topic") - addrinfo, err := n.FullApi.NetAddrsListen(ctx) - if err != nil { - return nil, err - } - t.SyncClient.MustPublish(ctx, ClientsAddrsTopic, &ClientAddressesMsg{ - PeerNetAddr: addrinfo, - WalletAddr: walletKey.Address, - GroupSeq: t.GroupSeq, - }) - - t.RecordMessage("waiting for all nodes to be ready") - t.SyncClient.MustSignalAndWait(ctx, StateReady, t.TestInstanceCount) - - // collect miner addresses. - addrs, err := CollectMinerAddrs(t, ctx, t.IntParam("miners")) - if err != nil { - return nil, err - } - t.RecordMessage("got %v miner addrs", len(addrs)) - - // densely connect the client to the full node and the miners themselves. - for _, miner := range addrs { - if err := n.FullApi.NetConnect(ctx, miner.FullNetAddrs); err != nil { - return nil, fmt.Errorf("client failed to connect to full node of miner: %w", err) - } - if err := n.FullApi.NetConnect(ctx, miner.MinerNetAddrs); err != nil { - return nil, fmt.Errorf("client failed to connect to storage miner node node of miner: %w", err) - } - } - - // wait for all clients to have completed identify, pubsub negotiation with miners. - time.Sleep(1 * time.Second) - - peers, err := n.FullApi.NetPeers(ctx) - if err != nil { - return nil, fmt.Errorf("failed to query connected peers: %w", err) - } - - t.RecordMessage("connected peers: %d", len(peers)) - - cl := &LotusClient{ - t: t, - LotusNode: n, - MinerAddrs: addrs, - } - return cl, nil -} - -func (c *LotusClient) RunDefault() error { - // run forever - c.t.RecordMessage("running default client forever") - c.t.WaitUntilAllDone() - return nil -} - -func startFullNodeAPIServer(t *TestEnvironment, repo repo.Repo, napi api.FullNode) (*http.Server, error) { - mux := mux.NewRouter() - - rpcServer := jsonrpc.NewServer() - rpcServer.Register("Filecoin", napi) - - mux.Handle("/rpc/v0", rpcServer) - - exporter, err := prometheus.NewExporter(prometheus.Options{ - Namespace: "lotus", - }) - if err != nil { - return nil, err - } - - mux.Handle("/debug/metrics", exporter) - - ah := &auth.Handler{ - Verify: func(ctx context.Context, token string) ([]auth.Permission, error) { - return api.AllPermissions, nil - }, - Next: mux.ServeHTTP, - } - - srv := &http.Server{Handler: ah} - - endpoint, err := repo.APIEndpoint() - if err != nil { - return nil, fmt.Errorf("no API endpoint in repo: %w", err) - } - - listenAddr, err := startServer(endpoint, srv) - if err != nil { - return nil, fmt.Errorf("failed to start client API endpoint: %w", err) - } - - t.RecordMessage("started node API server at %s", listenAddr) - return srv, nil -} diff --git a/testplans/lotus-soup/testkit/role_drand.go b/testplans/lotus-soup/testkit/role_drand.go deleted file mode 100644 index bae36bd61..000000000 --- a/testplans/lotus-soup/testkit/role_drand.go +++ /dev/null @@ -1,391 +0,0 @@ -package testkit - -import ( - "bytes" - "context" - "encoding/hex" - "fmt" - "io/ioutil" - "net" - "os" - "path" - "time" - - "github.com/drand/drand/chain" - "github.com/drand/drand/client" - hclient "github.com/drand/drand/client/http" - "github.com/drand/drand/core" - "github.com/drand/drand/key" - "github.com/drand/drand/log" - "github.com/drand/drand/lp2p" - dnet "github.com/drand/drand/net" - "github.com/drand/drand/protobuf/drand" - dtest "github.com/drand/drand/test" - "github.com/libp2p/go-libp2p/core/peer" - ma "github.com/multiformats/go-multiaddr" - "github.com/testground/sdk-go/sync" - - "github.com/filecoin-project/lotus/node/modules/dtypes" - "github.com/filecoin-project/lotus/testplans/lotus-soup/statemachine" -) - -var ( - PrepareDrandTimeout = 3 * time.Minute - secretDKG = "dkgsecret" -) - -type DrandInstance struct { - daemon *core.Drand - httpClient client.Client - ctrlClient *dnet.ControlClient - gossipRelay *lp2p.GossipRelayNode - - t *TestEnvironment - stateDir string - priv *key.Pair - pubAddr string - privAddr string - ctrlAddr string -} - -func (dr *DrandInstance) Start() error { - opts := []core.ConfigOption{ - core.WithLogLevel(getLogLevel(dr.t)), - core.WithConfigFolder(dr.stateDir), - core.WithPublicListenAddress(dr.pubAddr), - core.WithPrivateListenAddress(dr.privAddr), - core.WithControlPort(dr.ctrlAddr), - core.WithInsecure(), - } - conf := core.NewConfig(opts...) - fs := key.NewFileStore(conf.ConfigFolder()) - fs.SaveKeyPair(dr.priv) - key.Save(path.Join(dr.stateDir, "public.toml"), dr.priv.Public, false) - if dr.daemon == nil { - drand, err := core.NewDrand(fs, conf) - if err != nil { - return err - } - dr.daemon = drand - } else { - drand, err := core.LoadDrand(fs, conf) - if err != nil { - return err - } - drand.StartBeacon(true) - dr.daemon = drand - } - return nil -} - -func (dr *DrandInstance) Ping() bool { - cl := dr.ctrl() - if err := cl.Ping(); err != nil { - return false - } - return true -} - -func (dr *DrandInstance) Close() error { - dr.gossipRelay.Shutdown() - dr.daemon.Stop(context.Background()) - return os.RemoveAll(dr.stateDir) -} - -func (dr *DrandInstance) ctrl() *dnet.ControlClient { - if dr.ctrlClient != nil { - return dr.ctrlClient - } - cl, err := dnet.NewControlClient(dr.ctrlAddr) - if err != nil { - dr.t.RecordMessage("drand can't instantiate control client: %w", err) - return nil - } - dr.ctrlClient = cl - return cl -} - -func (dr *DrandInstance) RunDKG(nodes, thr int, timeout string, leader bool, leaderAddr string, beaconOffset int) *key.Group { - cl := dr.ctrl() - p := dr.t.DurationParam("drand_period") - catchupPeriod := dr.t.DurationParam("drand_catchup_period") - t, _ := time.ParseDuration(timeout) - var grp *drand.GroupPacket - var err error - if leader { - grp, err = cl.InitDKGLeader(nodes, thr, p, catchupPeriod, t, nil, secretDKG, beaconOffset) - } else { - leader := dnet.CreatePeer(leaderAddr, false) - grp, err = cl.InitDKG(leader, nil, secretDKG) - } - if err != nil { - dr.t.RecordMessage("drand dkg run failed: %w", err) - return nil - } - kg, _ := key.GroupFromProto(grp) - return kg -} - -func (dr *DrandInstance) Halt() { - dr.t.RecordMessage("drand node #%d halting", dr.t.GroupSeq) - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - dr.daemon.Stop(ctx) -} - -func (dr *DrandInstance) Resume() { - dr.t.RecordMessage("drand node #%d resuming", dr.t.GroupSeq) - dr.Start() - // block until we can fetch the round corresponding to the current time - startTime := time.Now() - round := dr.httpClient.RoundAt(startTime) - timeout := 120 * time.Second - ctx, cancel := context.WithTimeout(context.Background(), timeout) - defer cancel() - - done := make(chan struct{}, 1) - go func() { - for { - res, err := dr.httpClient.Get(ctx, round) - if err == nil { - dr.t.RecordMessage("drand chain caught up to round %d", res.Round()) - done <- struct{}{} - return - } - time.Sleep(2 * time.Second) - } - }() - - select { - case <-ctx.Done(): - dr.t.RecordMessage("drand chain failed to catch up after %s", timeout.String()) - case <-done: - dr.t.RecordMessage("drand chain resumed after %s catchup time", time.Since(startTime)) - } -} - -func (dr *DrandInstance) RunDefault() error { - dr.t.RecordMessage("running drand node") - - if dr.t.IsParamSet("suspend_events") { - suspender := statemachine.NewSuspender(dr, dr.t.RecordMessage) - suspender.RunEvents(dr.t.StringParam("suspend_events")) - } - - dr.t.WaitUntilAllDone() - return nil -} - -// prepareDrandNode starts a drand instance and runs a DKG with the other members of the composition group. -// Once the chain is running, the leader publishes the chain info needed by lotus nodes on -// drandConfigTopic -func PrepareDrandInstance(t *TestEnvironment) (*DrandInstance, error) { - ctx, cancel := context.WithTimeout(context.Background(), PrepareDrandTimeout) - defer cancel() - - ApplyNetworkParameters(t) - - startTime := time.Now() - - seq := t.GroupSeq - isLeader := seq == 1 - nNodes := t.TestGroupInstanceCount - - myAddr := t.NetClient.MustGetDataNetworkIP() - threshold := t.IntParam("drand_threshold") - runGossipRelay := t.BooleanParam("drand_gossip_relay") - - beaconOffset := 3 - - stateDir, err := ioutil.TempDir("/tmp", fmt.Sprintf("drand-%d", t.GroupSeq)) - if err != nil { - return nil, err - } - - dr := DrandInstance{ - t: t, - stateDir: stateDir, - pubAddr: dtest.FreeBind(myAddr.String()), - privAddr: dtest.FreeBind(myAddr.String()), - ctrlAddr: dtest.FreeBind("localhost"), - } - dr.priv = key.NewKeyPair(dr.privAddr) - - // share the node addresses with other nodes - // TODO: if we implement TLS, this is where we'd share public TLS keys - type NodeAddr struct { - PrivateAddr string - PublicAddr string - IsLeader bool - } - addrTopic := sync.NewTopic("drand-addrs", &NodeAddr{}) - var publicAddrs []string - var leaderAddr string - ch := make(chan *NodeAddr) - _, sub := t.SyncClient.MustPublishSubscribe(ctx, addrTopic, &NodeAddr{ - PrivateAddr: dr.privAddr, - PublicAddr: dr.pubAddr, - IsLeader: isLeader, - }, ch) - for i := 0; i < nNodes; i++ { - select { - case msg := <-ch: - publicAddrs = append(publicAddrs, fmt.Sprintf("http://%s", msg.PublicAddr)) - if msg.IsLeader { - leaderAddr = msg.PrivateAddr - } - case err := <-sub.Done(): - return nil, fmt.Errorf("unable to read drand addrs from sync service: %w", err) - } - } - if leaderAddr == "" { - return nil, fmt.Errorf("got %d drand addrs, but no leader", len(publicAddrs)) - } - - t.SyncClient.MustSignalAndWait(ctx, "drand-start", nNodes) - t.RecordMessage("Starting drand sharing ceremony") - if err := dr.Start(); err != nil { - return nil, err - } - - alive := false - waitSecs := 10 - for i := 0; i < waitSecs; i++ { - if !dr.Ping() { - time.Sleep(time.Second) - continue - } - t.R().RecordPoint("drand_first_ping", time.Now().Sub(startTime).Seconds()) - alive = true - break - } - if !alive { - return nil, fmt.Errorf("drand node %d failed to start after %d seconds", t.GroupSeq, waitSecs) - } - - // run DKG - t.SyncClient.MustSignalAndWait(ctx, "drand-dkg-start", nNodes) - if !isLeader { - time.Sleep(3 * time.Second) - } - grp := dr.RunDKG(nNodes, threshold, "10s", isLeader, leaderAddr, beaconOffset) - if grp == nil { - return nil, fmt.Errorf("drand dkg failed") - } - t.R().RecordPoint("drand_dkg_complete", time.Now().Sub(startTime).Seconds()) - - t.RecordMessage("drand dkg complete, waiting for chain start: %v", time.Until(time.Unix(grp.GenesisTime, 0).Add(grp.Period))) - - // wait for chain to begin - to := time.Until(time.Unix(grp.GenesisTime, 0).Add(5 * time.Second).Add(grp.Period)) - time.Sleep(to) - - t.RecordMessage("drand beacon chain started, fetching initial round via http") - // verify that we can get a round of randomness from the chain using an http client - info := chain.NewChainInfo(grp) - myPublicAddr := fmt.Sprintf("http://%s", dr.pubAddr) - dr.httpClient, err = hclient.NewWithInfo(myPublicAddr, info, nil) - if err != nil { - return nil, fmt.Errorf("unable to create drand http client: %w", err) - } - - _, err = dr.httpClient.Get(ctx, 1) - if err != nil { - return nil, fmt.Errorf("unable to get initial drand round: %w", err) - } - - // start gossip relay (unless disabled via testplan parameter) - var relayAddrs []peer.AddrInfo - - if runGossipRelay { - gossipDir := path.Join(stateDir, "gossip-relay") - listenAddr := fmt.Sprintf("/ip4/%s/tcp/7777", myAddr.String()) - relayCfg := lp2p.GossipRelayConfig{ - ChainHash: hex.EncodeToString(info.Hash()), - Addr: listenAddr, - DataDir: gossipDir, - IdentityPath: path.Join(gossipDir, "identity.key"), - Insecure: true, - Client: dr.httpClient, - } - t.RecordMessage("starting drand gossip relay") - dr.gossipRelay, err = lp2p.NewGossipRelayNode(log.NewLogger(nil, getLogLevel(t)), &relayCfg) - if err != nil { - return nil, fmt.Errorf("failed to construct drand gossip relay: %w", err) - } - - t.RecordMessage("sharing gossip relay addrs") - // share the gossip relay addrs so we can publish them in DrandRuntimeInfo - relayInfo, err := relayAddrInfo(dr.gossipRelay.Multiaddrs(), myAddr) - if err != nil { - return nil, err - } - infoCh := make(chan *peer.AddrInfo, nNodes) - infoTopic := sync.NewTopic("drand-gossip-addrs", &peer.AddrInfo{}) - - _, sub := t.SyncClient.MustPublishSubscribe(ctx, infoTopic, relayInfo, infoCh) - for i := 0; i < nNodes; i++ { - select { - case ai := <-infoCh: - relayAddrs = append(relayAddrs, *ai) - case err := <-sub.Done(): - return nil, fmt.Errorf("unable to get drand relay addr from sync service: %w", err) - } - } - } - - // if we're the leader, publish the config to the sync service - if isLeader { - buf := bytes.Buffer{} - if err := info.ToJSON(&buf); err != nil { - return nil, fmt.Errorf("error marshaling chain info: %w", err) - } - cfg := DrandRuntimeInfo{ - Config: dtypes.DrandConfig{ - Servers: publicAddrs, - ChainInfoJSON: buf.String(), - }, - GossipBootstrap: relayAddrs, - } - t.DebugSpew("publishing drand config on sync topic: %v", cfg) - t.SyncClient.MustPublish(ctx, DrandConfigTopic, &cfg) - } - - // signal ready state - t.SyncClient.MustSignalAndWait(ctx, StateReady, t.TestInstanceCount) - return &dr, nil -} - -// waitForDrandConfig should be called by filecoin instances before constructing the lotus Node -// you can use the returned dtypes.DrandConfig to override the default production config. -func waitForDrandConfig(ctx context.Context, client sync.Client) (*DrandRuntimeInfo, error) { - ch := make(chan *DrandRuntimeInfo, 1) - sub := client.MustSubscribe(ctx, DrandConfigTopic, ch) - select { - case cfg := <-ch: - return cfg, nil - case err := <-sub.Done(): - return nil, err - } -} - -func relayAddrInfo(addrs []ma.Multiaddr, dataIP net.IP) (*peer.AddrInfo, error) { - for _, a := range addrs { - if ip, _ := a.ValueForProtocol(ma.P_IP4); ip != dataIP.String() { - continue - } - return peer.AddrInfoFromP2pAddr(a) - } - return nil, fmt.Errorf("no addr found with data ip %s in addrs: %v", dataIP, addrs) -} - -func getLogLevel(t *TestEnvironment) int { - switch t.StringParam("drand_log_level") { - case "info": - return log.LogInfo - case "debug": - return log.LogDebug - default: - return log.LogNone - } -} diff --git a/testplans/lotus-soup/testkit/role_miner.go b/testplans/lotus-soup/testkit/role_miner.go deleted file mode 100644 index 1a3319add..000000000 --- a/testplans/lotus-soup/testkit/role_miner.go +++ /dev/null @@ -1,651 +0,0 @@ -package testkit - -import ( - "context" - "crypto/rand" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "path/filepath" - "time" - - "contrib.go.opencensus.io/exporter/prometheus" - "github.com/google/uuid" - "github.com/gorilla/mux" - "github.com/hashicorp/go-multierror" - "github.com/ipfs/go-datastore" - libp2pcrypto "github.com/libp2p/go-libp2p/core/crypto" - "github.com/libp2p/go-libp2p/core/peer" - "github.com/testground/sdk-go/sync" - - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-jsonrpc" - "github.com/filecoin-project/go-jsonrpc/auth" - "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-storedcounter" - "github.com/filecoin-project/specs-actors/actors/builtin" - saminer "github.com/filecoin-project/specs-actors/actors/builtin/miner" - - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/chain/actors" - genesis_chain "github.com/filecoin-project/lotus/chain/gen/genesis" - "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/chain/wallet/key" - "github.com/filecoin-project/lotus/cmd/lotus-seed/seed" - "github.com/filecoin-project/lotus/markets/storageadapter" - "github.com/filecoin-project/lotus/miner" - "github.com/filecoin-project/lotus/node" - "github.com/filecoin-project/lotus/node/config" - "github.com/filecoin-project/lotus/node/impl" - "github.com/filecoin-project/lotus/node/repo" - "github.com/filecoin-project/lotus/storage/paths" - sealing "github.com/filecoin-project/lotus/storage/pipeline" - "github.com/filecoin-project/lotus/storage/sealer/storiface" -) - -const ( - sealDelay = 30 * time.Second -) - -type LotusMiner struct { - *LotusNode - - MinerRepo repo.Repo - NodeRepo repo.Repo - FullNetAddrs []peer.AddrInfo - GenesisMsg *GenesisMsg - Subsystems config.MinerSubsystemConfig - - t *TestEnvironment -} - -func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { - ctx, cancel := context.WithTimeout(context.Background(), PrepareNodeTimeout) - defer cancel() - - ApplyNetworkParameters(t) - - pubsubTracer, err := GetPubsubTracerMaddr(ctx, t) - if err != nil { - return nil, err - } - - drandOpt, err := GetRandomBeaconOpts(ctx, t) - if err != nil { - return nil, err - } - - // first create a wallet - walletKey, err := key.GenerateKey(types.KTBLS) - if err != nil { - return nil, err - } - - // publish the account ID/balance - balance := t.FloatParam("balance") - balanceMsg := &InitialBalanceMsg{Addr: walletKey.Address, Balance: balance} - t.SyncClient.Publish(ctx, BalanceTopic, balanceMsg) - - // create and publish the preseal commitment - priv, _, err := libp2pcrypto.GenerateEd25519Key(rand.Reader) - if err != nil { - return nil, err - } - - minerID, err := peer.IDFromPrivateKey(priv) - if err != nil { - return nil, err - } - - // pick unique sequence number for each miner, no matter in which group they are - seq := t.SyncClient.MustSignalAndWait(ctx, StateMinerPickSeqNum, t.IntParam("miners")) - - minerAddr, err := address.NewIDAddress(genesis_chain.MinerStart + uint64(seq-1)) - if err != nil { - return nil, err - } - - presealDir, err := ioutil.TempDir("", "preseal") - if err != nil { - return nil, err - } - - sectors := t.IntParam("sectors") - genMiner, _, err := seed.PreSeal(minerAddr, abi.RegisteredSealProof_StackedDrg8MiBV1, 0, sectors, presealDir, []byte("TODO: randomize this"), &walletKey.KeyInfo, false) - if err != nil { - return nil, err - } - genMiner.PeerId = minerID - - t.RecordMessage("Miner Info: Owner: %s Worker: %s", genMiner.Owner, genMiner.Worker) - - presealMsg := &PresealMsg{Miner: *genMiner, Seqno: seq} - t.SyncClient.Publish(ctx, PresealTopic, presealMsg) - - // then collect the genesis block and bootstrapper address - genesisMsg, err := WaitForGenesis(t, ctx) - if err != nil { - return nil, err - } - - // prepare the repo - minerRepoDir, err := ioutil.TempDir("", "miner-repo-dir") - if err != nil { - return nil, err - } - - minerRepo, err := repo.NewFS(minerRepoDir) - if err != nil { - return nil, err - } - - err = minerRepo.Init(repo.StorageMiner) - if err != nil { - return nil, err - } - - var subsystems config.MinerSubsystemConfig - - { - lr, err := minerRepo.Lock(repo.StorageMiner) - if err != nil { - return nil, err - } - - c, err := lr.Config() - if err != nil { - return nil, err - } - - cfg := c.(*config.StorageMiner) - subsystems = cfg.Subsystems - - ks, err := lr.KeyStore() - if err != nil { - return nil, err - } - - kbytes, err := libp2pcrypto.MarshalPrivateKey(priv) - if err != nil { - return nil, err - } - - err = ks.Put("libp2p-host", types.KeyInfo{ - Type: "libp2p-host", - PrivateKey: kbytes, - }) - if err != nil { - return nil, err - } - - ds, err := lr.Datastore(context.Background(), "/metadata") - if err != nil { - return nil, err - } - - err = ds.Put(context.Background(), datastore.NewKey("miner-address"), minerAddr.Bytes()) - if err != nil { - return nil, err - } - - nic := storedcounter.New(ds, datastore.NewKey(sealing.StorageCounterDSPrefix)) - for i := 0; i < (sectors + 1); i++ { - _, err = nic.Next() - if err != nil { - return nil, err - } - } - - var localPaths []paths.LocalPath - - b, err := json.MarshalIndent(&paths.LocalStorageMeta{ - ID: storiface.ID(uuid.New().String()), - Weight: 10, - CanSeal: true, - CanStore: true, - }, "", " ") - if err != nil { - return nil, fmt.Errorf("marshaling storage config: %w", err) - } - - if err := ioutil.WriteFile(filepath.Join(lr.Path(), "sectorstore.json"), b, 0644); err != nil { - return nil, fmt.Errorf("persisting storage metadata (%s): %w", filepath.Join(lr.Path(), "sectorstore.json"), err) - } - - localPaths = append(localPaths, paths.LocalPath{ - Path: lr.Path(), - }) - - if err := lr.SetStorage(func(sc *paths.StorageConfig) { - sc.StoragePaths = append(sc.StoragePaths, localPaths...) - }); err != nil { - return nil, err - } - - err = lr.Close() - if err != nil { - return nil, err - } - } - - minerIP := t.NetClient.MustGetDataNetworkIP().String() - - // create the node - // we need both a full node _and_ and storage miner node - n := &LotusNode{} - - // prepare the repo - nodeRepoDir, err := ioutil.TempDir("", "node-repo-dir") - if err != nil { - return nil, err - } - - nodeRepo, err := repo.NewFS(nodeRepoDir) - if err != nil { - return nil, err - } - - err = nodeRepo.Init(repo.FullNode) - if err != nil { - return nil, err - } - - stop1, err := node.New(context.Background(), - node.FullAPI(&n.FullApi), - node.Base(), - node.Repo(nodeRepo), - withGenesis(genesisMsg.Genesis), - withApiEndpoint(fmt.Sprintf("/ip4/0.0.0.0/tcp/%s", t.PortNumber("node_rpc", "0"))), - withListenAddress(minerIP), - withBootstrapper(genesisMsg.Bootstrapper), - withPubsubConfig(false, pubsubTracer), - drandOpt, - ) - if err != nil { - return nil, fmt.Errorf("node node.new error: %w", err) - } - - // set the wallet - err = n.setWallet(ctx, walletKey) - if err != nil { - stop1(context.TODO()) - return nil, err - } - - minerOpts := []node.Option{ - node.StorageMiner(&n.MinerApi, subsystems), - node.Base(), - node.Repo(minerRepo), - node.Override(new(api.FullNode), n.FullApi), - node.Override(new(*storageadapter.DealPublisher), storageadapter.NewDealPublisher(nil, storageadapter.PublishMsgConfig{ - Period: 15 * time.Second, - MaxDealsPerMsg: 1, - })), - withApiEndpoint(fmt.Sprintf("/ip4/0.0.0.0/tcp/%s", t.PortNumber("miner_rpc", "0"))), - withMinerListenAddress(minerIP), - } - - if t.StringParam("mining_mode") != "natural" { - mineBlock := make(chan miner.MineReq) - - minerOpts = append(minerOpts, - node.Override(new(*miner.Miner), miner.NewTestMiner(mineBlock, minerAddr))) - - n.MineOne = func(ctx context.Context, cb miner.MineReq) error { - select { - case mineBlock <- cb: - return nil - case <-ctx.Done(): - return ctx.Err() - } - } - } - - stop2, err := node.New(context.Background(), minerOpts...) - if err != nil { - stop1(context.TODO()) - return nil, fmt.Errorf("miner node.new error: %w", err) - } - - registerAndExportMetrics(minerAddr.String()) - - // collect stats based on blockchain from first instance of `miner` role - if t.InitContext.GroupSeq == 1 && t.Role == "miner" { - go collectStats(t, ctx, n.FullApi) - } - - // Start listening on the full node. - fullNodeNetAddrs, err := n.FullApi.NetAddrsListen(ctx) - if err != nil { - panic(err) - } - - // set seal delay to lower value than 1 hour - err = n.MinerApi.SectorSetSealDelay(ctx, sealDelay) - if err != nil { - return nil, err - } - - // set expected seal duration to 1 minute - err = n.MinerApi.SectorSetExpectedSealDuration(ctx, 1*time.Minute) - if err != nil { - return nil, err - } - - // print out the admin auth token - token, err := n.MinerApi.AuthNew(ctx, api.AllPermissions) - if err != nil { - return nil, err - } - - t.RecordMessage("Auth token: %s", string(token)) - - // add local storage for presealed sectors - err = n.MinerApi.StorageAddLocal(ctx, presealDir) - if err != nil { - return nil, err - } - - // set the miner PeerID - minerIDEncoded, err := actors.SerializeParams(&saminer.ChangePeerIDParams{NewID: abi.PeerID(minerID)}) - if err != nil { - return nil, err - } - - changeMinerID := &types.Message{ - To: minerAddr, - From: genMiner.Worker, - Method: builtin.MethodsMiner.ChangePeerID, - Params: minerIDEncoded, - Value: types.NewInt(0), - } - - _, err = n.FullApi.MpoolPushMessage(ctx, changeMinerID, nil) - if err != nil { - return nil, err - } - - t.RecordMessage("publish our address to the miners addr topic") - minerActor, err := n.MinerApi.ActorAddress(ctx) - if err != nil { - return nil, err - } - - minerNetAddrs, err := n.MinerApi.NetAddrsListen(ctx) - if err != nil { - return nil, err - } - - t.SyncClient.MustPublish(ctx, MinersAddrsTopic, MinerAddressesMsg{ - FullNetAddrs: fullNodeNetAddrs, - MinerNetAddrs: minerNetAddrs, - MinerActorAddr: minerActor, - WalletAddr: walletKey.Address, - }) - - t.RecordMessage("connecting to all other miners") - - // densely connect the miner's full nodes. - minerCh := make(chan *MinerAddressesMsg, 16) - sctx, cancel := context.WithCancel(ctx) - defer cancel() - t.SyncClient.MustSubscribe(sctx, MinersAddrsTopic, minerCh) - var fullNetAddrs []peer.AddrInfo - for i := 0; i < t.IntParam("miners"); i++ { - m := <-minerCh - if m.MinerActorAddr == minerActor { - // once I find myself, I stop connecting to others, to avoid a simopen problem. - break - } - err := n.FullApi.NetConnect(ctx, m.FullNetAddrs) - if err != nil { - return nil, fmt.Errorf("failed to connect to miner %s on: %v", m.MinerActorAddr, m.FullNetAddrs) - } - t.RecordMessage("connected to full node of miner %s on %v", m.MinerActorAddr, m.FullNetAddrs) - - fullNetAddrs = append(fullNetAddrs, m.FullNetAddrs) - } - - t.RecordMessage("waiting for all nodes to be ready") - t.SyncClient.MustSignalAndWait(ctx, StateReady, t.TestInstanceCount) - - fullSrv, err := startFullNodeAPIServer(t, nodeRepo, n.FullApi) - if err != nil { - return nil, err - } - - minerSrv, err := startStorageMinerAPIServer(t, minerRepo, n.MinerApi) - if err != nil { - return nil, err - } - - n.StopFn = func(ctx context.Context) error { - var err *multierror.Error - err = multierror.Append(fullSrv.Shutdown(ctx)) - err = multierror.Append(minerSrv.Shutdown(ctx)) - err = multierror.Append(stop2(ctx)) - err = multierror.Append(stop2(ctx)) - err = multierror.Append(stop1(ctx)) - return err.ErrorOrNil() - } - - m := &LotusMiner{n, minerRepo, nodeRepo, fullNetAddrs, genesisMsg, subsystems, t} - - return m, nil -} - -func RestoreMiner(t *TestEnvironment, m *LotusMiner) (*LotusMiner, error) { - ctx, cancel := context.WithTimeout(context.Background(), PrepareNodeTimeout) - defer cancel() - - minerRepo := m.MinerRepo - nodeRepo := m.NodeRepo - fullNetAddrs := m.FullNetAddrs - genesisMsg := m.GenesisMsg - - minerIP := t.NetClient.MustGetDataNetworkIP().String() - - drandOpt, err := GetRandomBeaconOpts(ctx, t) - if err != nil { - return nil, err - } - - // create the node - // we need both a full node _and_ and storage miner node - n := &LotusNode{} - - stop1, err := node.New(context.Background(), - node.FullAPI(&n.FullApi), - node.Base(), - node.Repo(nodeRepo), - //withGenesis(genesisMsg.Genesis), - withApiEndpoint(fmt.Sprintf("/ip4/0.0.0.0/tcp/%s", t.PortNumber("node_rpc", "0"))), - withListenAddress(minerIP), - withBootstrapper(genesisMsg.Bootstrapper), - //withPubsubConfig(false, pubsubTracer), - drandOpt, - ) - if err != nil { - return nil, err - } - - minerOpts := []node.Option{ - node.StorageMiner(&n.MinerApi, m.Subsystems), - node.Base(), - node.Repo(minerRepo), - node.Override(new(api.FullNode), n.FullApi), - withApiEndpoint(fmt.Sprintf("/ip4/0.0.0.0/tcp/%s", t.PortNumber("miner_rpc", "0"))), - withMinerListenAddress(minerIP), - } - - stop2, err := node.New(context.Background(), minerOpts...) - if err != nil { - stop1(context.TODO()) - return nil, err - } - - fullSrv, err := startFullNodeAPIServer(t, nodeRepo, n.FullApi) - if err != nil { - return nil, err - } - - minerSrv, err := startStorageMinerAPIServer(t, minerRepo, n.MinerApi) - if err != nil { - return nil, err - } - - n.StopFn = func(ctx context.Context) error { - var err *multierror.Error - err = multierror.Append(fullSrv.Shutdown(ctx)) - err = multierror.Append(minerSrv.Shutdown(ctx)) - err = multierror.Append(stop2(ctx)) - err = multierror.Append(stop2(ctx)) - err = multierror.Append(stop1(ctx)) - return err.ErrorOrNil() - } - - for i := 0; i < len(fullNetAddrs); i++ { - err := n.FullApi.NetConnect(ctx, fullNetAddrs[i]) - if err != nil { - // we expect a failure since we also shutdown another miner - t.RecordMessage("failed to connect to miner %d on: %v", i, fullNetAddrs[i]) - continue - } - t.RecordMessage("connected to full node of miner %d on %v", i, fullNetAddrs[i]) - } - - pm := &LotusMiner{n, minerRepo, nodeRepo, fullNetAddrs, genesisMsg, m.Subsystems, t} - - return pm, err -} - -func (m *LotusMiner) RunDefault() error { - var ( - t = m.t - clients = t.IntParam("clients") - miners = t.IntParam("miners") - ) - - t.RecordMessage("running miner") - t.RecordMessage("block delay: %v", build.BlockDelaySecs) - t.D().Gauge("miner.block-delay").Update(float64(build.BlockDelaySecs)) - - ctx := context.Background() - myActorAddr, err := m.MinerApi.ActorAddress(ctx) - if err != nil { - return err - } - - // mine / stop mining - mine := true - done := make(chan struct{}) - - if m.MineOne != nil { - go func() { - defer t.RecordMessage("shutting down mining") - defer close(done) - - var i int - for i = 0; mine; i++ { - // synchronize all miners to mine the next block - t.RecordMessage("synchronizing all miners to mine next block [%d]", i) - stateMineNext := sync.State(fmt.Sprintf("mine-block-%d", i)) - t.SyncClient.MustSignalAndWait(ctx, stateMineNext, miners) - - ch := make(chan error) - const maxRetries = 100 - success := false - for retries := 0; retries < maxRetries; retries++ { - f := func(mined bool, epoch abi.ChainEpoch, err error) { - if mined { - t.D().Counter(fmt.Sprintf("block.mine,miner=%s", myActorAddr)).Inc(1) - } - ch <- err - } - req := miner.MineReq{ - Done: f, - } - err := m.MineOne(ctx, req) - if err != nil { - panic(err) - } - - miningErr := <-ch - if miningErr == nil { - success = true - break - } - t.D().Counter("block.mine.err").Inc(1) - t.RecordMessage("retrying block [%d] after %d attempts due to mining error: %s", - i, retries, miningErr) - } - if !success { - panic(fmt.Errorf("failed to mine block %d after %d retries", i, maxRetries)) - } - } - - // signal the last block to make sure no miners are left stuck waiting for the next block signal - // while the others have stopped - stateMineLast := sync.State(fmt.Sprintf("mine-block-%d", i)) - t.SyncClient.MustSignalEntry(ctx, stateMineLast) - }() - } else { - close(done) - } - - // wait for a signal from all clients to stop mining - err = <-t.SyncClient.MustBarrier(ctx, StateStopMining, clients).C - if err != nil { - return err - } - - mine = false - <-done - - t.SyncClient.MustSignalAndWait(ctx, StateDone, t.TestInstanceCount) - return nil -} - -func startStorageMinerAPIServer(t *TestEnvironment, repo repo.Repo, minerApi api.StorageMiner) (*http.Server, error) { - mux := mux.NewRouter() - - rpcServer := jsonrpc.NewServer() - rpcServer.Register("Filecoin", minerApi) - - mux.Handle("/rpc/v0", rpcServer) - mux.PathPrefix("/remote").HandlerFunc(minerApi.(*impl.StorageMinerAPI).ServeRemote(true)) - mux.PathPrefix("/").Handler(http.DefaultServeMux) // pprof - - exporter, err := prometheus.NewExporter(prometheus.Options{ - Namespace: "lotus", - }) - if err != nil { - return nil, err - } - - mux.Handle("/debug/metrics", exporter) - - ah := &auth.Handler{ - Verify: func(ctx context.Context, token string) ([]auth.Permission, error) { - return api.AllPermissions, nil - }, - Next: mux.ServeHTTP, - } - - endpoint, err := repo.APIEndpoint() - if err != nil { - return nil, fmt.Errorf("no API endpoint in repo: %w", err) - } - - srv := &http.Server{Handler: ah} - - listenAddr, err := startServer(endpoint, srv) - if err != nil { - return nil, fmt.Errorf("failed to start storage miner API endpoint: %w", err) - } - - t.RecordMessage("started storage miner API server at %s", listenAddr) - return srv, nil -} diff --git a/testplans/lotus-soup/testkit/role_pubsub_tracer.go b/testplans/lotus-soup/testkit/role_pubsub_tracer.go deleted file mode 100644 index 8d89f23d7..000000000 --- a/testplans/lotus-soup/testkit/role_pubsub_tracer.go +++ /dev/null @@ -1,78 +0,0 @@ -package testkit - -import ( - "context" - "crypto/rand" - "fmt" - - "github.com/libp2p/go-libp2p" - "github.com/libp2p/go-libp2p-pubsub-tracer/traced" - "github.com/libp2p/go-libp2p/core/crypto" - "github.com/libp2p/go-libp2p/core/host" - ma "github.com/multiformats/go-multiaddr" -) - -type PubsubTracer struct { - t *TestEnvironment - host host.Host - traced *traced.TraceCollector -} - -func PreparePubsubTracer(t *TestEnvironment) (*PubsubTracer, error) { - ctx := context.Background() - - privk, _, err := crypto.GenerateEd25519Key(rand.Reader) - if err != nil { - return nil, err - } - - tracedIP := t.NetClient.MustGetDataNetworkIP().String() - tracedAddr := fmt.Sprintf("/ip4/%s/tcp/4001", tracedIP) - - host, err := libp2p.New( - libp2p.Identity(privk), - libp2p.ListenAddrStrings(tracedAddr), - ) - if err != nil { - return nil, err - } - - tracedDir := t.TestOutputsPath + "/traced.logs" - traced, err := traced.NewTraceCollector(host, tracedDir) - if err != nil { - host.Close() - return nil, err - } - - tracedMultiaddrStr := fmt.Sprintf("%s/p2p/%s", tracedAddr, host.ID()) - t.RecordMessage("I am %s", tracedMultiaddrStr) - - _ = ma.StringCast(tracedMultiaddrStr) - tracedMsg := &PubsubTracerMsg{Multiaddr: tracedMultiaddrStr} - t.SyncClient.MustPublish(ctx, PubsubTracerTopic, tracedMsg) - - t.RecordMessage("waiting for all nodes to be ready") - t.SyncClient.MustSignalAndWait(ctx, StateReady, t.TestInstanceCount) - - tracer := &PubsubTracer{t: t, host: host, traced: traced} - return tracer, nil -} - -func (tr *PubsubTracer) RunDefault() error { - tr.t.RecordMessage("running pubsub tracer") - - defer func() { - err := tr.Stop() - if err != nil { - tr.t.RecordMessage("error stoping tracer: %s", err) - } - }() - - tr.t.WaitUntilAllDone() - return nil -} - -func (tr *PubsubTracer) Stop() error { - tr.traced.Stop() - return tr.host.Close() -} diff --git a/testplans/lotus-soup/testkit/sync.go b/testplans/lotus-soup/testkit/sync.go deleted file mode 100644 index cab08594c..000000000 --- a/testplans/lotus-soup/testkit/sync.go +++ /dev/null @@ -1,71 +0,0 @@ -package testkit - -import ( - "github.com/libp2p/go-libp2p/core/peer" - "github.com/testground/sdk-go/sync" - - "github.com/filecoin-project/go-address" - - "github.com/filecoin-project/lotus/genesis" - "github.com/filecoin-project/lotus/node/modules/dtypes" -) - -var ( - GenesisTopic = sync.NewTopic("genesis", &GenesisMsg{}) - BalanceTopic = sync.NewTopic("balance", &InitialBalanceMsg{}) - PresealTopic = sync.NewTopic("preseal", &PresealMsg{}) - ClientsAddrsTopic = sync.NewTopic("clients_addrs", &ClientAddressesMsg{}) - MinersAddrsTopic = sync.NewTopic("miners_addrs", &MinerAddressesMsg{}) - SlashedMinerTopic = sync.NewTopic("slashed_miner", &SlashedMinerMsg{}) - PubsubTracerTopic = sync.NewTopic("pubsub_tracer", &PubsubTracerMsg{}) - DrandConfigTopic = sync.NewTopic("drand_config", &DrandRuntimeInfo{}) -) - -var ( - StateReady = sync.State("ready") - StateDone = sync.State("done") - StateStopMining = sync.State("stop-mining") - StateMinerPickSeqNum = sync.State("miner-pick-seq-num") - StateAbortTest = sync.State("abort-test") -) - -type InitialBalanceMsg struct { - Addr address.Address - Balance float64 -} - -type PresealMsg struct { - Miner genesis.Miner - Seqno int64 -} - -type GenesisMsg struct { - Genesis []byte - Bootstrapper []byte -} - -type ClientAddressesMsg struct { - PeerNetAddr peer.AddrInfo - WalletAddr address.Address - GroupSeq int64 -} - -type MinerAddressesMsg struct { - FullNetAddrs peer.AddrInfo - MinerNetAddrs peer.AddrInfo - MinerActorAddr address.Address - WalletAddr address.Address -} - -type SlashedMinerMsg struct { - MinerActorAddr address.Address -} - -type PubsubTracerMsg struct { - Multiaddr string -} - -type DrandRuntimeInfo struct { - Config dtypes.DrandConfig - GossipBootstrap dtypes.DrandBootstrap -} diff --git a/testplans/lotus-soup/testkit/testenv.go b/testplans/lotus-soup/testkit/testenv.go deleted file mode 100644 index 63c297b03..000000000 --- a/testplans/lotus-soup/testkit/testenv.go +++ /dev/null @@ -1,88 +0,0 @@ -package testkit - -import ( - "context" - "encoding/json" - "fmt" - "strings" - "time" - - "github.com/davecgh/go-spew/spew" - "github.com/testground/sdk-go/run" - "github.com/testground/sdk-go/runtime" -) - -type TestEnvironment struct { - *runtime.RunEnv - *run.InitContext - - Role string -} - -// workaround for default params being wrapped in quote chars -func (t *TestEnvironment) StringParam(name string) string { - return strings.Trim(t.RunEnv.StringParam(name), "\"") -} - -func (t *TestEnvironment) DurationParam(name string) time.Duration { - d, err := time.ParseDuration(t.StringParam(name)) - if err != nil { - panic(fmt.Errorf("invalid duration value for param '%s': %w", name, err)) - } - return d -} - -func (t *TestEnvironment) DurationRangeParam(name string) DurationRange { - var r DurationRange - t.JSONParam(name, &r) - return r -} - -func (t *TestEnvironment) FloatRangeParam(name string) FloatRange { - r := FloatRange{} - t.JSONParam(name, &r) - return r -} - -func (t *TestEnvironment) DebugSpew(format string, args ...interface{}) { - t.RecordMessage(spew.Sprintf(format, args...)) -} - -func (t *TestEnvironment) DumpJSON(filename string, v interface{}) { - b, err := json.Marshal(v) - if err != nil { - t.RecordMessage("unable to marshal object to JSON: %s", err) - return - } - f, err := t.CreateRawAsset(filename) - if err != nil { - t.RecordMessage("unable to create asset file: %s", err) - return - } - defer f.Close() - - _, err = f.Write(b) - if err != nil { - t.RecordMessage("error writing json object dump: %s", err) - } -} - -// WaitUntilAllDone waits until all instances in the test case are done. -func (t *TestEnvironment) WaitUntilAllDone() { - ctx := context.Background() - t.SyncClient.MustSignalAndWait(ctx, StateDone, t.TestInstanceCount) -} - -// WrapTestEnvironment takes a test case function that accepts a -// *TestEnvironment, and adapts it to the original unwrapped SDK style -// (run.InitializedTestCaseFn). -func WrapTestEnvironment(f func(t *TestEnvironment) error) run.InitializedTestCaseFn { - return func(runenv *runtime.RunEnv, initCtx *run.InitContext) error { - t := &TestEnvironment{RunEnv: runenv, InitContext: initCtx} - t.Role = t.StringParam("role") - - t.DumpJSON("test-parameters.json", t.TestInstanceParams) - - return f(t) - } -} diff --git a/testplans/lotus-soup/testkit/testenv_ranges.go b/testplans/lotus-soup/testkit/testenv_ranges.go deleted file mode 100644 index 110ce60d1..000000000 --- a/testplans/lotus-soup/testkit/testenv_ranges.go +++ /dev/null @@ -1,77 +0,0 @@ -package testkit - -import ( - "encoding/json" - "fmt" - "math/rand" - "time" - - "github.com/testground/sdk-go/ptypes" -) - -// DurationRange is a Testground parameter type that represents a duration -// range, suitable use in randomized tests. This type is encoded as a JSON array -// of length 2 of element type ptypes.Duration, e.g. ["10s", "10m"]. -type DurationRange struct { - Min time.Duration - Max time.Duration -} - -func (r *DurationRange) ChooseRandom() time.Duration { - i := int64(r.Min) + rand.Int63n(int64(r.Max)-int64(r.Min)) - return time.Duration(i) -} - -func (r *DurationRange) UnmarshalJSON(b []byte) error { - var s []ptypes.Duration - if err := json.Unmarshal(b, &s); err != nil { - return err - } - if len(s) != 2 { - return fmt.Errorf("expected two-element array of duration strings, got array of length %d", len(s)) - } - if s[0].Duration > s[1].Duration { - return fmt.Errorf("expected first element to be <= second element") - } - r.Min = s[0].Duration - r.Max = s[1].Duration - return nil -} - -func (r *DurationRange) MarshalJSON() ([]byte, error) { - s := []ptypes.Duration{{r.Min}, {r.Max}} - return json.Marshal(s) -} - -// FloatRange is a Testground parameter type that represents a float -// range, suitable use in randomized tests. This type is encoded as a JSON array -// of length 2 of element type float32, e.g. [1.45, 10.675]. -type FloatRange struct { - Min float32 - Max float32 -} - -func (r *FloatRange) ChooseRandom() float32 { - return r.Min + rand.Float32()*(r.Max-r.Min) -} - -func (r *FloatRange) UnmarshalJSON(b []byte) error { - var s []float32 - if err := json.Unmarshal(b, &s); err != nil { - return err - } - if len(s) != 2 { - return fmt.Errorf("expected two-element array of floats, got array of length %d", len(s)) - } - if s[0] > s[1] { - return fmt.Errorf("expected first element to be <= second element") - } - r.Min = s[0] - r.Max = s[1] - return nil -} - -func (r *FloatRange) MarshalJSON() ([]byte, error) { - s := []float32{r.Min, r.Max} - return json.Marshal(s) -} diff --git a/testplans/notes/.empty b/testplans/notes/.empty deleted file mode 100644 index e69de29bb..000000000 diff --git a/testplans/notes/raulk.md b/testplans/notes/raulk.md deleted file mode 100644 index 88476f2a3..000000000 --- a/testplans/notes/raulk.md +++ /dev/null @@ -1,55 +0,0 @@ -# Raúl's notes - -## Storage mining - -The Storage Mining System is the part of the Filecoin Protocol that deals with -storing Client’s data, producing proof artifacts that demonstrate correct -storage behavior, and managing the work involved. - -## Preseals - -In the Filecoin consensus protocol, the miners' probability of being eligible -to mine a block in a given epoch is directly correlated with their power in the -network. This creates a chicken-and-egg problem at genesis. Since there are no -miners, there is no power in the network, therefore no miner is eligible to mine -and advance the chain. - -Preseals are sealed sectors that are blessed at genesis, thus conferring -their miners the possibility to win round elections and successfully mine a -block. Without preseals, the chain would be dead on arrival. - -Preseals work with fauxrep and faux sealing, which are special-case -implementations of PoRep and the sealing logic that do not depend on slow -sealing. - -### Not implemented things - -**Sector Resealing:** Miners should be able to ’re-seal’ sectors, to allow them -to take a set of sectors with mostly expired pieces, and combine the -not-yet-expired pieces into a single (or multiple) sectors. - -**Sector Transfer:** Miners should be able to re-delegate the responsibility of -storing data to another miner. This is tricky for many reasons, and will not be -implemented in the initial release of Filecoin, but could provide interesting -capabilities down the road. - -## Catch-up/rush mining - -In catch-up or rush mining, miners make up for chain history that does not -exist. It's a recovery/healing procedure. The chain runs at at constant -25 second epoch time. When in the network mining halts for some reason -(consensus/liveness bug, drand availability issues, etc.), upon a restart miners -will go and backfill the chain history by mining backdated blocks in -the appropriate timestamps. - -There are a few things worth highlighting: - * mining runs in a hot loop, and there is no time for miners to gossip about - their blocks; therefore they end up building the chain solo, as they can't - incorprate other blocks into tipsets. - * the miner with most power will mine most blocks. - * presumably, as many forks in the network will appear as miners who mined a - block + a fork filled with null rounds only (for miners that didn't win a - round). - * at the end of the catch-up, the heaviest fork will win the race, and it may - be possible for the most powerful miner pre-disruption to affect the - outcome by choosing the messages that go in their blocks. diff --git a/tools/packer/lotus-snap.pkr.hcl b/tools/packer/lotus-snap.pkr.hcl index 8ceb743d0..b42272c20 100644 --- a/tools/packer/lotus-snap.pkr.hcl +++ b/tools/packer/lotus-snap.pkr.hcl @@ -56,6 +56,11 @@ source "amazon-ebs" "lotus" { owners = ["099720109477"] } ssh_username = "ubuntu" + + aws_polling { + delay_seconds = 60 + max_attempts = 60 + } } source "digitalocean" "lotus" { @@ -82,3 +87,4 @@ build { script = "./tools/packer/setup-snap.sh" } } + diff --git a/tools/packer/setup-snap.sh b/tools/packer/setup-snap.sh index 3db06e5b4..615877f83 100644 --- a/tools/packer/setup-snap.sh +++ b/tools/packer/setup-snap.sh @@ -23,13 +23,11 @@ MANAGED_FILES=( ) # this is required on digitalocean, which does not have snap seeded correctly at this phase. -apt update -apt reinstall snapd +apt-get -y -o DPkg::Lock::Timeout=3 update \ + && apt-get -y -o DPkg::Lock::Timeout=3 reinstall snapd snap install lotus -snap alias lotus.lotus lotus -snap alias lotus.lotus-daemon lotus-daemon snap alias lotus.lotus-miner lotus-miner snap alias lotus.lotus-worker lotus-worker