diff --git a/.circleci/config.yml b/.circleci/config.yml index a40a162aa..3da57d246 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ jobs: executor: continuation/default steps: - checkout - - run: + - run: name: Generate params # for builds on the ipfs/kubo repo, use 2xlarge for faster builds # but since this is not available for many contributors, we otherwise use medium diff --git a/.circleci/main.yml b/.circleci/main.yml index 08e176656..6406c6655 100644 --- a/.circleci/main.yml +++ b/.circleci/main.yml @@ -143,14 +143,17 @@ jobs: path: /tmp/circleci-test-results sharness: machine: - image: ubuntu-2004:202010-01 + image: ubuntu-2204:2022.10.1 resource_class: << pipeline.parameters.resource_class >> working_directory: ~/ipfs/kubo environment: <<: *default_environment TEST_NO_DOCKER: 0 + TEST_NO_PLUGIN: 1 TEST_NO_FUSE: 1 TEST_VERBOSE: 1 + TEST_JUNIT: 1 + TEST_EXPENSIVE: 1 steps: - run: sudo apt update - run: | @@ -159,7 +162,7 @@ jobs: tar xfz go1.19.1.linux-amd64.tar.gz echo "export PATH=$(pwd)/go/bin:\$PATH" >> ~/.bashrc - run: go version - - run: sudo apt install socat net-tools fish + - run: sudo apt install socat net-tools fish libxml2-utils - checkout - run: @@ -183,7 +186,7 @@ jobs: command: echo "export TEST_DOCKER_HOST=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')" >> $BASH_ENV - run: echo TEST_DOCKER_HOST=$TEST_DOCKER_HOST && - make -O -j << pipeline.parameters.make_jobs >> coverage/sharness_tests.coverprofile test/sharness/test-results/sharness.xml TEST_GENERATE_JUNIT=1 CONTINUE_ON_S_FAILURE=1 TEST_DOCKER_HOST=$TEST_DOCKER_HOST + make -O -j << pipeline.parameters.make_jobs >> test_sharness coverage/sharness_tests.coverprofile test/sharness/test-results/sharness.xml CONTINUE_ON_S_FAILURE=1 TEST_DOCKER_HOST=$TEST_DOCKER_HOST - run: when: always command: bash <(curl -s https://codecov.io/bash) -cF sharness -X search -f coverage/sharness_tests.coverprofile @@ -345,13 +348,13 @@ jobs: npx playwright install working_directory: ~/ipfs/kubo/ipfs-webui - run: - name: Running upstream tests (finish early if they fail) + name: Run ipfs-webui@main build and smoke-test to confirm the upstream repo is not broken command: | - npm test || circleci-agent step halt + npm test working_directory: ~/ipfs/kubo/ipfs-webui - run: - name: Running tests with kubo built from current commit - command: npm test + name: Test ipfs-webui@main E2E against the locally built Kubo binary + command: npm run test:e2e working_directory: ~/ipfs/kubo/ipfs-webui environment: IPFS_GO_EXEC: /tmp/circleci-workspace/bin/ipfs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..d0b4194b7 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,200 @@ +name: 'ci/gh-experiment: interop' + +on: + workflow_dispatch: + pull_request: + push: + branches: + - 'master' + +env: + GO_VERSION: 1.19.1 + +jobs: + prepare: + if: github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + env: + TEST_NO_DOCKER: 1 + TEST_NO_FUSE: 1 + TEST_VERBOSE: 1 + TRAVIS: 1 + GIT_PAGER: cat + IPFS_CHECK_RCMGR_DEFAULTS: 1 + defaults: + run: + shell: bash + steps: + - uses: actions/setup-go@v3 + with: + go-version: ${{ env.GO_VERSION }} + - uses: actions/checkout@v3 + - uses: protocol/cache-go-action@v1 + with: + name: ${{ github.job }} + - run: make build + - uses: actions/upload-artifact@v3 + with: + name: kubo + path: cmd/ipfs/ipfs + ipfs-interop: + needs: [prepare] + runs-on: ubuntu-latest + strategy: + matrix: + suites: + - 'exchange-files' + - 'files pin circuit ipns cid-version-agnostic ipns-pubsub pubsub' + fail-fast: false + defaults: + run: + shell: bash + steps: + - uses: actions/setup-node@v3 + with: + node-version: 16.12.0 + - uses: actions/download-artifact@v3 + with: + name: kubo + path: cmd/ipfs + - run: chmod +x cmd/ipfs/ipfs + - run: | + echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT + id: npm-cache-dir + - uses: actions/cache@v3 + with: + path: ${{ steps.npm-cache-dir.outputs.dir }} + key: ${{ runner.os }}-${{ github.job }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-${{ github.job }}- + - run: mkdir interop + - run: | + npm init -y + npm install ipfs@^0.61.0 + npm install ipfs-interop@^8.0.10 + working-directory: interop + - run: npx ipfs-interop -- -t node $(sed -e 's#[^ ]*#-f test/&.js#g' <<< '${{ matrix.suites }}') + env: + LIBP2P_TCP_REUSEPORT: false + LIBP2P_ALLOW_WEAK_RSA_KEYS: 1 + IPFS_GO_EXEC: ${{ github.workspace }}/cmd/ipfs/ipfs + working-directory: interop + go-ipfs-api: + needs: [prepare] + runs-on: ubuntu-latest + env: + TEST_NO_DOCKER: 1 + TEST_NO_FUSE: 1 + TEST_VERBOSE: 1 + TRAVIS: 1 + GIT_PAGER: cat + IPFS_CHECK_RCMGR_DEFAULTS: 1 + defaults: + run: + shell: bash + steps: + - uses: actions/setup-go@v3 + with: + go-version: ${{ env.GO_VERSION }} + - uses: actions/download-artifact@v3 + with: + name: kubo + path: cmd/ipfs + - run: chmod +x cmd/ipfs/ipfs + - uses: actions/checkout@v3 + with: + repository: ipfs/go-ipfs-api + path: go-ipfs-api + - run: cmd/ipfs/ipfs daemon --init --enable-namesys-pubsub & + - run: | + while ! cmd/ipfs/ipfs id --api=/ip4/127.0.0.1/tcp/5001 2>/dev/null; do + sleep 1 + done + timeout-minutes: 5 + - uses: protocol/cache-go-action@v1 + with: + name: ${{ github.job }} + - run: go test -count=1 -v ./... + working-directory: go-ipfs-api + - run: cmd/ipfs/ipfs shutdown + if: always() + go-ipfs-http-client: + needs: [prepare] + runs-on: ubuntu-latest + env: + TEST_NO_DOCKER: 1 + TEST_NO_FUSE: 1 + TEST_VERBOSE: 1 + TRAVIS: 1 + GIT_PAGER: cat + IPFS_CHECK_RCMGR_DEFAULTS: 1 + defaults: + run: + shell: bash + steps: + - uses: actions/setup-go@v3 + with: + go-version: ${{ env.GO_VERSION }} + - uses: actions/download-artifact@v3 + with: + name: kubo + path: cmd/ipfs + - run: chmod +x cmd/ipfs/ipfs + - uses: actions/checkout@v3 + with: + repository: ipfs/go-ipfs-http-client + path: go-ipfs-http-client + - uses: protocol/cache-go-action@v1 + with: + name: ${{ github.job }} + - run: echo '${{ github.workspace }}/cmd/ipfs' >> $GITHUB_PATH + - run: go test -count=1 -v ./... + working-directory: go-ipfs-http-client + ipfs-webui: + needs: [prepare] + runs-on: ubuntu-latest + env: + NO_SANDBOX: true + LIBP2P_TCP_REUSEPORT: false + LIBP2P_ALLOW_WEAK_RSA_KEYS: 1 + E2E_IPFSD_TYPE: go + TRAVIS: 1 + GIT_PAGER: cat + IPFS_CHECK_RCMGR_DEFAULTS: 1 + defaults: + run: + shell: bash + steps: + - uses: actions/setup-node@v3 + with: + node-version: 16.12.0 + - uses: actions/download-artifact@v3 + with: + name: kubo + path: cmd/ipfs + - run: chmod +x cmd/ipfs/ipfs + - uses: actions/checkout@v3 + with: + repository: ipfs/ipfs-webui + path: ipfs-webui + - run: | + echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT + id: npm-cache-dir + - uses: actions/cache@v3 + with: + path: ${{ steps.npm-cache-dir.outputs.dir }} + key: ${{ runner.os }}-${{ github.job }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-${{ github.job }}- + - run: | + npm ci --prefer-offline --no-audit --progress=false + npx playwright install + working-directory: ipfs-webui + - name: Run ipfs-webui@main build and smoke-test to confirm the upstream repo is not broken + run: npm test + working-directory: ipfs-webui + - name: Test ipfs-webui@main E2E against the locally built Kubo binary + run: npm run test:e2e + env: + IPFS_GO_EXEC: ${{ github.workspace }}/cmd/ipfs/ipfs + working-directory: ipfs-webui diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index af9006adf..e12af6b4e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,5 +1,5 @@ # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed -name: "CodeQL" +name: CodeQL on: workflow_dispatch: diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 000000000..86c50bec7 --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,25 @@ +name: 'ci/gh-experiment: docker-build' + +on: + workflow_dispatch: + pull_request: + push: + branches: + - 'master' + +jobs: + docker-build: + if: github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + env: + IMAGE_NAME: ipfs/kubo + WIP_IMAGE_TAG: wip + defaults: + run: + shell: bash + steps: + - uses: actions/setup-go@v3 + with: + go-version: 1.19.1 + - uses: actions/checkout@v3 + - run: docker build -t $IMAGE_NAME:$WIP_IMAGE_TAG . diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 76e0c1c11..a7416e388 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -30,15 +30,15 @@ jobs: - name: Get tags id: tags run: | - TAGS="$(./bin/get-docker-tags.sh $(date -u +%F))" - TAGS="${TAGS//$'\n'/'%0A'}" - echo "::set-output name=value::$(echo $TAGS)" + echo "value<> $GITHUB_OUTPUT + ./bin/get-docker-tags.sh "$(date -u +%F)" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT shell: bash - name: Log in to Docker Hub uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 with: - username: ${{ secrets.DOCKER_USERNAME }} + username: ${{ vars.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build Docker image and publish to Docker Hub diff --git a/.github/workflows/gobuild.yml b/.github/workflows/gobuild.yml new file mode 100644 index 000000000..120e94693 --- /dev/null +++ b/.github/workflows/gobuild.yml @@ -0,0 +1,39 @@ +name: 'ci/gh-experiment: go build' + +on: + workflow_dispatch: + pull_request: + push: + branches: + - 'master' + +jobs: + runner: + if: github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch' + uses: ipfs/kubo/.github/workflows/runner.yml@master + gobuild: + needs: [runner] + runs-on: ${{ fromJSON(needs.runner.outputs.config).labels }} + env: + TEST_NO_DOCKER: 1 + TEST_VERBOSE: 1 + TRAVIS: 1 + GIT_PAGER: cat + IPFS_CHECK_RCMGR_DEFAULTS: 1 + defaults: + run: + shell: bash + steps: + - uses: actions/setup-go@v3 + with: + go-version: 1.19.1 + - uses: actions/checkout@v3 + - uses: protocol/cache-go-action@v1 + with: + name: ${{ github.job }} + - run: make cmd/ipfs-try-build + env: + TEST_NO_FUSE: 0 + - run: make cmd/ipfs-try-build + env: + TEST_NO_FUSE: 1 diff --git a/.github/workflows/golang-analysis.yml b/.github/workflows/golang-analysis.yml index 3a74e61a2..958ece668 100644 --- a/.github/workflows/golang-analysis.yml +++ b/.github/workflows/golang-analysis.yml @@ -1,8 +1,15 @@ -on: [push, pull_request] name: Go Checks +on: + workflow_dispatch: + pull_request: + push: + branches: + - 'master' + jobs: unit: + if: github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest name: All steps: diff --git a/.github/workflows/golint.yml b/.github/workflows/golint.yml new file mode 100644 index 000000000..9623ae4b6 --- /dev/null +++ b/.github/workflows/golint.yml @@ -0,0 +1,32 @@ +name: 'ci/gh-experiment: go lint' + +on: + workflow_dispatch: + pull_request: + push: + branches: + - 'master' + +jobs: + golint: + if: github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + env: + TEST_NO_DOCKER: 1 + TEST_NO_FUSE: 1 + TEST_VERBOSE: 1 + TRAVIS: 1 + GIT_PAGER: cat + IPFS_CHECK_RCMGR_DEFAULTS: 1 + defaults: + run: + shell: bash + steps: + - uses: actions/setup-go@v3 + with: + go-version: 1.19.1 + - uses: actions/checkout@v3 + - uses: protocol/cache-go-action@v1 + with: + name: ${{ github.job }} + - run: make -O test_go_lint diff --git a/.github/workflows/gotest.yml b/.github/workflows/gotest.yml new file mode 100644 index 000000000..2c50fd3e5 --- /dev/null +++ b/.github/workflows/gotest.yml @@ -0,0 +1,65 @@ +name: 'ci/gh-experiment: go test' + +on: + workflow_dispatch: + pull_request: + push: + branches: + - 'master' + +jobs: + gotest: + if: github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + env: + TEST_NO_DOCKER: 1 + TEST_NO_FUSE: 1 + TEST_VERBOSE: 1 + TRAVIS: 1 + GIT_PAGER: cat + IPFS_CHECK_RCMGR_DEFAULTS: 1 + defaults: + run: + shell: bash + steps: + - uses: actions/setup-go@v3 + with: + go-version: 1.19.1 + - uses: actions/checkout@v3 + - uses: protocol/cache-go-action@v1 + with: + name: ${{ github.job }} + - run: | + make -j 1 test/unit/gotest.junit.xml && + [[ ! $(jq -s -c 'map(select(.Action == "fail")) | .[]' test/unit/gotest.json) ]] + - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + if: always() + with: + name: unittests + files: coverage/unit_tests.coverprofile + - run: | + # we want to first test with the kubo version in the go.mod file + go test -v ./... + + # we also want to test the examples against the current version of kubo + # however, that version might be in a fork so we need to replace the dependency + + # backup the go.mod and go.sum files to restore them after we run the tests + cp go.mod go.mod.bak + cp go.sum go.sum.bak + + # make sure the examples run against the current version of kubo + go mod edit -replace github.com/ipfs/kubo=./../../.. + go mod tidy + + go test -v ./... + + # restore the go.mod and go.sum files to their original state + mv go.mod.bak go.mod + mv go.sum.bak go.sum + working-directory: docs/examples/kubo-as-a-library + - uses: actions/upload-artifact@v3 + with: + name: unit + path: test/unit/gotest.junit.xml + if: always() diff --git a/.github/workflows/runner.yml b/.github/workflows/runner.yml new file mode 100644 index 000000000..afb4d740d --- /dev/null +++ b/.github/workflows/runner.yml @@ -0,0 +1,33 @@ +name: 'ci/gh-experiment: choose runner' + +on: + workflow_call: + outputs: + config: + description: "The runner's configuration" + value: ${{ jobs.choose.outputs.config }} + +jobs: + choose: + runs-on: ubuntu-latest + outputs: + config: ${{ steps.config.outputs.result }} + steps: + - uses: actions/github-script@v6 + id: config + with: + script: | + if (`${context.repo.owner}/${context.repo.repo}` === 'ipfs/kubo') { + return { + labels: ['self-hosted', 'linux', 'x64', 'kubo'], + parallel: 10, + aws: true + } + } else { + return { + labels: ['ubuntu-latest'], + parallel: 3, + aws: false + } + } + - run: echo ${{ steps.config.outputs.result }} diff --git a/.github/workflows/sharness.yml b/.github/workflows/sharness.yml new file mode 100644 index 000000000..6241e3fe6 --- /dev/null +++ b/.github/workflows/sharness.yml @@ -0,0 +1,124 @@ +name: 'ci/gh-experiment: sharness' + +on: + workflow_dispatch: + pull_request: + push: + branches: + - 'master' + +jobs: + runner: + if: github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch' + uses: ipfs/kubo/.github/workflows/runner.yml@master + sharness: + needs: [runner] + runs-on: ${{ fromJSON(needs.runner.outputs.config).labels }} + defaults: + run: + shell: bash + steps: + - name: Setup Go + uses: actions/setup-go@v3 + with: + go-version: 1.19.1 + - name: Checkout Kubo + uses: actions/checkout@v3 + with: + path: kubo + - name: Install missing tools + run: sudo apt install -y socat net-tools fish libxml2-utils + - name: Checkout IPFS Pinning Service API + uses: actions/checkout@v3 + with: + repository: ipfs-shipyard/rb-pinning-service-api + ref: 773c3adbb421c551d2d89288abac3e01e1f7c3a8 + path: rb-pinning-service-api + # TODO: check if docker compose (not docker-compose) is available on default gh runners + - name: Start IPFS Pinning Service API + run: | + (for i in {1..3}; do docker compose pull && break || sleep 5; done) && + docker compose up -d + working-directory: rb-pinning-service-api + - name: Restore Go Cache + uses: protocol/cache-go-action@v1 + with: + name: ${{ github.job }} + - name: Find IPFS Pinning Service API address + run: echo "TEST_DOCKER_HOST=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')" >> $GITHUB_ENV + - uses: actions/cache@v3 + with: + path: test/sharness/lib/dependencies + key: ${{ runner.os }}-test-generate-junit-html-${{ hashFiles('test/sharness/lib/test-generate-junit-html.sh') }} + - name: Run Sharness tests + run: | + make -O -j "$PARALLEL" \ + test_sharness \ + coverage/sharness_tests.coverprofile \ + test/sharness/test-results/sharness.xml \ + test/sharness/test-results/sharness.html \ + test/sharness/test-results/sharness-html + working-directory: kubo + env: + TEST_NO_DOCKER: 0 + TEST_NO_PLUGIN: 1 + TEST_NO_FUSE: 1 + TEST_VERBOSE: 1 + TEST_JUNIT: 1 + TEST_EXPENSIVE: 1 + IPFS_CHECK_RCMGR_DEFAULTS: 1 + CONTINUE_ON_S_FAILURE: 1 + PARALLEL: ${{ fromJSON(needs.runner.outputs.config).parallel }} + - name: Upload coverage report + uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + if: failure() || success() + with: + name: sharness + files: kubo/coverage/sharness_tests.coverprofile + - name: Aggregate results + run: find kubo/test/sharness/test-results -name 't*-*.sh.*.counts' | kubo/test/sharness/lib/sharness/aggregate-results.sh > kubo/test/sharness/test-results/summary.txt + - name: 👉️ If this step failed, go to «Summary» (top left) → «HTML Report» → inspect the «Failures» column + run: | + cat kubo/test/sharness/test-results/summary.txt && + grep 'failed\s*0' kubo/test/sharness/test-results/summary.txt + - name: Add aggregate results to the summary + if: failure() || success() + run: | + echo "# Summary" >> $GITHUB_STEP_SUMMARY + echo >> $GITHUB_STEP_SUMMARY + cat kubo/test/sharness/test-results/summary.txt >> $GITHUB_STEP_SUMMARY + - name: Upload one-page HTML report to S3 + id: one-page + uses: pl-strflt/tf-aws-gh-runner/.github/actions/upload-artifact@main + if: fromJSON(needs.runner.outputs.config).aws && (failure() || success()) + with: + source: kubo/test/sharness/test-results/sharness.html + destination: sharness.html + - name: Upload one-page HTML report + if: (! fromJSON(needs.runner.outputs.config).aws) && (failure() || success()) + uses: actions/upload-artifact@v3 + with: + name: sharness.html + path: kubo/test/sharness/test-results/sharness.html + - name: Upload full HTML report to S3 + id: full + uses: pl-strflt/tf-aws-gh-runner/.github/actions/upload-artifact@main + if: fromJSON(needs.runner.outputs.config).aws && (failure() || success()) + with: + source: kubo/test/sharness/test-results/sharness-html + destination: sharness-html/ + - name: Upload full HTML report + if: (! fromJSON(needs.runner.outputs.config).aws) && (failure() || success()) + uses: actions/upload-artifact@v3 + with: + name: sharness-html + path: kubo/test/sharness/test-results/sharness-html + - name: Add S3 links to the summary + if: fromJSON(needs.runner.outputs.config).aws && (failure() || success()) + run: echo "$MD" >> $GITHUB_STEP_SUMMARY + env: + MD: | + # HTML Reports + + - View the [one page HTML report](${{ steps.one-page.outputs.url }}) + - View the [full HTML report](${{ steps.full.outputs.url }}index.html) diff --git a/.golangci.yml b/.golangci.yml index de174afc4..2c46046aa 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,3 +1,8 @@ linters: enable: - stylecheck + +linters-settings: + stylecheck: + dot-import-whitelist: + - github.com/ipfs/kubo/test/cli/testutils diff --git a/CHANGELOG.md b/CHANGELOG.md index 389576e73..16e72bcb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Kubo Changelogs +- [v0.19](docs/changelogs/v0.19.md) +- [v0.18](docs/changelogs/v0.18.md) - [v0.17](docs/changelogs/v0.17.md) - [v0.16](docs/changelogs/v0.16.md) - [v0.15](docs/changelogs/v0.15.md) diff --git a/README.md b/README.md index 307f0b566..e734fef66 100644 --- a/README.md +++ b/README.md @@ -62,13 +62,13 @@ Before opening an issue, consider using one of the following locations to ensure - [openSUSE](#opensuse) - [Guix](#guix) - [Snap](#snap) - - [Unofficial MacOS packages](#unofficial-macos-packages) - - [MacPorts](#macports) - - [Nix](#nix-1) - - [Homebrew](#homebrew) - [Unofficial Windows packages](#unofficial-windows-packages) - [Chocolatey](#chocolatey) - [Scoop](#scoop) + - [Unofficial MacOS packages](#unofficial-macos-packages) + - [MacPorts](#macports) + - [Nix](#nix-macos) + - [Homebrew](#homebrew) - [Build from Source](#build-from-source) - [Install Go](#install-go) - [Download and Compile IPFS](#download-and-compile-ipfs) @@ -166,10 +166,12 @@ $ ipfs get /ipns/dist.ipfs.tech/kubo/$VERSION/kubo_$VERSION_windows-amd64.zip ### Unofficial Linux packages -- [Arch Linux](#arch-linux) -- [Nix](#nix-linux) +- [ArchLinux](#arch-linux) +- [Nix](#nix) - [Solus](#solus) - [openSUSE](#opensuse) +- [Guix](#guix) +- [Snap](#snap) #### Arch Linux @@ -193,11 +195,10 @@ You can also install the Package by using its attribute name, which is also `ipf #### Solus -In solus, kubo (go-ipfs) is available in the main repository as -[go-ipfs](https://dev.getsol.us/source/go-ipfs/repository/master/). +[Package for Solus](https://dev.getsol.us/source/kubo/repository/master/) ``` -$ sudo eopkg install go-ipfs +$ sudo eopkg install kubo ``` You can also install it through the Solus software center. @@ -208,16 +209,36 @@ You can also install it through the Solus software center. #### Guix -GNU's functional package manager, [Guix](https://www.gnu.org/software/guix/), also provides a go-ipfs package: - -``` -$ guix package -i go-ipfs -``` +[Community Package for go-ipfs](https://packages.guix.gnu.org/packages/go-ipfs/0.11.0/) is no out-of-date. #### Snap No longer supported, see rationale in [kubo#8688](https://github.com/ipfs/kubo/issues/8688). +### Unofficial Windows packages + +- [Chocolatey](#chocolatey) +- [Scoop](#scoop) + +#### Chocolatey + +No longer supported, see rationale in [kubo#9341](https://github.com/ipfs/kubo/issues/9341). + +#### Scoop + +Scoop provides kubo as `kubo` in its 'extras' bucket. + +```Powershell +PS> scoop bucket add extras +PS> scoop install kubo +``` + +### Unofficial macOS packages + +- [MacPorts](#macports) +- [Nix](#nix-macos) +- [Homebrew](#homebrew) + #### MacPorts The package [ipfs](https://ports.macports.org/port/ipfs) currently points to kubo (go-ipfs) and is being maintained. @@ -244,31 +265,6 @@ A Homebrew formula [ipfs](https://formulae.brew.sh/formula/ipfs) is maintained t $ brew install --formula ipfs ``` -### Unofficial Windows packages - -- [Chocolatey](#chocolatey) -- [Scoop](#scoop) - -#### Chocolatey - -No longer supported, see rationale in [kubo#9341](https://github.com/ipfs/kubo/issues/9341). - -#### Scoop - -Scoop provides kubo as `kubo` in its 'extras' bucket. - -```Powershell -PS> scoop bucket add extras -PS> scoop install kubo -``` - -### Unofficial macOS packages - -- [MacPorts](#macports) -- [Nix](#nix-macos) -- [Homebrew](#homebrew) - - ### Build from Source ![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/ipfs/kubo?label=Requires%20Go&logo=go&style=flat-square&cacheSeconds=3600) diff --git a/Rules.mk b/Rules.mk index 3d6f621cc..f7e962549 100644 --- a/Rules.mk +++ b/Rules.mk @@ -136,8 +136,7 @@ help: @echo ' test_go_expensive - Run all go tests and compile on all platforms' @echo ' test_go_race - Run go tests with the race detector enabled' @echo ' test_go_lint - Run the `golangci-lint` vetting tool' - @echo ' test_sharness_short - Run short sharness tests' - @echo ' test_sharness_expensive - Run all sharness tests' + @echo ' test_sharness - Run sharness tests' @echo ' coverage - Collects coverage info from unit tests and sharness' @echo .PHONY: help diff --git a/appveyor.yml b/appveyor.yml index 696102ffc..5f2907d00 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,8 +14,8 @@ environment: GOPATH: c:\gopath TEST_VERBOSE: 1 #TEST_NO_FUSE: 1 - #TEST_SUITE: test_sharness_expensive - #GOFLAGS: -tags nofuse + #TEST_SUITE: test_sharness + #GOFLAGS: -tags nofuse global: BASH: C:\cygwin\bin\bash matrix: @@ -23,27 +23,27 @@ environment: GOVERSION: 1.5.1 GOROOT: c:\go DOWNLOADPLATFORM: "x64" - + install: # Enable make #- SET PATH=c:\MinGW\bin;%PATH% #- copy c:\MinGW\bin\mingw32-make.exe c:\MinGW\bin\make.exe - go version - go env - + # Cygwin build script # # NOTES: # # The stdin/stdout file descriptor appears not to be valid for the Appveyor -# build which causes failures as certain functions attempt to redirect +# build which causes failures as certain functions attempt to redirect # default file handles. Ensure a dummy file descriptor is opened with 'exec'. -# +# build_script: - '%BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0 HTML representation for non-UnixFS DAGs such as DAG-CBOR. diff --git a/assets/dag-index-html/index.go b/assets/dag-index-html/index.go deleted file mode 100644 index 214b06a38..000000000 --- a/assets/dag-index-html/index.go +++ /dev/null @@ -1,81 +0,0 @@ -package dagindexhtml - -import "html/template" - -// TODO: DagIndexTemplate - replace static CSS with shared one with ../dir-index-html - -// DagIndexTemplate is HTML-based template for non-UnixFS DAGs when request was -// made with Accept: text/html (web browsers). -var DagIndexTemplate = template.Must(template.New("redirect").Parse(` - - - - - - - - - - - - - - - - - - {{ .Path }} - - - - -
-
-

CID: {{.CID}}
- Codec: {{.CodecName}} ({{.CodecHex}})

-
-
- - - - - - - -
-

Preview as JSON
(application/json)

-
-

Or download as: -

-

-
-
-
- -`)) - -type DagIndexTemplateData struct { - Path string - CID string - CodecName string - CodecHex string -} diff --git a/assets/dir-index-html/README.md b/assets/dir-index-html/README.md deleted file mode 100644 index 3dd45eb59..000000000 --- a/assets/dir-index-html/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# dir-index-html - -> Directory listing HTML for HTTP gateway - -![](https://user-images.githubusercontent.com/157609/88379209-ce6f0600-cda2-11ea-9620-20b9237bb441.png) - -## Updating - -When making updates to the directory listing page template, please note the following: - -1. Make your changes to the (human-friendly) source documents in the `src` directory and run `npm run build` -3. Before testing or releasing, go to the top-level `./assets` directory and make sure to run the `go generate .` script to update the bindata version - -## Testing - -1. Make sure you have [Go](https://golang.org/dl/) installed -2. Start the test server, which lives in its own directory: - -```bash -> cd test -> go run . -``` -This will listen on [`localhost:3000`](http://localhost:3000/) and reload the template every time you refresh the page. - -If you get a "no such file or directory" error upon trying `go run .`, make sure you ran `npm run build` to generate the minified artifact that the test is looking for. - diff --git a/assets/dir-index-html/dir-index.html b/assets/dir-index-html/dir-index.html deleted file mode 100644 index 1d00e5fe7..000000000 --- a/assets/dir-index-html/dir-index.html +++ /dev/null @@ -1,99 +0,0 @@ - -{{ $root := . }} - - - - - - - - - - - - - - - - - -{{ .Path }} - - - - -
-
-
- - Index of - {{ range .Breadcrumbs -}} - /{{ if .Path }}{{ .Name }}{{ else }}{{ .Name }}{{ end }} - {{- else }} - {{ .Path }} - {{ end }} - - {{ if .Hash }} -
- {{ .Hash }} -
- {{ end }} -
- {{ if .Size }} -
-  {{ .Size }} -
- {{ end }} -
-
- - {{ if .BackLink }} - - - - - - - {{ end }} - {{ range .Listing }} - - - - - - - {{ end }} -
-
 
-
- .. -
-
 
-
- {{ .Name }} - - {{ if .Hash }} - - {{ .ShortHash }} - - {{ end }} - {{ .Size }}
-
-
- - diff --git a/assets/dir-index-html/index.go b/assets/dir-index-html/index.go deleted file mode 100644 index 98933e3f6..000000000 --- a/assets/dir-index-html/index.go +++ /dev/null @@ -1 +0,0 @@ -package dirindexhtml diff --git a/assets/dir-index-html/knownIcons.txt b/assets/dir-index-html/knownIcons.txt deleted file mode 100644 index c110530ea..000000000 --- a/assets/dir-index-html/knownIcons.txt +++ /dev/null @@ -1,65 +0,0 @@ -.aac -.aiff -.ai -.avi -.bmp -.c -.cpp -.css -.dat -.dmg -.doc -.dotx -.dwg -.dxf -.eps -.exe -.flv -.gif -.h -.hpp -.html -.ics -.iso -.java -.jpg -.jpeg -.js -.key -.less -.mid -.mkv -.mov -.mp3 -.mp4 -.mpg -.odf -.ods -.odt -.otp -.ots -.ott -.pdf -.php -.png -.ppt -.psd -.py -.qt -.rar -.rb -.rtf -.sass -.scss -.sql -.tga -.tgz -.tiff -.txt -.wav -.wmv -.xls -.xlsx -.xml -.yml -.zip diff --git a/assets/dir-index-html/package.json b/assets/dir-index-html/package.json deleted file mode 100644 index 4b2427574..000000000 --- a/assets/dir-index-html/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "dir-index-html", - "description": "Directory listing HTML for go-ipfs gateways", - "version": "1.3.0", - "private": true, - "homepage": "https://github.com/ipfs/go-ipfs", - "license": "MIT", - "scripts": { - "start": "cd test && go run .", - "build": "npm run build:clean && npm run build:remove-style-links && npm run build:minify-wrap-css && npm run build:combine-html-css && npm run build:remove-unused", - "build:clean": "rm dir-index.html", - "build:remove-style-links": "sed '/ ./base-html.html", - "build:minify-wrap-css": "(echo \"\") > ./minified-wrapped-style.html", - "build:combine-html-css": "sed '/<\\/title>/ r ./minified-wrapped-style.html' ./base-html.html > ./dir-index.html", - "build:remove-unused": "rm ./base-html.html && rm ./minified-wrapped-style.html" - } -} diff --git a/assets/dir-index-html/src/dir-index.html b/assets/dir-index-html/src/dir-index.html deleted file mode 100644 index a763b3e76..000000000 --- a/assets/dir-index-html/src/dir-index.html +++ /dev/null @@ -1,98 +0,0 @@ - -{{ $root := . }} - - - - - - - - - - - - - - - - - - - -{{ .Path }} - - - -
-
-
- - Index of - {{ range .Breadcrumbs -}} - /{{ if .Path }}{{ .Name }}{{ else }}{{ .Name }}{{ end }} - {{- else }} - {{ .Path }} - {{ end }} - - {{ if .Hash }} -
- {{ .Hash }} -
- {{ end }} -
- {{ if .Size }} -
-  {{ .Size }} -
- {{ end }} -
-
- - {{ if .BackLink }} - - - - - - - {{ end }} - {{ range .Listing }} - - - - - - - {{ end }} -
-
 
-
- .. -
-
 
-
- {{ .Name }} - - {{ if .Hash }} - - {{ .ShortHash }} - - {{ end }} - {{ .Size }}
-
-
- - diff --git a/assets/dir-index-html/src/icons.css b/assets/dir-index-html/src/icons.css deleted file mode 100644 index dcdbd3cd9..000000000 --- a/assets/dir-index-html/src/icons.css +++ /dev/null @@ -1,403 +0,0 @@ -/* Source - fileicons.org */ - -.ipfs-_blank { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAWBJREFUeNqEUj1LxEAQnd1MVA4lyIEWx6UIKEGUExGsbC3tLfwJ/hT/g7VlCnubqxXBwg/Q4hQP/LhKL5nZuBsvuGfW5MGyuzM7jzdvVuR5DgYnZ+f99ai7Vt5t9K9unu4HLweI3qWYxI6PDosdy0fhcntxO44CcOBzPA7mfEyuHwf7ntQk4jcnywOxIlfxOCNYaLVgb6cXbkTdhJXq2SIlNMC0xIqhHczDbi8OVzpLSUa0WebRfmigLHqj1EcPZnwf7gbDIrYVRyEinurj6jTBHyI7pqVrFQqEbt6TEmZ9v1NRAJNC1xTYxIQh/MmRUlmFQE3qWOW1nqB2TWk1/3tgJV0waVvkFIEeZbHq4ElyKzAmEXOx6gnEVJuWBzmkRJBRPYGZBDsVaOlpSgVJE2yVaAe/0kx/3azBRO0VsbMFZE3CDSZKweZfYIVg+DZ6v7h9GDVOwZPw/PoxKu/fAgwALbDAXf7DdQkAAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-_page { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmhJREFUeNpsUztv01AYPfdhOy/XTZ80VV1VoCqlA2zQqUgwMEErWBALv4GJDfEDmOEHsFTqVCTExAiiSI2QEKJKESVFFBWo04TESRzfy2c7LY/kLtf2d8+555zvM9NaI1ora5svby9OnbUEBxgDlIKiWjXQeLy19/X17sEtcPY2rtHS96/Hu0RvXXLz+cUzM87zShsI29DpHCYt4E6Box4IZzTnbDx7V74GjhOSfwgE0H2638K9h08A3iHGVbjTw7g6YmAyw/BgecHNGGJjvfQhIfmfIFDAXJpjuugi7djIFVI4P0plctgJQ0xnFe5eOO02OwEp2VkhSCnC8WOCdqgwnzFx4/IyppwRVN+XYXsecqZA1pB48ekAnw9/4GZx3L04N/GoTwEjX4cNH5vlPfjtAIYp8cWrQutxrC5Mod3VsXVTMFSqtaE+gl9dhaUxE2tXZiF7nYiiatJ3v5s8R/1yOCNLOuwjkELiTbmC9dJHpIaGASsDkoFQGJQwHWMcHWJYOmUj1OjvQotuytt5nHMLEGkCyx6QU384jwkUAd2sxJbS/QShZtg/8rHzzQOzSaFhxQrA6YgQMQHojCUlgnCAAvKFBoXXaHfArSCZDE0gyWJgFIKmvUFKO4MUNIk2a4+hODtDUVuJ/J732AKS6ZtImdTyAQQB3bZN8l9t75IFh0JMUdVKsohsUPqRgnka0tYgggYpCHkKGTsHI5NOMojB4iTICCepvX53AIEfQta1iUCmoTiBmdEri2RgddKFhuJoqb/af/yw/d3zTNM6UkaOfis62aUgddAbnz+rXuPY+Vnzjt9/CzAAbmLjCrfBiRgAAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-aac { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAnhJREFUeNp0Uk1PE0EYftruVlvAUkhVEPoBcsEoLRJBY01MPHjCs3cvogcT/4qJJN5NvHhoohcOnPw4YEGIkCh+oLGBKm3Z7nZ3dme2vjOhTcjiJJvZzPvOM8/HG2q325Dr3kLp7Y1ibpIxjs4KhQBZfvV6s7K5Vb0bjeof5ZlcGysP1a51mifODybvzE8mzCbrAoTDIThMoGXZiZ4YSiurf+Z1XeuCqJ7Oj+sK3jQcNAmg8xkGQ71mYejcAB49vpmeuzJccl0+dUj6KIAvfHCPg3N+uAv4vg9BOxcCmfEzuP/genpmeqhEMgude10Jwm+DuUIyUdTlqu2byoMfX/dRermBeExHsTiWNi3+lMpzRwDki8zxCIATmzbevfmClukiP5NFhJgwkjeRTeLShdOoVJqnAgwkgCAZ6+UdLC9twjQZ8pdzioFkZBHY3q6B3l4dJEEEPOCeD4cYVH7Xsf15F+FImC775INAJBJSkVoWo0QY9YqgiR4ZZzRaGBkdwK3bFxGLRZUfB3Rm2x4x9CGtsUxH9QYkKICDFuLxKAozGZwdTqBRs2FbLlXbiPdECMCHadj/AaDXZNFqedCIvnRcS4UpRo7+hC5zUmw8Ope9wUFinvpmZ7NKt2RTmB4hKZo6n8qP4Oq1HBkKlVYAQBrUlziB0XQSif4YmQhksgNIJk9iaLhPaV9b/Um+uJSCdzyDbGZQRSkvjo+n4JNxubGUSsCj+ZCpODYjkGMAND2k7exUsfhkCd+29yguB88Wl7FW/o6tT7/gcXqAgGv7hhx1LWBireHVn79YP6ChQ3njb/eFlfWqGqT3H3ZlGIhGI2i2UO/U/wkwAAmoalcxlNA1AAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-ai { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAk5JREFUeNpsU01vElEUPTPzZqBAQaSFQiJYUmlKYhoTF41L3Tbu/Q/+AvsX3Bp/gPsuWLrqyqQ7TUxMtAvF1tYGoXwNw7wv7zwYgtKX3Lw379575p5z77O01ohW+/DVh8zj7aYKhflGdG9ZsGwLNydffgVfr19YHvsEa+Zu/nxndob5StQK+dyzvZzyw/gKlmMj7IygFM+xvNcanp4/t5dAomXHBy2UUBOO2MAl/B9/cPb6PULuoHx0WM0e3GvpUOxD3wZAJWutZqYUYmqpSg5OMgH3YQObL59W0/ullpryR3HegkKEqiWBSGV4R3vQ7sIhScTZFTpHx3A215B5sluVY/WWMg7+ATB/lcLsKpTonHzD+OMFEuTz8ikkt9Kwt9YJZB38cpBdoQAZJdLvCGByfoPB6Xdk90pYy6Xg3c/DaWwArg09DaG5lCsUFN0pckZAojdC8m4auBqaALuSgez7VB1RtDSUWOQvUaBLFUzJBMJ2DwmPgd1Jwm0WoSgJfjDvrTKxtwAIyEkAOQ5hU//Zdg5uowDlUNMnwZLW0sSuUuACYhwQRwFvJxupCjEYUUccOkoaKmdOlZnY1TkgAcXAhxhOwLsDsHoN3u4O5JTDfVCH6I9nfjId3gIgSUATFJk/hVevGtOMwS0XwQ3AzB/FrlKg8Q27I2javVoZrFgwD4qVipAEyMlnaFArzaj/D0DiMXlJAFQyK2r8fnMMRZp4lQ1MaSL5tU/1kqAkMCh2tYI+7+kh70cjPbr4bEZ51jZr8TJnB9PJXpz3V4ABAPOQVJn2Q60GAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-aiff { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAohJREFUeNpkU9tqE1EUXZmZpE3aTBLbJFPTtFURtSCthr7UCyKKFJ/9An3og6Ag/oXfoUj7og9asCBYKT6UIPHaWtpq7NU2aZK5z5wZ9xxMpMwZDuewz9prr32ZiO/7CNaDx3OLt6fOjBqGg/aKRCIInp8+KzfKH7fudnVF58nE16el+/yU2mBFSWZKpWJKVc0OgUBo02K4NDmU6o75Mx+Wdu9IUXFeiOA/pn1xHeYaugVDdzpbp91qGlAKGTx8dC19/Wpxhjnsxj/RRwk85hGJC9d1O6fneWAuoztDYSSLe9OT6SuXB2ccx73Z9uukwDwfls1g0xZIY/Ad/Gnyt/XVfbyYrSDRE8PExHB6/8B6QuaxIwRBFMt0iIAiMx+LCys8jfGJEUik2WpZOD2SQf9oDtVqQwopCAiY66FS/om3b75CVS2MlU7AJ2WiJBCZjZ2dJuRkDJZFwFAR7UCBja3fNfxY2YEoCtRCj9em3Tpds6FpJseGCBxS0GgYGBzqw62p84gnYnAI2CSbSbPhEpFAaE2zODaUAlWWwDoS5DheGqbWpVE/0CmqCY9qkEyINBceb2uADRNQ8bSWAVVzIFKomCQim+0luS4yKYlsHlRyZo7EsSEC23K5vAsXh/H92zZkuRvxeBS5nEx2yp2KqhxPoV5TYS/8CtdApylM9sZQKKSQzyeRTseRV2QoAzIYY8jme5DN9fI0dQoUIjANGydP9VM7PZw9p/AiBpNYrdbw/t0yTJqRtdU9UrfJCUMpSJIgbWzsYe51BcViHzLHeqCRqhZ1YX1tFwNfZBxS9O3NWkAcHqR606k/n/3coKAoV/Y7vQ/OYCZevlrmv3c0GsFh06u3/f4KMABvSWfDHmbK2gAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-avi { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAm1JREFUeNpsU8tu00AUPXZcN0nzTpq2KQ3pAwkIAnWHqCoeexBb+AQ+ABZ8A2s+AIkdm266QUJIFWKBkHg1KpRHi5omJGkbJ3bGHj+4M1EQrTvSyGPPueeec++1EgQBxHp+/9mbyuriRZdxjJaiKBD3W+u1+p9a856max+gDO8ebT+WT20Ezi9NZi/crqadvn2MQBAGfpCOpqNru2937vxPIpY6Onjccx3Twck9MBiSU0ncfHirXFmZX3Md9wqCUwiEVN/zaQfHt0vfbBe5uQyuPVgpl5Zn11ybL4/i/lkICOw5niQRGQShoiqI6Bo43W2ub8n3hRtLZT7gTynk6gkCX9gAOxpAnxhHZDwC1/aI1EViJolu/QhKRMHZ1UX0Gr1USIEn5FPWHy+/wTokkrQOq2vBaHZBN4hmY9Jwfr4An/teiEB45ZZDwDiMhoExT0N+sYDCuUkkplLIlXP4/XEXdo+RUhdhBSSfUwtVTUG8MIHK9QVqI7D/uY6vr2pwmCPrkz+Tk9gwARWQ9WxppbXZhNnpw+ya4A5HZi6L4lIR8WyCcL6sTZiAWjWgAmpxkn5+kqTamK6WkCwmERmLDLvjB0ML9ikWXPLFuozYOap3L8HYN6DHdbS/d5CeTVBndBz87FCBLYkNTyIjBQemnIEsSY5lYrK1+UoWcToLMjEHAyIQ2BCBSx/NVh+ZUhrqmEqBebS3WyhdLg0zt/ugAaIklsSGLHCLa6zDMGhZ2HjyGsnpFPqNHnY2fmHv3R5SMymYbROszSQ2ROAY9qHiofvlxSc5xsKKqqnY3diRE9h4X5d/pzg7lnM4ivsrwADe9Wg/CQJgFAAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-bmp { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmZJREFUeNp0U+1rUlEY/13v9YV0vq2wttI5CdpL9aEGBZUDv0df668I6n+or0UQ/RuuD0EgVDAZrsKF4AR1a6COKW5qXvXec27PuVeda3bgcF6e8/ye5/d7niMZhgExnK9fbTrm5pbBGMZDkgCyq+VyhTUaT6Eo2ZHJePPWXJXRhez3B1yxmM/QdctXUSCgtV4Py4CvY3cky4e1x5DlLCaGbbzjXDcousG5OQe5HPRSCQPK4PpsEM/XH4WvhS4noeu3JwHGGRiULhsMoKZS4I0GtEIB9mgULJGA0+9DPBpBT7sffvf1W/Lg6OgJufw8C0CRGEXWazUwiiyFQjA8bsjVKjaJzovMD/Q5gxyJhG2cvyeXe2cAuADQNGBmBvLaGuTFRaDfh31lBTWi9pumjbK0B4JQul3vOQpM8JdskOLrdCvDcDjAsjtg5TIkoiKLaokMNR2cnZbqNAMycqG7XbHKR2fMzwO/dsxSwu0BiBJsNsv2LwAJAJCI5ux2gXYbqNetcz5PoORI1cDS0n8AxGW7A+zvEYBKZ2ZlcsEtJLbedMjePBaCTQMghx45ulyWkzxMVUQ2RMQhLfFO16YAqCrixPnm6iqKrRb2W23EfF4cUNSrHg90cr7hDyB33MTnSmUKALVs4uIlROjxg+AsPhGVl3fuIl2tIOB0Ya91gkOi9mxhAal0ekork1ic/kGLBORMxy2K1qS9V1ZQbNThIj2EGh+2tsyOnSai8r1UxMNIBB+LRTTULr4Uds0K1tU/uOLxIrmbNz8XXSrnASSpubG9fbKRyVh1n/zSw29t9oC1b47MfwUYAAUsLiWr4QUJAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-c { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAcxJREFUeNqEUk1rE0EYfmZnkgoJCaGNCehuJTalhJZSUZB66a0HwXsP/Qn+FM+9+hty0LNYCr2I7UVLIW0Fc0hpQpSS7O7MrO9MspuvVV8YMnk/nn2e5x0WRRFMvP/w6WSz5jbi/9NxfP693Wp3DrJCnMW5d28P7a+IE15lufR8o1ZEStwPhkWHsWbrZ+eNEPxsuubEF6m0TBv2Q4liPofXuzveulttSqW2UwH+GjqC0horpSL2njU89+FyMwjlTlxOJMTa9ZQHzDQIjgwdom9zLzfXPc75kbnOAswBJTlC2XrqQRMLxhi442DgB4UFBhgPpm3B5pgBHNUUxQKAHs8pHf3TEuFMetM9IKr/i2mWMwC0SnuSFTG2YKyppwKYVdGO7TFhzBqGIenVeLCUtfURgErucx5ECKREKBU4d3B718PHz6cICGT/1Qs8qpQtGOdyhtGEARWDQFqQJSeDL98u4VbLaKw9IRAJPwjtoJGlVAoDQ800+fRFTTYXcjlcXN2g++s36p5Lzzlve1iEROa8BGH1EbrSAeqrjxEqicHQt8/YSDHMpaNs7wJAp9vvfb287idboAVkRAa5fBYXP9rxO4Mgf0xvPPdHgAEA8OoGd40i1j0AAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-cpp { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAfJJREFUeNqEUs9PE0EU/mZ2WgqpXX+QIDFdalVslh8NlAOQaOKFAwfvHvwT/FM8e/U/MOnBmwcj8WD0ACEGghIkbU0baaEthe3OTJ0ZWV26q37JZt68ee/b9733yGAwgMbL12/fz+azbnAPY2Nrt7Zfqz9JMrYZ+J4/e2pOFjiciRvXlgp5GzHonXk2o6S8V6k/TjBrM/xGA4MLyeOSPZ8jkx7D+uqCU3Amy1yIYizB36AlCSkwfjWDR4uu40yMl/s+XwjeWThQQ4Z6QNSnSkYykcDXasP4lmfvOZTSF9q8TDBEFPbN5bOqCglCCCxK0TvvZyIV4CIxbgpC+4gm/PUmFCIE8iJPyME/e8Lon9j4HvyHYLjKSwRCSEUgf9+15mFbx8QS6CZJMzJ9SlBCwX3fJDLG4PX7ykcwkmQmJtpEhWa7g1dvNlSwjwelebz7tAXLolh0p/Fxe9fErK2WDFGEgKjxfNjegX0lDTc/heNuF99/HGEslcKXwyoazWNDdlCr6+DoJgrBzdI0T9rYO6yg2zszMlaKM3Dv5OBzbuyZuzm1B16U4Nzz2f3cFOx0Gq12F9cztpExncsqYoaHpSIKtx0zJdVIFpHQ6py29muNk1uTN829o/6SHEnh80HFaE6NjmLnWxUJy1LyTltB3k8BBgBeEeQTiWRskAAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-css { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAk1JREFUeNpsUktvUlEQ/u5DoCLl/RAKKKUvWmIxjYntQtcu3LvwJ/hTXLt16coFC2PsojEaMKZtCqFaTdGmjbS0CG3By+vei3OOBSGXSU7uzNyZ78z3zRF6vR6YvXzzPrMUCyf68bB9zO+VfpROn5hkOdfPPX/2lH/lfiLidztX5mN2jLGG0rKLENIE8liWpdzwP7HvqJqujmvudFU4bFY8Wk1FZsOBtKppd8YCDNu77CZevd3gflfTUFcUhP0ePLibiIR9rjSBpgwAfe4dVcV6dhtep4PH5msylGYLrzeybErcT85FYiH/CyPAf74gObC2vMhzsiRhPhpC6eQUM+EA1pJzILEnjRSuJsju7MJqsUCSRei6Dp3yXqcdGlHZ/rLPazQWGCn8+6YW4pAkEW0SjzUzanWlCa/LgcR0lNfovTEi6lcIkzesnM/R8RlN0INGp3h4DHoDsE5YRvQyiKiRSMzikRAOS2WoqoZWu41K7RwzlOOAVDMMMHhIGvFlRxJFrKYW0ep0IYgC3SDh4b1lTJjNfENsrazOAMAw680mPuW+8lFno1P4XDigRhOiwQAyJK7TbsNS/PaA7giAIAhYz2yRgBIfsVA8wIetPG6FAqhdNrC5u0f+TUyHgyMTDDToEt/ftQsEvW4EPG5OZcrvw0mlimarTXkPfpXPcNlQoGtjACgpryQXsPNtH/nvRXqBJpoKHMzGNkNB0Odls7LNyAYKpUq1dt1iuvB7fRDp9kr9D1xOFwkpoksXusmXaZWFn0coV89r/b6/AgwAkUENaQaRxswAAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-dat { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAfVJREFUeNqMU01PE1EUPe/Na0uptmlASg3MoiZgCA3hQ8PHAjbqwsS9C3+CP8W1W/+BSReyYUPwI4QAVkAgUEgIbVIg1FZb2pl5b3zv2cHBjsaTTOa+e989OffcGeK6LhTevFv+OJoZHPHOfrz/sl86KpWfhxnLe7lXL1/oN/MSZqonOXU/k0AA6lfNhEFIrlAsP2PMyPtr1AscLpyg5pbtIHErhqez4+awmc45nI8FEvwNaiQuBHqTcSxMjJhmX0/Osp1xr878FxWEzwMinxAzEA4xFIpnOjedHTKpYbxW4U2CP4j8uWxmUKsghMCgFI2mFe9QgHZj0Ba4yhFF+KvGJToIRLuPC/efnjD6+26wB1Lq/xgbSCBXKeWJG/OTdky8cWTdT3C9RmWSGk2XCLlWo4xTNbfN5qh7PpXM72GjZeHt0gpq9QbmH4whGb+NpU/reDQ7hcWVVXxvXOHxzCQopQEKXKEbL6o1ZIcy+LC5g62DY2zsHeC0fA4zndIrHOjvg2XbAQRSfsuy9XxC2qzi/H5B6/68W0AsGkW0KyJPBLbDO0fg3JX/CUM81i0bD6WKe6j9qOPJ3EMcF0tSNsFA6g6alqW+VtZBUL78Vtk+Oqne7U9rs5qOQCjSheJFBeFIFOfVujSUYu3rIc4uqxWv76cAAwCwbvRb3SgYxQAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-dmg { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAn9JREFUeNpsU01rE1EUPe9lkk47yWTStCmtNhFSWxos2EXVhSsRcasuxYV05V8Qf4DgD/AvCK5EV1oFI7iUBqmCNdDvppq2mWSSzEzy3vPOpFFq+uDNfR/3nnvueXeYUgrBWH1/9/NE7k5BKRnuRcfF2qdnmJq9DeF9tQ+2isuMsxXGWHh/a1mEVsPJSI5fSU3OPEj291IIlN49RXz0KqzEQjIeZS/L5Y/3wPGhDxIM/i/A7fZWgVG0t5EaG0ZUa0JGM8gvPrZmLt58QYwv91mfAqCIE0sAqgumBFITGQzpUYhuF0KfRa7waDyXXXolpVrsh/0tgSLDr5I+wUZo1UHCSkAficPzY6juFSmbRPrC/azjq+fkcO00gAqoU7B0ETKkfWbuCTjTYeq5oESAauexcTScX+ZACWFm0YQSLZKhHdr67+/wW0e0dgjYo3sCEXXybYtBDVSHLp2es3IpsILS24c42lkBg6DzRjgRzCDZ/xr0GNRJwwYiWgzt+hYMawleu0V3wbkT+kUirOc7IGJAz68R/Qak1BAlx3hqASPGBJRXpXOv58dkz3eAgQoOm4hyj57NgZm0MHvpBmK6QdUdg/DAg9cRkhicBSDaKJdeo1bdxmR2DtWDDUxl51HZ+QHTysD3XdQO95Gfv06aeGcAdBrY3Chi8lwO3768QWX7J5q1XWyVSxgajiOXLyBG2hzurRKV9lmt7ISNkkjo6HhNyjoK+2gXRsKE57ZIE2ot10Z1fz0Ue4ABVw3NMjnW14rInh8jTYywoTg3EOFpOM4mXNfH9PQUfGlrAwBOs3I8ljbtuMWhRWzIIPrkn+GcYcgIWEowbZ+0qB334/4IMADESjqbnHbH0gAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-doc { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAppJREFUeNpsU79PFEEU/mZ39vZu77g7DokcP04BBSUmiEKCSCxs7Ei00JAYO2NlTKyMrX+CJhaGwopSQ0dMtFEsbDRBgiZEQIF4IHcg+2t2Z8eZ5QDlnM1mZ9+8973vfe8NEUJArfSNhzPG0VIfeIiDRSDkw1cWVt3N8rhG6SdSO2Gvn8dfuueqZwuNZqk3Jxg7iNcIfBbgXD6ZC8u5qffzX8eoYeyDxC77uygKhcouovgVUQj1H4YB2ovNuD9+tTTU0zMVBmG/+C8AIYh8F361DL/yE5HnADKYlVdg6MDAmW7cuz5WGuw+PsWDYGAvbL8ECFUt4K7/AHd/I9c7BLaxinD2Ld5Zo7g78RLuRhlBS2cpWbGfStfhfwCEpK0nUjCbWuGsLciSOELPhkq/YgdY3l6HsLfRcLYf+pHNbH0JigEPkLAyMsiEJ7NrqQzM1i7wyhoMZqOhvQs6Z0ovXgdAJACRoulEg5HOwrOroKk0zOY2BDtVpTF0CU6kLkQJXa+BNEoG0lMSsBBKQXWNQktmoGcaYeSaQCIVWOvUYQAiWZFQtk5mSMoSzEILtBrTfEcviC5bwVwQmoh96wA0ic5dB57ngeoaTIPCdb34zDITYNLOOIeVSsW+dQC+7+NSWx6jJ4tY/rWNV7PfcGv0tBoPTM7M4eKJVgx2FTE9u4QPS6x+kHzfw/mOAjarW2hJG3hy8zIceweuY+PRtREMdzbjzcd5WBqPB6xeRGUMGRzHjWvMmxQ7tiOF1JBN6FiTd6Sy9RuFbHpX7MMMqOD088Ii+op5OUAO7jyeRGfBwrF8Cg8mXuDL4neMXzgFwhwZz+hf7a9d5yu3Z6DTPjVQIY9k7erO7Y63Lvc8ErEeyq6JaM6efjai4v4IMABI0DEPqPKkigAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-dotx { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAndJREFUeNpsU01rE1EUPTPzJk0y+WhMStW2qdVWxUVEQUF0I+4ELQiC7lz4N9z0T+hG9wrdZKUgLqulhrbSag1CKpT0g7RpYjqZmffle5NEKdMHlzfvvXvPPffcO4aUEno9f3Vt4dTp+BXOe+fB0u/NbVpv7h89NU1j1TCM8H7+xY9wJwPHZMbOjRadLAvE/2gToJTiTPx89k+OlVd/LT+0TPIPpO/SzyQk40xCMxBSZ9Z3CoAx5DOjeHT7SbE0XSpzwa8OWB9jINELolQg8AR0EgUKn1PIlIWpkUt4cPNxkTOU12trs8p95RiAXpqaztqou8q6SKQJJmZSqGwsodFsIJk1kcyLYv7IeafcLx4HUNkFF4jFTExMZ0B9DrfD4HUEusYhWs4GPEJg5wly/tBYRIOeDhpEwlS34xcyajdQr3UwOT2MlJOEBRuGNHWp9AQRVXDfQiFV/U5GBSiQ5p6ngBEa5z3fiIhC6g6IMDBwOdoHPkYnHPVyhN0tF7E4QSpr94CEOKELffq+y9Bq+DCJ7rWBoQQBVbPR2O6G4OlsLASJMtCZfQqm0NP5IVWnamdAkUxbyuIYtD7wWegb0YAzAVMkkI6NwPM9xEwHloyDGAmk7AKS9rAS0FKOdugbYeAHPu7OPEM+MY7q3hIKqTFQHmC3XcONc/fxdfMDrk/ew/edzyhvvTmBAddocVRqH3Frahau56qpZDho7+PnTgXffi/gbHYmLEvPSIQBp5JU62sYz13G609zKBXvoOMdYn2zgm7Xg2MVML/4Eu3uPgxhk2gXmNl8v/i2pcXTP8tKdTEcbWLZqDQXwu/l6pfwbEnSGsT9FWAA4mdHv2/9YJ4AAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-dwg { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAoFJREFUeNpsU0tPE2EUPfOg006hD4rQh8WgbCSwkKgbF2owujaCiQsXxpX+D6MmbtXEsHCLmIAbE6NLo8YlGIxREIshIqVl+mQ6j8/zFVCb4UtuZua795577rl3FCEE5Bl79vPd5LHYiOP7cH1AUWi85ytmvlas1bJ9E5ryBntH3BpuP/X9i7ovkluuiE8N9SDepaLpCcRCCqa/VDCaMuIjSWP25Upl6n+QDoCz6Yh7KKzh3sI2LuUimPtRRyaqodj0MDloYiITSTi+mH29Wu0AUf9CsZPJoW5czJl48LmCc5kIKo5Al67B9gUGYxrun+5NnMlFZ+GKiQADj2a7AquseLIvjMv5KMaSBu4sWVir+3i8VIVKYSby0UTdFU8Znu8AYBHQgVOJEN5uOXi4UsdawwU0FSf6TaSoyw6DRvukPkgGWpDKy4F8a3jImCrqFDFn6rhKPR4VGnhvOTAY3WLcjifcQAsqRfhUc/Gq1MKNbBh9nIAMDjEppocxs9HCMktfGTCwP/oOBkUKNk/qF3pDYC6Ktk8RfWzyaaoKrqdDaBDwya8W1m0/CPCR3kFy7CcnmWQRUJqcRJFUKtTnPCeR71LwoeYF92CYyVnCFZpCTrRtCv5to2St8SOrKxiPqEEA4fkYT+mI0rdoeUiH1XZVuQPpsIKqw2QmfifTsnOABiWySlH9uU0Hh2MqjsZV5LtpPSoGeN9rKnhBX7ehoOSLIIPfnGONXGMMWN7xUfVldYDbjM3mrh5HCDgS17DhHgDQcIU+XbBxnDTn1x1UuQcJ9iv7l5Q5e1zLGri92EDJFnoAgHtcfr6wbbVXUqq193+0z97n3UJt1+d51n7aHwEGAAHXJoAuZNlzAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-dxf { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAo5JREFUeNpsU0trE1EYPfNMmtdoH2kDNmJbaVFcaBVFpAsREQpFwY0bu3HjQnTj1mVd+ANcuC3qQixmry6E0kWFVIQ+bKy2tbFJm3emyXTujGca+4DkwsedfLnn3POd77uS67rw1vC79ek7fZEzpu3AYUqS9tKQGZPLpa3VXP0uFCmJ/8t9OLC3q/uJbcs5bkIybvdHoMsSbLKENRmvU2WcNnTjRFD7ML1WGSPJHI6sA4KRWMAWVDPxLYex3iCmfpuIh1QsFSyMxQO4GvXHHwOJ6XWSyIck8v6HQsnjAxFc7vTj2VwBg4aG78VdBHQFCk+dbVcxMdwev9gTSEC455sIBOu2KLsoJFzqasP9vjCeDBlYqzn4VXXwarGKZN7Crd5QfLDT/7KpBM84c9fFUFjFp2wdk6smflRsKKqMa7EgfJJ3Ac2OKlit2pEmBTQfngdpnupoU7BUtRGiiTe7fXiRqmK+KuDn6TpvYogmBRJcrOwIJLIWxmM+dOsyLKryQAaJpjJ1/AxrGO3SqdZt7kKZJrzJWBg5piHENuY8vV6e0UOye1TyftvC5l+gZB8SHJTwpSx4q4JeTUKaxhXoR57h7Rn+3iFolJ3xvPhab6HgJG/pJ7jsNP4sUX+jZiCgEsWd/DjH5IrSYpBUAr0yHpzSoXKOP25a6OBhndh0zcX1qIYM2RIbu6i0KiHD5B/GTMHG03kTGpEL7H80wHFOWwhqDZ+SpkBOtCDYJDhZE4gRcKNbYynAqbCMbXpwpVPFbEng0aKJGbYzK1p4wIegLlcEPmdt+DjXbzcsxFlCynRwwVAwW6hjqeg0Zt521SYCWCJvbe0Un29UDx7Hgrs3IEitHXkw3jOv2fl92D8BBgAJeyqBh90ENQAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-eps { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNp0U01vElEUPfMFCEVArdoSqEA0KV246UJdUJM2Lo2JK/9FjXu3utJqTNz4D9worrsQExbFpAFT0TYp0CZ8pIAiyMfMvBnvm2Foa9uX3Lw7c98979x77hNM0wRf7ufPsq7Z2SQYw2QJAkDxQalUZa3WI8hy3gmZr15bu+z8kILBkCeRCJi6bufKMji0NhwiCQR6iitdatTvQ5LyOLLEiWcYukm3m4Zhmbq1BX13FyoxuH7xAlbvpqKRK1fT0PWbRwEmDEyiy1QVg/V1GO02tO1tKLEY2PIy3KEAlmJRDLXb0TeZL+n9g4MHlLJ5HIBuYnSzXq+DlcsQLk/D9Hoh1WrIUjlPcpsYGQzS3LWoaBhvKeXWMQCDA1D9pt8PaXERUjwOjEZQFhZQp9L2yERiqYRCkPt/z58ogTGqHQLE1BLgUmC6XGD5AlipBIFKkbhanKHGYLBDqQ4ZED0OAbfLlo8OIxwGvhVgyTHlA3xkomjH/gegBgDURMv6faDbBZpN+/tHkUApkdTA/PwZAPxntwdUyjYA/+ZMqJHjLgM9iv/6zRt2GgMaIE21aVIjnSm0DGPfmhzyde0UAE2Dj+p7urKCPvkZku9eJILOSMUnkvVhIo7GYIB3xSKYdhoA1erXGVKXpvFxZwdBonnD68PQ7YEwM4O4xwMPxc8RYE87g4FIcz+kvfmnA0YzIJIy77/m0OCqsTkkCTysKPjJG3viLei63Gm3kCO6UWqcMejjxecMPmxsoFKtYop6UNirYL9Wtc5OHqzznIXHq1na7OfMJROcK8a6O7MjW7nfzZdrd7jzT4ABACh3NGsh3GcdAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-exe { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAo1JREFUeNp0k8tPE1EUxr+ZzvRJO62lUAQaKIQ0FVJFjBBdoIkrDDHuXJi4NnHtX+HCjW408Q/QmHTRaCRRohIJifgiiBICTQu29mHfnc7MHc+MlECKdxZz595zf+c737nD6boOYzxJLC6Nhwej7e/24HkO779s7G6mMjcEwfKZ21+/d+em+RbagaFev28qEpZwzKg3ZckqCPH1nfS8hScIdyhBe6JqTG3PfyTTeLrwFhvbKdy9/xi5QglXL0yGJsKDccZY7LDIAwWHpSferWBh+RN8ni4UylVER8MY6PHj0uSpUK0hxzfTmWsUtnoEwO3rer64jEyxim6/Hy67DXaHExvJX3jw7CX8XjfORUdDlOohhU4fAVjILCPbm9V1yIqK2FgYt+ZmsZcv4lH8Nb5upXD7+hVMjIRQa8qeDg8UTYPU5cTcxSk4nS709XTD53ZhpD+IYMAPj+TBz93fZiz5oHV4AP1fGdlyHZIkIZkrI7GyhnK9CZXy+Aig6p1+HQAY003AcF8AVtGGfLWG9XTO4MLZ5cL0WAixoT4zVmPHADSiMo3hzHA/xgeDWFjbNg8H3A7kKnX0koEcPdTu/ylgRGZgOjNv38zoSXC8BZJDRKOlwGEV0VJVGM0y4joAPO1spXbx6sNHeD1uRIYGUCxVSRlDt1fC8rfvcDnsmJ+dOaLgoAs6AVLZPJJ7WdhEkUyT8GJpBflSBcVKDTvpDBw2GzQqQT1OgaZqUOhtFQUTUKnVTVWNpgy51YLVKph7sqKYkA4A1ScEfT66vm5kC3+ofh6Xz59FQ5bpkvE4QW3M5Apoyorhl9ABIKnFgNdTOh2NkJG6WSf9eRBJtmFwLDJmriUzeaOkYvvcXwEGAIVNH6cDA1DkAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-flv { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmtJREFUeNpsUl1PE0EUPbssLYUCXdpaC9gWoSTgAyFigiRGY+KjvuuTr/4A44MP/gx/gMYfwIsan0RjIjGiJIZgSIGFIoXSD0t3Z3dnd70zpITazuZmJzP3nnvumaMEQQCx3jx69SV3a3KWMxetpSgKxP3m242Do43SQy2k/YRydvds67n8a63k+FRSn7l/bdg5tdsAuM3he/5weDC8vLdqPLgIIpba2niux52mg//DqlsYSg3iztO7mczN3DJ3+ByCLgCBH4hOFEF7cDpzPCRyOpaeLGXSc2PL3HbnW3XaRQCPEgWI2MsRVAVqrwbX9bHxbhOKpiJ/bzpDOr2k68V2BtRNzMtqDEqPejY/4zSGjb54BM0mQ8k4xsDoIMauXxnqYOD7PmwScP31d0SS/eAuh1lrolFpIBQNQw2pqJdqsAlIceB1AJCIkkE/FZskXDQVRXw6IYHiE0nBEcaPXSSvJnGwWkQXAE4acAhbxPMJpOdHweoMhc9b2F8zwKizbdlyPLVH7QLg+JKBYzoorxzjz3oRzUoToaEw9KyO8XQW5AE5jrFT6AbAYVVNxCZ0Ka3So+DSTAoDiej5ywTySbls1OEDobhFlMcXxrHw+AbINEjNXgb7y6BndLhk8cRkHHbD7g4gEhiJFxsdhrDqaamBaDKKerGGSKwPI9kR9EZCaNA5ubE7A5s8IFhsrxQkgJhZoa/06xC5xRz2v+3BOjFlbqcGlquxsondT9vY+2pAJdeZR6fI355CgQCN2A4O1w7gkQ7cdLUOAKdhV6uFSv3kd/n8mT68eC8dKWLnY4FsfeZQh7nVVt0/AQYAsf5g+SvepeQAAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-gif { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmVJREFUeNp0U0tPE1EU/trplAqlL0laiw40xASByEJIZFGVnSvj1j+gWxNXJq7VrbrwF7h10cSNhMRHojEuACVBKmH6SJQyJeXRxzzv9dyZPiCtN5lMe8853znf953xcc4hztDzZ1+C6fQMHAfd4/MBFG+p6h/n4OAeAoGNToi/eOm+A50LKRaLh6amoty2vVpZdotNXccMEK3LwZxa2bsDSdrAqePv/mLM5tSdMwYBYqyvw9zdhUn/L59P4OGtG8qlZCoH254/DdCdQBCxqZu+ugqnWoW9swN5ehp2NotgIo6bGQWGtaS8+vQ5V9a0u5S+1gfABEilAqdUgm98HDwUQkDT8JXoPPq+BoM5kCYmFT9jryn1+hkAt7heBx8dhbSwACmTAUwTgdlZ/CVKJaLnI1GD8TikZiPSR8Gxib8chH95mZTxgwWHwH7+gFMswqcokIRbjMO2HDCnZ1VvArpjEmnKZc8+cZJJYGsLsMiZ8AgwEqaY6Mb6RQR33JFhGECzCRyfAFXNu9v+RVNRZWIMuDJNuYMAaDycUFGhCOgtuAtFVDA83G5A8TrFDw+F5QMAxAKJJxz2xnW3RPJGbm+rCyjotZetH4DGzaSSeDA3h4Zl4R0JOEZWTpIzF4n/m995bNdqZwB6m0gFft3Ak6vz+KYWwFsGlqIxXItEcDt1ARMEtKdVgZb+fwA0G2C2hXM0ZTZNRcSf0b1pmXi7uYnjI+Lfanm5fRQsK8BIxKcrK7i/uIgP+Tw+FlREqHN5fx/vyU4uHBE6UO4gDWqk/JFaLuMxcXeFk6TuJ90V0HOk1in7J8AAjmgkPfjU+isAAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-h { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAbRJREFUeNqMUk1Lw0AQnf0woK0ttVqp0hwqVCl+UBERT94F7x78Cf4Uz179DT14F8WbYHtRkBYRLNqDtdaPZLObuLs1NGlXcWDJZGbey+x7QUEQgIqT07PL5WKhHL5H46J+22q22vsWpbWwdnR4oJ80LNiz2czGUjENhvj4ctIE4Wrj8XmPUlKL9nCYcOFzE9j1OKSTCdjdrtiLdr7KhVgzEvwW6krC92E6k4Kd9bJt57JV5vFK2KfRQRV+RAMkzxglYI1RaDy2dW1rpWRjQo5VGicYIorWVooFvQVCCAjG8Omw1MgG8AM0uSBUDSnCfk/IGCHwf3DCD/7UhOLBrFkDuep/hDUSSCv1iYo4rIfqGwmUSNJjfYbBcQKhZw0aBMA4B48LwBhBt/cON80HmM9NQ6fXg/Wlku4TwmNWDzaQqzHG+0PSKod5cH5Vh2RiAhYKc8DlV1UPSyuFMGygVlMg1/P6BC6DqXQK8jNZDXAYA1f21V34wMXYFaiyVw0rJyzLgs3VMkxOjGtix/V0XWChZ0cI2i/dzvXdfTd0Qf91BMPrhyNzgKfOmxaWypqaDXHfAgwAtCL8XOfF47gAAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-hpp { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAehJREFUeNqEUk1v00AUHK/XKf1yZdESVRBXjRSRFqMQVBA5Ic5I3DnwE/gpnLnyG3LgXglx4UDDLZS0RWkDLiRxSusk9u6GXSembmLgWZbX7+2bnZl92mg0goo3b3ffO/ncdvyfjHef6q2Dlvs8Q2ktzr16+SL60jhhZ69bO8X8ClLC7w9XdKJVG8fuM0r1WrJG4gXjgqU1D0MGc2kBTytl+7a9XmWcl1IB/hZKEhccq5aJJ/e3bTu7Wg1CVo7rNLlRhUh4oMnXoDoyhoHGyWmUe+QUbELIa7W8CjAFlMzdzeckCwFN06ATAn8QmDMMMGlMuwWucpoCHNe4jBkAMenjYvRPTyi53JvuwX8AplleAeBcRFrH6rXIxLim9I/pi3QA1RhKaYxdjkN8IwalCMIwWs9ljMkh0wzk+9M7w179C3LZNXxve2h+c3Hu91HeKmD/6zHOLnw83ilB1/V0CeqU3Q81LC/O41b2Btx2N2JVP2riR8eTUxmi0TzBwrKZMsqMoz8MsDh/DWuWhUBKURLKxQIeOMWoptYPnS1c+INZBkwISomOSsmBZS7B+3WOzZvrKGzkMAiGqNy7g+LmRkRfekBnANy2163PZXrSbrQ6vch19Xz8fPDHyL39QzkHBKedXjfu+y3AAGU37INBJto1AAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-html { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmBJREFUeNqEUktPE1EU/mY605a+hhZTBNKRDApNrWIRA4nEBUZdmCgLNi4MK5f+FNdu3bFv1J1EXODCR1JJSMTwpqUP6NiCpe10Zjz3hj5Mm3iSybl37jnf+c53jmDbNpi9eb+6Ftcisea909bWNzNb6dwzSXKkhIt/r14+515qBqmDA8HpqKagh53XaopblpIbe+knDpFAhPab2Dw0TKvRK7lmNODzePBgZlK9oUWSpmVNdpIU8T+jaMsyMaD4MDcZVa+NhJMN00w0n6V2nN3yQgdHWZag+LzYPTomIAtT0THVtPGanmb/BbjwLFkvn2IttYGYplKyDzsHh7gdmyAWfh5zVq0Guhg4RAHFUhmfvq3j134aXo8bd+ITnMFOOovU5jbGRoZwNxFn1cxuAIcDW/sZDjA/c4u+BNxOJyxqaenpI3z88gMfPn9Hv98HQZS6RazW6kjExvFi8TGdDSy/W0Emf4LS6R8sv11BmfzSwkPcm74Jo9Ei0GZgmkw8QCOao8OXcaz/5vSZnPdnp3ApqBBLkWJE0Ci7ASzbIhCLLQ1E0iOkBDh9NpUgiUejo8oNuJwyn0YPABtn51UYFFivG3yBGCNZkuDtc/MW+ZQI3OrYpBaARCKufk3B5XIiWyhiL5ODp8+FfFHH+KiKSqWKUL8fC/NznGlPBmz+24dZjKnD0CJDcMoyW0SqXuMtHBFw7rhIAD1ErNUNafxKBNevapwu65NpEQ4FqXIA+RMd6VwBP3cPSERb6gLIFIq61+UqGWaFdcrVt/lmAuWjAi2aiMFwmOYuIJ/N6M28vwIMAMoNDyg4rcU9AAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-ics { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAhRJREFUeNqEUkFPE0EU/mZ2dra7bLNpi2AxQFKalkJrohICiYkXPagXrx78Df4K48GDBzmQePLMhUODNxQ5ciEkJVqDtJGmMWrCATRbd2ecoS5u3aovmezsvu9973vfPiKlhI4XL7c2r5YL81LIELEghLA3u/udxmHnPmfGW/Wuv+LpwwdneRYBx7PeWK0wOYYhcXxyckGV1fdbnbuMsXcklqPRJQxFMKz4RxDCtVO4s3xlRjWoB0FYjlQPEEBieChwKCRGMx5uLtaKs1P5ei8IKlGa/YkXMXYtlTEDlsnw/mMXhBJcqxSK6vlcpa4PEpCooUyIqs5M6hG1o2CUwqA091cFcYLf/sjzcX75EiQIojI9779CTYR4jwTBf+r7GAwh0AxCiL6JMT/04vQ79u8aI2O/7Jzg69o6Go8ewycUahtBpADhHKLnK/eVbkMdtROWIv80NQ2sPhncA9Htwn+9hZG0rY6DzFwJl+7dhs0ZstUy8rduwPS/wd/ehmi3kwq4zTHiWUgXp+EuL8FvNvFl5Rn4xAS86iyI2kY3n0Mv48ByrOQmancdi8I0Kcj3U5iuA29xAelKCUHrEIayzltagG2E4IwkFaQgSC6lYI09iN0d8It5uNV5nG5sgJdKYC0G8WoTOZvBISFNEBxnsuzD3GX4vfDsszzqAu0jkJQDedCGbB6AWg54pYbPo+NGVPdTgAEAqQq70PytIL0AAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-iso { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAjlJREFUeNp0kstrU0EUxr/k5qbJzdPYpGkpsUJoA2q1oLjTdiGiIC5cuXHlxv9BEOrStTvBnQvRrSAIsejCrlqpsURq2hCJNQ+TNLm5uc/x3MmzJh34mDNnvvnNzOE4GGOwx8+t9XQkfn0VE0Y5/7Z+kHm+dvOhtd3P9c/xwNZh7nWaMYtNUmX/Fct/vlN7/8J5aRRgyzm8xzpRDjGE2aVH4VTqdnoUYg/XkEhmy+Cx3DhA5tMzdFolvg5Mx3Fx9SmH0JIg79Zo3j4GADMIokJTKtjbfAKXU4Y/2NvSfyH75TFOxa9Cmr0XnlPFl5ReOQ6wNMDsoFX6AElqQlNV1KsOuNwS/AGFjEUIDhmn5+/DMM16/9igBowAzFKIswPJr6MjlxFP3sV04gaP7RzMPe6xvWM1gNUBM2UKYlBau3QghGphg29J3gDlLLilWNdD3gkvIIDRhD9yGe2mCV0V4HFXuCxT5Dlv8Dz3sIkAs03FalDxBMQSt9BRBMhNncuO7dyU28c9tnf8C/Q0ZtR4GImeQSj8APLRH772BWcgiFODffCv/t8H9tO0v3RjV7VqkeeXLlzDfvYjj88uXhl4JwIsrYxmLY/M1gYclIvGE9jZfNPrSCD3/QgLyeWTADV6wW9AryIcCkB0u1Aq/oCPumlufoF72vIheaLDr4wCLIOqrYnULA14PSoqpSJEAUilZrD77Sv3LK+cI0+Be8cAbbmAOrob0agtD491LYfkoqvnyZLsWRkA/gkwABL4S3L78XYyAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-java { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAjxJREFUeNp8U01v00AUnNiOEyepQyhQobRBSlVIoRCBEPTAjQsSEneE+An8FM5cuXLNoQduIAE3qopKNJAIIppA2jrOR93aa6/N8yZuUxyxkrXr3ffmzczbTQRBgHC83nj3ca28dD36nx6fvnzrNNrdp4oibyUmey9fPBezEgWVFuYLdyvlPGaMY4fl1aRS+9pqP5ElAkmcnknRwuO+Nyt5u/ETYfyj9WrpZnmpxn2/Ok1Swn/GvtnH5k4TLue4kNfxoFoprRQv1TzOb8cAIu3+ZD7oD/Hm7XuxzqRUNDtdkuLiTmW5tFxceBXlnXgQTAORSMt2oGezUJJJrK9dFWdEH7Ik4dB29LiESeUEJXd7/dAT3L+1ivlCHr8NEzutXTBvbJPPSdO/AH5wysChwM/1HzCGlmAzOrKxu2eCud6Z2Jke2MwThpUXL6Nn2ZAVFTlNw70bK0iRnGAq9qwHtOmTRpsx1NsHyKRVnNPnoMoK9kc2BjbD4vk5JGV5NkBoEPM4FFnCteJFWOS4ntHEfphQyKaFTWFLw704AJ26ZFx/ZEEi3YyY0O1Dmr4EKTUHA8hUnS6siI0DEHLYog+b28RCRuNXR/iQUpPUEQ+NVht6Lodnjx+GXYgDSFRnq97Ed2pXSlXhUSeGhxYc5sKlNXM5DGLR2TMwfZVPAIi+otGNWy1fEZUKeo4qc4ysI+F8VksLIJfYcD9QYgB/DNPMptWBlsnBIS86xmDMTBo/PWd0LB6VZfdEbJT3V4ABAA5HIzlv9dtdAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-jpeg, -.ipfs-jpg { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNpsU8luUlEY/s4dmMpkWxRopGJNNbiwhk1tItbGtXHr0hcwmvgOdWld6Bu4coXumtREE3ZKu8FgOlC1kIoXtC3jPfdc/8PUIpzkBM7wf+f/hsts24YczuerGUc0moBlYTAYA+i8sbdXtAzjITRtq39kr73s/Gr9DTUYPOeamwvYnHdrdR0SnDebuCbswJGqpX+Uf92Hqm7hzFAG/4TgNr1uCwEJ0trcBC8U0Kb1/PQkHt9JxSLnL6TB+Y2zAIMOJBGLXmtsbEAYBsx8HnqCGKVScAX8uHf5EpqmGXv18VO6VDEe0PXsKABN8+AAgiabmYFNNJTDQ2RUFc8+Z9G0OPR4PKYwvKari0MAgiY/OQGCAajhMNR4nDZMaInrKBGl70SPMScck1NQG3X/CAWLE3/dAWV5hRRVIJxOWNksrP19sFgMqqAebUGYHMI6teq0A9oTVAhqu2sfbYYjsL7lCZ3683gA70T3TK7/B4BNoO020GwB9TpwfAz8LgMtWn/NkV8EHgoB81c7nYwCyBZlEVkHcqMTKFnkmehJTOPvEfCnKi0fAyADJKfXC/h83TaZTJjaa5lANLpOFqAXtlEAorAwO9u5syT5UxLfU0e3o1FMu1x4u7ODYq02BKAMAVSrSNLrK1MhLPj8mNF0vFm+C1ZvwKBwXXE4AGn1WAASazESwUW3BzUSMeJ2o1Aq4sPurvQYSRLwlhRR6mSaYyi0WlpAJrFRx3ouh5/lMt5lv8BLwXp0M4lSpYL17e2uK5wP6lj/c2ZPn2RI+YT8fDvqoyegVLyfG5kBKaQQOfvF2pLc+ifAABiQH3PEc1i/AAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-js { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RUQ5ODY5Q0NGMTE4MTFFMTlDRjlDN0VBQTY3QTk0MTEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RUQ5ODY5Q0RGMTE4MTFFMTlDRjlDN0VBQTY3QTk0MTEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFRDk4NjlDQUYxMTgxMUUxOUNGOUM3RUFBNjdBOTQxMSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFRDk4NjlDQkYxMTgxMUUxOUNGOUM3RUFBNjdBOTQxMSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoT8zQ8AAAJdSURBVHjadFNbTxNREP52t7S0bktbKFAvTUVaw60YqkExUTD6oD74qC/yD/wp/gh885XEEI0RAyYQUiMpIBGMkYR6o23abi+73e2uc04v1LROMtnZPTPffvPNHMGyLDB7sbJ2ciUSli3U35smkK9t7x9v7n2dD/g8KUkUwWqeP3vKz23NxJGzgwOx0RC6mSgIo+WKuvP56MeUzy2nJEk8PWsGJVVTuhWbpgmHw47FB7d98Wg4mVWK52o1sxOg3Va3PmFp+Q2PdUquaFUM9/vw+O6cP3bxwm46Xwh1ALR3/vL1e+hGjcc9koScUsTSq3coVDQsXJ3wzo5HEs3clgZNMTVdx1T0Ep7cn6//QRQwMhzA6uZHLD5cIFEFSKIU+G8LK+tb0KsGZKcTJoEyP08AbpcLy6sbPKdQrigdAGaDwWxsDH1uGbliCYIgcM8WFPg8Mq5Pjzdyu4jYbCE44EepXMHuwXe+A8x3KKYxYsjvbUzmlPGpBmYdgI1oYjSMbL4Ao1YXMkcM2Dd2xnbAamPQAqg1GORLZdycmYTdJqFKk2DPR3fmwI4zBDrg9RADqxPAbPBif2WTSB584/3/TGegEOit+DRcvQ4OZJi1LgwIQKVCg2i6nb1I7H3Br3QWqT9pBAP9uDY5xjdSM3RqxeoUkfVnEOW8UkLykERTNXjkM7h3Iw6NNvHw6JjuhAhVrba0+QeALozcI9nQR0VvNxJc/ZmxCNGvIBQcpDG6udA22kyW29HC72wu8yG579ZoiSYuR/ly2+y9CA4NceWLmo717T1i5ULqJNtapL8CDACskxPFZRxLwQAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-key { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAlZJREFUeNpsU11PE0EUPbM7u/2AtJUWU6qiiSYYo5EmmPDCD9AH46sx8cEnja/+CB989z+Y+MKPgMiDsYQACcbaWBBogYD92t2Zud7ZlQZsbzKZ3bl3zj3n3IwgItjYeDO3MlWme0bjUth8e8/fO2tHzx3XqUEk50uft+Ndnhdmc3SlfNPkVZT8Cy600DoIISvVfKYtlvfX1p66XmoIYsMZdjJQWvEFbbsC/S5g2QhSkKUK7rx6OzvzqLpsovAhaAxA3DUBQn2TUFsl7KwTfm4Z9DoO5LW7uPXi9Wxpfn7ZKF09vyPxX2iWcNRkKGZz0mQWKoNs8AVB6x1yRY2pYnc2LLofuXTxMgAlmlXIfngCxNxEzM+DPv6NQa2BygLgZyX6JT83ngHTN5GAL0WSoUQkSQnXkyBh/k0GegTAaldM20sTKvet+yyhIZApECamL0jUSe3oFChx3TopM4TeEQP2gc6BgGIwb4KGNXRhCkMGxgg2kJeybRiZM45D8W61qEAknSmpHStBhywu0nFVupSCTAcM4ECwqapv+NQ6LS9JGALoMIIoPYDjZiEL1xHtbyO39AQUDaA7R1AH23DSeSA4hv5RG/VAhxomPYP8sw9A4TaC9iHkjUWmrtGvbyC18BLe3GP0m3WW4I5hEBEnPIStXzyuFIxb4EkMEJ79Qa/xHbKxCdM7xeCwzUZOjgEwnuzt7qLz6T3cySmQP43uzjeIiTJM6io6W19B/NLCKMVGCzkCoLR/0lrfOI2fNy/huKC1FTsK/rbGNeMRC8dHpHByfu+vAAMAL/0jvAVZQl0AAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-less { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RjZERjZENTJGMTE4MTFFMUIwOEVERjQ5MTZEMkVBREUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RjZERjZENTNGMTE4MTFFMUIwOEVERjQ5MTZEMkVBREUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpGNkRGNkQ1MEYxMTgxMUUxQjA4RURGNDkxNkQyRUFERSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpGNkRGNkQ1MUYxMTgxMUUxQjA4RURGNDkxNkQyRUFERSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pl1w97IAAAJhSURBVHjahJNLbxJRFMf/wPAIMIxMkUI7tS0VYqlGDLGhjdKkqyZ24cJFN925de+XcONHaHRj4k7TND6SGo1VWwmp2kSLhlqMDbQ87gzPYcY7k4GgoJ6bmdw598zvnvM/95pUVYVma+svcovx8yMnFZHAMJPJBJfDzq5vpX6+/vD5qo/z7DOMBdo/d26t6jFMJ3iY51jBz4M+LP6wxEw40Gy23qYzB3HO7fpmpZCOmfEfa7Xb4NxOrC4lvbPToe2yKE3K1PdPwNOtHdx79ESfq4qKkijB5/XgevIyHxEC24USmewDqD2ABxubaLRkfW6zMqjWGlh7/ByyAtxYnOPnL0Q2+gGGmKRaw8zUBJaTiS5QOO1FJnuIAM8hciaIWHgi8NcSNt+loVDY8JBXh2ojJAR1HbTSNFMUpV8Dxcjg0nSYBrtBxdLbqI1iheCUh9XXNGurAwCdEkb9QyBSFam9TDfoPZ1LUg1BH28IiwEARTVAQOzcFKRaHZpLoa9avY6L1Gfs0c32t4PU6W2lWsV8LAorw0Cs1nXftYWE3qZGqwWHzYp2zzlgetuolVFvtiDLbRRKFTAWCxx2G/KlMtXFhWPqOzsWHJwBx7rxKv2R7mwFz3lw9/5DLC/M4Us2RwV0g3U58XJnF7dvrsBOoX0Abbej/DFKRMKI30fTVGC32WA2m5H9cQQvhYi0vE/7Wdgczn6ARA9QPBrBszcp/XvpyqxebzQ0Tlsq6llxLhe9bD4cFMr9XdjLHpLv+SLGBYHAYiVu1kNOpAaRTWbCejgiw0zGhFGSK1aw+zXbvfK/BBgAPwADAs5GpGsAAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-logo { - background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 553 235.3'%3E%3Cdefs%3E%3C/defs%3E%3Cpath fill='%23ffffff' d='M239 63h17.8v105H239V63zm35.6 0h36.3c7.9 0 14.5.9 19.6 2.6s9.2 4.1 12.1 7.1a24.45 24.45 0 0 1 6.2 10.2 40.75 40.75 0 0 1 1.8 12.1 45.69 45.69 0 0 1-1.8 12.9 26.58 26.58 0 0 1-6.2 10.8 30.59 30.59 0 0 1-12.1 7.3c-5.1 1.8-11.5 2.7-19.3 2.7h-19.1V168h-17.5V63zm36.2 51a38.37 38.37 0 0 0 11.1-1.3 16.3 16.3 0 0 0 6.8-3.7 13.34 13.34 0 0 0 3.5-5.8 29.75 29.75 0 0 0 1-7.6 25.68 25.68 0 0 0-1-7.7 12 12 0 0 0-3.6-5.5 17.15 17.15 0 0 0-6.9-3.4 41.58 41.58 0 0 0-10.9-1.2h-18.5V114h18.5zm119.9-51v15.3h-49.2V108h46.3v15.4h-46.3V168h-17.8V63h67zm26.2 72.9c.8 6.9 3.3 11.9 7.4 15s10.4 4.7 18.6 4.7a32.61 32.61 0 0 0 10.1-1.3 20.52 20.52 0 0 0 6.6-3.5 12 12 0 0 0 3.5-5.2 19.08 19.08 0 0 0 1-6.4 16.14 16.14 0 0 0-.7-4.9 12.87 12.87 0 0 0-2.6-4.5 16.59 16.59 0 0 0-5.1-3.6 35 35 0 0 0-8.2-2.4l-13.4-2.5a89.76 89.76 0 0 1-14.1-3.7 33.51 33.51 0 0 1-10.4-5.8 22.28 22.28 0 0 1-6.3-8.8 34.1 34.1 0 0 1-2.1-12.7 26 26 0 0 1 11.3-22.4 36.35 36.35 0 0 1 12.6-5.6 65.89 65.89 0 0 1 15.8-1.8c7.2 0 13.3.8 18.2 2.5a34.46 34.46 0 0 1 11.9 6.5 28.21 28.21 0 0 1 6.9 9.3 42.1 42.1 0 0 1 3.2 11l-16.8 2.6c-1.4-5.9-3.7-10.2-7.1-13.1s-8.7-4.3-16.1-4.3a43.9 43.9 0 0 0-10.5 1.1 19.47 19.47 0 0 0-6.8 3.1 11.63 11.63 0 0 0-3.7 4.6 14.08 14.08 0 0 0-1.1 5.4c0 4.6 1.2 8 3.7 10.3s6.9 4 13.2 5.3l14.5 2.8c11.1 2.1 19.2 5.6 24.4 10.5s7.8 12.1 7.8 21.4a31.37 31.37 0 0 1-2.4 12.3 25.27 25.27 0 0 1-7.4 9.8 36.58 36.58 0 0 1-12.4 6.6 56 56 0 0 1-17.3 2.4c-13.4 0-24-2.8-31.6-8.5s-11.9-14.4-12.6-26.2h18z'/%3E%3Cpath fill='%23469ea2' d='M30.3 164l84 48.5 84-48.5V67l-84-48.5-84 48.5v97z'/%3E%3Cpath fill='%236acad1' d='M105.7 30.1l-61 35.2a18.19 18.19 0 0 1 0 3.3l60.9 35.2a14.55 14.55 0 0 1 17.3 0l60.9-35.2a18.19 18.19 0 0 1 0-3.3L123 30.1a14.55 14.55 0 0 1-17.3 0zm84 48.2l-61 35.6a14.73 14.73 0 0 1-8.6 15l.1 70a15.57 15.57 0 0 1 2.8 1.6l60.9-35.2a14.73 14.73 0 0 1 8.6-15V79.9a20 20 0 0 1-2.8-1.6zm-150.8.4a15.57 15.57 0 0 1-2.8 1.6v70.4a14.38 14.38 0 0 1 8.6 15l60.9 35.2a15.57 15.57 0 0 1 2.8-1.6v-70.4a14.38 14.38 0 0 1-8.6-15L38.9 78.7z'/%3E%3Cpath fill='%23469ea2' d='M114.3 29l75.1 43.4v86.7l-75.1 43.4-75.1-43.4V72.3L114.3 29m0-10.3l-84 48.5v97l84 48.5 84-48.5v-97l-84-48.5z'/%3E%3Cpath fill='%23469ea2' d='M114.9 132h-1.2A15.66 15.66 0 0 1 98 116.3v-1.2a15.66 15.66 0 0 1 15.7-15.7h1.2a15.66 15.66 0 0 1 15.7 15.7v1.2a15.66 15.66 0 0 1-15.7 15.7zm0 64.5h-1.2a15.65 15.65 0 0 0-13.7 8l14.3 8.2 14.3-8.2a15.65 15.65 0 0 0-13.7-8zm83.5-48.5h-.6a15.66 15.66 0 0 0-15.7 15.7v1.2a15.13 15.13 0 0 0 2 7.6l14.3-8.3V148zm-14.3-89a15.4 15.4 0 0 0-2 7.6v1.2a15.66 15.66 0 0 0 15.7 15.7h.6V67.2L184.1 59zm-69.8-40.3L100 26.9a15.73 15.73 0 0 0 13.7 8.1h1.2a15.65 15.65 0 0 0 13.7-8l-14.3-8.3zM44.6 58.9l-14.3 8.3v16.3h.6a15.66 15.66 0 0 0 15.7-15.7v-1.2a16.63 16.63 0 0 0-2-7.7zM30.9 148h-.6v16.2l14.3 8.3a15.4 15.4 0 0 0 2-7.6v-1.2A15.66 15.66 0 0 0 30.9 148z'/%3E%3Cpath fill='%23083b54' fill-opacity='0.15' d='M114.3 213.2v-97.1l-84-48.5v97.1z'/%3E%3Cpath fill='%23083b54' fill-opacity='0.05' d='M198.4 163.8v-97l-84 48.5v97.1z'/%3E%3C/svg%3E%0A"); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-mid { - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-mkv { - background-image:url("data:image/svg+xml;charset=utf8,%3Csvg id='Layer_2' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 72 100'%3E%3Cstyle/%3E%3ClinearGradient id='SVGID_1_' gradientUnits='userSpaceOnUse' x1='36.2' y1='101' x2='36.2' y2='3.005' gradientTransform='matrix(1 0 0 -1 0 102)'%3E%3Cstop offset='0' stop-color='%23e2cde4'/%3E%3Cstop offset='.17' stop-color='%23e0cae2'/%3E%3Cstop offset='.313' stop-color='%23dbc0dd'/%3E%3Cstop offset='.447' stop-color='%23d2b1d4'/%3E%3Cstop offset='.575' stop-color='%23c79dc7'/%3E%3Cstop offset='.698' stop-color='%23ba84b9'/%3E%3Cstop offset='.819' stop-color='%23ab68a9'/%3E%3Cstop offset='.934' stop-color='%239c4598'/%3E%3Cstop offset='1' stop-color='%23932a8e'/%3E%3C/linearGradient%3E%3Cpath d='M45.2 1l27 26.7V99H.2V1h45z' fill='url(%23SVGID_1_)'/%3E%3Cpath d='M45.2 1l27 26.7V99H.2V1h45z' fill-opacity='0' stroke='%23882383' stroke-width='2'/%3E%3Cpath d='M7.5 91.1V71.2h6.1l3.6 13.5 3.6-13.5h6.1V91h-3.8V75.4l-4 15.6h-3.9l-4-15.6V91H7.5zm23.5 0V71.2h4V80l8.2-8.8h5.4L41.1 79l8 12.1h-5.2l-5.5-9.3-3.4 3.3v6h-4zm25.2 0L49 71.3h4.4L58.5 86l4.9-14.7h4.3l-7.2 19.8h-4.3z' fill='%23fff'/%3E%3ClinearGradient id='SVGID_2_' gradientUnits='userSpaceOnUse' x1='18.2' y1='50.023' x2='18.2' y2='50.023' gradientTransform='matrix(1 0 0 -1 0 102)'%3E%3Cstop offset='.005' stop-color='%23963491'/%3E%3Cstop offset='1' stop-color='%2370136b'/%3E%3C/linearGradient%3E%3ClinearGradient id='SVGID_3_' gradientUnits='userSpaceOnUse' x1='11.511' y1='51.716' x2='65.211' y2='51.716' gradientTransform='matrix(1 0 0 -1 0 102)'%3E%3Cstop offset='.005' stop-color='%23963491'/%3E%3Cstop offset='1' stop-color='%2370136b'/%3E%3C/linearGradient%3E%3Cpath d='M64.3 55.5c-1.7-.2-3.4-.3-5.1-.3-7.3-.1-13.3 1.6-18.8 3.7S29.6 63.6 23.3 64c-3.4.2-7.3-.6-8.5-2.4-.8-1.3-.8-3.5-1-5.7-.6-5.7-1.6-11.7-2.4-17.3.8-.9 2.1-1.3 3.4-1.7.4 1.1.2 2.7.6 3.8 7.1.7 13.6-.4 20-1.5 6.3-1.1 12.4-2.2 19.4-2.6 3.4-.2 6.9-.2 10.3 0m-9.9 15.3c.5-.2 1.1-.3 1.9-.2.2-3.7.3-7.3.3-11.2-6.2.2-11.9.9-17 2.2.2 4 .4 7.8.3 12 4-1.1 7.7-2.5 12.6-2.7m2-12.1h1.1c.4-.4.2-1.2.2-1.9-1.5-.6-1.8 1-1.3 1.9zm3.9-.2h1.5V38h-1.3c0 .7-.4.9-.2 1.7zm4 0c.5-.1.8 0 1.1.2.4-.3.2-1.2.2-1.9h-1.3v1.7zm-11.5.3h.9c.4-.3.2-1.2.2-1.9-1.4-.4-1.6 1.2-1.1 1.9zm-4 .4c.7.2.8-.3 1.5-.2v-1.7c-1.5-.4-1.7.6-1.5 1.9zm-3.6-1.1c0 .6-.1 1.4.2 1.7.5.1.5-.4 1.1-.2-.2-.6.5-2-.4-1.9-.1.4-.8.1-.9.4zm-31.5.8c.4-.1 1.1.6 1.3 0-.5 0-.1-.8-.2-1.1-.7.2-1.3.3-1.1 1.1zm28.3-.4c-.3.3.2 1.1 0 1.9.6.2.6-.3 1.1-.2-.2-.6.5-2-.4-1.9-.1.3-.4.2-.7.2zm-3.5 2.8c.5-.1.9-.2 1.3-.4.2-.8-.4-.9-.2-1.7h-.9c-.3.3-.1 1.3-.2 2.1zm26.9-1.8c-2.1-.1-3.3-.2-5.5-.2-.5 3.4 0 7.8-.5 11.2 2.4 0 3.6.1 5.8.3M33.4 41.6c.5.2.1 1.2.2 1.7.5-.1 1.1-.2 1.5-.4.6-1.9-.9-2.4-1.7-1.3zm-4.7.6v1.9c.9.2 1.2-.2 1.9-.2-.1-.7.2-1.7-.2-2.1-.5.2-1.3.1-1.7.4zm-5.3.6c.3.5 0 1.6.4 2.1.7.1.8-.4 1.5-.2-.1-.7-.3-1.2-.2-2.1-.8-.2-.9.3-1.7.2zm-7.5 2H17c.2-.9-.4-1.2-.2-2.1-.4.1-1.2-.3-1.3.2.6.2-.1 1.7.4 1.9zm3.4 1c.1 4.1.9 9.3 1.4 13.7 8 .1 13.1-2.7 19.2-4.5-.5-3.9.1-8.7-.7-12.2-6.2 1.6-12.1 3.2-19.9 3zm.5-.8h1.1c.4-.5-.2-1.2 0-2.1h-1.5c.1.7.1 1.6.4 2.1zm-5.4 7.8c.2 0 .3.2.4.4-.4-.7-.7.5-.2.6.1-.2 0-.4.2-.4.3.5-.8.7-.2.8.7-.5 1.3-1.2 2.4-1.5-.1 1.5.4 2.4.4 3.8-.7.5-1.7.7-1.9 1.7 1.2.7 2.5 1.2 4.2 1.3-.7-4.9-1.1-8.8-1.6-13.7-2.2.3-4-.8-5.1-.9.9.8.6 2.5.8 3.6 0-.2 0-.4.2-.4-.1.7.1 1.7-.2 2.1.7.3.5-.2.4.9m44.6 3.2h1.1c.3-.3.2-1.1.2-1.7h-1.3v1.7zm-4-1.4v1.3c.4.4.7-.2 1.5 0v-1.5c-.6 0-1.2 0-1.5.2zm7.6 1.4h1.3v-1.5h-1.3c.1.5 0 1 0 1.5zm-11-1v1.3h1.1c.3-.3.4-1.7-.2-1.7-.1.4-.8.1-.9.4zm-3.6.4c.1.6-.3 1.7.4 1.7 0-.3.5-.2.9-.2-.2-.5.4-1.8-.4-1.7-.1.3-.6.2-.9.2zm-3.4 1v1.5c.7.2.6-.4 1.3-.2-.2-.5.4-1.8-.4-1.7-.1.3-.8.2-.9.4zM15 57c.7-.5 1.3-1.7.2-2.3-.7.4-.8 1.6-.2 2.3zm26.1-1.3c-.1.7.4.8.2 1.5.9 0 1.2-.6 1.1-1.7-.4-.5-.8.1-1.3.2zm-3 2.7c1 0 1.2-.8 1.1-1.9h-.9c-.3.4-.1 1.3-.2 1.9zm-3.6-.4v1.7c.6-.1 1.3-.2 1.5-.8-.6 0 .3-1.6-.6-1.3 0 .4-.7.1-.9.4zM16 60.8c-.4-.7-.2-2-1.3-1.9.2.7.2 2.7 1.3 1.9zm13.8-.9c.5 0 .1.9.2 1.3.8.1 1.2-.2 1.7-.4v-1.7c-.9-.1-1.6.1-1.9.8zm-4.7.6c0 .8-.1 1.7.4 1.9 0-.5.8-.1 1.1-.2.3-.3-.2-1.1 0-1.9-.7-.2-1 .1-1.5.2zM19 62.3v-1.7c-.5 0-.6-.4-1.3-.2-.1 1.1 0 2.1 1.3 1.9zm2.5.2h1.3c.2-.9-.3-1.1-.2-1.9h-1.3c-.1.9.2 1.2.2 1.9z' fill='url(%23SVGID_3_)'/%3E%3ClinearGradient id='SVGID_4_' gradientUnits='userSpaceOnUse' x1='45.269' y1='74.206' x2='58.769' y2='87.706' gradientTransform='matrix(1 0 0 -1 0 102)'%3E%3Cstop offset='0' stop-color='%23f9eff6'/%3E%3Cstop offset='.378' stop-color='%23f8edf5'/%3E%3Cstop offset='.515' stop-color='%23f3e6f1'/%3E%3Cstop offset='.612' stop-color='%23ecdbeb'/%3E%3Cstop offset='.69' stop-color='%23e3cce2'/%3E%3Cstop offset='.757' stop-color='%23d7b8d7'/%3E%3Cstop offset='.817' stop-color='%23caa1c9'/%3E%3Cstop offset='.871' stop-color='%23bc88bb'/%3E%3Cstop offset='.921' stop-color='%23ae6cab'/%3E%3Cstop offset='.965' stop-color='%239f4d9b'/%3E%3Cstop offset='1' stop-color='%23932a8e'/%3E%3C/linearGradient%3E%3Cpath d='M45.2 1l27 26.7h-27V1z' fill='url(%23SVGID_4_)'/%3E%3Cpath d='M45.2 1l27 26.7h-27V1z' fill-opacity='0' stroke='%23882383' stroke-width='2' stroke-linejoin='bevel'/%3E%3C/svg%3E"); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-mov { - background-image:url("data:image/svg+xml;charset=utf8,%3Csvg id='Layer_2' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 72 100'%3E%3Cstyle/%3E%3ClinearGradient id='SVGID_1_' gradientUnits='userSpaceOnUse' x1='36.2' y1='101' x2='36.2' y2='3.005' gradientTransform='matrix(1 0 0 -1 0 102)'%3E%3Cstop offset='0' stop-color='%23e2cde4'/%3E%3Cstop offset='.17' stop-color='%23e0cae2'/%3E%3Cstop offset='.313' stop-color='%23dbc0dd'/%3E%3Cstop offset='.447' stop-color='%23d2b1d4'/%3E%3Cstop offset='.575' stop-color='%23c79dc7'/%3E%3Cstop offset='.698' stop-color='%23ba84b9'/%3E%3Cstop offset='.819' stop-color='%23ab68a9'/%3E%3Cstop offset='.934' stop-color='%239c4598'/%3E%3Cstop offset='1' stop-color='%23932a8e'/%3E%3C/linearGradient%3E%3Cpath d='M45.2 1l27 26.7V99H.2V1h45z' fill='url(%23SVGID_1_)'/%3E%3Cpath d='M45.2 1l27 26.7V99H.2V1h45z' fill-opacity='0' stroke='%23882383' stroke-width='2'/%3E%3Cpath d='M6.1 91.1V71.2h6.1l3.6 13.5 3.6-13.5h6.1V91h-3.8V75.4l-4 15.6h-3.9l-4-15.6V91H6.1zm22.6-9.8c0-2 .3-3.7.9-5.1.5-1 1.1-1.9 1.9-2.7.8-.8 1.7-1.4 2.6-1.8 1.2-.5 2.7-.8 4.3-.8 3 0 5.3.9 7.1 2.7 1.8 1.8 2.7 4.3 2.7 7.6 0 3.2-.9 5.7-2.6 7.5-1.8 1.8-4.1 2.7-7.1 2.7s-5.4-.9-7.1-2.7c-1.8-1.8-2.7-4.3-2.7-7.4zm4.1-.2c0 2.2.5 4 1.6 5.1 1 1.2 2.4 1.7 4 1.7s2.9-.6 4-1.7c1-1.2 1.6-2.9 1.6-5.2 0-2.3-.5-4-1.5-5.1-1-1.1-2.3-1.7-4-1.7s-3 .6-4 1.7c-1.1 1.2-1.7 3-1.7 5.2zm23.6 10l-7.2-19.8h4.4L58.7 86l4.9-14.7h4.3l-7.2 19.8h-4.3z' fill='%23fff'/%3E%3ClinearGradient id='SVGID_2_' gradientUnits='userSpaceOnUse' x1='18.2' y1='50.023' x2='18.2' y2='50.023' gradientTransform='matrix(1 0 0 -1 0 102)'%3E%3Cstop offset='.005' stop-color='%23963491'/%3E%3Cstop offset='1' stop-color='%2370136b'/%3E%3C/linearGradient%3E%3ClinearGradient id='SVGID_3_' gradientUnits='userSpaceOnUse' x1='11.511' y1='51.716' x2='65.211' y2='51.716' gradientTransform='matrix(1 0 0 -1 0 102)'%3E%3Cstop offset='.005' stop-color='%23963491'/%3E%3Cstop offset='1' stop-color='%2370136b'/%3E%3C/linearGradient%3E%3Cpath d='M64.3 55.5c-1.7-.2-3.4-.3-5.1-.3-7.3-.1-13.3 1.6-18.8 3.7S29.6 63.6 23.3 64c-3.4.2-7.3-.6-8.5-2.4-.8-1.3-.8-3.5-1-5.7-.6-5.7-1.6-11.7-2.4-17.3.8-.9 2.1-1.3 3.4-1.7.4 1.1.2 2.7.6 3.8 7.1.7 13.6-.4 20-1.5 6.3-1.1 12.4-2.2 19.4-2.6 3.4-.2 6.9-.2 10.3 0m-9.9 15.3c.5-.2 1.1-.3 1.9-.2.2-3.7.3-7.3.3-11.2-6.2.2-11.9.9-17 2.2.2 4 .4 7.8.3 12 4-1.1 7.7-2.5 12.6-2.7m2-12.1h1.1c.4-.4.2-1.2.2-1.9-1.5-.6-1.8 1-1.3 1.9zm3.9-.2h1.5V38h-1.3c0 .7-.4.9-.2 1.7zm4 0c.5-.1.8 0 1.1.2.4-.3.2-1.2.2-1.9h-1.3v1.7zm-11.5.3h.9c.4-.3.2-1.2.2-1.9-1.4-.4-1.6 1.2-1.1 1.9zm-4 .4c.7.2.8-.3 1.5-.2v-1.7c-1.5-.4-1.7.6-1.5 1.9zm-3.6-1.1c0 .6-.1 1.4.2 1.7.5.1.5-.4 1.1-.2-.2-.6.5-2-.4-1.9-.1.4-.8.1-.9.4zm-31.5.8c.4-.1 1.1.6 1.3 0-.5 0-.1-.8-.2-1.1-.7.2-1.3.3-1.1 1.1zm28.3-.4c-.3.3.2 1.1 0 1.9.6.2.6-.3 1.1-.2-.2-.6.5-2-.4-1.9-.1.3-.4.2-.7.2zm-3.5 2.8c.5-.1.9-.2 1.3-.4.2-.8-.4-.9-.2-1.7h-.9c-.3.3-.1 1.3-.2 2.1zm26.9-1.8c-2.1-.1-3.3-.2-5.5-.2-.5 3.4 0 7.8-.5 11.2 2.4 0 3.6.1 5.8.3M33.4 41.6c.5.2.1 1.2.2 1.7.5-.1 1.1-.2 1.5-.4.6-1.9-.9-2.4-1.7-1.3zm-4.7.6v1.9c.9.2 1.2-.2 1.9-.2-.1-.7.2-1.7-.2-2.1-.5.2-1.3.1-1.7.4zm-5.3.6c.3.5 0 1.6.4 2.1.7.1.8-.4 1.5-.2-.1-.7-.3-1.2-.2-2.1-.8-.2-.9.3-1.7.2zm-7.5 2H17c.2-.9-.4-1.2-.2-2.1-.4.1-1.2-.3-1.3.2.6.2-.1 1.7.4 1.9zm3.4 1c.1 4.1.9 9.3 1.4 13.7 8 .1 13.1-2.7 19.2-4.5-.5-3.9.1-8.7-.7-12.2-6.2 1.6-12.1 3.2-19.9 3zm.5-.8h1.1c.4-.5-.2-1.2 0-2.1h-1.5c.1.7.1 1.6.4 2.1zm-5.4 7.8c.2 0 .3.2.4.4-.4-.7-.7.5-.2.6.1-.2 0-.4.2-.4.3.5-.8.7-.2.8.7-.5 1.3-1.2 2.4-1.5-.1 1.5.4 2.4.4 3.8-.7.5-1.7.7-1.9 1.7 1.2.7 2.5 1.2 4.2 1.3-.7-4.9-1.1-8.8-1.6-13.7-2.2.3-4-.8-5.1-.9.9.8.6 2.5.8 3.6 0-.2 0-.4.2-.4-.1.7.1 1.7-.2 2.1.7.3.5-.2.4.9m44.6 3.2h1.1c.3-.3.2-1.1.2-1.7h-1.3v1.7zm-4-1.4v1.3c.4.4.7-.2 1.5 0v-1.5c-.6 0-1.2 0-1.5.2zm7.6 1.4h1.3v-1.5h-1.3c.1.5 0 1 0 1.5zm-11-1v1.3h1.1c.3-.3.4-1.7-.2-1.7-.1.4-.8.1-.9.4zm-3.6.4c.1.6-.3 1.7.4 1.7 0-.3.5-.2.9-.2-.2-.5.4-1.8-.4-1.7-.1.3-.6.2-.9.2zm-3.4 1v1.5c.7.2.6-.4 1.3-.2-.2-.5.4-1.8-.4-1.7-.1.3-.8.2-.9.4zM15 57c.7-.5 1.3-1.7.2-2.3-.7.4-.8 1.6-.2 2.3zm26.1-1.3c-.1.7.4.8.2 1.5.9 0 1.2-.6 1.1-1.7-.4-.5-.8.1-1.3.2zm-3 2.7c1 0 1.2-.8 1.1-1.9h-.9c-.3.4-.1 1.3-.2 1.9zm-3.6-.4v1.7c.6-.1 1.3-.2 1.5-.8-.6 0 .3-1.6-.6-1.3 0 .4-.7.1-.9.4zM16 60.8c-.4-.7-.2-2-1.3-1.9.2.7.2 2.7 1.3 1.9zm13.8-.9c.5 0 .1.9.2 1.3.8.1 1.2-.2 1.7-.4v-1.7c-.9-.1-1.6.1-1.9.8zm-4.7.6c0 .8-.1 1.7.4 1.9 0-.5.8-.1 1.1-.2.3-.3-.2-1.1 0-1.9-.7-.2-1 .1-1.5.2zM19 62.3v-1.7c-.5 0-.6-.4-1.3-.2-.1 1.1 0 2.1 1.3 1.9zm2.5.2h1.3c.2-.9-.3-1.1-.2-1.9h-1.3c-.1.9.2 1.2.2 1.9z' fill='url(%23SVGID_3_)'/%3E%3ClinearGradient id='SVGID_4_' gradientUnits='userSpaceOnUse' x1='45.269' y1='74.206' x2='58.769' y2='87.706' gradientTransform='matrix(1 0 0 -1 0 102)'%3E%3Cstop offset='0' stop-color='%23f9eff6'/%3E%3Cstop offset='.378' stop-color='%23f8edf5'/%3E%3Cstop offset='.515' stop-color='%23f3e6f1'/%3E%3Cstop offset='.612' stop-color='%23ecdbeb'/%3E%3Cstop offset='.69' stop-color='%23e3cce2'/%3E%3Cstop offset='.757' stop-color='%23d7b8d7'/%3E%3Cstop offset='.817' stop-color='%23caa1c9'/%3E%3Cstop offset='.871' stop-color='%23bc88bb'/%3E%3Cstop offset='.921' stop-color='%23ae6cab'/%3E%3Cstop offset='.965' stop-color='%239f4d9b'/%3E%3Cstop offset='1' stop-color='%23932a8e'/%3E%3C/linearGradient%3E%3Cpath d='M45.2 1l27 26.7h-27V1z' fill='url(%23SVGID_4_)'/%3E%3Cpath d='M45.2 1l27 26.7h-27V1z' fill-opacity='0' stroke='%23882383' stroke-width='2' stroke-linejoin='bevel'/%3E%3C/svg%3E"); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-mp3 { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAnxJREFUeNp0U89PE0EU/ra7XWxpSsFYIbVQf9REFBHkYBRIPJh4wrN3DsZ4MPGP8b/wUCIHEw5EY0w04o9ILcREGmwVgaXbbXdnd2bXNxPahGyczebtzrz3ve99740WRRHkWn5cebu4cH6SMY7e0jRAHr9c3WxsVvcemmbys9yT6+uHJ8oaPefypdPDD5Ymh5w26wMkEho8JtDtuEOZFCrvN/4uJZNGH0T59D58X/C27aFNAL3Xthmsww5GCyN4+uzu+OLtQsUPxPQx6ZMAoQjBAw7O+bEVCMMQgqygs+LFs1h+dGd8bna0QmXO9OL6JYgwAvOFZKKoy3V44CgNfv7Yx8oLH+lUEgvzF8Ydhz+n41snAGRG5gUEwClzhHdvttFxfNyYK0EnJozKK5eGcf1qHo1GOxtjwI+pfvm4g/W1qtJgerYE2SXJSIL9+W0jk0mCShAxDXgQKgbNXxZq35vQKCiKQkSUXdc1+gcch1FHGPmKuIgBCdc66qJQHMG9+1NIpUylxxHtuW6gEiTIu+N4yjdWgty0yTmdNjFzcwKjY0MU7MLt+IjoSad16FoIx3b/A0DZ7FYXnsdpAjUMDOjI5zPgfoBsRodhhGhZHfBBU/nGAGRtxWIOg5lT2NtrI5dL0SB5KJzLodloqXaOEatPGztKq5gG3S5DNjuAK5NjKJfPYKI0okBkSdemCiSgS/rkQNLSePtxBj4LSCwfFtE0krqqX7ZVMnu9XlMXy2l7ME0dzA3iANQyY6vWxC61UY41zTyNcYh6/QCNXQvzi5dR39nHVq1BUyuMGAARsF6tbbe4iKD1r7Om5iFBdmW1SsDflLiuB6sX90+AAQDHAW7dW0YnzgAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-mp4 { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAnBJREFUeNpsk99r01AUx79psrTrujVtbceabnZs4DYRHSoMh6Dgq77rn+AfoA/+If4Bok+C0CfxVRDBh+I2NqZzrpS1DVvbtU3SJPcm8SSlsJlecsn9dT73nO85V/B9H0H78OLdt/LDlQ1uMYybIAgI9n99OWxoe83nkiz9hDDae330JvxL48O51Xxm/enNtKPbVwAh0Ec6kYpXat9Pnl2GBC02HrjM5Y7h4P8+7FtIFVJ49OrxUnl7ucIdfhv+BIDv+fBcj7p/tXMPrs2RXVTw4OX2UnFTrXCbbY7tpMsA13FDSDAOQ4gJEGUJLs0PPh9CkESsPrmxxEz2lra3rnpAt3G6adgdQhBpmeLkFodNmsjpOPoXBrQTDcmFFNS7i3MRDzzPCw/vva8ikU+COQxm14BBhvJcHLGpGPTOAJxxeLbrRgAkYujBdH4G5oWJWXUW19YL4XqunAMFhnq1BqWYgaY1MAHASQOiU96zKzkU76mwehaOvx6h9uMv7KFN3RopL4oTAI4HRh4wSl399xla+00YbR3yrIzM9SzSqgJJnoKcklGrH08CcJjnBtLLCsSEGGpSWJvHtDKNoFippsJ0ulIsDDUCCATMlBQkNuahEyiZTcLsmFBKaQxaOk53TlHeKkM70AjAooCghBOk9sKtIvqtPqS4FBaRnJSRX8tj2DOh3lFB5Qw2ZNFK5LRo6w4sKt2ggAzywidAMN/9uIPSZglBLDO5FF3mRD3wHE9qVRvoHrUpfn+UEQK0/7ShtwboHJ6jdH8RZxSC57hSVETb7e5/2u0FxqPHJow+8iZ4lYY2QGu3idhIxO7Y7p8AAwALCGZKEPBGCgAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-mpg { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAnxJREFUeNpsU0tPE1EU/ubRdlqmnUBboa0UeUQDiUGCC1+JmrhxoXt/gBvXJi74If4AV0Y3sNKF0YUaICqoIfjgVShEiGF4tDOdO/fOeOaSKtie5GZu7pzz3e/c7ztKGIaI4vn9p+/P3h4e4a6Pv6EoQBDiy7P5rc1P1Xt6XP8M5ejXo6UJ+dWbuemeTGdpvNdiNe9YvQLe4Bi4PmTpRmyq8m71rp74BxKF2twIHvAo+f/l1T2Yp0zceHizfOZa/xRnfBRhG4CQqAYioBWeXDyA8Di6ei1ceXC1XBwrTXHPH2vW6ccBBBMI6BsSUEQzakGL6xB0tvjyBxRNxdCtc2Xf8R9TyaWTDOg2TjfVdw6hqIoE9B2GxkEDWlLH7s4ette2kSp0oDRezrQwCIIA3oGHr0/mKMmE53qo23W4+w5S+Q5ohob9X3tgHgO8ULQACC7gMx9mKQP30EW6mEHpYi8xcJEdzMucjfkKcrTfmqmiFYBxCF/Id+gayKJwoQjHdrA5v4HK7Cq44KjZNWpagaqp7QACks0H9znW365ia24DzoEDozOJbH8eVtGShXHTwNracnsG7q6LzsEuaAlNPm9h7DSSVjLyCMkppDI+GS2StQWA1RlKo0X56n2X+6QHkmkDakxF9WMVqWyK+s/BrthYfvWz1Ug+zUDcjMPMm0h3pxEjFma3CbIuCud7oMc0LL1ZgmElpGJtW3B+15HIGNITrMYIlOH7i0U41NrInREylYbu4R5qQbQBaAh95fVKZCnpQCnb9DrWZyrRERS6NDeUw+yHaXh7rt4C4B8y+9vkwn7kwKNRpDoa9aiFKBYnF+RcREqQ2e1m3R8BBgAy9kz9ysCE6QAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-odf { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAi5JREFUeNp0UktrU0EU/mbu3FfE1KRRUpWYheALNBURUVy7cy9UkO6KW/+Lbt0IPsFui4gLBbUqFaUuXETUKCYa0jS5yZ2ZO557b5MmTXpgmDPnfOc7jznMGINYPi0de5UvmpORxpjE/kbNqW005DVu8TWw1H758ZfkFgNgJmtyxSPRjJIj0QTW/RDiYGXGb7Dl32/eXrVsd0gSCx9miqC0ooCdp69g5Q/h6OLN0ty5ynIkwzMwUwh2FwMdcbDiCZQXlkqFCpEoPT/wih1YjLInANcD+/Ua9bu3wJlGvrBZCmet2+S6ME5g4oGlZ9A/I70XCDhhDexPNTFmswJBwcnuXkF86VSNZxVu0ukLSGnBcqlnN4HoCQIaIuIv7LUooMOgQ7q75LAAb59B9gCBHSKgqemRr94mMKmD24CfM8nb7THYGQNLpAkUkcb66JyGBFFEWRVL57gFEH5qj8Lxwca2qS3EZaugmzAw24dR/XQgwtsCSBjPIdWbUoE2UJLBnV8Ac/ciWHsK9/glWLnD6K2vgPszsOdOQdfeQ1c/ThKoTgDn9A3KUED/52d45xchZsvorD6Bf/Z60riV3Q9Z/0bbGU1uopYGkfERSQ3VbsMwl0qlqoIARmSoPYXWy0dor79LfBMEEd8jGs/uQ3Yl7PJFNFbuEXiV2riCf88fovXhBbo/vqP3t02/ZYmJFqTkzY160Go9uEMbFK8hR/NrdXtFuUVmnmySVGgO4v4LMAAjRgmO+SJJiQAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-ods { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAetJREFUeNqMUj1IHEEU/i7u7Z23e8tGgneGQPw3hZDkkhQiSuwMQREba4uUgpVlCrvEQhurkCoWqcQQ0oTAaYKNqJygGEwgHCSB6Knn7eXcdX/GmdHVPWYFP3gw78173/vmvYkQQsAwNvckq96UnyIEh7/d4t7uUd/8y+85P+bXSX4grkhI6nJYPW7LrXpBK2YxiSoShhu4Buq1NPofDeqdrZ3Z4cl7D4J3UtA5VyVAlmJoru9Af2ZAp1lcCQ3nqgiuKmbY3l/BH+MnHM9GVLP0Ww3KNA33CQoQQnL834Fj74PUGkANEIkCSSsa8gQqgYTIcB0PVsXB318GInRiCVWCkpRFAs+j5gKlA4t29Ggh4d0t04FKt9PQqF4UFgumSEA8ApeaElilWbYRVy/lsns/N1QBkxtENF4jxPxcgcB1CZVOrvMteK5IQDtJJIGh++PcX9iYwWjXK37+vP0WdYk0Ht99jtX8JywWFkQChw4tc+cZcvlF7rMze+ubbxN40fMalRMDP/6twaiUeK7wlZ0TD0a5hLTWxo2d45KKprqHKJslTsy209s2wnMFBTYNZjc/oLt9gPvLOx+hxVJIKS2YW5pCbSyJTGMK775O8VyBwDJd2LTDl/X5i8v3S7NVw9vJb51tITDEUwEGANCx2/rXEEFFAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-odt { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAepJREFUeNqMkz1II1EQx/+7Ca6JkqyYiJ8cKEpAQbBQFDm0sVOsFBS9wt5KOTgEG5twxVlZ+XEnKNiIghYKxx5nwEpIIXaiSAgKGmMi0d23u8+3T7OaZJEMLG9mmPnN/w1vBUopLPNNhRWXHOyDg0nx82TiJtZPlPVoNpftc2cTotcHtxx06kdXpSQ/BvzKESZzIDmAz6y+NojOjpDMZiqRPIgNoFyWM8DrKUV7axO+gcp4g7AzmquAdVNqOgL2z2I4id1B0wgeygOyt/rLL5buLwAIDgA9dY+L+DkuDQOCrkMgBsRglcMOqAGwIstMg8AkGsuZMNUMRMkLqE+QGloglvlA7uIOAKvZajR0qJkUj/XHe0BTIclVKKlrfKsj9qA8gA6wqSJzPaXlr7ky//tdLEUfawsBjExUFGVWbT7AxSa42H2LMfODmvd3wKb7RAMLYwM8nts8xJ/pEe7/3PmP2eGv3D+9usb35W0bINoA7RmjXSHsH0f5Z/mUSZ0Ir2JmsBtD80s8/rGyzWsLFTD5yUQCbfUBHl9d38LvkdDTXIuHVBo0k+bbt06qO+yAPGXwe/cA4wO9PN44jKDG70GougIzi2tQ00ms7/3lpwnBBgjZ37Kkd1Shht5XzBIFl/ufFtniT/lFgAEAU//g6kvdGBMAAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-otp { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAcJJREFUeNqMkssvA1EUxr+ZjkdbrfFKVD12ErYSRELY2fkH+BMsLcQaSwsrSzZi47EjJEQkEhYkFlhYSVtFpdqOqpk717l3jKZmiC+5mZlzv/s795wzCuccQncz3YeRBj4KHz0/RrOZe2NsZPP20o255zQ3EAxzEAC+6uzTw13G4TFQAakA/CWtIYbY0KBOrx7IvwDQqlHV1o3YxKTOvyAUvfQCfqmA3e4ikyS/zRAKvOot7eoSHEgZIHrCfQAfBqBaKQQDKScQAExd8emBANg+2U2CvNMkkgSqBmrCxFB8mujeoJBWwEqARcssKTAJEGrmaGrjqK1zvNknH4BtyxKl2VUpRxmj5W+x73q9AEaZrR/ND1EJluIpS3i9JQiA+a+hSq8HwJjTsLrRaWitPTCOlhEZn5N75sM1qigmlN+dB3u++Qao5W4TtbEXXIsiszGL4PA00itTsu6XnQWo0TjMTAJqfMDx/ryBJcaVzSNSH4fW0Q+rkIf5rsjRiid7yyN7uoXS3Zn0egE0NiORAN9bQ017D1Lri7CLlP2EDr3Rf7C/itzV2bfXA/igLDaRixfngFhSCooH2xVPCWBlwKcAAwBX1suA6te+hAAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-ots { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAfZJREFUeNqMUk1rE1EUPS8zmabJdDKB2glEwY9ExJYiBUEQpV25qgtBXfgbpEtXuujKf+AfEKRddOdOGHClbYVCvyKWaijT2mhjphk7Sd7Me76ZONp0EsiBYWbOvfe88+69hHOOAE9f3zTVnDKNHvhlsfqPw/rM0ovyWsRFdXJEpDIyRnSlVz0KSkmvabaJeXSJBEhgAJzTDNybmtUnS5Pmg/lrN07H5NM/f13FoMgpXDSuhiIiK3Qi6LUugX7FAbaPPsJqfIHHKCStqRsXVFPQuZgD9BBxjikSiRq41AAkgCQBzVf0+BWEBX7GBm0xgHHUqk1UbBuEcIydzyCZlOI9YEGuDxwduCCitS3Xh3viCZ4jrcq4PJ6DLHd67tjtuAAXib54dCPVEfQ5XIcik/0/2iDeOYz3ceCxrisMi904y0XiMQFfkB7lg6xFHwFxEqUMV0anUNBLWKm8xd3i4zBWOzmASx0UsiW831mA59Xjm+h7HCOygduXHqJatzA7Poey9QnXjTuoVD/j/sRcmDOWLgqnLC5A2wwST+Pn8T629lahSCo291bwu9XA7vcy3m2+gTaUR14thrk9BXasbdiOjSe3nmPpwys0xSi/HpbDd3bIQC6dx/q3ZbRb/j8BEi3Po5cTJpHI9CBNDEa++GyDBN9/BBgAwfDlCVUQaNAAAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-ott { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdFJREFUeNqMU89r02AYfpJ0iVm7EqhVOxw7dDBEdpiCE1RoEZRddvUgbIex/Rs7eehppyF4LOzQu4MxwYp0HgShIuwwUVSCVtl0s13afl+SzzcpyZYmyF74eN583/s+PO+PSEIIeJZdrtQVI19Cgmk/Ph39bpllXq82g7sgLxVcyKNZpIx8Uj5u5zSjc9Gov8ZihCRC8D+7On4JczevGeTGSEIC4ctKJtB1DTPXi1iCCEkIm1EFlC2Em0iwtWfinXkIzjiO0jljtDC5TtflGIGUQMB+mfja/oPv2Rx9MMjpMdJxOXyXTwkcwIkewfqQ1QtQNB385zcI14FrtQexsSb6SRysZ4Fbf+F6eHwATc9gJGNAm5iCTL5n/LCVRGADNoeaGoHqyaXj5gqQlTODovcwNk5Aj6wXqV8eCo7EDhMonEHpW+dZC7gUG98D3geo7vkb01h9cAvPdt76OGy1xntUd3bjUxAk3+l2sHJ/FgtrT0MUJNfDSm0bjQ/72Hzxxo+NK+h3B7XRNO4UrwymQtMIkdTBU0m+sBOayLsn8Ka78mQDjx/e87HXPkb1+UsfP37+AmZ1fP/suknBb6nefVQXjl06TxMlJfWKNWr+Kv8TYAAkUueexJF47QAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-pdf { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmhJREFUeNp0U0trU0EYPTP35qYxaW6TlDapNKWGbgo2FkF8rARB6rboXusf0F/hyq2U4krFqugqSBeuAyL4SERBstHa0iR9JKZJ7mvu+M0tqZGkH3x8987jzDnnm2FSSqh4ns0VU1ybFzj674Wa3uWiWbfsFQb+jrGj8Xvbm0HlvYVRxhJprpmTlGmum+OMm5uNPZNbtjk3l82ey8++8oW4Jv/H/wdA456g2kvH99FyHNiuAz2dwflbN8YW8zMK5Go/CMfQkAhpGsyQgRCtlpE4jIULyC9fHzu7MPPEl/5ib6WOE0JJNRiHHg6j86mMjw/2gG4bkbY4PW4Yj2j64skA5FTHdaEMPiAJszt1sK0d4suJmY4k0+IDDGRfqmh0u5gejQc+fG8eYCIahRQCEfgQnIuhEkgtONE+dGxYxEDj1DhiEycZ+1YXdUpHCqTMJIYyEES5aXXQsi2kYlGEia5GtHVKn+amPBeCutPgfLALPuVu+xDVPw2EQyFEjHDghbpYNm1yKVVnYjTOerepn4E6XQmLGSPkPkOXWATMSDcjQEkAaqOu6+i/rccALtFL53LI3r0Nq1ZD4/MXZJaWYFer+PXiJc6s3IEgY3+uPYZHTAcAHM+DTE8gnM1CSyaCulv+GrRy8uYyElcu4XfhLVpkpNtn/DGA5Uu0abFH36WnzzCayWAkmYJvWeCkfb9SwY+NDbSoOx4bYqJF8rZqVRRXV/HhzWtUSmWwmWl0RmN4v76OUqGASrmMOkntSHF8MOs954dT08W248wzYsJDOujRBAaqqikTpRo/qqd0/dv97c3Lat9fAQYA4z8bX9nTsb8AAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-php { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAhNJREFUeNqMkltrE0EUx//ZbDaXNrvZzdIkbYOXGgxYQlCK2IIY6EufxGdB8Av44AdR8AP44JOPBR+Ego0PClUKTTXQSmkTYtOkmubSJrQ1e3H2yJSEJNIDs3PmP+f89pyZcdm2DcdWvn7LzkxFHmCIra7nm9ulg8yLZ09yXON55Dgjt1PM2iPs0+aW/frdh8bzV2/SvQBnCLiEqcFxLKSSodlrU9leiGPihWePBkgeEZO6ShC2dCAZNuf6ADb+ldQ5PUPx4BCFcgXfdwq4Ph1Dtd5CZi4Nw7SQiMdCXkl6yVIy/QBWgcU+yx/XsLK2cdHndqlK/lZxH/OpJO7fnsWY3z/YAq+g0TmHpoUH2vB5PXi8RD9Fo10aAmDJTgWyIuOupmK38rsPcOvqJO33XWEvwLJsmKxHRVEwf/MKWl/yUMf8mIloWN8rw+sP0D6PHQmYuzGNgCRiMZVA17IQV4OIaTI8buH/AJMFd02Tkp05PO4jnWvc57EDAINt7u1X8Pb9KgI+Lxbv3cFR8xjx6AQ+b+Txs/qL9KePlih2CMBCq92hg2qzt1AoV7H5YxdhdqhHzRbgcpFeqdUplpvQW4FhmAixZ/sws4BoWCM/qmsE5XqE3dDQCrqGAYWdejqZgK6GUD8+IV9VghBFN1RZJv3sT5diBwC15gncggCPJKF0WCPN8dun55jQdVpz3Ynl9leAAQAJhiGatD9AOgAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-png { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmtJREFUeNpsU9tOE1EUXXPp0CAUWmJbC04xBANNTF+kKhG8fID6aqL/gPEj9E0lIf6Dj30HL03wxQtVIC0QKrWxNG1Dk9Z2Oj1zxn1m0oIZTnIyZ8/ee+211z5Hsm0bYg29fLGpxWIJWBYGS5IA8ncKhT9Wvf4Yqprtu+w3q85X7f9QxseD/pmZMZsxN9fnc5JNw0ACGGv6tPSvyvEDKEoWZ5Y8OHHObKpucw4B0t3agnl4CJPs2YkQVu4s61ORaBqMJc8CDBiIRhhVM9bXYdVqYAcH8M3NgS0tQQsFcfdKHEbvlr6WyaR/V6uPKPy7B4DT7lUq4MUipMlJ2MPDUKtVfKZ2nn/5BoNbkONxXeb8LYXe/A9AJLNWCxgdhZJagDI9DZg9qIkEytRSkdqTSFQtGILSbgc8LViM+tc0yPfukzIyOJ359k9YR0eQdB2KmBbpwXoM3Dod1SkD+scpEapCI5DdpsJhIJcjajQZagcjI+5oLe4VkeQnyiZgdIH2X6BJ7dSqQLfrggjw0AQwP+/GegCIHppNoFAgEMO1RZKo7BQgRi3yN05cnwdA0BQMAgF3C6pnbuNg92M9AFT1diSCh6kb+FGvo2MxnBB9ocZxp4Mns1cde213B81e7xwAcl4jkaa0IUSjUdLJwkL0Ej6VSvArCt7l81iku6GrKnYEU89VJlSJRmR0Dax+fI9suYxSo4HlWIw6M3FBlnD9YhiXabyOsOeIqG7TzDeIYo6EDGp+ZPb2kKKqH8h+mkxiI5/D1/19J3bwYPvPWXq2skkiJVxesqt0XzghpKM8nRVV2Lv2q9eLIvSfAAMAaacnllcFBmYAAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-ppt { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAkhJREFUeNpsU11rE0EUPTM7ySZpmzT9DNamWAtFfSiCigr+AxF9zKtv/hvf/Aki+FEi6ov4ItWHPGiwiBUKoUqqTUJImmR3M7Mz3t0kNe1m4LIwc+65595zlxljEJzdR5uf5nLmsvZx6gSvtd9W9bjhF7jg5dH9nRc/wq8YXaTSJptb0xklx7IZoKUEz1zJ2DUU69/37vFYrDxegJ9U0lC+AoIIVGg9CL+vIObP48KDQn7x0sWiVnJrnEDg7KGk+i/Ac4iUM/R7BsmrSSxtXMfa3X7el8+Kjf3KfUJ+iRJQw4w0Tc8BRyWGRAZY3rBR/VlC+XED2ayDhZyXl03+hNA3TxNQshlGLAnE44zCIL1goXZwiMNvB1i6zbC0KuAsxNITWwgNMYPeLVJiFEO9ArjHAivrAjNzBr4f4vwIgdGD4YUACsZCE8AtYGWT5jCsGQw5wEYJzP/pj5RwYTA1b07eQmfZ8P0sgdaM2FlYwWkMgMpl6NQAO33GKM0wsQWflkh1uqGVmVWblsiDkQyqxwfag35SqcktaEWTUTHYNx4iGU/C29+BvX4Lpu/C7zYgFjegSY63WySsHyXwpYHU00ieu0bAOuJbBTArBkiXKiaAmTzcvRJUV9E8rOgqBwqlY8ASs/AadbRLb8CzeTjVClqft6FdB17tL7yeCbFRBYoLr6vR/PiSEl5BZJaBD0/R2nkOZqfQ2fsKt+0SEQ+GLSIEUvJm+6jbah2+pS2aon+4g/afd4SYJVuA7vvXdC/IHQtSoTnK+yfAAIEaId1m+vudAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-psd { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAqxJREFUeNpsU01ME0EYfbtdKKWGtoItRWgJHApCBE2I0YuoiSaaeDJeOJh41YN3TfTixcRwMfEk8eDJGA+Eg0YTTRRMg02KKFooCBbTlkJLS7f7P+u3K9Xo8iWT3Zn55s173/uGM00TVlwZfzJztD92iKO5ouvQGQPHcQDN380vlDPr65fdLj4Oa41i9sFt+ytgN7o7woGOrqgvvpLBaF8vWj1NUAwGTVNRM3mf5vU/zaU+XySQuTqIFXz9hxmGLkoS7r+YxvVnrzGzlgXPDOzUZPT4m3Dt/KlIuH9oUjXYEHZZ/wOgGQZi4TZcGI5hLb+FO++TSOSKcLtcMA0dI0EPrp4+HtnfG5skiUecDGwQE2MjAwiGWlFVNDz+tIyCokJhPKYSX7Gdz2I01hOJdnY9rJ/7UwPGTEiqjtbmJtw4MYx78S/4Wa3h5UoOYwPdIOp2Xi/t18rlFgcDw6o+ydiWVRwOBnCpL0oOAMmNEhLZIgSeoxwGSWcERon/M9DoBknTIdNQNAMnO4PIVGpIFXcwndlA2OtGc4MAxml27p4AIulWSIa9QVadiYSoJxhqBJivKgh5ad3k9gaw6JdlDaqq7q5wINY4F22HaLHSDZQkBW72O9cBYFEviBIURQH7a7MN0uDisUW12ZZcaGlmdq4DwCqeTo1zNtZuW7hUqGIw7MNqSUS2ImNsKEpSdEwt5lGhfQdAkQBEoub3NNrDJfAIeBuRrcrY5xGQ2RFJAjl00I8PCckJUCB9q1URBnk38XEJEuk41tmGwZAf66s1VOh2keqwoUnYpFxHH4iKIixkN3HzVQKP3iQR/5GDKMuYmE3h+fx3MHqh1sMafztHLuiCg0FAk0uFdLqcpGY5QEXbTC/j7mIaVjc18DxufUtBJ/vcggs+3ijVz/0SYABsJHPUtu/OYwAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-py { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAlVJREFUeNpsUktvEmEUPTPzTUFmgJK2UqXQFG3pA6OBLrQxamJcaYwuu3Dp0l9iXLvVtRuDpgt3JIYaTVSaxtRHsJq2xEJBHgXmifebMhECXzKZme+ee+65516h2+2Cn2cb2VwyHl12//vP2/zOQaF4uD7GWN69e/LogfNm7kUsPBFaXYwHMeK0OlpQEJApHJTuykzK98dE98O0bLM/UNgr4v32Dj1fwSQRt9dSsfmZcMa0rIv9ODaqYrPVxuPnL1Cu1aEbJu7fvIZUIo4bqeVYRzcyv/8c3SPYpwECt/dmu4ON3Ed4TymI+hQc1ZqoE+F+uQLDsnHlwkKMscJTgl4eJOi9fxZLePNhGx6ZQRRFqH4VjZaGSv0Y6cQcJLpra0ZguIWegqDiw7lYBBZV6xiGk9DQDLzK5bEyF4Hi9VLMsoYI7J6Es5PjeHjnOl5ubqHaaJGBEkzbxplQAKIgDmBHekDTgI+qKKqKLvNApgmEgyquLs1CoFn2Y4cIeLJpkjoCLkWnUSIF3JxISIUsCjAoxhWNJLBIJs3YeXj/08oYZkOKY65HllE/bkMmY504YUd40HUq2JSSyW6iVPmLiXE/ZMYQCU+hXK3h1toqdNN0sEObyKtqtDQ6kXDwcadDS2TBryp4nX2HxXjsJK6bDnZIAZem6Tp5YMMmicn5OC4lztNWtvB9cg+hQABtWjKL2jH/T3GgBcYDXEE6mcDM6SlaJAGMWkivLBC54ZgniZaDHSI4rNSqn7/t1vgkGJPwZXffSeCjk2iUWz9+nSTQN8e6ef8EGAClUi/qoiOc3wAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-qt { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAnVJREFUeNpsU8tu00AUPU5sp41NkzRxpfSZqi0VIIQqEEJUZYXECvbwCWxYsuBD+ABUFrDrCnWBQEJdIWigBSr6pqRJ1ebhxrE9M7aZmSrQ4o505fHMnXPPPWdGiaIIYrx89GKpNDdxmXkU3aEoCsT+z8W1Sm21+jCpJctQTvaerj+TX7WbnJ+0cpfuX8mQtn8GgJ4AZtIFY2Hz3foDVRcgyt+cRHcS0IARh+D/8G0PpmVi7smd0dLs+AIjwTVEiANEYYQwCHlEZyJgIQKfoX84g9uPZ0cHZ4YWmE9nuufU0wABCSSImMsWEgqSuoqA/39/swZFTWLy7vQo7dDnfPvWWQa8GuOV3IYLJXmyzDzG2/ChZ3pwbHdQ267BKJoYuj7SF2MQhiF8LuDK/Gf0DKTBKINz1IbTbEMzU1ANDW7LAfEIQKIgBsBFlAx6LYOz6MAcvoDCtAVGGPKlAiIu/F55F33FDA6W93EOAOMaMOl7biKPwRtD8Foetj5sYPfTDtxjl1f3Ubo5jkQieQ4ACSUD2iE4XDpAdbUiW9D7UsiN9WNkZgxajwbd0LGzt3keAJPUc1N5SVeENT0Ao2BKV6QzwlZeRBSKAYhe3aYHcZWn7l1EfjyPypcK9LQGa8qCvW9j9+MvaasQOHaRhGWdhsNLR8hwodYWf6B4tYjDjSOovRqq32rSYq/lytw4A77o1V2ERiAtzY5kkUrrsH+3QF2KY87ArTtQuQ6nAf4x6FCV1D001+vYersBM2vA4y1Rm2D7/Rac/TZIw4d/6MrcGAPf9htN0miJh7Lyuoyvr8rQeP9iVJcrSKgJ+TrFcyYebXTP/RFgAFQobmIOBxbsAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-rar { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAnpJREFUeNpsUktPE1EU/u68OgylZXi0hZACQU1LEKKCMcat7jTRnQsXxsQtv4E/4M74P1iriUaNCw1FgxpjCJQKKAU60+m8mJnrmSll4XCTc8+959zz3e88GOcc8aq9evChOHl/lvMoubvWX/z4+BwTlbvw7bXdg8b7h6LE1gGW+O88CRMt4XTlR6/rYxce5Xv3jlHH19fPkBu+gWy5mlcFb3Wn/umeKOEMJF5C7xCFbtA9dRXjFoYKGiTRAlPGUV1aKU9O3VwNQ74A8DQAIZxqAuAhBPIMFYpQVAVB4CPSZjEzv1weH5tbDQN+JQ2Abu488mnzIbAAA3o/VK2PwDJo7r5Fy7ZRuvi4PFS6+qIXdVYD8Jg6BUcuOD8BozSLlRWyicgVKkTMQWwUlFF0Ooe5FIPk57BD7G0SiywyjD8bCDyHsOkeeeR3SUxEkROmU6BfQYFJMHfhWXV8efkUrb13VPMTsrcTQSzxZ/+n0GVA6EGbSGdgG9vo15fg2nFgbO8k70SRdd+mahDT81vUxTZRlJBRMsjq89C0EXCvSf7TIBZ136YZUJEiE7LgJ2dN01BZuE0dkIhxE7KcQTK1QUj+cwAEyrPZ+IydzRoyah+mLy2isbWBweESJEnB9q+1RM9Ub9GQOWkABg8HjRr2d9Yh0hTlBlRsfn+D4vg0BvUC9rZqECUJuk7Tzr1zahCYlB6HJAREPwfbbMBzLBzsbUKVI0qBgQkc+SxgWUYaIAqOpKwKXJ6bgGlaaDV/YvHaFNrtDsKTfVSrJeqIg/bRNwjclFIALeP3saybhu8SC4VBHwnhBXXIKocYRXD9QzBi4Xgchmkd9+L+CTAAMqwy+ZzluBgAAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-rb { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAixJREFUeNqEUktvElEU/mag5f2yJhXLwxIt0kiqsVEXujP+A925cu1Pce3WtXVtYuJCF7KtTY0NrVQIpRVKeXTkMcO9F8+9ZVooJJ5kcmbmfOe733fO1YbDIWS8+/g1dycVX7W/xyO3vdsuVKqvnE7HZ230783rlyo7bVBicSGyfjsVwozomVbIPe/c+FmsPHfoRKJd1HT7hXHBZjVbA4aA14NnD9bC2VR8gwuxPi5Sx39Cp+M0XUP0ahhP1jLhW7HFD4zze3b93ILtXYyyVKlR8/5hFbnvO9gtlrGSjOF+OpXkYviWyo8mCS4R6bqO4p86vm3v4fC4DrPfw4unj1XN6JvBaQtjChzUXK43sVU4wNFJA43Tv/B73edQwTmfIhAjCVL6UdPAj1IVFSKhCdAcAI9rnjBiAjtBYEu3GEeh1sKJ0YXR68sVIujzIhzwY8DEBHZqiLRKkicQDfvABxaiQTc4Y/C65pCOXwcjcmlvJgHtlwi4epYifiQWgmoLZwPW6HQG07LgcOgKO0UglAKOTt/E+09fwAiUWU7QAE9xUK3jbvomsispZVHMVEDSZdHo9rCZ/4VIMKAu0XGjpU7d2S8hk0pCELHEzrjKnCQOYJoD+Dxu1RyiwUm5LaMDo9NFt2cqDLvY4oQFp/QpfT/MrmI5FkWebt+NpWto0j2QmQkOjZ9hpwhqjXZzM/+7LU+cc7lRrjXh8/lVLRK5ovLWXglOsiOxdt8/AQYAzv8qbmu6vgEAAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-rtf { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAe5JREFUeNqEU01PE0EYfnZmd5FSvgLYFuwWt9EgHyEaox68eDJevHvwJ/hTPHv1N/QgZ2NC4g3kUAQKFKGhjVKqRrvbnRlnht262FHfy+y8877PPM8z71pCCKh4/ebt+rJfXEz26Vjf2mnsN5rPKKWbVpx7+eK5Xu2kyMtNTd5d8MdhiJ9BOO7atFI9ajy1UyAqSPIRMR6ZmoNehNHMMB7fX/UWvEKFMbYKE8DfQnAhwRmmJkbx6M6S5+WmK2Evup2c9yUk2nnKA0XVcSiGXAe1k5beP1i+4RFCXqnPywB/AKVzK34RjHNYlgVKCH50w7EBBogbTa/AVM5SgBdn0gc2AMDjPsbFPz2xye9asweS6n+NTbG8BCCfUtLjff2WoVnVpAH6z6hMUtJE3EykYfpF4vUiL3QNS7FMeSAQRBHW3r1Hq91B+VoBQRji4+ExFsvz6Hz7jm7Yw5OH92AcJKW9G4SoHhzhy/lXbB98Qmm2oCXN5WawsV2TACEoJXqwTKOsb3BtR2ucmZxANpPB8JUhyPnHWDaDpfJ1eZFALzJJ4MKO5MEtv4TSXB7V/br8iQLMz+almRZWbvoo5q9qRlxwewCgeXbe3qrVO5ZkUD/9jJGRLPaOm6COi92TU1DbxYe9umRD0DrrtJO+XwIMABWp9nS+FgaoAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-sass { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDNDMTBBM0JGMTE5MTFFMTg3N0NFOTIyMTQ2QzhBNkQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDNDMTBBM0NGMTE5MTFFMTg3N0NFOTIyMTQ2QzhBNkQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowM0MxMEEzOUYxMTkxMUUxODc3Q0U5MjIxNDZDOEE2RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowM0MxMEEzQUYxMTkxMUUxODc3Q0U5MjIxNDZDOEE2RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Po72XUcAAAJcSURBVHjahFJdTxNBFD1bykc/ttvdtttWGgI0bYrUgDZoNYqRJ014kMRXHvwB/hQTH/wFhMREJfFBQxBjhMRIFEQSCAlQxKYGggiU3e3HbnfX2bFt1EU9k9m9mblz5p4zlzFNExYmpue/jmTSZw5PZAl1MAwDT0c7O72wvPdudeNakPNtOZ0tsM7cvzdOc5yN5LDAsTFRAJks/kC2PxFRVe39Si6f4byez62EpAEH/gNN18F53Ri/Ocxf7OtdLMpKT42s/ZPg1cISJp/P0tg0TBzLCoK8D7eHh4RkLLJ4cCz12AjMXwgez8yhqtVo3NbqRKlcxcSL16gZwJ2Ry8KVc8kZO0HdTKlURn+8G6PD2SZhLMQj96WAiMAh2RXFYKI78lcJcx9WYBCycICnpNbojUWpD5Y0C4Zh2D0w6hWc70uQZC+IWfQZrXF0IsHvY+meBd08haAhoVMMQFJKWF7PNZM+klhRyogGhbqxOIXAMOtEwGAqDqVcgbVkkE+5UsEAWavf0az2t0ZqvK2qabh6IU3joizDwTgwej1LdVfJXkdbK8mt2QkayO99A0/0trQ46I1lVcX+UREhnsP34yLp1AD1xibBMuntpzU8mJyi3Tc1O4+l9U06n7x8Q/8PHz1DrrALt8tlr0CrkbJMHTop9Sk5sLa1g8L+ARJdnShKClY3tunN69t5iGLYTlCtakjFY7gxNABdN3B37BaqqoYT8pyX0in4ORbRkIA46YlDRbUTbBZ2Jb/Pw4qiKFnapcpPo9pdbrg8DjAOBsFgELJmsGs7eWkkc5bu/xBgAHkWC6UPADTOAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-scss { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RkM4QjYyNDVGMTE4MTFFMTlBREZCNDNEM0ExMTk0MUIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RkM4QjYyNDZGMTE4MTFFMTlBREZCNDNEM0ExMTk0MUIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpGQzhCNjI0M0YxMTgxMUUxOUFERkI0M0QzQTExOTQxQiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpGQzhCNjI0NEYxMTgxMUUxOUFERkI0M0QzQTExOTQxQiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pkf1yeMAAAJbSURBVHjahFNdTxNBFD0tLULpB91uodVWPmorUIxo0VSiNSExMYYHE33l0Ud/in+C+OSjYgjRGDBRCKJIUkIEWi0WKlja0ul22+5219lJ26gLeiezuXvn7rnnnrlrUFUVms3Mvd2bjIyezRVLBA0zGAzo6jhjm1te+7EU37rFO+w7JlMbtG+ePJ5mOaZmci/nsPl6ONBtw18WDQc9tZq0sp7YjTisXV/NFKRpRvzHpHodDqsF03djzuvDg6vHJWFAprF/Arxe/oins6+YryoqCiUBvNOO+7FrXMjnWc0WyIAOQP0N4Nn8IqqSzPx2swllsYqZl28gK8DDyRvcxKXQvB6gISYpiwgH+jEVi7YAfW4nEqk0PJwDofNejAX7Pae2sPhhHQoF63U5Gai2Bn1epoPWmmaKoug1UBoMrgwHabIVVCx2jdrKFwm67TZ2plldPQGg2cK5HheIUMbaZqKV9In6giDCy3MNYXECgKI2gICxoQAEsQItpNCHWKngMo01arTY/jFIzbutShJuXh1Fm9FImYiM7tTtKOtbO+toN9Nc+fQ5SGUOIVYl7HzPIH2YRZ0y2KZ+sVzBHn2v1mpMGx0DTaR3nzfwfGEJdybGkdo/wEigDyvxLzg4yiESvojZhfd49OAeLJ2degaSLIPOO6vwgiYaaRErTRREEdn8MeJbSVZ5M7nLdNExqFLaQwEfFfACQn1+HBWKSKb3MT4Sgstuh9vVDa+bQ4DORE6o6RlspzMk9TOPfr+fiLJCLFYr3TZSKNcI7+aJwWQmPM+TkqRg49tu65f/JcAAMwMas6WUKd8AAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-sql { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAh5JREFUeNp8kctrE1EUxr+ZyXMkoa1NBROaSkpTBE23PhZ25cql2y5duvAPUdGFS1FxIRRBXZlFQ9GVdDENIhGJxkDsw2mneZnM83ruNZlOmNoDhzlzz3d/9zv3Sowx8Ch/qlYK2XM3cEJsbH0+qjV/rd6/u6aN18b7RMFT+9aosP/Ex+0ae/puw7j36PlKEMAzctKJ3aGFamMHjV0d+wcGitkMrpWWp6hVIciEk2MAOwbUWjosx0UiFoWqJpGMx5DNzODq5aIPoa82AWBg/lyKLMH1PMp/a9XvLXLzG1cuFlBaWpiKxaIPSLY6CaC93ggQjyiQZRkeQSzLRovGaPciWLt5faSWEBoh6KBvOhiaNga0+Y9pwaFxvu7rfp8F5pWDt+qNMp2IijHGwddWCvN+33/CoAOP5nVdT9SdoQ1JkggiQ6Yvr7V60+9z7akA2gfH9cRF8hO5F5Ve4lQAF9uuK+qFsylkzsQxrcaQm04hdWkR83Mzfp9rQ3fAFzu9Ph6+WMfjl6/pGBdb2jbKmx8QlRjWy5vkyhUZBPgOeGNHN9AbDLGUz6He2hVj3Ll9C8/evsdgaMK0HV8bcmDTU0UUBYXcedR+NLGnH0I3jvDk1Rsy46FP4C/1BtrdntCGHNiOAzWZgEKQ5Qt5lIqLojbaXSQTcRy2OwT4SZqk0IYAOgkVWUE+lxX/zb0DpFNpkTzmZmfFtzewhHYcfwUYAMZmVaZQlLFHAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-tga { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAnxJREFUeNp0U89PE0EU/ra725K22ILRGipb22pMG6JcSEQTbUIwnozxpBcvepeEP0KPogcT/wlNT17kIKbEmChFUYKGVtL0R2gLtNCl3Z1Z3+zSAlonmezOe/O+973vvZEsy4JYnqdPMu6RkSQYQ29JEkB+PZcrslrtPhQl23VZc8/tr9I1yMHg0EA8HrBM04lVFAhoY38fSSDQVN3pfKV8G7KcxZHl6v1xblqU3eLc3p2VFZjr6+gQgwsnhzGTuq6Nhs6kYZqXjwL0GFhEl3U60OfnwWs1GGtrUKNRsKkpeIIBpKIRtI1J7cX7hXRhc/MOhXw5DkCZGG2zXAajzFIoBMvng1ypIKOqmP30GW3OIEcimovzlxRy5RgAFwDEAIODkCcmIMdiQLsNdWwMZdJlg8pzEUt1aBhKq3XinxKYqF9yQbqRIqsMy+0Gyy47bKgUWXSLtDENE5wdtuqQATm50F1VnPbRGeEw8HXZbiV8fsDvI9ldju9vADAyihLEbrWAZhOoVp3z6iqBUiB1A4nEfwCEsbkL/M4TgE5n5jDx+oTEzp1d8m9tC8H6MaAB0imzx0NU/WKUYE+loEyawDBo2ui6TGfT6ANAxrvx87gYCGCxXEKVJvCWFsG3eh1vN/J4OD6Od4UC8o0G3TX7TGLHwI9iEQmvF9X6Fh7F4/iYy+GcLOMSlfEgGsP0qdNOmX0BiGKpVkV1bw/1nW2b/gCpf1PTcI+Y7eg6ps+G4bG4PR99SjAVo9HE4q+fKNE0vl5awuSohjeijbRefVjAtUgEQRK7Yhi9OKn7nKWZxxlSPWl3QwgnaIrW8QMhD542vUbx/W49m7sq4v4IMABOqi3Ej7bAEAAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-tgz { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAnhJREFUeNpsU1trE0EYPbMzSTfdtInFtkkpiaXVWou2FRUEn/so6JugL/oH/Af+B1988if40jcFERQURNBSQdDWlLQN2lsue8neZsZvc7FoOrDszM75znfOmVmmtUYyvry++36yfOeS1qqzDtvH2P76ApPlW3Drb2sHex/uccHWAdbZX30kO2+B3siN3zhTnHuQ66+95i423jzFzOVljBdKOZNHazvVT7e5wF+SZBj9iZJ+3J11mbW2kR8T4LwFli5i4fqTUvnczTUp9RLtDhKgJx0q4dEwWAxrREKICHEsoYYXMXvlcWmquLgmY71yCkG/c0AkARgLMZpnMDMpGNzEYe0dGp6HwvmHpbHC1Wf9MnFCkHQOyYEPzSJwQ2B65Tm5NZG3Fshim6wbMNJn4bpHowMKtIqo2COgR2IcAptwjvcgo6i77igjEmVDqbY8xQJ1VwRULhiBI6+G9Zf3cbTziuzIDkmHSNqECTFgQScEcYuc2NA8TcdYwXD+GkK/TYVN+u72WrIudiAD8o6oAR2RRCmQMjis3CIy1iSpPySCXhFTXeyAgh4BR+JVw8pauLi0Cp4yCX9A90FQhnSBYtnF/k+Q+HYam9itfIZB3QvT8zj8XSW5EhNTs9ivbSLwPUzPLNPJBIMEKnaQYg6aB9+RGR5F5VsNgnNKXMI1NdJGG5WfHzFVLJ7k8c8xUngpVodlDSGbFYj8Y4yMpOG09lHf3yIFPzA3fwHZTAQVtU4JUTeFDrdgDdlI8wAz5Qy2KxswReI7QODZcOr0ZH3q2hIDBI7zq16tuk3FNPxAI4wN+pkoccYoE4YJU5EdUtM4Qst26v26PwIMAKj3P/2YUKgYAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-tiff { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmRJREFUeNp0UktPE1EU/qYzHWstlrYJNcWUElyUJsaNGh9B0g1Lo0v9Ey78EbrVxBhXuHShm25YGBJRQpAYBDEWpaEPEhksdVpbyjzveO4MfZDCTWbauefc736PIziOA77OPH2yJCcSGdg2uksQAKofFou/7VrtASRpvVNynj13f6XOhjg8HAlMTIQdy/LO+v3uYUPTkAHCTb+cK+0pdyGK6+hbvu4/xiyHbncYAwfR19ZgbG/DoO9LsSgeTd9JXoxfyMG2rvQDdBlwIZauQ5ufh12twioU4E+nYU1NIRCNIDs+Bt28mXzx8VNuZ796j9q/DgAwomwqClilAmF0FE4wCInAlkjO4y+r0JgNX2os6XPYS2q/cQyAcQatFjA0BPH6NYipccAwIGUy2CVJFZInkKlyJAqx3T4/IMGmJkeWIWSz5KgI5pdhb3yDXS5DSCYh8rTID8s0wexeVD0GtMd85KkkefFxUfE47M1NokbJkByEQl6tL+ouAI+MUwbFhnYbaJKc/Sqg0x4H4eDRGDA56fUOABA9/GsCpaIHwr8FOhQ823O5RfW66tUGADhNy3RNRDjcN41HLxdQ8J6jYTsOQLfOJBK4f+s2/uoathoNGKT1MtFeVHZxdWTEZfEq/wMKl3rCJOIzTV6ADs2R5ulYDDNkYjp0DhrF+zCVgkw31+v1UxjQZkNV0SADd2o1MIuc9gmY+/kLxb0/UFoHePd9A1qzeUoKpilx9xcLWzgg+u/zeVfuQqkM9bCN1ysrWKXxdtPgvScwUAm58XZ52W16QyPtifRUzi588GbEi1ztHPsvwAC4uC9qhnsZvwAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-txt { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAeJJREFUeNp8UrtOG1EQPfsyXiyzBguIJSyChZBBEFCKpKHLo6egpErNn8CHgH8gkZIiTSIXLhJAWCgkoMgRMSiRBSK29z4y9+I1d/HCrFb3MTPnnjkzlpQSynY+fP70fGF2gQuByCz6lfdd9Uurfvrrjes6762eb3tzQ69uFJwPsqOPC+MBEmxxphi4tlU5OGmsOzaBWLc+O9oIIVhScidkyGZ8vH62nHtSKlaI4cse6TjAfSaFBBcco0EWqyvzubmpyQrj/FXk75cQaSEMeMXU8xykPA/Hjd/6/LRcyjEpt2i7HAe4A2TeLZWKUOJaVLxj27j813EHGKCXaAJExu/4BOdiAED08riQD2riOrexyRoYc3CvsAbLGAAjZga7vgZG23WMCdBvoxKJc36TRBlMiaa2JByjNqqD8qkYc1pjDK7abey+/YhrWlfKswhpiCR96aEU9o5+QE3g2ovVWDm2Sc22bBQm8vrVpbkS9r+doPr1EOWZaQ0yFoxg2PcREosEAI4uvZhJpzFMP+cSXRbq+043RManez+tNWKMI6GN0g0Z04HFR+NoNC/0yx717efZOSbzY3AcR4Op2AGA5p/W31r9e0vNgSrh9OwCrpeCkqvZuqTybnpRqx/r2CjvvwADAJC/7lzAzQmwAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-wav { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAApFJREFUeNpsU1tPE0EYPXtpKbX0wqUQKVQMFdIXQBNCQBs06KP+B8ODGh+Mf4b/4IsGE54kxhcMBrkp7YOQgBRvSKG73fvsrt8Otoask0xmd+b7zpxzvm8E3/cRjPkniyulW0NFy2JoDkEAguOlpXJ9p3L8MBqVl4O9YHxae8pXuRlcGO7KPLhfTDVUqwUgigJMy4Whm6lEXHjxYf3XnByRN0QB/2KaH7btMlUxoRJAcyqKhdOaht7+DJ49n+2cvTnwynXcsb+kLwJ4rgfmMDDGWqvneXCZS9ND7mov5h9ND85M9y86Dpto5rUkuJ4Py3YDJpy6QGJPayqB+Njf+43XL220t0cwOZkfrNXsBUqZugDA6CbLdAiAwaek1ZU9LmP8Rh6S78GsGxjOp9FdzKJaVZIhBgGASzK21w/wbrnCk8euX+EMAjaaZuPHdwUdHVFYluuGPGCORwwYjg5rqOwccRk+3Ux0IEvntmsNG4ZmUayL/wAwKHUNfZfTKN0ZRaw9Cof8qJ/pMAyHy5KkAMTksSEJtnMenM7EMVMawbejMzJRh67bXEYiIXEAVTW50SEAhzqwfqrBcXx4VOhYm4RsNgHbsJFOyZTsQ1MN+hcohoUlkFiMT+TQFpMwXOjGpXgE+XwGk1N5pFJtKNCequgYGupCRBbCDOp0KBJc4VoP3dyBONW8uydBgBHUThqQKCk3mEZ/LoUG+RBioJO7VarAwEAntjYPiUUW9Hh4b2R7k9j98hN37xWx8fGAt3eIAdVMLn+uUv+b2KReSCZjZJiB9bV9jIz2ofr1BKvvd7G9dRC80lae0HzOt+cWVnrSKDrMJykifwNBpCgE/UAllEXufmDu8Zlffvvm8XSQ90eAAQA0pF7c08o4PAAAAABJRU5ErkJggg==); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-wmv { - background-image:url("data:image/svg+xml;charset=utf8,%3Csvg id='Layer_2' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 72 100'%3E%3Cstyle/%3E%3ClinearGradient id='SVGID_1_' gradientUnits='userSpaceOnUse' x1='36.2' y1='101' x2='36.2' y2='3.005' gradientTransform='matrix(1 0 0 -1 0 102)'%3E%3Cstop offset='0' stop-color='%23e2cde4'/%3E%3Cstop offset='.17' stop-color='%23e0cae2'/%3E%3Cstop offset='.313' stop-color='%23dbc0dd'/%3E%3Cstop offset='.447' stop-color='%23d2b1d4'/%3E%3Cstop offset='.575' stop-color='%23c79dc7'/%3E%3Cstop offset='.698' stop-color='%23ba84b9'/%3E%3Cstop offset='.819' stop-color='%23ab68a9'/%3E%3Cstop offset='.934' stop-color='%239c4598'/%3E%3Cstop offset='1' stop-color='%23932a8e'/%3E%3C/linearGradient%3E%3Cpath d='M45.2 1l27 26.7V99H.2V1h45z' fill='url(%23SVGID_1_)'/%3E%3Cpath d='M45.2 1l27 26.7V99H.2V1h45z' fill-opacity='0' stroke='%23882383' stroke-width='2'/%3E%3Cpath d='M9.1 91.1L4.7 72.5h3.9l2.8 12.8 3.4-12.8h4.5l3.3 13 2.9-13h3.8l-4.6 18.6h-4L17 77.2l-3.7 13.9H9.1zm22.1 0V72.5h5.7l3.4 12.7 3.4-12.7h5.7v18.6h-3.5V76.4l-3.7 14.7h-3.7l-3.7-14.7v14.7h-3.6zm26.7 0l-6.7-18.6h4.1l4.8 13.8 4.6-13.8h4L62 91.1h-4.1z' fill='%23fff'/%3E%3ClinearGradient id='SVGID_2_' gradientUnits='userSpaceOnUse' x1='18.2' y1='50.023' x2='18.2' y2='50.023' gradientTransform='matrix(1 0 0 -1 0 102)'%3E%3Cstop offset='.005' stop-color='%23963491'/%3E%3Cstop offset='1' stop-color='%2370136b'/%3E%3C/linearGradient%3E%3ClinearGradient id='SVGID_3_' gradientUnits='userSpaceOnUse' x1='11.511' y1='51.716' x2='65.211' y2='51.716' gradientTransform='matrix(1 0 0 -1 0 102)'%3E%3Cstop offset='.005' stop-color='%23963491'/%3E%3Cstop offset='1' stop-color='%2370136b'/%3E%3C/linearGradient%3E%3Cpath d='M64.3 55.5c-1.7-.2-3.4-.3-5.1-.3-7.3-.1-13.3 1.6-18.8 3.7S29.6 63.6 23.3 64c-3.4.2-7.3-.6-8.5-2.4-.8-1.3-.8-3.5-1-5.7-.6-5.7-1.6-11.7-2.4-17.3.8-.9 2.1-1.3 3.4-1.7.4 1.1.2 2.7.6 3.8 7.1.7 13.6-.4 20-1.5 6.3-1.1 12.4-2.2 19.4-2.6 3.4-.2 6.9-.2 10.3 0m-9.9 15.3c.5-.2 1.1-.3 1.9-.2.2-3.7.3-7.3.3-11.2-6.2.2-11.9.9-17 2.2.2 4 .4 7.8.3 12 4-1.1 7.7-2.5 12.6-2.7m2-12.1h1.1c.4-.4.2-1.2.2-1.9-1.5-.6-1.8 1-1.3 1.9zm3.9-.2h1.5V38h-1.3c0 .7-.4.9-.2 1.7zm4 0c.5-.1.8 0 1.1.2.4-.3.2-1.2.2-1.9h-1.3v1.7zm-11.5.3h.9c.4-.3.2-1.2.2-1.9-1.4-.4-1.6 1.2-1.1 1.9zm-4 .4c.7.2.8-.3 1.5-.2v-1.7c-1.5-.4-1.7.6-1.5 1.9zm-3.6-1.1c0 .6-.1 1.4.2 1.7.5.1.5-.4 1.1-.2-.2-.6.5-2-.4-1.9-.1.4-.8.1-.9.4zm-31.5.8c.4-.1 1.1.6 1.3 0-.5 0-.1-.8-.2-1.1-.7.2-1.3.3-1.1 1.1zm28.3-.4c-.3.3.2 1.1 0 1.9.6.2.6-.3 1.1-.2-.2-.6.5-2-.4-1.9-.1.3-.4.2-.7.2zm-3.5 2.8c.5-.1.9-.2 1.3-.4.2-.8-.4-.9-.2-1.7h-.9c-.3.3-.1 1.3-.2 2.1zm26.9-1.8c-2.1-.1-3.3-.2-5.5-.2-.5 3.4 0 7.8-.5 11.2 2.4 0 3.6.1 5.8.3M33.4 41.6c.5.2.1 1.2.2 1.7.5-.1 1.1-.2 1.5-.4.6-1.9-.9-2.4-1.7-1.3zm-4.7.6v1.9c.9.2 1.2-.2 1.9-.2-.1-.7.2-1.7-.2-2.1-.5.2-1.3.1-1.7.4zm-5.3.6c.3.5 0 1.6.4 2.1.7.1.8-.4 1.5-.2-.1-.7-.3-1.2-.2-2.1-.8-.2-.9.3-1.7.2zm-7.5 2H17c.2-.9-.4-1.2-.2-2.1-.4.1-1.2-.3-1.3.2.6.2-.1 1.7.4 1.9zm3.4 1c.1 4.1.9 9.3 1.4 13.7 8 .1 13.1-2.7 19.2-4.5-.5-3.9.1-8.7-.7-12.2-6.2 1.6-12.1 3.2-19.9 3zm.5-.8h1.1c.4-.5-.2-1.2 0-2.1h-1.5c.1.7.1 1.6.4 2.1zm-5.4 7.8c.2 0 .3.2.4.4-.4-.7-.7.5-.2.6.1-.2 0-.4.2-.4.3.5-.8.7-.2.8.7-.5 1.3-1.2 2.4-1.5-.1 1.5.4 2.4.4 3.8-.7.5-1.7.7-1.9 1.7 1.2.7 2.5 1.2 4.2 1.3-.7-4.9-1.1-8.8-1.6-13.7-2.2.3-4-.8-5.1-.9.9.8.6 2.5.8 3.6 0-.2 0-.4.2-.4-.1.7.1 1.7-.2 2.1.7.3.5-.2.4.9m44.6 3.2h1.1c.3-.3.2-1.1.2-1.7h-1.3v1.7zm-4-1.4v1.3c.4.4.7-.2 1.5 0v-1.5c-.6 0-1.2 0-1.5.2zm7.6 1.4h1.3v-1.5h-1.3c.1.5 0 1 0 1.5zm-11-1v1.3h1.1c.3-.3.4-1.7-.2-1.7-.1.4-.8.1-.9.4zm-3.6.4c.1.6-.3 1.7.4 1.7 0-.3.5-.2.9-.2-.2-.5.4-1.8-.4-1.7-.1.3-.6.2-.9.2zm-3.4 1v1.5c.7.2.6-.4 1.3-.2-.2-.5.4-1.8-.4-1.7-.1.3-.8.2-.9.4zM15 57c.7-.5 1.3-1.7.2-2.3-.7.4-.8 1.6-.2 2.3zm26.1-1.3c-.1.7.4.8.2 1.5.9 0 1.2-.6 1.1-1.7-.4-.5-.8.1-1.3.2zm-3 2.7c1 0 1.2-.8 1.1-1.9h-.9c-.3.4-.1 1.3-.2 1.9zm-3.6-.4v1.7c.6-.1 1.3-.2 1.5-.8-.6 0 .3-1.6-.6-1.3 0 .4-.7.1-.9.4zM16 60.8c-.4-.7-.2-2-1.3-1.9.2.7.2 2.7 1.3 1.9zm13.8-.9c.5 0 .1.9.2 1.3.8.1 1.2-.2 1.7-.4v-1.7c-.9-.1-1.6.1-1.9.8zm-4.7.6c0 .8-.1 1.7.4 1.9 0-.5.8-.1 1.1-.2.3-.3-.2-1.1 0-1.9-.7-.2-1 .1-1.5.2zM19 62.3v-1.7c-.5 0-.6-.4-1.3-.2-.1 1.1 0 2.1 1.3 1.9zm2.5.2h1.3c.2-.9-.3-1.1-.2-1.9h-1.3c-.1.9.2 1.2.2 1.9z' fill='url(%23SVGID_3_)'/%3E%3ClinearGradient id='SVGID_4_' gradientUnits='userSpaceOnUse' x1='45.269' y1='74.206' x2='58.769' y2='87.706' gradientTransform='matrix(1 0 0 -1 0 102)'%3E%3Cstop offset='0' stop-color='%23f9eff6'/%3E%3Cstop offset='.378' stop-color='%23f8edf5'/%3E%3Cstop offset='.515' stop-color='%23f3e6f1'/%3E%3Cstop offset='.612' stop-color='%23ecdbeb'/%3E%3Cstop offset='.69' stop-color='%23e3cce2'/%3E%3Cstop offset='.757' stop-color='%23d7b8d7'/%3E%3Cstop offset='.817' stop-color='%23caa1c9'/%3E%3Cstop offset='.871' stop-color='%23bc88bb'/%3E%3Cstop offset='.921' stop-color='%23ae6cab'/%3E%3Cstop offset='.965' stop-color='%239f4d9b'/%3E%3Cstop offset='1' stop-color='%23932a8e'/%3E%3C/linearGradient%3E%3Cpath d='M45.2 1l27 26.7h-27V1z' fill='url(%23SVGID_4_)'/%3E%3Cpath d='M45.2 1l27 26.7h-27V1z' fill-opacity='0' stroke='%23882383' stroke-width='2' stroke-linejoin='bevel'/%3E%3C/svg%3E"); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-xls { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmxJREFUeNpsU0trFEEQ/mamZ3Y2+0zIC2MmITEkUYgERFQErx5E8KTi1b/h79A/4SW3nCNeYggBYZVEMU/y3N3Z7M7OTD/G6lk2ruw20zRdU/XV91VVG0mSQK/3n1a/jky6d6Xs3G8WXS+Pw5N6LXjLLGuna/78oZKerGsYKtrDE16uJGL1L9gEOOcYd2dL1fNwrbL//aXN7J1efPMmkUqEFAk0A0VZNbFEaQCBscIkXj975y3NLq9xye8PBkAniHOFph+j2eC4rsdoB4LsFubGl/Hq8RtvYWpxTQi52o1jvWiGYaRZL0/auDgOkC/Z8BYL2Pqxidp1FZkhoDxpeaXA/Ujuj/4HoOxKKjiOiek7RUShRNQWaNYFQuMafrYCxiw4ozZKfqbYJ0EvRdl1DQyyTs8XCNTA6UELMwvDyLpZWIZNNlNLlQOK2LMJRJ+5AkuZ1S7CFFzJzk56GnUjQWlYkqCoBWFbonEVYcLLA4dNnB624GQsDBWIgfZJEgxkoChzSFWvn4VpQemDm2VwXQsXJwF1h6c+gxlQ5jgSiEUEt0wdIe7tMES+nEG2aCLiJMOIIWIr9e0DEELAMUrwRuchVAyTKimUwO75Jm6VF3Bv7imOaj+xd7UFKVS/BPJF1b/E4tgTrE49J60O5kceoNqowiuuYKa8ghHXA48U9MT2AQgyRvTThE30bQiaSGa4yLMJNFo+Dq/2cHt4CYlwyFf2S6BHwwrMw/avDbR5C1k7h1YQ4KH3Amf+AcZyEbZPv9CItzQD1l9EbtYOjv74v/d3O9RMPTDrsEwGIWN8q2yk7XNYRs9JrRv3V4ABADSGR6eQ0/NQAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-xlsx { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNpsU8tqFEEUPVXdPY/ueWZIoiYZiSYKYhJc6EbduHOhgijo3t/wH1z6B0JAhOyMILhxo4kJGk1ASTAxwWF0Mpp5dHc9vFUzYwidaoqmq+8959xzbzGtNcx69PTS26ETmQtS9r4Hy/xv7MW7jV+th5yzVcaYPX/++It9u4NAv+CVR6tBUUTqMJsDcRzjZOZM8W9ZLKx+/XDb4e5/kH5In0lpIYWGUaC0YTZnBCAEKoVR3L36oDo7NbsglZwbqD6iQKOXFMcKUVfBkBAoQhlD5xxMDp/HrSv3q1JgYW3z0x0KXzkCYJaRZljru23aHWTzLiamAyytv0O9UYdf5PArqlppBfMUfu4oALErqZBKcUxMFRCHEp0DgW5Lo4N9NIN1dF0XXsVFOUyPJTzo+WBANDidjp8tgHGG3c0DnJ4uIRf4cOCBaW5KjY8xkZL72xpJ9QcFz5bVqHUJGHZL2YtNmKi06YCyiVFb4s/vEKMTAf1p4edOG6mMi1zR6wEpdUwX+vLDtkCzHoK7ptcM6ayLmGajvtex4PliyoIkFRjmUEASelB2rXQRSfjUCT9PlWpmW21iTGzCAyEkUixPRqXhe2V4zKczbdmybgkpJ0cGOuA6Y2MTCsKoi5HsNK7N3MN+uwYaWbxYfoLLkzdxcew6lrYWaZhm8PHHG3zffp1UwJSHz9vvkU8PodbcQYYYS5lxYkxTkGdVDQdV1Js1qPgYD6JIuIE7gsXVefIhIuM05k7dwMbeMmh87a18ufIMaVYyprrJLgje2Nr+1tzYXANnDnr3zRhHj37Vvy2wpXHtNAd5/wQYAD6WMuT2CwoVAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-xml { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAilJREFUeNqMks1PE0EYxh+g3W2t1G0sEqyISynUFJsSOShNwCamiYZED3LgIkcuxoN/iCZePZiYGD2aGD+i0F5KMChxlVaakAK2ykcAt+WzdLu7zkxo3WZL4pu8mXfmeeY3885ug67roPFh5nvc62m9hjoR+5LMp7MrkYf370qVtco+VtCUFpbj+jGR+JbWn76OyQ8ePwsZATQb8R/hanZgINgj9IqeuBFCw1Kt9OMBnNWCs24XwkG/QKYUEiGjVAPQof/rq0783pShET3ULQo8xz0iS5FaANmrHQH2DoqY+DSLSz6RzecWlnD9ymU47LYjd4O5BXqDTG4FM3NpTEkpdJ5rw0AowLRMbhUfp58gTOaD/UHmNQPI6YmvKWRX1zESHUJ/oBs2nmPa+Mgw0ZIM3tZyGoJwygzQNB2jNyJIZX7iB0lpPoM70UGmPX8zCU+rG8NDVxHwdiC5mKsPUFUN/gvtLLf39sFzVqaN3YrC6TjBauqhXhNA1TQoqloV7Da+pjZq1FsXUCamF29j6LvYhf3iISamZ3Fv9DZevouhRzzPfOG+3hpA9U9UyioOlTJ7pFeTCQS6RGzIebyf+oz5pSzWtmSW1EO9phvQ00slBRt/8qR3DoWdXbiczUiTzd52D+tdLmyTB14mx1rMAKVcRpEATjrsuElee/HXGmnFRyBOGD30C/nEDjNgs7CDpsYmnHG3YPegBCvHs9oYfm8nG9dJa5X4K8AAQzQX4KSN3wcAAAAASUVORK5CYII=); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-yml { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdxJREFUeNqMUl1rE0EUPbM7m5Y0Zptu21AwWwhYpfSDFh+kvvRd8N0Hf4I/xWdf/Q158F0QoQ+CVsFKaLSQpt/dpmvztTOzzky6cetOpWcZZvbO3MO5514SxzEU3r57/3GpWllM/tP4sL3TarROXuSo/SWJvX71Uu80Cfhlr/T4UdWFAVfdnmsTUtvdP35OUyQKVnJgXDBTcj9icAsTeLax7j/052qM81UjwW1QJXEhMF0qYnN90fdnvdogYmvJPU0/VBApD4hcDrWRcyikfB17srzgW7b9Rh1vEvxDlI4tVytaBSEEtmWh0xsUMwpwnWjqAlcxogiHd1wiQyCu87iI/+sJtf6+NXsgpd7FWCMB50KvkYMGMbLdZgLlfj+K9K4+FnFQ2x7WntIs50AbmiGwLILt+k+EvzvSNIHzdigdJ/AmXQRhiHv5POSwYmG+cqPVo0HqDxj8uTK2vn1Hfa+JmdIkvtZ/4fOPXU3WPDpFeNWVyUKryCiIGMN4zsH98gym3CIcOTwT+XHdXrdQQHAZotE8kBPpSqPNHtBOr48HUmLOcXRJT9dWNMGYJFby91pHOAvaykSaITg+bwefdhrteDRTMSwyrFCgI88E056Hy+4Ah2cXQZL3R4ABALUe7fqXWFN6AAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} - -.ipfs-zip { - background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAm9JREFUeNpsk0tv00AUhc+MY6dOmgeFJg1FoVVpUWlFC0s2IFF1jxBbhKj4BSxYdscPYcEmQmIDq0gsERIViy4TpD7VFzF1Ho5je2a4thOqNhlp5Mz4zudzzp0wpRTC8fPrk0/TC6+fDtYicLH97T1Kc2vQDcs+rH3eUAxVznn0fn1DRM8E+iOdv5ct3XmZG6yVlNj6solUbgVTt0q5FGtX6vXqC6VklTE+KAO/OODHSIQPRQpsXC+kkEz2ELA0ystv84tLzyucsbWByisAGf+QAS2CCDRRLMJMmxC+i8C4jdLCm/zM7OOKFGptcO6/BTpJ0yeQB0Y+mfKQuZZG0jQgeRbW8Xdomobs9LN8scc+UPHNy4Dwq8IljotIIQEm59/RoSyM1CKkXKZNBm7kIVgyM6wgAnSgRK9vqQfHPiMFDHqyFVsLR9Cm0o4YzoAASrSjCelQfRPb1Vc4qn0EY5L2W9GEaBLcxQgFHpGbkMIDJ69e+wjJ8VXqRgKid0r7ftQdxkRs9SqA2kgAm14SSIQh9uhuLGPMnKJs/5KquL1x0N0RCsizigoDaLqBdHoMiyvrlBsHVx1wphD4BCewoqxGKKDwAgtOy8JufYuk+5golGGaGZwc1sIGoDz3AOPZSVLaHgVwydoJDM1H4DbQODughB3YpOD44HfoHgnu4e7So0uAi0stHLJ3Aud8B9bpHu6vPoSu9TtDl6tUuoFiIYOgu0+158MKmOxomtyD3Qi/3MTR7i8K0EDG1GHO5DE3X4DvNahZlJOwEkOATvdPc2//hx3mXJ5lFJaF8K8bStd0YGfnOJbMGex21x6c+yfAAOlIPDJzr7cLAAAAAElFTkSuQmCC); - background-repeat:no-repeat; - background-size:contain -} diff --git a/assets/dir-index-html/src/style.css b/assets/dir-index-html/src/style.css deleted file mode 100644 index 3e7b8a734..000000000 --- a/assets/dir-index-html/src/style.css +++ /dev/null @@ -1,212 +0,0 @@ -body { - color:#34373f; - font-family:"Helvetica Neue", Helvetica, Arial, sans-serif; - font-size:14px; - line-height:1.43; - margin:0; - word-break:break-all; - -webkit-text-size-adjust:100%; - -ms-text-size-adjust:100%; - -webkit-tap-highlight-color:transparent -} - -a { - color:#117eb3; - text-decoration:none -} - -a:hover { - color:#00b0e9; - text-decoration:underline -} - -a:active, -a:visited { - color:#00b0e9 -} - -strong { - font-weight:700 -} - -table { - border-collapse:collapse; - border-spacing:0; - max-width:100%; - width:100% -} - -table:last-child { - border-bottom-left-radius:3px; - border-bottom-right-radius:3px -} - -tr:first-child td { - border-top:0 -} - -tr:nth-of-type(even) { - background-color:#f7f8fa -} - -td { - border-top:1px solid #d9dbe2; - padding:.65em; - vertical-align:top -} - -#page-header { - align-items:center; - background:#0b3a53; - border-bottom:4px solid #69c4cd; - color:#fff; - display:flex; - font-size:1.12em; - font-weight:500; - justify-content:space-between; - padding:0 1em -} - -#page-header a { - color:#69c4cd -} - -#page-header a:active { - color:#9ad4db -} - -#page-header a:hover { - color:#fff -} - -#page-header-logo { - height:2.25em; - margin:.7em .7em .7em 0; - width:7.15em -} - -#page-header-menu { - align-items:center; - display:flex; - margin:.65em 0 -} - -#page-header-menu div { - margin:0 .6em -} - -#page-header-menu div:last-child { - margin:0 0 0 .6em -} - -#page-header-menu svg { - fill:#69c4cd; - height:1.8em; - margin-top:.125em -} - -#page-header-menu svg:hover { - fill:#fff -} - -.menu-item-narrow { - display:none -} - -#content { - border:1px solid #d9dbe2; - border-radius:4px; - margin:1em -} - -#content-header { - background-color:#edf0f4; - border-bottom:1px solid #d9dbe2; - border-top-left-radius:3px; - border-top-right-radius:3px; - padding:.7em 1em -} - -.type-icon, -.type-icon>* { - width:1.15em -} - -.no-linebreak { - white-space:nowrap -} - -.ipfs-hash { - color:#7f8491; - font-family:monospace -} - -@media only screen and (max-width:500px) { - .menu-item-narrow { - display:inline - } - .menu-item-wide { - display:none - } -} - -@media print { - #page-header { - display:none - } - #content-header, - .ipfs-hash, - body { - color:#000 - } - #content-header { - border-bottom:1px solid #000 - } - #content { - border:1px solid #000 - } - a, - a:visited { - color:#000; - text-decoration:underline - } - a[href]:after { - content:" (" attr(href) ")" - } - tr { - page-break-inside:avoid - } - tr:nth-of-type(even) { - background-color:transparent - } - td { - border-top:1px solid #000 - } -} - -@-ms-viewport { - width:device-width -} - -.d-flex { - display:flex -} - -.flex-wrap { - flex-flow:wrap -} - -.flex-shrink-1 { - flex-shrink:1 -} - -.ml-auto { - margin-left:auto -} - -.table-responsive { - display:block; - width:100%; - overflow-x:auto; - -webkit-overflow-scrolling:touch -} diff --git a/assets/dir-index-html/test/go.mod b/assets/dir-index-html/test/go.mod deleted file mode 100644 index c1cff1b74..000000000 --- a/assets/dir-index-html/test/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/ipfs/dir-index-html/test - -go 1.17 diff --git a/assets/dir-index-html/test/main.go b/assets/dir-index-html/test/main.go deleted file mode 100644 index 43b4a0981..000000000 --- a/assets/dir-index-html/test/main.go +++ /dev/null @@ -1,117 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - "net/url" - "os" - "text/template" -) - -const templateFile = "../dir-index.html" - -// Copied from go-ipfs/core/corehttp/gateway_indexPage.go -type listingTemplateData struct { - GatewayURL string - DNSLink bool - Listing []directoryItem - Size string - Path string - Breadcrumbs []breadcrumb - BackLink string - Hash string - FastDirIndexThreshold int -} - -type directoryItem struct { - Size string - Name string - Path string - Hash string - ShortHash string -} - -type breadcrumb struct { - Name string - Path string -} - -var testPath = "/ipfs/QmFooBarQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7/a/b/c" -var testData = listingTemplateData{ - GatewayURL: "//localhost:3000", - DNSLink: true, - Listing: []directoryItem{{ - Size: "25 MiB", - Name: "short-film.mov", - Path: testPath + "/short-film.mov", - Hash: "QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR", - ShortHash: "QmbW\u2026sMnR", - }, { - Size: "23 KiB", - Name: "250pxيوسف_الوزاني_صورة_ملتقطة_بواسطة_مرصد_هابل_الفضائي_توضح_سديم_السرطان،_وهو_بقايا_مستعر_أعظم._.jpg", - Path: testPath + "/250pxيوسف_الوزاني_صورة_ملتقطة_بواسطة_مرصد_هابل_الفضائي_توضح_سديم_السرطان،_وهو_بقايا_مستعر_أعظم._.jpg", - Hash: "QmUwrKrMTrNv8QjWGKMMH5QV9FMPUtRCoQ6zxTdgxATQW6", - ShortHash: "QmUw\u2026TQW6", - }, { - Size: "1 KiB", - Name: "this-piece-of-papers-got-47-words-37-sentences-58-words-we-wanna-know.txt", - Path: testPath + "/this-piece-of-papers-got-47-words-37-sentences-58-words-we-wanna-know.txt", - Hash: "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi", - ShortHash: "bafy\u2026bzdi", - }}, - Size: "25 MiB", - Path: testPath, - Breadcrumbs: []breadcrumb{{ - Name: "ipfs", - }, { - Name: "QmFooBarQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7", - Path: testPath + "/../../..", - }, { - Name: "a", - Path: testPath + "/../..", - }, { - Name: "b", - Path: testPath + "/..", - }, { - Name: "c", - Path: testPath, - }}, - BackLink: testPath + "/..", - Hash: "QmFooBazBar2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7", -} - -func main() { - mux := http.NewServeMux() - mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - if r.URL.Path != "/" { - http.Error(w, "Ha-ha, tricked you! There are no files here!", http.StatusNotFound) - return - } - listingTemplate, err := template.New("dir-index.html").Funcs(template.FuncMap{ - "iconFromExt": func(name string) string { - return "ipfs-_blank" // place-holder - }, - "urlEscape": func(rawUrl string) string { - pathUrl := url.URL{Path: rawUrl} - return pathUrl.String() - }, - }).ParseFiles(templateFile) - if err != nil { - http.Error(w, fmt.Sprintf("failed to parse template file: %s", err), http.StatusInternalServerError) - return - } - err = listingTemplate.Execute(w, &testData) - if err != nil { - http.Error(w, fmt.Sprintf("failed to execute template: %s", err), http.StatusInternalServerError) - return - } - w.WriteHeader(http.StatusOK) - }) - if _, err := os.Stat(templateFile); err != nil { - wd, _ := os.Getwd() - fmt.Printf("could not open template file %q, relative to %q: %s\n", templateFile, wd, err) - os.Exit(1) - } - fmt.Printf("listening on localhost:3000\n") - http.ListenAndServe("localhost:3000", mux) -} diff --git a/cmd/ipfs/add_migrations.go b/cmd/ipfs/add_migrations.go index 6d62b4d6b..50ea9ad1c 100644 --- a/cmd/ipfs/add_migrations.go +++ b/cmd/ipfs/add_migrations.go @@ -8,7 +8,7 @@ import ( "os" "path/filepath" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" coreiface "github.com/ipfs/interface-go-ipfs-core" "github.com/ipfs/interface-go-ipfs-core/options" ipath "github.com/ipfs/interface-go-ipfs-core/path" diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index 1bfb9d6f1..12b3f4d9c 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -30,6 +30,8 @@ import ( fsrepo "github.com/ipfs/kubo/repo/fsrepo" "github.com/ipfs/kubo/repo/fsrepo/migrations" "github.com/ipfs/kubo/repo/fsrepo/migrations/ipfsfetcher" + p2pcrypto "github.com/libp2p/go-libp2p/core/crypto" + pnet "github.com/libp2p/go-libp2p/core/pnet" sockets "github.com/libp2p/go-socket-activation" cmds "github.com/ipfs/go-ipfs-cmds" @@ -61,6 +63,7 @@ const ( routingOptionNoneKwd = "none" routingOptionCustomKwd = "custom" routingOptionDefaultKwd = "default" + routingOptionAutoKwd = "auto" unencryptTransportKwd = "disable-transport-encryption" unrestrictedAPIAccessKwd = "unrestricted-api" writableKwd = "writable" @@ -89,7 +92,7 @@ For example, to change the 'Gateway' port: ipfs config Addresses.Gateway /ip4/127.0.0.1/tcp/8082 -The API address can be changed the same way: +The RPC API address can be changed the same way: ipfs config Addresses.API /ip4/127.0.0.1/tcp/5002 @@ -100,14 +103,14 @@ other computers in the network, use 0.0.0.0 as the ip address: ipfs config Addresses.Gateway /ip4/0.0.0.0/tcp/8080 -Be careful if you expose the API. It is a security risk, as anyone could +Be careful if you expose the RPC API. It is a security risk, as anyone could control your node remotely. If you need to control the node remotely, make sure to protect the port as you would other services or database (firewall, authenticated proxy, etc). HTTP Headers -ipfs supports passing arbitrary headers to the API and Gateway. You can +ipfs supports passing arbitrary headers to the RPC API and Gateway. You can do this by setting headers on the API.HTTPHeaders and Gateway.HTTPHeaders keys: @@ -141,18 +144,6 @@ environment variable: export IPFS_PATH=/path/to/ipfsrepo -Routing - -IPFS by default will use a DHT for content routing. There is an alternative -that operates the DHT in a 'client only' mode that can be enabled by -running the daemon as: - - ipfs daemon --routing=dhtclient - -Or you can set routing to dhtclient in the config: - - ipfs config Routing.Type dhtclient - DEPRECATION NOTICE Previously, ipfs used an environment variable as seen below: @@ -402,14 +393,30 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment routingOption, _ := req.Options[routingOptionKwd].(string) if routingOption == routingOptionDefaultKwd { - routingOption = cfg.Routing.Type + routingOption = cfg.Routing.Type.WithDefault(routingOptionAutoKwd) if routingOption == "" { + routingOption = routingOptionAutoKwd + } + } + + // Private setups can't leverage peers returned by default IPNIs (Routing.Type=auto) + // To avoid breaking existing setups, switch them to DHT-only. + if routingOption == routingOptionAutoKwd { + if key, _ := repo.SwarmKey(); key != nil || pnet.ForcePrivateNetwork { + log.Error("Private networking (swarm.key / LIBP2P_FORCE_PNET) does not work with public HTTP IPNIs enabled by Routing.Type=auto. Kubo will use Routing.Type=dht instead. Update config to remove this message.") routingOption = routingOptionDHTKwd } } + switch routingOption { case routingOptionSupernodeKwd: return errors.New("supernode routing was never fully implemented and has been removed") + case routingOptionDefaultKwd, routingOptionAutoKwd: + ncfg.Routing = libp2p.ConstructDefaultRouting( + cfg.Identity.PeerID, + cfg.Addresses.Swarm, + cfg.Identity.PrivKey, + ) case routingOptionDHTClientKwd: ncfg.Routing = libp2p.DHTClientOption case routingOptionDHTKwd: @@ -446,8 +453,29 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment fmt.Printf("Swarm key fingerprint: %x\n", node.PNetFingerprint) } + if (pnet.ForcePrivateNetwork || node.PNetFingerprint != nil) && routingOption == routingOptionAutoKwd { + // This should never happen, but better safe than sorry + log.Fatal("Private network does not work with Routing.Type=auto. Update your config to Routing.Type=dht (or none, and do manual peering)") + } + printSwarmAddrs(node) + if node.PrivateKey.Type() == p2pcrypto.RSA { + fmt.Print(` +Warning: You are using an RSA Peer ID, which was replaced by Ed25519 +as the default recommended in Kubo since September 2020. Signing with +RSA Peer IDs is more CPU-intensive than with other key types. +It is recommended that you change your public key type to ed25519 +by using the following command: + + ipfs key rotate -o rsa-key-backup -t ed25519 + +After changing your key type, restart your node for the changes to +take effect. + +`) + } + defer func() { // We wait for the node to close first, as the node has children // that it will wait for before closing, such as the API server. diff --git a/cmd/ipfs/init.go b/cmd/ipfs/init.go index 745ceb3e2..4232cc262 100644 --- a/cmd/ipfs/init.go +++ b/cmd/ipfs/init.go @@ -19,7 +19,7 @@ import ( fsrepo "github.com/ipfs/kubo/repo/fsrepo" cmds "github.com/ipfs/go-ipfs-cmds" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" options "github.com/ipfs/interface-go-ipfs-core/options" config "github.com/ipfs/kubo/config" ) diff --git a/cmd/ipfs/main.go b/cmd/ipfs/main.go index 83cc81fca..8b9822c99 100644 --- a/cmd/ipfs/main.go +++ b/cmd/ipfs/main.go @@ -12,26 +12,27 @@ import ( "runtime/pprof" "time" - util "github.com/ipfs/kubo/cmd/ipfs/util" + "github.com/ipfs/kubo/cmd/ipfs/util" oldcmds "github.com/ipfs/kubo/commands" - core "github.com/ipfs/kubo/core" + "github.com/ipfs/kubo/core" corecmds "github.com/ipfs/kubo/core/commands" - corehttp "github.com/ipfs/kubo/core/corehttp" - loader "github.com/ipfs/kubo/plugin/loader" - repo "github.com/ipfs/kubo/repo" - fsrepo "github.com/ipfs/kubo/repo/fsrepo" + "github.com/ipfs/kubo/core/corehttp" + "github.com/ipfs/kubo/plugin/loader" + "github.com/ipfs/kubo/repo" + "github.com/ipfs/kubo/repo/fsrepo" "github.com/ipfs/kubo/tracing" - "go.opentelemetry.io/otel" cmds "github.com/ipfs/go-ipfs-cmds" "github.com/ipfs/go-ipfs-cmds/cli" cmdhttp "github.com/ipfs/go-ipfs-cmds/http" u "github.com/ipfs/go-ipfs-util" logging "github.com/ipfs/go-log" - loggables "github.com/libp2p/go-libp2p-loggables" ma "github.com/multiformats/go-multiaddr" madns "github.com/multiformats/go-multiaddr-dns" manet "github.com/multiformats/go-multiaddr/net" + + "github.com/google/uuid" + "go.opentelemetry.io/otel" ) // log is the command logger @@ -77,9 +78,19 @@ func printErr(err error) int { return 1 } +func newUUID(key string) logging.Metadata { + ids := "#UUID-ERROR#" + if id, err := uuid.NewRandom(); err == nil { + ids = id.String() + } + return logging.Metadata{ + key: ids, + } +} + func mainRet() (exitCode int) { rand.Seed(time.Now().UnixNano()) - ctx := logging.ContextWithLoggable(context.Background(), loggables.Uuid("session")) + ctx := logging.ContextWithLoggable(context.Background(), newUUID("session")) var err error tp, err := tracing.NewTracerProvider(ctx) @@ -109,7 +120,7 @@ func mainRet() (exitCode int) { os.Args[1] = "version" } - //Handle `ipfs help` and `ipfs help ` + // Handle `ipfs help` and `ipfs help ` if os.Args[1] == "help" { if len(os.Args) > 2 { os.Args = append(os.Args[:1], os.Args[2:]...) diff --git a/cmd/ipfswatch/main.go b/cmd/ipfswatch/main.go index d555f14b9..06215687c 100644 --- a/cmd/ipfswatch/main.go +++ b/cmd/ipfswatch/main.go @@ -19,7 +19,7 @@ import ( fsrepo "github.com/ipfs/kubo/repo/fsrepo" fsnotify "github.com/fsnotify/fsnotify" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" process "github.com/jbenet/goprocess" homedir "github.com/mitchellh/go-homedir" ) diff --git a/codecov.yml b/codecov.yml index 71f774147..f6d4fc05b 100644 --- a/codecov.yml +++ b/codecov.yml @@ -4,6 +4,7 @@ codecov: - "!travis-ci.org" - "!ci.ipfs.team:8111" - "!ci.ipfs.team" + - "!github.com" notify: require_ci_to_pass: no after_n_builds: 2 diff --git a/config/gateway.go b/config/gateway.go index 8b8c65d1d..ad01b263b 100644 --- a/config/gateway.go +++ b/config/gateway.go @@ -45,14 +45,6 @@ type Gateway struct { // PathPrefixes was removed: https://github.com/ipfs/go-ipfs/issues/7702 PathPrefixes []string - // FastDirIndexThreshold is the maximum number of items in a directory - // before the Gateway switches to a shallow, faster listing which only - // requires the root node. This allows for listing big directories fast, - // without the linear slowdown caused by reading size metadata from child - // nodes. - // Setting to 0 will enable fast listings for all directories. - FastDirIndexThreshold *OptionalInteger `json:",omitempty"` - // FIXME: Not yet implemented: https://github.com/ipfs/kubo/issues/8059 APICommands []string diff --git a/config/init.go b/config/init.go index 29e960e8b..621ff95f3 100644 --- a/config/init.go +++ b/config/init.go @@ -48,7 +48,7 @@ func InitWithIdentity(identity Identity) (*Config, error) { }, Routing: Routing{ - Type: "dht", + Type: nil, Methods: nil, Routers: nil, }, @@ -76,8 +76,8 @@ func InitWithIdentity(identity Identity) (*Config, error) { APICommands: []string{}, }, Reprovider: Reprovider{ - Interval: "12h", - Strategy: "all", + Interval: nil, + Strategy: nil, }, Pinning: Pinning{ RemoteServices: map[string]RemotePinningService{}, @@ -96,11 +96,11 @@ func InitWithIdentity(identity Identity) (*Config, error) { // DefaultConnMgrHighWater is the default value for the connection managers // 'high water' mark -const DefaultConnMgrHighWater = 150 +const DefaultConnMgrHighWater = 96 // DefaultConnMgrLowWater is the default value for the connection managers 'low // water' mark -const DefaultConnMgrLowWater = 50 +const DefaultConnMgrLowWater = 32 // DefaultConnMgrGracePeriod is the default value for the connection managers // grace period @@ -110,13 +110,21 @@ const DefaultConnMgrGracePeriod = time.Second * 20 // type. const DefaultConnMgrType = "basic" +// DefaultResourceMgrMinInboundConns is a MAGIC number that probably a good +// enough number of inbound conns to be a good network citizen. +const DefaultResourceMgrMinInboundConns = 800 + func addressesConfig() Addresses { return Addresses{ Swarm: []string{ "/ip4/0.0.0.0/tcp/4001", "/ip6/::/tcp/4001", "/ip4/0.0.0.0/udp/4001/quic", + "/ip4/0.0.0.0/udp/4001/quic-v1", + "/ip4/0.0.0.0/udp/4001/quic-v1/webtransport", "/ip6/::/udp/4001/quic", + "/ip6/::/udp/4001/quic-v1", + "/ip6/::/udp/4001/quic-v1/webtransport", }, Announce: []string{}, AppendAnnounce: []string{}, diff --git a/config/profile.go b/config/profile.go index 6748b5fb2..1a4013918 100644 --- a/config/profile.go +++ b/config/profile.go @@ -174,9 +174,9 @@ functionality - performance of content discovery and data fetching may be degraded. `, Transform: func(c *Config) error { - c.Routing.Type = "dhtclient" + c.Routing.Type = NewOptionalString("dhtclient") // TODO: https://github.com/ipfs/kubo/issues/9480 c.AutoNAT.ServiceMode = AutoNATServiceDisabled - c.Reprovider.Interval = "0" + c.Reprovider.Interval = NewOptionalDuration(0) lowWater := int64(20) highWater := int64(40) diff --git a/config/pubsub.go b/config/pubsub.go index ba8084300..36f9a9881 100644 --- a/config/pubsub.go +++ b/config/pubsub.go @@ -1,5 +1,24 @@ package config +const ( + // LastSeenMessagesStrategy is a strategy that calculates the TTL countdown + // based on the last time a Pubsub message is seen. This means that if a message + // is received and then seen again within the specified TTL window, it + // won't be emitted until the TTL countdown expires from the last time the + // message was seen. + LastSeenMessagesStrategy = "last-seen" + + // FirstSeenMessagesStrategy is a strategy that calculates the TTL + // countdown based on the first time a Pubsub message is seen. This means that if + // a message is received and then seen again within the specified TTL + // window, it won't be emitted. + FirstSeenMessagesStrategy = "first-seen" + + // DefaultSeenMessagesStrategy is the strategy that is used by default if + // no Pubsub.SeenMessagesStrategy is specified. + DefaultSeenMessagesStrategy = LastSeenMessagesStrategy +) + type PubsubConfig struct { // Router can be either floodsub (legacy) or gossipsub (new and // backwards compatible). @@ -12,7 +31,11 @@ type PubsubConfig struct { // Enable pubsub (--enable-pubsub-experiment) Enabled Flag `json:",omitempty"` - // SeenMessagesTTL configures the duration after which a previously seen - // message ID can be forgotten about. + // SeenMessagesTTL is a value that controls the time window within which + // duplicate messages will be identified and won't be emitted. SeenMessagesTTL *OptionalDuration `json:",omitempty"` + + // SeenMessagesStrategy is a setting that determines how the time-to-live + // (TTL) countdown for deduplicating messages is calculated. + SeenMessagesStrategy *OptionalString `json:",omitempty"` } diff --git a/config/reprovider.go b/config/reprovider.go index fa029c2fc..19ee1c58d 100644 --- a/config/reprovider.go +++ b/config/reprovider.go @@ -1,6 +1,11 @@ package config +import "time" + +const DefaultReproviderInterval = time.Hour * 22 // https://github.com/ipfs/kubo/pull/9326 +const DefaultReproviderStrategy = "all" + type Reprovider struct { - Interval string // Time period to reprovide locally stored objects to the network - Strategy string // Which keys to announce + Interval *OptionalDuration `json:",omitempty"` // Time period to reprovide locally stored objects to the network + Strategy *OptionalString `json:",omitempty"` // Which keys to announce } diff --git a/config/routing.go b/config/routing.go index 90d91d28b..f19414ff3 100644 --- a/config/routing.go +++ b/config/routing.go @@ -10,9 +10,10 @@ import ( type Routing struct { // Type sets default daemon routing mode. // - // Can be one of "dht", "dhtclient", "dhtserver", "none", or "custom". - // When "custom" is set, you can specify a list of Routers. - Type string + // Can be one of "auto", "dht", "dhtclient", "dhtserver", "none", or "custom". + // When unset or set to "auto", DHT and implicit routers are used. + // When "custom" is set, user-provided Routing.Routers is used. + Type *OptionalString `json:",omitempty"` Routers Routers @@ -21,10 +22,7 @@ type Routing struct { type Router struct { - // Currenly supported Types are "reframe", "dht", "parallel", "sequential". - // Reframe type allows to add other resolvers using the Reframe spec: - // https://github.com/ipfs/specs/tree/main/reframe - // In the future we will support "dht" and other Types here. + // Router type ID. See RouterType for more info. Type RouterType // Parameters are extra configuration that this router might need. @@ -106,11 +104,11 @@ func (r *RouterParser) UnmarshalJSON(b []byte) error { type RouterType string const ( - RouterTypeReframe RouterType = "reframe" - RouterTypeHTTP RouterType = "http" - RouterTypeDHT RouterType = "dht" - RouterTypeSequential RouterType = "sequential" - RouterTypeParallel RouterType = "parallel" + RouterTypeReframe RouterType = "reframe" // More info here: https://github.com/ipfs/specs/tree/main/reframe . Actually deprecated. + RouterTypeHTTP RouterType = "http" // HTTP JSON API for delegated routing systems (IPIP-337). + RouterTypeDHT RouterType = "dht" // DHT router. + RouterTypeSequential RouterType = "sequential" // Router helper to execute several routers sequentially. + RouterTypeParallel RouterType = "parallel" // Router helper to execute several routers in parallel. ) type DHTMode string diff --git a/config/routing_test.go b/config/routing_test.go index 013e285a5..49068f976 100644 --- a/config/routing_test.go +++ b/config/routing_test.go @@ -13,7 +13,7 @@ func TestRouterParameters(t *testing.T) { sec := time.Second min := time.Minute r := Routing{ - Type: "custom", + Type: NewOptionalString("custom"), Routers: map[string]RouterParser{ "router-dht": {Router{ Type: RouterTypeDHT, @@ -113,7 +113,7 @@ func TestRouterMissingParameters(t *testing.T) { require := require.New(t) r := Routing{ - Type: "custom", + Type: NewOptionalString("custom"), Routers: map[string]RouterParser{ "router-wrong-reframe": {Router{ Type: RouterTypeReframe, diff --git a/config/types.go b/config/types.go index e3f61546b..1af244f9c 100644 --- a/config/types.go +++ b/config/types.go @@ -218,6 +218,11 @@ type OptionalDuration struct { value *time.Duration } +// NewOptionalDuration returns an OptionalDuration from a string +func NewOptionalDuration(d time.Duration) *OptionalDuration { + return &OptionalDuration{value: &d} +} + func (d *OptionalDuration) UnmarshalJSON(input []byte) error { switch string(input) { case "null", "undefined", "\"null\"", "", "default", "\"\"", "\"default\"": diff --git a/core/builder.go b/core/builder.go index aacb51884..7a1d6fef2 100644 --- a/core/builder.go +++ b/core/builder.go @@ -84,6 +84,7 @@ func NewNode(ctx context.Context, cfg *BuildCfg) (*IpfsNode, error) { return nil, fmt.Errorf("building fx opts: %w", err) } } + //nolint:staticcheck // https://github.com/ipfs/kubo/pull/9423#issuecomment-1341038770 opts = append(opts, fx.Extract(n)) app := fx.New(opts...) diff --git a/core/commands/add.go b/core/commands/add.go index 9f686e14b..7afe10f1e 100644 --- a/core/commands/add.go +++ b/core/commands/add.go @@ -12,8 +12,8 @@ import ( "github.com/cheggaaa/pb" cmds "github.com/ipfs/go-ipfs-cmds" - files "github.com/ipfs/go-ipfs-files" ipld "github.com/ipfs/go-ipld-format" + "github.com/ipfs/go-libipfs/files" mfs "github.com/ipfs/go-mfs" coreiface "github.com/ipfs/interface-go-ipfs-core" "github.com/ipfs/interface-go-ipfs-core/options" diff --git a/core/commands/bitswap.go b/core/commands/bitswap.go index d524263be..a7e8965b1 100644 --- a/core/commands/bitswap.go +++ b/core/commands/bitswap.go @@ -8,10 +8,10 @@ import ( e "github.com/ipfs/kubo/core/commands/e" humanize "github.com/dustin/go-humanize" - bitswap "github.com/ipfs/go-bitswap" - decision "github.com/ipfs/go-bitswap/decision" cidutil "github.com/ipfs/go-cidutil" cmds "github.com/ipfs/go-ipfs-cmds" + bitswap "github.com/ipfs/go-libipfs/bitswap" + decision "github.com/ipfs/go-libipfs/bitswap/decision" peer "github.com/libp2p/go-libp2p/core/peer" ) diff --git a/core/commands/block.go b/core/commands/block.go index b0591b002..c8001b49c 100644 --- a/core/commands/block.go +++ b/core/commands/block.go @@ -6,7 +6,7 @@ import ( "io" "os" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" cmdenv "github.com/ipfs/kubo/core/commands/cmdenv" "github.com/ipfs/kubo/core/commands/cmdutils" diff --git a/core/commands/cat.go b/core/commands/cat.go index 151ac126e..c80bacf02 100644 --- a/core/commands/cat.go +++ b/core/commands/cat.go @@ -9,9 +9,9 @@ import ( "github.com/ipfs/kubo/core/commands/cmdenv" "github.com/cheggaaa/pb" - "github.com/ipfs/go-ipfs-cmds" - "github.com/ipfs/go-ipfs-files" - "github.com/ipfs/interface-go-ipfs-core" + cmds "github.com/ipfs/go-ipfs-cmds" + "github.com/ipfs/go-libipfs/files" + iface "github.com/ipfs/interface-go-ipfs-core" "github.com/ipfs/interface-go-ipfs-core/path" ) diff --git a/core/commands/cmdenv/file.go b/core/commands/cmdenv/file.go index 50ce748eb..43c12abc4 100644 --- a/core/commands/cmdenv/file.go +++ b/core/commands/cmdenv/file.go @@ -3,7 +3,7 @@ package cmdenv import ( "fmt" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" ) // GetFileArg returns the next file from the directory or an error diff --git a/core/commands/commands_test.go b/core/commands/commands_test.go index ec4cc1bb6..8f94e5d64 100644 --- a/core/commands/commands_test.go +++ b/core/commands/commands_test.go @@ -173,6 +173,7 @@ func TestCommands(t *testing.T) { "/multibase/transcode", "/multibase/list", "/name", + "/name/inspect", "/name/publish", "/name/pubsub", "/name/pubsub/cancel", diff --git a/core/commands/dag/export.go b/core/commands/dag/export.go index e9d120e87..b78523ce5 100644 --- a/core/commands/dag/export.go +++ b/core/commands/dag/export.go @@ -9,9 +9,9 @@ import ( "time" "github.com/cheggaaa/pb" - blocks "github.com/ipfs/go-block-format" cid "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" + blocks "github.com/ipfs/go-libipfs/blocks" iface "github.com/ipfs/interface-go-ipfs-core" "github.com/ipfs/kubo/core/commands/cmdenv" diff --git a/core/commands/dag/import.go b/core/commands/dag/import.go index 87daaae11..c9f0ebbde 100644 --- a/core/commands/dag/import.go +++ b/core/commands/dag/import.go @@ -6,9 +6,9 @@ import ( "io" cid "github.com/ipfs/go-cid" - files "github.com/ipfs/go-ipfs-files" ipld "github.com/ipfs/go-ipld-format" ipldlegacy "github.com/ipfs/go-ipld-legacy" + "github.com/ipfs/go-libipfs/files" iface "github.com/ipfs/interface-go-ipfs-core" "github.com/ipfs/interface-go-ipfs-core/options" "github.com/ipfs/kubo/core/commands/cmdenv" diff --git a/core/commands/dag/put.go b/core/commands/dag/put.go index d8dbaa3f1..351b9cacd 100644 --- a/core/commands/dag/put.go +++ b/core/commands/dag/put.go @@ -4,17 +4,17 @@ import ( "bytes" "fmt" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" ipldlegacy "github.com/ipfs/go-ipld-legacy" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/ipfs/kubo/core/commands/cmdenv" "github.com/ipfs/kubo/core/commands/cmdutils" "github.com/ipld/go-ipld-prime/multicodec" basicnode "github.com/ipld/go-ipld-prime/node/basic" cmds "github.com/ipfs/go-ipfs-cmds" - files "github.com/ipfs/go-ipfs-files" ipld "github.com/ipfs/go-ipld-format" + "github.com/ipfs/go-libipfs/files" mc "github.com/multiformats/go-multicodec" // Expected minimal set of available format/ienc codecs. diff --git a/core/commands/get.go b/core/commands/get.go index 7e915ea29..e5648b28f 100644 --- a/core/commands/get.go +++ b/core/commands/get.go @@ -16,7 +16,7 @@ import ( "github.com/cheggaaa/pb" cmds "github.com/ipfs/go-ipfs-cmds" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" "github.com/ipfs/go-libipfs/tar" "github.com/ipfs/interface-go-ipfs-core/path" ) diff --git a/core/commands/name/name.go b/core/commands/name/name.go index d9e3de57f..7999aee3d 100644 --- a/core/commands/name/name.go +++ b/core/commands/name/name.go @@ -1,7 +1,25 @@ package name import ( - "github.com/ipfs/go-ipfs-cmds" + "bytes" + "encoding/json" + "fmt" + "io" + "strings" + "text/tabwriter" + "time" + + "github.com/gogo/protobuf/proto" + cmds "github.com/ipfs/go-ipfs-cmds" + "github.com/ipfs/go-ipns" + ipns_pb "github.com/ipfs/go-ipns/pb" + cmdenv "github.com/ipfs/kubo/core/commands/cmdenv" + "github.com/ipld/go-ipld-prime" + "github.com/ipld/go-ipld-prime/codec/dagcbor" + "github.com/ipld/go-ipld-prime/codec/dagjson" + ic "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/peer" + mbase "github.com/multiformats/go-multibase" ) type IpnsEntry struct { @@ -62,5 +80,204 @@ Resolve the value of a dnslink: "publish": PublishCmd, "resolve": IpnsCmd, "pubsub": IpnsPubsubCmd, + "inspect": IpnsInspectCmd, + }, +} + +type IpnsInspectValidation struct { + Valid bool + Reason string + PublicKey peer.ID +} + +// IpnsInspectEntry contains the deserialized values from an IPNS Entry: +// https://github.com/ipfs/specs/blob/main/ipns/IPNS.md#record-serialization-format +type IpnsInspectEntry struct { + Value string + ValidityType *ipns_pb.IpnsEntry_ValidityType + Validity *time.Time + Sequence uint64 + TTL *uint64 + PublicKey string + SignatureV1 string + SignatureV2 string + Data interface{} +} + +type IpnsInspectResult struct { + Entry IpnsInspectEntry + Validation *IpnsInspectValidation +} + +var IpnsInspectCmd = &cmds.Command{ + Status: cmds.Experimental, + Helptext: cmds.HelpText{ + Tagline: "Inspects an IPNS Record", + ShortDescription: ` +Prints values inside of IPNS Record protobuf and its DAG-CBOR Data field. +Passing --verify will verify signature against provided public key. +`, + LongDescription: ` +Prints values inside of IPNS Record protobuf and its DAG-CBOR Data field. + +The input can be a file or STDIN, the output can be JSON: + + $ ipfs routing get "/ipns/$PEERID" > ipns_record + $ ipfs name inspect --enc=json < ipns_record + +Values in PublicKey, SignatureV1 and SignatureV2 fields are raw bytes encoded +in Multibase. The Data field is DAG-CBOR represented as DAG-JSON. + +Passing --verify will verify signature against provided public key. + +`, + }, + Arguments: []cmds.Argument{ + cmds.FileArg("record", true, false, "The IPNS record payload to be verified.").EnableStdin(), + }, + Options: []cmds.Option{ + cmds.StringOption("verify", "CID of the public IPNS key to validate against."), + }, + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + file, err := cmdenv.GetFileArg(req.Files.Entries()) + if err != nil { + return err + } + defer file.Close() + + var b bytes.Buffer + + _, err = io.Copy(&b, file) + if err != nil { + return err + } + + var entry ipns_pb.IpnsEntry + err = proto.Unmarshal(b.Bytes(), &entry) + if err != nil { + return err + } + + encoder, err := mbase.EncoderByName("base64") + if err != nil { + return err + } + + result := &IpnsInspectResult{ + Entry: IpnsInspectEntry{ + Value: string(entry.Value), + ValidityType: entry.ValidityType, + Sequence: *entry.Sequence, + TTL: entry.Ttl, + PublicKey: encoder.Encode(entry.PubKey), + SignatureV1: encoder.Encode(entry.SignatureV1), + SignatureV2: encoder.Encode(entry.SignatureV2), + Data: nil, + }, + } + + if len(entry.Data) != 0 { + // This is hacky. The variable node (datamodel.Node) doesn't directly marshal + // to JSON. Therefore, we need to first decode from DAG-CBOR, then encode in + // DAG-JSON and finally unmarshal it from JSON. Since DAG-JSON is a subset + // of JSON, that should work. Then, we can store the final value in the + // result.Entry.Data for further inspection. + node, err := ipld.Decode(entry.Data, dagcbor.Decode) + if err != nil { + return err + } + + var buf bytes.Buffer + err = dagjson.Encode(node, &buf) + if err != nil { + return err + } + + err = json.Unmarshal(buf.Bytes(), &result.Entry.Data) + if err != nil { + return err + } + } + + validity, err := ipns.GetEOL(&entry) + if err == nil { + result.Entry.Validity = &validity + } + + verify, ok := req.Options["verify"].(string) + if ok { + key := strings.TrimPrefix(verify, "/ipns/") + id, err := peer.Decode(key) + if err != nil { + return err + } + + result.Validation = &IpnsInspectValidation{ + PublicKey: id, + } + + pub, err := id.ExtractPublicKey() + if err != nil { + // Make sure it works with all those RSA that cannot be embedded into the + // Peer ID. + if len(entry.PubKey) > 0 { + pub, err = ic.UnmarshalPublicKey(entry.PubKey) + } + } + if err != nil { + return err + } + + err = ipns.Validate(pub, &entry) + if err == nil { + result.Validation.Valid = true + } else { + result.Validation.Reason = err.Error() + } + } + + return cmds.EmitOnce(res, result) + }, + Type: IpnsInspectResult{}, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *IpnsInspectResult) error { + tw := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0) + defer tw.Flush() + + fmt.Fprintf(tw, "Value:\t%q\n", string(out.Entry.Value)) + fmt.Fprintf(tw, "Validity Type:\t%q\n", out.Entry.ValidityType) + if out.Entry.Validity != nil { + fmt.Fprintf(tw, "Validity:\t%s\n", out.Entry.Validity.Format(time.RFC3339Nano)) + } + fmt.Fprintf(tw, "Sequence:\t%d\n", out.Entry.Sequence) + if out.Entry.TTL != nil { + fmt.Fprintf(tw, "TTL:\t%d\n", *out.Entry.TTL) + } + fmt.Fprintf(tw, "PublicKey:\t%q\n", out.Entry.PublicKey) + fmt.Fprintf(tw, "Signature V1:\t%q\n", out.Entry.SignatureV1) + fmt.Fprintf(tw, "Signature V2:\t%q\n", out.Entry.SignatureV2) + + data, err := json.Marshal(out.Entry.Data) + if err != nil { + return err + } + fmt.Fprintf(tw, "Data:\t%s\n", string(data)) + + if out.Validation == nil { + tw.Flush() + fmt.Fprintf(w, "\nThis record was not validated.\n") + } else { + tw.Flush() + fmt.Fprintf(w, "\nValidation results:\n") + + fmt.Fprintf(tw, "\tValid:\t%v\n", out.Validation.Valid) + if out.Validation.Reason != "" { + fmt.Fprintf(tw, "\tReason:\t%s\n", out.Validation.Reason) + } + fmt.Fprintf(tw, "\tPublicKey:\t%s\n", out.Validation.PublicKey) + } + + return nil + }), }, } diff --git a/core/commands/routing.go b/core/commands/routing.go index bf7d2a699..d0f13c556 100644 --- a/core/commands/routing.go +++ b/core/commands/routing.go @@ -2,7 +2,6 @@ package commands import ( "context" - "encoding/base64" "errors" "fmt" "io" @@ -135,6 +134,7 @@ const ( ) var provideRefRoutingCmd = &cmds.Command{ + Status: cmds.Experimental, Helptext: cmds.HelpText{ Tagline: "Announce to the network that you are providing given values.", }, @@ -346,6 +346,7 @@ var findPeerRoutingCmd = &cmds.Command{ } var getValueRoutingCmd = &cmds.Command{ + Status: cmds.Experimental, Helptext: cmds.HelpText{ Tagline: "Given a key, query the routing system for its best value.", ShortDescription: ` @@ -362,78 +363,30 @@ Different key types can specify other 'best' rules. Arguments: []cmds.Argument{ cmds.StringArg("key", true, true, "The key to find a value for."), }, - Options: []cmds.Option{ - cmds.BoolOption(dhtVerboseOptionName, "v", "Print extra information."), - }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - nd, err := cmdenv.GetNode(env) + api, err := cmdenv.GetApi(env, req) if err != nil { return err } - if !nd.IsOnline { - return ErrNotOnline - } - - dhtkey, err := escapeDhtKey(req.Arguments[0]) + r, err := api.Routing().Get(req.Context, req.Arguments[0]) if err != nil { return err } - ctx, cancel := context.WithCancel(req.Context) - ctx, events := routing.RegisterForQueryEvents(ctx) - - var getErr error - go func() { - defer cancel() - var val []byte - val, getErr = nd.Routing.GetValue(ctx, dhtkey) - if getErr != nil { - routing.PublishQueryEvent(ctx, &routing.QueryEvent{ - Type: routing.QueryError, - Extra: getErr.Error(), - }) - } else { - routing.PublishQueryEvent(ctx, &routing.QueryEvent{ - Type: routing.Value, - Extra: base64.StdEncoding.EncodeToString(val), - }) - } - }() - - for e := range events { - if err := res.Emit(e); err != nil { - return err - } - } - - return getErr + return res.Emit(r) }, Encoders: cmds.EncoderMap{ - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *routing.QueryEvent) error { - pfm := pfuncMap{ - routing.Value: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error { - if verbose { - _, err := fmt.Fprintf(out, "got value: '%s'\n", obj.Extra) - return err - } - res, err := base64.StdEncoding.DecodeString(obj.Extra) - if err != nil { - return err - } - _, err = out.Write(res) - return err - }, - } - - verbose, _ := req.Options[dhtVerboseOptionName].(bool) - return printEvent(out, w, verbose, pfm) + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out []byte) error { + _, err := w.Write(out) + return err }), }, - Type: routing.QueryEvent{}, + Type: []byte{}, } var putValueRoutingCmd = &cmds.Command{ + Status: cmds.Experimental, Helptext: cmds.HelpText{ Tagline: "Write a key/value pair to the routing system.", ShortDescription: ` @@ -459,20 +412,8 @@ identified by QmFoo. cmds.StringArg("key", true, false, "The key to store the value at."), cmds.FileArg("value-file", true, false, "A path to a file containing the value to store.").EnableStdin(), }, - Options: []cmds.Option{ - cmds.BoolOption(dhtVerboseOptionName, "v", "Print extra information."), - }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - nd, err := cmdenv.GetNode(env) - if err != nil { - return err - } - - if !nd.IsOnline { - return ErrNotOnline - } - - key, err := escapeDhtKey(req.Arguments[0]) + api, err := cmdenv.GetApi(env, req) if err != nil { return err } @@ -488,50 +429,20 @@ identified by QmFoo. return err } - ctx, cancel := context.WithCancel(req.Context) - ctx, events := routing.RegisterForQueryEvents(ctx) - - var putErr error - go func() { - defer cancel() - putErr = nd.Routing.PutValue(ctx, key, []byte(data)) - if putErr != nil { - routing.PublishQueryEvent(ctx, &routing.QueryEvent{ - Type: routing.QueryError, - Extra: putErr.Error(), - }) - } - }() - - for e := range events { - if err := res.Emit(e); err != nil { - return err - } + err = api.Routing().Put(req.Context, req.Arguments[0], data) + if err != nil { + return err } - return putErr + return res.Emit([]byte(fmt.Sprintf("%s added", req.Arguments[0]))) }, Encoders: cmds.EncoderMap{ - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *routing.QueryEvent) error { - pfm := pfuncMap{ - routing.FinalPeer: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error { - if verbose { - fmt.Fprintf(out, "* closest peer %s\n", obj.ID) - } - return nil - }, - routing.Value: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error { - fmt.Fprintf(out, "%s\n", obj.ID.Pretty()) - return nil - }, - } - - verbose, _ := req.Options[dhtVerboseOptionName].(bool) - - return printEvent(out, w, verbose, pfm) + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out []byte) error { + _, err := w.Write(out) + return err }), }, - Type: routing.QueryEvent{}, + Type: []byte{}, } type printFunc func(obj *routing.QueryEvent, out io.Writer, verbose bool) error diff --git a/core/commands/swarm.go b/core/commands/swarm.go index 84e78d4d8..d00291f78 100644 --- a/core/commands/swarm.go +++ b/core/commands/swarm.go @@ -12,7 +12,7 @@ import ( "sync" "time" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" "github.com/ipfs/kubo/commands" "github.com/ipfs/kubo/config" "github.com/ipfs/kubo/core/commands/cmdenv" @@ -337,12 +337,15 @@ The scope can be one of the following: - all -- reports the resource usage for all currently active scopes. The output of this command is JSON. + +To see all resources that are close to hitting their respective limit, one can do something like: + ipfs swarm stats --min-used-limit-perc=90 all `}, Arguments: []cmds.Argument{ cmds.StringArg("scope", true, false, "scope of the stat report"), }, Options: []cmds.Option{ - cmds.IntOption(swarmUsedResourcesPercentageName, "Display only resources that are using above the specified percentage"), + cmds.IntOption(swarmUsedResourcesPercentageName, "Only display resources that are using above the specified percentage of their respective limit"), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { node, err := cmdenv.GetNode(env) diff --git a/core/commands/urlstore.go b/core/commands/urlstore.go index bd67c56ff..b17dc713a 100644 --- a/core/commands/urlstore.go +++ b/core/commands/urlstore.go @@ -9,7 +9,7 @@ import ( cmdenv "github.com/ipfs/kubo/core/commands/cmdenv" cmds "github.com/ipfs/go-ipfs-cmds" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" "github.com/ipfs/interface-go-ipfs-core/options" ) diff --git a/core/core_test.go b/core/core_test.go index 488eb8421..1d0703de0 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -221,7 +221,7 @@ func GetNode(t *testing.T, reframeURLs ...string) *IpfsNode { API: []string{"/ip4/127.0.0.1/tcp/0"}, }, Routing: config.Routing{ - Type: "custom", + Type: config.NewOptionalString("custom"), Routers: routers, Methods: config.Methods{ config.MethodNameFindPeers: config.Method{ diff --git a/core/coreapi/block.go b/core/coreapi/block.go index 886a21bf4..4f086ae86 100644 --- a/core/coreapi/block.go +++ b/core/coreapi/block.go @@ -6,9 +6,9 @@ import ( "errors" "io" - blocks "github.com/ipfs/go-block-format" cid "github.com/ipfs/go-cid" pin "github.com/ipfs/go-ipfs-pinner" + blocks "github.com/ipfs/go-libipfs/blocks" coreiface "github.com/ipfs/interface-go-ipfs-core" caopts "github.com/ipfs/interface-go-ipfs-core/options" path "github.com/ipfs/interface-go-ipfs-core/path" diff --git a/core/coreapi/coreapi.go b/core/coreapi/coreapi.go index fb549171a..85bd60c12 100644 --- a/core/coreapi/coreapi.go +++ b/core/coreapi/coreapi.go @@ -144,6 +144,11 @@ func (api *CoreAPI) PubSub() coreiface.PubSubAPI { return (*PubSubAPI)(api) } +// Routing returns the RoutingAPI interface implementation backed by the kubo node +func (api *CoreAPI) Routing() coreiface.RoutingAPI { + return (*RoutingAPI)(api) +} + // WithOptions returns api with global options applied func (api *CoreAPI) WithOptions(opts ...options.ApiOption) (coreiface.CoreAPI, error) { settings := api.parentOpts // make sure to copy diff --git a/core/coreapi/name.go b/core/coreapi/name.go index 69dc1137b..87af34af4 100644 --- a/core/coreapi/name.go +++ b/core/coreapi/name.go @@ -15,6 +15,7 @@ import ( ipath "github.com/ipfs/go-path" coreiface "github.com/ipfs/interface-go-ipfs-core" caopts "github.com/ipfs/interface-go-ipfs-core/options" + nsopts "github.com/ipfs/interface-go-ipfs-core/options/namesys" path "github.com/ipfs/interface-go-ipfs-core/path" ci "github.com/libp2p/go-libp2p/core/crypto" peer "github.com/libp2p/go-libp2p/core/peer" @@ -37,8 +38,6 @@ func (e *ipnsEntry) Value() path.Path { return e.value } -type requestContextKey string - // Publish announces new IPNS name and returns the new IPNS entry. func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.NamePublishOption) (coreiface.IpnsEntry, error) { ctx, span := tracing.Span(ctx, "CoreAPI.NameAPI", "Publish", trace.WithAttributes(attribute.String("path", p.String()))) @@ -76,13 +75,17 @@ func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.Nam return nil, err } - if options.TTL != nil { - // nolint: staticcheck // non-backward compatible change - ctx = context.WithValue(ctx, requestContextKey("ipns-publish-ttl"), *options.TTL) + eol := time.Now().Add(options.ValidTime) + + publishOptions := []nsopts.PublishOption{ + nsopts.PublishWithEOL(eol), } - eol := time.Now().Add(options.ValidTime) - err = api.namesys.PublishWithEOL(ctx, k, pth, eol) + if options.TTL != nil { + publishOptions = append(publishOptions, nsopts.PublishWithTTL(*options.TTL)) + } + + err = api.namesys.Publish(ctx, k, pth, publishOptions...) if err != nil { return nil, err } diff --git a/core/coreapi/routing.go b/core/coreapi/routing.go new file mode 100644 index 000000000..78f21c429 --- /dev/null +++ b/core/coreapi/routing.go @@ -0,0 +1,53 @@ +package coreapi + +import ( + "context" + "errors" + + "github.com/ipfs/go-path" + coreiface "github.com/ipfs/interface-go-ipfs-core" + peer "github.com/libp2p/go-libp2p/core/peer" +) + +type RoutingAPI CoreAPI + +func (r *RoutingAPI) Get(ctx context.Context, key string) ([]byte, error) { + if !r.nd.IsOnline { + return nil, coreiface.ErrOffline + } + + dhtKey, err := normalizeKey(key) + if err != nil { + return nil, err + } + + return r.routing.GetValue(ctx, dhtKey) +} + +func (r *RoutingAPI) Put(ctx context.Context, key string, value []byte) error { + if !r.nd.IsOnline { + return coreiface.ErrOffline + } + + dhtKey, err := normalizeKey(key) + if err != nil { + return err + } + + return r.routing.PutValue(ctx, dhtKey, value) +} + +func normalizeKey(s string) (string, error) { + parts := path.SplitList(s) + if len(parts) != 3 || + parts[0] != "" || + !(parts[1] == "ipns" || parts[1] == "pk") { + return "", errors.New("invalid key") + } + + k, err := peer.Decode(parts[2]) + if err != nil { + return "", err + } + return path.Join(append(parts[:2], string(k))), nil +} diff --git a/core/coreapi/test/path_test.go b/core/coreapi/test/path_test.go index bf26b39ce..acba1c47f 100644 --- a/core/coreapi/test/path_test.go +++ b/core/coreapi/test/path_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" "github.com/ipfs/go-merkledag" uio "github.com/ipfs/go-unixfs/io" "github.com/ipfs/interface-go-ipfs-core/options" diff --git a/core/coreapi/unixfs.go b/core/coreapi/unixfs.go index 3d6966ac1..7ab7d34d6 100644 --- a/core/coreapi/unixfs.go +++ b/core/coreapi/unixfs.go @@ -17,8 +17,8 @@ import ( cidutil "github.com/ipfs/go-cidutil" filestore "github.com/ipfs/go-filestore" bstore "github.com/ipfs/go-ipfs-blockstore" - files "github.com/ipfs/go-ipfs-files" ipld "github.com/ipfs/go-ipld-format" + "github.com/ipfs/go-libipfs/files" merkledag "github.com/ipfs/go-merkledag" dagtest "github.com/ipfs/go-merkledag/test" mfs "github.com/ipfs/go-mfs" @@ -271,32 +271,36 @@ func (api *UnixfsAPI) processLink(ctx context.Context, linkres ft.LinkResult, se lnk.Type = coreiface.TFile lnk.Size = linkres.Link.Size case cid.DagProtobuf: - if !settings.ResolveChildren { - break - } - - linkNode, err := linkres.Link.GetNode(ctx, api.dag) - if err != nil { - lnk.Err = err - break - } - - if pn, ok := linkNode.(*merkledag.ProtoNode); ok { - d, err := ft.FSNodeFromBytes(pn.Data()) + if settings.ResolveChildren { + linkNode, err := linkres.Link.GetNode(ctx, api.dag) if err != nil { lnk.Err = err break } - switch d.Type() { - case ft.TFile, ft.TRaw: - lnk.Type = coreiface.TFile - case ft.THAMTShard, ft.TDirectory, ft.TMetadata: - lnk.Type = coreiface.TDirectory - case ft.TSymlink: - lnk.Type = coreiface.TSymlink - lnk.Target = string(d.Data()) + + if pn, ok := linkNode.(*merkledag.ProtoNode); ok { + d, err := ft.FSNodeFromBytes(pn.Data()) + if err != nil { + lnk.Err = err + break + } + switch d.Type() { + case ft.TFile, ft.TRaw: + lnk.Type = coreiface.TFile + case ft.THAMTShard, ft.TDirectory, ft.TMetadata: + lnk.Type = coreiface.TDirectory + case ft.TSymlink: + lnk.Type = coreiface.TSymlink + lnk.Target = string(d.Data()) + } + if !settings.UseCumulativeSize { + lnk.Size = d.FileSize() + } } - lnk.Size = d.FileSize() + } + + if settings.UseCumulativeSize { + lnk.Size = linkres.Link.Size } } diff --git a/core/corehttp/gateway.go b/core/corehttp/gateway.go index 0d0a234d9..d5eccf73c 100644 --- a/core/corehttp/gateway.go +++ b/core/corehttp/gateway.go @@ -1,15 +1,12 @@ package corehttp import ( - "context" "fmt" "net" "net/http" - "sort" - coreiface "github.com/ipfs/interface-go-ipfs-core" + "github.com/ipfs/go-libipfs/gateway" options "github.com/ipfs/interface-go-ipfs-core/options" - path "github.com/ipfs/interface-go-ipfs-core/path" version "github.com/ipfs/kubo" core "github.com/ipfs/kubo/core" coreapi "github.com/ipfs/kubo/core/coreapi" @@ -17,47 +14,6 @@ import ( "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) -type GatewayConfig struct { - Headers map[string][]string - Writable bool - FastDirIndexThreshold int -} - -// NodeAPI defines the minimal set of API services required by a gateway handler -type NodeAPI interface { - // Unixfs returns an implementation of Unixfs API - Unixfs() coreiface.UnixfsAPI - - // Block returns an implementation of Block API - Block() coreiface.BlockAPI - - // Dag returns an implementation of Dag API - Dag() coreiface.APIDagService - - // ResolvePath resolves the path using Unixfs resolver - ResolvePath(context.Context, path.Path) (path.Resolved, error) -} - -// A helper function to clean up a set of headers: -// 1. Canonicalizes. -// 2. Deduplicates. -// 3. Sorts. -func cleanHeaderSet(headers []string) []string { - // Deduplicate and canonicalize. - m := make(map[string]struct{}, len(headers)) - for _, h := range headers { - m[http.CanonicalHeaderKey(h)] = struct{}{} - } - result := make([]string, 0, len(m)) - for k := range m { - result = append(result, k) - } - - // Sort - sort.Strings(result) - return result -} - func GatewayOption(writable bool, paths ...string) ServeOption { return func(n *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) { cfg, err := n.Repo.Config() @@ -75,17 +31,16 @@ func GatewayOption(writable bool, paths ...string) ServeOption { headers[http.CanonicalHeaderKey(h)] = v } - AddAccessControlHeaders(headers) + gateway.AddAccessControlHeaders(headers) offlineAPI, err := api.WithOptions(options.Api.Offline(true)) if err != nil { return nil, err } - gateway := NewGatewayHandler(GatewayConfig{ - Headers: headers, - Writable: writable, - FastDirIndexThreshold: int(cfg.Gateway.FastDirIndexThreshold.WithDefault(100)), + gateway := gateway.NewHandler(gateway.Config{ + Headers: headers, + Writable: writable, }, api, offlineAPI) gateway = otelhttp.NewHandler(gateway, "Gateway.Request") @@ -97,50 +52,6 @@ func GatewayOption(writable bool, paths ...string) ServeOption { } } -// AddAccessControlHeaders adds default headers used for controlling -// cross-origin requests. This function adds several values to the -// Access-Control-Allow-Headers and Access-Control-Expose-Headers entries. -// If the Access-Control-Allow-Origin entry is missing a value of '*' is -// added, indicating that browsers should allow requesting code from any -// origin to access the resource. -// If the Access-Control-Allow-Methods entry is missing a value of 'GET' is -// added, indicating that browsers may use the GET method when issuing cross -// origin requests. -func AddAccessControlHeaders(headers map[string][]string) { - // Hard-coded headers. - const ACAHeadersName = "Access-Control-Allow-Headers" - const ACEHeadersName = "Access-Control-Expose-Headers" - const ACAOriginName = "Access-Control-Allow-Origin" - const ACAMethodsName = "Access-Control-Allow-Methods" - - if _, ok := headers[ACAOriginName]; !ok { - // Default to *all* - headers[ACAOriginName] = []string{"*"} - } - if _, ok := headers[ACAMethodsName]; !ok { - // Default to GET - headers[ACAMethodsName] = []string{http.MethodGet} - } - - headers[ACAHeadersName] = cleanHeaderSet( - append([]string{ - "Content-Type", - "User-Agent", - "Range", - "X-Requested-With", - }, headers[ACAHeadersName]...)) - - headers[ACEHeadersName] = cleanHeaderSet( - append([]string{ - "Content-Length", - "Content-Range", - "X-Chunked-Output", - "X-Stream-Output", - "X-Ipfs-Path", - "X-Ipfs-Roots", - }, headers[ACEHeadersName]...)) -} - func VersionOption() ServeOption { return func(_ *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) { mux.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) { diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go deleted file mode 100644 index 1222b17bc..000000000 --- a/core/corehttp/gateway_handler.go +++ /dev/null @@ -1,1106 +0,0 @@ -package corehttp - -import ( - "context" - "fmt" - "html/template" - "io" - "mime" - "net/http" - "net/textproto" - "net/url" - "os" - gopath "path" - "regexp" - "runtime/debug" - "strings" - "time" - - cid "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" - mfs "github.com/ipfs/go-mfs" - path "github.com/ipfs/go-path" - "github.com/ipfs/go-path/resolver" - coreiface "github.com/ipfs/interface-go-ipfs-core" - ipath "github.com/ipfs/interface-go-ipfs-core/path" - routing "github.com/libp2p/go-libp2p/core/routing" - mc "github.com/multiformats/go-multicodec" - prometheus "github.com/prometheus/client_golang/prometheus" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" - "go.uber.org/zap" -) - -const ( - ipfsPathPrefix = "/ipfs/" - ipnsPathPrefix = "/ipns/" - immutableCacheControl = "public, max-age=29030400, immutable" -) - -var ( - onlyASCII = regexp.MustCompile("[[:^ascii:]]") - noModtime = time.Unix(0, 0) // disables Last-Modified header if passed as modtime -) - -// HTML-based redirect for errors which can be recovered from, but we want -// to provide hint to people that they should fix things on their end. -var redirectTemplate = template.Must(template.New("redirect").Parse(` - - - - - - - -
{{.ErrorMsg}}
(if a redirect does not happen in 10 seconds, use "{{.SuggestedPath}}" instead)
- -`)) - -type redirectTemplateData struct { - RedirectURL string - SuggestedPath string - ErrorMsg string -} - -// gatewayHandler is a HTTP handler that serves IPFS objects (accessible by default at /ipfs/) -// (it serves requests like GET /ipfs/QmVRzPKPzNtSrEzBFm2UZfxmPAgnaLke4DMcerbsGGSaFe/link) -type gatewayHandler struct { - config GatewayConfig - api NodeAPI - offlineAPI NodeAPI - - // generic metrics - firstContentBlockGetMetric *prometheus.HistogramVec - unixfsGetMetric *prometheus.SummaryVec // deprecated, use firstContentBlockGetMetric - - // response type metrics - unixfsFileGetMetric *prometheus.HistogramVec - unixfsGenDirGetMetric *prometheus.HistogramVec - carStreamGetMetric *prometheus.HistogramVec - rawBlockGetMetric *prometheus.HistogramVec -} - -// StatusResponseWriter enables us to override HTTP Status Code passed to -// WriteHeader function inside of http.ServeContent. Decision is based on -// presence of HTTP Headers such as Location. -type statusResponseWriter struct { - http.ResponseWriter -} - -// Custom type for collecting error details to be handled by `webRequestError` -type requestError struct { - Message string - StatusCode int - Err error -} - -func (r *requestError) Error() string { - return r.Err.Error() -} - -func newRequestError(message string, err error, statusCode int) *requestError { - return &requestError{ - Message: message, - Err: err, - StatusCode: statusCode, - } -} - -func (sw *statusResponseWriter) WriteHeader(code int) { - // Check if we need to adjust Status Code to account for scheduled redirect - // This enables us to return payload along with HTTP 301 - // for subdomain redirect in web browsers while also returning body for cli - // tools which do not follow redirects by default (curl, wget). - redirect := sw.ResponseWriter.Header().Get("Location") - if redirect != "" && code == http.StatusOK { - code = http.StatusMovedPermanently - log.Debugw("subdomain redirect", "location", redirect, "status", code) - } - sw.ResponseWriter.WriteHeader(code) -} - -// ServeContent replies to the request using the content in the provided ReadSeeker -// and returns the status code written and any error encountered during a write. -// It wraps http.ServeContent which takes care of If-None-Match+Etag, -// Content-Length and range requests. -func ServeContent(w http.ResponseWriter, req *http.Request, name string, modtime time.Time, content io.ReadSeeker) (int, bool, error) { - ew := &errRecordingResponseWriter{ResponseWriter: w} - http.ServeContent(ew, req, name, modtime, content) - - // When we calculate some metrics we want a flag that lets us to ignore - // errors and 304 Not Modified, and only care when requested data - // was sent in full. - dataSent := ew.code/100 == 2 && ew.err == nil - - return ew.code, dataSent, ew.err -} - -// errRecordingResponseWriter wraps a ResponseWriter to record the status code and any write error. -type errRecordingResponseWriter struct { - http.ResponseWriter - code int - err error -} - -func (w *errRecordingResponseWriter) WriteHeader(code int) { - if w.code == 0 { - w.code = code - } - w.ResponseWriter.WriteHeader(code) -} - -func (w *errRecordingResponseWriter) Write(p []byte) (int, error) { - n, err := w.ResponseWriter.Write(p) - if err != nil && w.err == nil { - w.err = err - } - return n, err -} - -// ReadFrom exposes errRecordingResponseWriter's underlying ResponseWriter to io.Copy -// to allow optimized methods to be taken advantage of. -func (w *errRecordingResponseWriter) ReadFrom(r io.Reader) (n int64, err error) { - n, err = io.Copy(w.ResponseWriter, r) - if err != nil && w.err == nil { - w.err = err - } - return n, err -} - -func newGatewaySummaryMetric(name string, help string) *prometheus.SummaryVec { - summaryMetric := prometheus.NewSummaryVec( - prometheus.SummaryOpts{ - Namespace: "ipfs", - Subsystem: "http", - Name: name, - Help: help, - }, - []string{"gateway"}, - ) - if err := prometheus.Register(summaryMetric); err != nil { - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - summaryMetric = are.ExistingCollector.(*prometheus.SummaryVec) - } else { - log.Errorf("failed to register ipfs_http_%s: %v", name, err) - } - } - return summaryMetric -} - -func newGatewayHistogramMetric(name string, help string) *prometheus.HistogramVec { - // We can add buckets as a parameter in the future, but for now using static defaults - // suggested in https://github.com/ipfs/kubo/issues/8441 - defaultBuckets := []float64{0.05, 0.1, 0.25, 0.5, 1, 2, 5, 10, 30, 60} - histogramMetric := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Namespace: "ipfs", - Subsystem: "http", - Name: name, - Help: help, - Buckets: defaultBuckets, - }, - []string{"gateway"}, - ) - if err := prometheus.Register(histogramMetric); err != nil { - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - histogramMetric = are.ExistingCollector.(*prometheus.HistogramVec) - } else { - log.Errorf("failed to register ipfs_http_%s: %v", name, err) - } - } - return histogramMetric -} - -// NewGatewayHandler returns an http.Handler that can act as a gateway to IPFS content -// offlineApi is a version of the API that should not make network requests for missing data -func NewGatewayHandler(c GatewayConfig, api NodeAPI, offlineAPI NodeAPI) http.Handler { - return newGatewayHandler(c, api, offlineAPI) -} - -func newGatewayHandler(c GatewayConfig, api NodeAPI, offlineAPI NodeAPI) *gatewayHandler { - i := &gatewayHandler{ - config: c, - api: api, - offlineAPI: offlineAPI, - // Improved Metrics - // ---------------------------- - // Time till the first content block (bar in /ipfs/cid/foo/bar) - // (format-agnostic, across all response types) - firstContentBlockGetMetric: newGatewayHistogramMetric( - "gw_first_content_block_get_latency_seconds", - "The time till the first content block is received on GET from the gateway.", - ), - - // Response-type specific metrics - // ---------------------------- - // UnixFS: time it takes to return a file - unixfsFileGetMetric: newGatewayHistogramMetric( - "gw_unixfs_file_get_duration_seconds", - "The time to serve an entire UnixFS file from the gateway.", - ), - // UnixFS: time it takes to generate static HTML with directory listing - unixfsGenDirGetMetric: newGatewayHistogramMetric( - "gw_unixfs_gen_dir_listing_get_duration_seconds", - "The time to serve a generated UnixFS HTML directory listing from the gateway.", - ), - // CAR: time it takes to return requested CAR stream - carStreamGetMetric: newGatewayHistogramMetric( - "gw_car_stream_get_duration_seconds", - "The time to GET an entire CAR stream from the gateway.", - ), - // Block: time it takes to return requested Block - rawBlockGetMetric: newGatewayHistogramMetric( - "gw_raw_block_get_duration_seconds", - "The time to GET an entire raw Block from the gateway.", - ), - - // Legacy Metrics - // ---------------------------- - unixfsGetMetric: newGatewaySummaryMetric( // TODO: remove? - // (deprecated, use firstContentBlockGetMetric instead) - "unixfs_get_latency_seconds", - "The time to receive the first UnixFS node on a GET from the gateway.", - ), - } - return i -} - -func parseIpfsPath(p string) (cid.Cid, string, error) { - rootPath, err := path.ParsePath(p) - if err != nil { - return cid.Cid{}, "", err - } - - // Check the path. - rsegs := rootPath.Segments() - if rsegs[0] != "ipfs" { - return cid.Cid{}, "", fmt.Errorf("WritableGateway: only ipfs paths supported") - } - - rootCid, err := cid.Decode(rsegs[1]) - if err != nil { - return cid.Cid{}, "", err - } - - return rootCid, path.Join(rsegs[2:]), nil -} - -func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - // the hour is a hard fallback, we don't expect it to happen, but just in case - ctx, cancel := context.WithTimeout(r.Context(), time.Hour) - defer cancel() - r = r.WithContext(ctx) - - defer func() { - if r := recover(); r != nil { - log.Error("A panic occurred in the gateway handler!") - log.Error(r) - debug.PrintStack() - } - }() - - if i.config.Writable { - switch r.Method { - case http.MethodPost: - i.postHandler(w, r) - return - case http.MethodPut: - i.putHandler(w, r) - return - case http.MethodDelete: - i.deleteHandler(w, r) - return - } - } - - switch r.Method { - case http.MethodGet, http.MethodHead: - i.getOrHeadHandler(w, r) - return - case http.MethodOptions: - i.optionsHandler(w, r) - return - } - - errmsg := "Method " + r.Method + " not allowed: " - var status int - if !i.config.Writable { - status = http.StatusMethodNotAllowed - errmsg = errmsg + "read only access" - w.Header().Add("Allow", http.MethodGet) - w.Header().Add("Allow", http.MethodHead) - w.Header().Add("Allow", http.MethodOptions) - } else { - status = http.StatusBadRequest - errmsg = errmsg + "bad request for " + r.URL.Path - } - http.Error(w, errmsg, status) -} - -func (i *gatewayHandler) optionsHandler(w http.ResponseWriter, r *http.Request) { - /* - OPTIONS is a noop request that is used by the browsers to check - if server accepts cross-site XMLHttpRequest (indicated by the presence of CORS headers) - https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests - */ - i.addUserHeaders(w) // return all custom headers (including CORS ones, if set) -} - -func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request) { - begin := time.Now() - - logger := log.With("from", r.RequestURI) - logger.Debug("http request received") - - if err := handleUnsupportedHeaders(r); err != nil { - webRequestError(w, err) - return - } - - if requestHandled := handleProtocolHandlerRedirect(w, r, logger); requestHandled { - return - } - - if err := handleServiceWorkerRegistration(r); err != nil { - webRequestError(w, err) - return - } - - contentPath := ipath.New(r.URL.Path) - - if requestHandled := i.handleOnlyIfCached(w, r, contentPath, logger); requestHandled { - return - } - - if requestHandled := handleSuperfluousNamespace(w, r, contentPath); requestHandled { - return - } - - // Detect when explicit Accept header or ?format parameter are present - responseFormat, formatParams, err := customResponseFormat(r) - if err != nil { - webError(w, "error while processing the Accept header", err, http.StatusBadRequest) - return - } - trace.SpanFromContext(r.Context()).SetAttributes(attribute.String("ResponseFormat", responseFormat)) - - resolvedPath, contentPath, ok := i.handlePathResolution(w, r, responseFormat, contentPath, logger) - if !ok { - return - } - trace.SpanFromContext(r.Context()).SetAttributes(attribute.String("ResolvedPath", resolvedPath.String())) - - // Detect when If-None-Match HTTP header allows returning HTTP 304 Not Modified - if inm := r.Header.Get("If-None-Match"); inm != "" { - pathCid := resolvedPath.Cid() - // need to check against both File and Dir Etag variants - // because this inexpensive check happens before we do any I/O - cidEtag := getEtag(r, pathCid) - dirEtag := getDirListingEtag(pathCid) - if etagMatch(inm, cidEtag, dirEtag) { - // Finish early if client already has a matching Etag - w.WriteHeader(http.StatusNotModified) - return - } - } - - if err := i.handleGettingFirstBlock(r, begin, contentPath, resolvedPath); err != nil { - webRequestError(w, err) - return - } - - if err := i.setCommonHeaders(w, r, contentPath); err != nil { - webRequestError(w, err) - return - } - - // Support custom response formats passed via ?format or Accept HTTP header - switch responseFormat { - case "": - switch resolvedPath.Cid().Prefix().Codec { - case uint64(mc.Json), uint64(mc.DagJson), uint64(mc.Cbor), uint64(mc.DagCbor): - logger.Debugw("serving codec", "path", contentPath) - i.serveCodec(r.Context(), w, r, resolvedPath, contentPath, begin, responseFormat) - default: - logger.Debugw("serving unixfs", "path", contentPath) - i.serveUnixFS(r.Context(), w, r, resolvedPath, contentPath, begin, logger) - } - return - case "application/vnd.ipld.raw": - logger.Debugw("serving raw block", "path", contentPath) - i.serveRawBlock(r.Context(), w, r, resolvedPath, contentPath, begin) - return - case "application/vnd.ipld.car": - logger.Debugw("serving car stream", "path", contentPath) - carVersion := formatParams["version"] - i.serveCAR(r.Context(), w, r, resolvedPath, contentPath, carVersion, begin) - return - case "application/x-tar": - logger.Debugw("serving tar file", "path", contentPath) - i.serveTAR(r.Context(), w, r, resolvedPath, contentPath, begin, logger) - return - case "application/json", "application/vnd.ipld.dag-json", - "application/cbor", "application/vnd.ipld.dag-cbor": - logger.Debugw("serving codec", "path", contentPath) - i.serveCodec(r.Context(), w, r, resolvedPath, contentPath, begin, responseFormat) - return - default: // catch-all for unsuported application/vnd.* - err := fmt.Errorf("unsupported format %q", responseFormat) - webError(w, "failed respond with requested content type", err, http.StatusBadRequest) - return - } -} - -func (i *gatewayHandler) postHandler(w http.ResponseWriter, r *http.Request) { - p, err := i.api.Unixfs().Add(r.Context(), files.NewReaderFile(r.Body)) - if err != nil { - internalWebError(w, err) - return - } - - i.addUserHeaders(w) // ok, _now_ write user's headers. - w.Header().Set("IPFS-Hash", p.Cid().String()) - log.Debugw("CID created, http redirect", "from", r.URL, "to", p, "status", http.StatusCreated) - http.Redirect(w, r, p.String(), http.StatusCreated) -} - -func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - ds := i.api.Dag() - - // Parse the path - rootCid, newPath, err := parseIpfsPath(r.URL.Path) - if err != nil { - webError(w, "WritableGateway: failed to parse the path", err, http.StatusBadRequest) - return - } - if newPath == "" || newPath == "/" { - http.Error(w, "WritableGateway: empty path", http.StatusBadRequest) - return - } - newDirectory, newFileName := gopath.Split(newPath) - - // Resolve the old root. - - rnode, err := ds.Get(ctx, rootCid) - if err != nil { - webError(w, "WritableGateway: Could not create DAG from request", err, http.StatusInternalServerError) - return - } - - pbnd, ok := rnode.(*dag.ProtoNode) - if !ok { - webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest) - return - } - - // Create the new file. - newFilePath, err := i.api.Unixfs().Add(ctx, files.NewReaderFile(r.Body)) - if err != nil { - webError(w, "WritableGateway: could not create DAG from request", err, http.StatusInternalServerError) - return - } - - newFile, err := ds.Get(ctx, newFilePath.Cid()) - if err != nil { - webError(w, "WritableGateway: failed to resolve new file", err, http.StatusInternalServerError) - return - } - - // Patch the new file into the old root. - - root, err := mfs.NewRoot(ctx, ds, pbnd, nil) - if err != nil { - webError(w, "WritableGateway: failed to create MFS root", err, http.StatusBadRequest) - return - } - - if newDirectory != "" { - err := mfs.Mkdir(root, newDirectory, mfs.MkdirOpts{Mkparents: true, Flush: false}) - if err != nil { - webError(w, "WritableGateway: failed to create MFS directory", err, http.StatusInternalServerError) - return - } - } - dirNode, err := mfs.Lookup(root, newDirectory) - if err != nil { - webError(w, "WritableGateway: failed to lookup directory", err, http.StatusInternalServerError) - return - } - dir, ok := dirNode.(*mfs.Directory) - if !ok { - http.Error(w, "WritableGateway: target directory is not a directory", http.StatusBadRequest) - return - } - err = dir.Unlink(newFileName) - switch err { - case os.ErrNotExist, nil: - default: - webError(w, "WritableGateway: failed to replace existing file", err, http.StatusBadRequest) - return - } - err = dir.AddChild(newFileName, newFile) - if err != nil { - webError(w, "WritableGateway: failed to link file into directory", err, http.StatusInternalServerError) - return - } - nnode, err := root.GetDirectory().GetNode() - if err != nil { - webError(w, "WritableGateway: failed to finalize", err, http.StatusInternalServerError) - return - } - newcid := nnode.Cid() - - i.addUserHeaders(w) // ok, _now_ write user's headers. - w.Header().Set("IPFS-Hash", newcid.String()) - - redirectURL := gopath.Join(ipfsPathPrefix, newcid.String(), newPath) - log.Debugw("CID replaced, redirect", "from", r.URL, "to", redirectURL, "status", http.StatusCreated) - http.Redirect(w, r, redirectURL, http.StatusCreated) -} - -func (i *gatewayHandler) deleteHandler(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - - // parse the path - - rootCid, newPath, err := parseIpfsPath(r.URL.Path) - if err != nil { - webError(w, "WritableGateway: failed to parse the path", err, http.StatusBadRequest) - return - } - if newPath == "" || newPath == "/" { - http.Error(w, "WritableGateway: empty path", http.StatusBadRequest) - return - } - directory, filename := gopath.Split(newPath) - - // lookup the root - - rootNodeIPLD, err := i.api.Dag().Get(ctx, rootCid) - if err != nil { - webError(w, "WritableGateway: failed to resolve root CID", err, http.StatusInternalServerError) - return - } - rootNode, ok := rootNodeIPLD.(*dag.ProtoNode) - if !ok { - http.Error(w, "WritableGateway: empty path", http.StatusInternalServerError) - return - } - - // construct the mfs root - - root, err := mfs.NewRoot(ctx, i.api.Dag(), rootNode, nil) - if err != nil { - webError(w, "WritableGateway: failed to construct the MFS root", err, http.StatusBadRequest) - return - } - - // lookup the parent directory - - parentNode, err := mfs.Lookup(root, directory) - if err != nil { - webError(w, "WritableGateway: failed to look up parent", err, http.StatusInternalServerError) - return - } - - parent, ok := parentNode.(*mfs.Directory) - if !ok { - http.Error(w, "WritableGateway: parent is not a directory", http.StatusInternalServerError) - return - } - - // delete the file - - switch parent.Unlink(filename) { - case nil, os.ErrNotExist: - default: - webError(w, "WritableGateway: failed to remove file", err, http.StatusInternalServerError) - return - } - - nnode, err := root.GetDirectory().GetNode() - if err != nil { - webError(w, "WritableGateway: failed to finalize", err, http.StatusInternalServerError) - return - } - ncid := nnode.Cid() - - i.addUserHeaders(w) // ok, _now_ write user's headers. - w.Header().Set("IPFS-Hash", ncid.String()) - - redirectURL := gopath.Join(ipfsPathPrefix+ncid.String(), directory) - // note: StatusCreated is technically correct here as we created a new resource. - log.Debugw("CID deleted, redirect", "from", r.RequestURI, "to", redirectURL, "status", http.StatusCreated) - http.Redirect(w, r, redirectURL, http.StatusCreated) -} - -func (i *gatewayHandler) addUserHeaders(w http.ResponseWriter) { - for k, v := range i.config.Headers { - w.Header()[k] = v - } -} - -func addCacheControlHeaders(w http.ResponseWriter, r *http.Request, contentPath ipath.Path, fileCid cid.Cid) (modtime time.Time) { - // Set Etag to based on CID (override whatever was set before) - w.Header().Set("Etag", getEtag(r, fileCid)) - - // Set Cache-Control and Last-Modified based on contentPath properties - if contentPath.Mutable() { - // mutable namespaces such as /ipns/ can't be cached forever - - /* For now we set Last-Modified to Now() to leverage caching heuristics built into modern browsers: - * https://github.com/ipfs/kubo/pull/8074#pullrequestreview-645196768 - * but we should not set it to fake values and use Cache-Control based on TTL instead */ - modtime = time.Now() - - // TODO: set Cache-Control based on TTL of IPNS/DNSLink: https://github.com/ipfs/kubo/issues/1818#issuecomment-1015849462 - // TODO: set Last-Modified based on /ipns/ publishing timestamp? - } else { - // immutable! CACHE ALL THE THINGS, FOREVER! wolololol - w.Header().Set("Cache-Control", immutableCacheControl) - - // Set modtime to 'zero time' to disable Last-Modified header (superseded by Cache-Control) - modtime = noModtime - - // TODO: set Last-Modified? - TBD - /ipfs/ modification metadata is present in unixfs 1.5 https://github.com/ipfs/kubo/issues/6920? - } - - return modtime -} - -// Set Content-Disposition if filename URL query param is present, return preferred filename -func addContentDispositionHeader(w http.ResponseWriter, r *http.Request, contentPath ipath.Path) string { - /* This logic enables: - * - creation of HTML links that trigger "Save As.." dialog instead of being rendered by the browser - * - overriding the filename used when saving subresource assets on HTML page - * - providing a default filename for HTTP clients when downloading direct /ipfs/CID without any subpath - */ - - // URL param ?filename=cat.jpg triggers Content-Disposition: [..] filename - // which impacts default name used in "Save As.." dialog - name := getFilename(contentPath) - urlFilename := r.URL.Query().Get("filename") - if urlFilename != "" { - disposition := "inline" - // URL param ?download=true triggers Content-Disposition: [..] attachment - // which skips rendering and forces "Save As.." dialog in browsers - if r.URL.Query().Get("download") == "true" { - disposition = "attachment" - } - setContentDispositionHeader(w, urlFilename, disposition) - name = urlFilename - } - return name -} - -// Set Content-Disposition to arbitrary filename and disposition -func setContentDispositionHeader(w http.ResponseWriter, filename string, disposition string) { - utf8Name := url.PathEscape(filename) - asciiName := url.PathEscape(onlyASCII.ReplaceAllLiteralString(filename, "_")) - w.Header().Set("Content-Disposition", fmt.Sprintf("%s; filename=\"%s\"; filename*=UTF-8''%s", disposition, asciiName, utf8Name)) -} - -// Set X-Ipfs-Roots with logical CID array for efficient HTTP cache invalidation. -func (i *gatewayHandler) buildIpfsRootsHeader(contentPath string, r *http.Request) (string, error) { - /* - These are logical roots where each CID represent one path segment - and resolves to either a directory or the root block of a file. - The main purpose of this header is allow HTTP caches to do smarter decisions - around cache invalidation (eg. keep specific subdirectory/file if it did not change) - - A good example is Wikipedia, which is HAMT-sharded, but we only care about - logical roots that represent each segment of the human-readable content - path: - - Given contentPath = /ipns/en.wikipedia-on-ipfs.org/wiki/Block_of_Wikipedia_in_Turkey - rootCidList is a generated by doing `ipfs resolve -r` on each sub path: - /ipns/en.wikipedia-on-ipfs.org → bafybeiaysi4s6lnjev27ln5icwm6tueaw2vdykrtjkwiphwekaywqhcjze - /ipns/en.wikipedia-on-ipfs.org/wiki/ → bafybeihn2f7lhumh4grizksi2fl233cyszqadkn424ptjajfenykpsaiw4 - /ipns/en.wikipedia-on-ipfs.org/wiki/Block_of_Wikipedia_in_Turkey → bafkreibn6euazfvoghepcm4efzqx5l3hieof2frhp254hio5y7n3hv5rma - - The result is an ordered array of values: - X-Ipfs-Roots: bafybeiaysi4s6lnjev27ln5icwm6tueaw2vdykrtjkwiphwekaywqhcjze,bafybeihn2f7lhumh4grizksi2fl233cyszqadkn424ptjajfenykpsaiw4,bafkreibn6euazfvoghepcm4efzqx5l3hieof2frhp254hio5y7n3hv5rma - - Note that while the top one will change every time any article is changed, - the last root (responsible for specific article) may not change at all. - */ - var sp strings.Builder - var pathRoots []string - pathSegments := strings.Split(contentPath[6:], "/") - sp.WriteString(contentPath[:5]) // /ipfs or /ipns - for _, root := range pathSegments { - if root == "" { - continue - } - sp.WriteString("/") - sp.WriteString(root) - resolvedSubPath, err := i.api.ResolvePath(r.Context(), ipath.New(sp.String())) - if err != nil { - return "", err - } - pathRoots = append(pathRoots, resolvedSubPath.Cid().String()) - } - rootCidList := strings.Join(pathRoots, ",") // convention from rfc2616#sec4.2 - return rootCidList, nil -} - -func webRequestError(w http.ResponseWriter, err *requestError) { - webError(w, err.Message, err.Err, err.StatusCode) -} - -func webError(w http.ResponseWriter, message string, err error, defaultCode int) { - if _, ok := err.(resolver.ErrNoLink); ok { - webErrorWithCode(w, message, err, http.StatusNotFound) - } else if err == routing.ErrNotFound { - webErrorWithCode(w, message, err, http.StatusNotFound) - } else if ipld.IsNotFound(err) { - webErrorWithCode(w, message, err, http.StatusNotFound) - } else if err == context.DeadlineExceeded { - webErrorWithCode(w, message, err, http.StatusRequestTimeout) - } else { - webErrorWithCode(w, message, err, defaultCode) - } -} - -func webErrorWithCode(w http.ResponseWriter, message string, err error, code int) { - http.Error(w, fmt.Sprintf("%s: %s", message, err), code) - if code >= 500 { - log.Warnf("server error: %s: %s", message, err) - } -} - -// return a 500 error and log -func internalWebError(w http.ResponseWriter, err error) { - webErrorWithCode(w, "internalWebError", err, http.StatusInternalServerError) -} - -func getFilename(contentPath ipath.Path) string { - s := contentPath.String() - if (strings.HasPrefix(s, ipfsPathPrefix) || strings.HasPrefix(s, ipnsPathPrefix)) && strings.Count(gopath.Clean(s), "/") <= 2 { - // Don't want to treat ipfs.io in /ipns/ipfs.io as a filename. - return "" - } - return gopath.Base(s) -} - -// etagMatch evaluates if we can respond with HTTP 304 Not Modified -// It supports multiple weak and strong etags passed in If-None-Matc stringh -// including the wildcard one. -func etagMatch(ifNoneMatchHeader string, cidEtag string, dirEtag string) bool { - buf := ifNoneMatchHeader - for { - buf = textproto.TrimString(buf) - if len(buf) == 0 { - break - } - if buf[0] == ',' { - buf = buf[1:] - continue - } - // If-None-Match: * should match against any etag - if buf[0] == '*' { - return true - } - etag, remain := scanETag(buf) - if etag == "" { - break - } - // Check for match both strong and weak etags - if etagWeakMatch(etag, cidEtag) || etagWeakMatch(etag, dirEtag) { - return true - } - buf = remain - } - return false -} - -// scanETag determines if a syntactically valid ETag is present at s. If so, -// the ETag and remaining text after consuming ETag is returned. Otherwise, -// it returns "", "". -// (This is the same logic as one executed inside of http.ServeContent) -func scanETag(s string) (etag string, remain string) { - s = textproto.TrimString(s) - start := 0 - if strings.HasPrefix(s, "W/") { - start = 2 - } - if len(s[start:]) < 2 || s[start] != '"' { - return "", "" - } - // ETag is either W/"text" or "text". - // See RFC 7232 2.3. - for i := start + 1; i < len(s); i++ { - c := s[i] - switch { - // Character values allowed in ETags. - case c == 0x21 || c >= 0x23 && c <= 0x7E || c >= 0x80: - case c == '"': - return s[:i+1], s[i+1:] - default: - return "", "" - } - } - return "", "" -} - -// etagWeakMatch reports whether a and b match using weak ETag comparison. -func etagWeakMatch(a, b string) bool { - return strings.TrimPrefix(a, "W/") == strings.TrimPrefix(b, "W/") -} - -// generate Etag value based on HTTP request and CID -func getEtag(r *http.Request, cid cid.Cid) string { - prefix := `"` - suffix := `"` - responseFormat, _, err := customResponseFormat(r) - if err == nil && responseFormat != "" { - // application/vnd.ipld.foo → foo - // application/x-bar → x-bar - shortFormat := responseFormat[strings.LastIndexAny(responseFormat, "/.")+1:] - // Etag: "cid.shortFmt" (gives us nice compression together with Content-Disposition in block (raw) and car responses) - suffix = `.` + shortFormat + suffix - } - // TODO: include selector suffix when https://github.com/ipfs/kubo/issues/8769 lands - return prefix + cid.String() + suffix -} - -// return explicit response format if specified in request as query parameter or via Accept HTTP header -func customResponseFormat(r *http.Request) (mediaType string, params map[string]string, err error) { - if formatParam := r.URL.Query().Get("format"); formatParam != "" { - // translate query param to a content type - switch formatParam { - case "raw": - return "application/vnd.ipld.raw", nil, nil - case "car": - return "application/vnd.ipld.car", nil, nil - case "tar": - return "application/x-tar", nil, nil - case "dag-json": - return "application/vnd.ipld.dag-json", nil, nil - case "json": - return "application/json", nil, nil - case "dag-cbor": - return "application/vnd.ipld.dag-cbor", nil, nil - case "cbor": - return "application/cbor", nil, nil - } - } - // Browsers and other user agents will send Accept header with generic types like: - // Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 - // We only care about explicit, vendor-specific content-types. - for _, accept := range r.Header.Values("Accept") { - // respond to the very first ipld content type - if strings.HasPrefix(accept, "application/vnd.ipld") || - strings.HasPrefix(accept, "application/x-tar") || - strings.HasPrefix(accept, "application/json") || - strings.HasPrefix(accept, "application/cbor") { - mediatype, params, err := mime.ParseMediaType(accept) - if err != nil { - return "", nil, err - } - return mediatype, params, nil - } - } - return "", nil, nil -} - -// returns unquoted path with all special characters revealed as \u codes -func debugStr(path string) string { - q := fmt.Sprintf("%+q", path) - if len(q) >= 3 { - q = q[1 : len(q)-1] - } - return q -} - -// Resolve the provided contentPath including any special handling related to -// the requested responseFormat. Returned ok flag indicates if gateway handler -// should continue processing the request. -func (i *gatewayHandler) handlePathResolution(w http.ResponseWriter, r *http.Request, responseFormat string, contentPath ipath.Path, logger *zap.SugaredLogger) (resolvedPath ipath.Resolved, newContentPath ipath.Path, ok bool) { - // Attempt to resolve the provided path. - resolvedPath, err := i.api.ResolvePath(r.Context(), contentPath) - - switch err { - case nil: - return resolvedPath, contentPath, true - case coreiface.ErrOffline: - webError(w, "ipfs resolve -r "+debugStr(contentPath.String()), err, http.StatusServiceUnavailable) - return nil, nil, false - default: - // The path can't be resolved. - if isUnixfsResponseFormat(responseFormat) { - // If we have origin isolation (subdomain gw, DNSLink website), - // and response type is UnixFS (default for website hosting) - // check for presence of _redirects file and apply rules defined there. - // See: https://github.com/ipfs/specs/pull/290 - if hasOriginIsolation(r) { - resolvedPath, newContentPath, ok, hadMatchingRule := i.serveRedirectsIfPresent(w, r, resolvedPath, contentPath, logger) - if hadMatchingRule { - logger.Debugw("applied a rule from _redirects file") - return resolvedPath, newContentPath, ok - } - } - - // if Accept is text/html, see if ipfs-404.html is present - // This logic isn't documented and will likely be removed at some point. - // Any 404 logic in _redirects above will have already run by this time, so it's really an extra fall back - if i.serveLegacy404IfPresent(w, r, contentPath) { - logger.Debugw("served legacy 404") - return nil, nil, false - } - } - - // Note: webError will replace http.StatusBadRequest with StatusNotFound if necessary - webError(w, "ipfs resolve -r "+debugStr(contentPath.String()), err, http.StatusBadRequest) - return nil, nil, false - } -} - -// Detect 'Cache-Control: only-if-cached' in request and return data if it is already in the local datastore. -// https://github.com/ipfs/specs/blob/main/http-gateways/PATH_GATEWAY.md#cache-control-request-header -func (i *gatewayHandler) handleOnlyIfCached(w http.ResponseWriter, r *http.Request, contentPath ipath.Path, logger *zap.SugaredLogger) (requestHandled bool) { - if r.Header.Get("Cache-Control") == "only-if-cached" { - _, err := i.offlineAPI.Block().Stat(r.Context(), contentPath) - if err != nil { - if r.Method == http.MethodHead { - w.WriteHeader(http.StatusPreconditionFailed) - return true - } - errMsg := fmt.Sprintf("%q not in local datastore", contentPath.String()) - http.Error(w, errMsg, http.StatusPreconditionFailed) - return true - } - if r.Method == http.MethodHead { - w.WriteHeader(http.StatusOK) - return true - } - } - return false -} - -func handleUnsupportedHeaders(r *http.Request) (err *requestError) { - // X-Ipfs-Gateway-Prefix was removed (https://github.com/ipfs/kubo/issues/7702) - // TODO: remove this after go-ipfs 0.13 ships - if prfx := r.Header.Get("X-Ipfs-Gateway-Prefix"); prfx != "" { - err := fmt.Errorf("X-Ipfs-Gateway-Prefix support was removed: https://github.com/ipfs/kubo/issues/7702") - return newRequestError("unsupported HTTP header", err, http.StatusBadRequest) - } - return nil -} - -// ?uri query param support for requests produced by web browsers -// via navigator.registerProtocolHandler Web API -// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/registerProtocolHandler -// TLDR: redirect /ipfs/?uri=ipfs%3A%2F%2Fcid%3Fquery%3Dval to /ipfs/cid?query=val -func handleProtocolHandlerRedirect(w http.ResponseWriter, r *http.Request, logger *zap.SugaredLogger) (requestHandled bool) { - if uriParam := r.URL.Query().Get("uri"); uriParam != "" { - u, err := url.Parse(uriParam) - if err != nil { - webError(w, "failed to parse uri query parameter", err, http.StatusBadRequest) - return true - } - if u.Scheme != "ipfs" && u.Scheme != "ipns" { - webError(w, "uri query parameter scheme must be ipfs or ipns", err, http.StatusBadRequest) - return true - } - path := u.Path - if u.RawQuery != "" { // preserve query if present - path = path + "?" + u.RawQuery - } - - redirectURL := gopath.Join("/", u.Scheme, u.Host, path) - logger.Debugw("uri param, redirect", "to", redirectURL, "status", http.StatusMovedPermanently) - http.Redirect(w, r, redirectURL, http.StatusMovedPermanently) - return true - } - - return false -} - -// Disallow Service Worker registration on namespace roots -// https://github.com/ipfs/kubo/issues/4025 -func handleServiceWorkerRegistration(r *http.Request) (err *requestError) { - if r.Header.Get("Service-Worker") == "script" { - matched, _ := regexp.MatchString(`^/ip[fn]s/[^/]+$`, r.URL.Path) - if matched { - err := fmt.Errorf("registration is not allowed for this scope") - return newRequestError("navigator.serviceWorker", err, http.StatusBadRequest) - } - } - - return nil -} - -// Attempt to fix redundant /ipfs/ namespace as long as resulting -// 'intended' path is valid. This is in case gremlins were tickled -// wrong way and user ended up at /ipfs/ipfs/{cid} or /ipfs/ipns/{id} -// like in bafybeien3m7mdn6imm425vc2s22erzyhbvk5n3ofzgikkhmdkh5cuqbpbq :^)) -func handleSuperfluousNamespace(w http.ResponseWriter, r *http.Request, contentPath ipath.Path) (requestHandled bool) { - // If the path is valid, there's nothing to do - if pathErr := contentPath.IsValid(); pathErr == nil { - return false - } - - // If there's no superflous namespace, there's nothing to do - if !(strings.HasPrefix(r.URL.Path, "/ipfs/ipfs/") || strings.HasPrefix(r.URL.Path, "/ipfs/ipns/")) { - return false - } - - // Attempt to fix the superflous namespace - intendedPath := ipath.New(strings.TrimPrefix(r.URL.Path, "/ipfs")) - if err := intendedPath.IsValid(); err != nil { - webError(w, "invalid ipfs path", err, http.StatusBadRequest) - return true - } - intendedURL := intendedPath.String() - if r.URL.RawQuery != "" { - // we render HTML, so ensure query entries are properly escaped - q, _ := url.ParseQuery(r.URL.RawQuery) - intendedURL = intendedURL + "?" + q.Encode() - } - // return HTTP 400 (Bad Request) with HTML error page that: - // - points at correct canonical path via header - // - displays human-readable error - // - redirects to intendedURL after a short delay - - w.WriteHeader(http.StatusBadRequest) - if err := redirectTemplate.Execute(w, redirectTemplateData{ - RedirectURL: intendedURL, - SuggestedPath: intendedPath.String(), - ErrorMsg: fmt.Sprintf("invalid path: %q should be %q", r.URL.Path, intendedPath.String()), - }); err != nil { - webError(w, "failed to redirect when fixing superfluous namespace", err, http.StatusBadRequest) - } - - return true -} - -func (i *gatewayHandler) handleGettingFirstBlock(r *http.Request, begin time.Time, contentPath ipath.Path, resolvedPath ipath.Resolved) *requestError { - // Update the global metric of the time it takes to read the final root block of the requested resource - // NOTE: for legacy reasons this happens before we go into content-type specific code paths - _, err := i.api.Block().Get(r.Context(), resolvedPath) - if err != nil { - return newRequestError("ipfs block get "+resolvedPath.Cid().String(), err, http.StatusInternalServerError) - } - ns := contentPath.Namespace() - timeToGetFirstContentBlock := time.Since(begin).Seconds() - i.unixfsGetMetric.WithLabelValues(ns).Observe(timeToGetFirstContentBlock) // deprecated, use firstContentBlockGetMetric instead - i.firstContentBlockGetMetric.WithLabelValues(ns).Observe(timeToGetFirstContentBlock) - return nil -} - -func (i *gatewayHandler) setCommonHeaders(w http.ResponseWriter, r *http.Request, contentPath ipath.Path) *requestError { - i.addUserHeaders(w) // ok, _now_ write user's headers. - w.Header().Set("X-Ipfs-Path", contentPath.String()) - - if rootCids, err := i.buildIpfsRootsHeader(contentPath.String(), r); err == nil { - w.Header().Set("X-Ipfs-Roots", rootCids) - } else { // this should never happen, as we resolved the contentPath already - return newRequestError("error while resolving X-Ipfs-Roots", err, http.StatusInternalServerError) - } - - return nil -} diff --git a/core/corehttp/gateway_handler_block.go b/core/corehttp/gateway_handler_block.go deleted file mode 100644 index 3bf7c76be..000000000 --- a/core/corehttp/gateway_handler_block.go +++ /dev/null @@ -1,55 +0,0 @@ -package corehttp - -import ( - "bytes" - "context" - "io" - "net/http" - "time" - - ipath "github.com/ipfs/interface-go-ipfs-core/path" - "github.com/ipfs/kubo/tracing" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -// serveRawBlock returns bytes behind a raw block -func (i *gatewayHandler) serveRawBlock(ctx context.Context, w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, begin time.Time) { - ctx, span := tracing.Span(ctx, "Gateway", "ServeRawBlock", trace.WithAttributes(attribute.String("path", resolvedPath.String()))) - defer span.End() - blockCid := resolvedPath.Cid() - blockReader, err := i.api.Block().Get(ctx, resolvedPath) - if err != nil { - webError(w, "ipfs block get "+blockCid.String(), err, http.StatusInternalServerError) - return - } - block, err := io.ReadAll(blockReader) - if err != nil { - webError(w, "ipfs block get "+blockCid.String(), err, http.StatusInternalServerError) - return - } - content := bytes.NewReader(block) - - // Set Content-Disposition - var name string - if urlFilename := r.URL.Query().Get("filename"); urlFilename != "" { - name = urlFilename - } else { - name = blockCid.String() + ".bin" - } - setContentDispositionHeader(w, name, "attachment") - - // Set remaining headers - modtime := addCacheControlHeaders(w, r, contentPath, blockCid) - w.Header().Set("Content-Type", "application/vnd.ipld.raw") - w.Header().Set("X-Content-Type-Options", "nosniff") // no funny business in the browsers :^) - - // ServeContent will take care of - // If-None-Match+Etag, Content-Length and range requests - _, dataSent, _ := ServeContent(w, r, name, modtime, content) - - if dataSent { - // Update metrics - i.rawBlockGetMetric.WithLabelValues(contentPath.Namespace()).Observe(time.Since(begin).Seconds()) - } -} diff --git a/core/corehttp/gateway_handler_car.go b/core/corehttp/gateway_handler_car.go deleted file mode 100644 index 3363c5199..000000000 --- a/core/corehttp/gateway_handler_car.go +++ /dev/null @@ -1,99 +0,0 @@ -package corehttp - -import ( - "context" - "fmt" - "net/http" - "time" - - blocks "github.com/ipfs/go-block-format" - cid "github.com/ipfs/go-cid" - coreiface "github.com/ipfs/interface-go-ipfs-core" - ipath "github.com/ipfs/interface-go-ipfs-core/path" - "github.com/ipfs/kubo/tracing" - gocar "github.com/ipld/go-car" - selectorparse "github.com/ipld/go-ipld-prime/traversal/selector/parse" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -// serveCAR returns a CAR stream for specific DAG+selector -func (i *gatewayHandler) serveCAR(ctx context.Context, w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, carVersion string, begin time.Time) { - ctx, span := tracing.Span(ctx, "Gateway", "ServeCAR", trace.WithAttributes(attribute.String("path", resolvedPath.String()))) - defer span.End() - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - switch carVersion { - case "": // noop, client does not care about version - case "1": // noop, we support this - default: - err := fmt.Errorf("only version=1 is supported") - webError(w, "unsupported CAR version", err, http.StatusBadRequest) - return - } - rootCid := resolvedPath.Cid() - - // Set Content-Disposition - var name string - if urlFilename := r.URL.Query().Get("filename"); urlFilename != "" { - name = urlFilename - } else { - name = rootCid.String() + ".car" - } - setContentDispositionHeader(w, name, "attachment") - - // Set Cache-Control (same logic as for a regular files) - addCacheControlHeaders(w, r, contentPath, rootCid) - - // Weak Etag W/ because we can't guarantee byte-for-byte identical - // responses, but still want to benefit from HTTP Caching. Two CAR - // responses for the same CID and selector will be logically equivalent, - // but when CAR is streamed, then in theory, blocks may arrive from - // datastore in non-deterministic order. - etag := `W/` + getEtag(r, rootCid) - w.Header().Set("Etag", etag) - - // Finish early if Etag match - if r.Header.Get("If-None-Match") == etag { - w.WriteHeader(http.StatusNotModified) - return - } - - // Make it clear we don't support range-requests over a car stream - // Partial downloads and resumes should be handled using requests for - // sub-DAGs and IPLD selectors: https://github.com/ipfs/go-ipfs/issues/8769 - w.Header().Set("Accept-Ranges", "none") - - w.Header().Set("Content-Type", "application/vnd.ipld.car; version=1") - w.Header().Set("X-Content-Type-Options", "nosniff") // no funny business in the browsers :^) - - // Same go-car settings as dag.export command - store := dagStore{dag: i.api.Dag(), ctx: ctx} - - // TODO: support selectors passed as request param: https://github.com/ipfs/kubo/issues/8769 - dag := gocar.Dag{Root: rootCid, Selector: selectorparse.CommonSelector_ExploreAllRecursively} - car := gocar.NewSelectiveCar(ctx, store, []gocar.Dag{dag}, gocar.TraverseLinksOnlyOnce()) - - if err := car.Write(w); err != nil { - // We return error as a trailer, however it is not something browsers can access - // (https://github.com/mdn/browser-compat-data/issues/14703) - // Due to this, we suggest client always verify that - // the received CAR stream response is matching requested DAG selector - w.Header().Set("X-Stream-Error", err.Error()) - return - } - - // Update metrics - i.carStreamGetMetric.WithLabelValues(contentPath.Namespace()).Observe(time.Since(begin).Seconds()) -} - -// FIXME(@Jorropo): https://github.com/ipld/go-car/issues/315 -type dagStore struct { - dag coreiface.APIDagService - ctx context.Context -} - -func (ds dagStore) Get(_ context.Context, c cid.Cid) (blocks.Block, error) { - return ds.dag.Get(ds.ctx, c) -} diff --git a/core/corehttp/gateway_handler_codec.go b/core/corehttp/gateway_handler_codec.go deleted file mode 100644 index 95a151c79..000000000 --- a/core/corehttp/gateway_handler_codec.go +++ /dev/null @@ -1,258 +0,0 @@ -package corehttp - -import ( - "bytes" - "context" - "fmt" - "html" - "io" - "net/http" - "strings" - "time" - - cid "github.com/ipfs/go-cid" - ipldlegacy "github.com/ipfs/go-ipld-legacy" - ipath "github.com/ipfs/interface-go-ipfs-core/path" - "github.com/ipfs/kubo/assets" - dih "github.com/ipfs/kubo/assets/dag-index-html" - "github.com/ipfs/kubo/tracing" - "github.com/ipld/go-ipld-prime" - "github.com/ipld/go-ipld-prime/multicodec" - mc "github.com/multiformats/go-multicodec" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -// codecToContentType maps the supported IPLD codecs to the HTTP Content -// Type they should have. -var codecToContentType = map[uint64]string{ - uint64(mc.Json): "application/json", - uint64(mc.Cbor): "application/cbor", - uint64(mc.DagJson): "application/vnd.ipld.dag-json", - uint64(mc.DagCbor): "application/vnd.ipld.dag-cbor", -} - -// contentTypeToCodecs maps the HTTP Content Type to the respective -// possible codecs. If the original data is in one of those codecs, -// we stream the raw bytes. Otherwise, we encode in the last codec -// of the list. -var contentTypeToCodecs = map[string][]uint64{ - "application/json": {uint64(mc.Json), uint64(mc.DagJson)}, - "application/vnd.ipld.dag-json": {uint64(mc.DagJson)}, - "application/cbor": {uint64(mc.Cbor), uint64(mc.DagCbor)}, - "application/vnd.ipld.dag-cbor": {uint64(mc.DagCbor)}, -} - -// contentTypeToExtension maps the HTTP Content Type to the respective file -// extension, used in Content-Disposition header when downloading the file. -var contentTypeToExtension = map[string]string{ - "application/json": ".json", - "application/vnd.ipld.dag-json": ".json", - "application/cbor": ".cbor", - "application/vnd.ipld.dag-cbor": ".cbor", -} - -func (i *gatewayHandler) serveCodec(ctx context.Context, w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, begin time.Time, requestedContentType string) { - ctx, span := tracing.Span(ctx, "Gateway", "ServeCodec", trace.WithAttributes(attribute.String("path", resolvedPath.String()), attribute.String("requestedContentType", requestedContentType))) - defer span.End() - - cidCodec := resolvedPath.Cid().Prefix().Codec - responseContentType := requestedContentType - - // If the resolved path still has some remainder, return error for now. - // TODO: handle this when we have IPLD Patch (https://ipld.io/specs/patch/) via HTTP PUT - // TODO: (depends on https://github.com/ipfs/kubo/issues/4801 and https://github.com/ipfs/kubo/issues/4782) - if resolvedPath.Remainder() != "" { - path := strings.TrimSuffix(resolvedPath.String(), resolvedPath.Remainder()) - err := fmt.Errorf("%q of %q could not be returned: reading IPLD Kinds other than Links (CBOR Tag 42) is not implemented: try reading %q instead", resolvedPath.Remainder(), resolvedPath.String(), path) - webError(w, "unsupported pathing", err, http.StatusNotImplemented) - return - } - - // If no explicit content type was requested, the response will have one based on the codec from the CID - if requestedContentType == "" { - cidContentType, ok := codecToContentType[cidCodec] - if !ok { - // Should not happen unless function is called with wrong parameters. - err := fmt.Errorf("content type not found for codec: %v", cidCodec) - webError(w, "internal error", err, http.StatusInternalServerError) - return - } - responseContentType = cidContentType - } - - // Set HTTP headers (for caching etc) - modtime := addCacheControlHeaders(w, r, contentPath, resolvedPath.Cid()) - name := setCodecContentDisposition(w, r, resolvedPath, responseContentType) - w.Header().Set("Content-Type", responseContentType) - w.Header().Set("X-Content-Type-Options", "nosniff") - - // No content type is specified by the user (via Accept, or format=). However, - // we support this format. Let's handle it. - if requestedContentType == "" { - isDAG := cidCodec == uint64(mc.DagJson) || cidCodec == uint64(mc.DagCbor) - acceptsHTML := strings.Contains(r.Header.Get("Accept"), "text/html") - download := r.URL.Query().Get("download") == "true" - - if isDAG && acceptsHTML && !download { - i.serveCodecHTML(ctx, w, r, resolvedPath, contentPath) - } else { - i.serveCodecRaw(ctx, w, r, resolvedPath, contentPath, name, modtime) - } - - return - } - - // Otherwise, the user has requested a specific content type. Let's first get - // the codecs that can be used with this content type. - codecs, ok := contentTypeToCodecs[requestedContentType] - if !ok { - // This is never supposed to happen unless function is called with wrong parameters. - err := fmt.Errorf("unsupported content type: %s", requestedContentType) - webError(w, err.Error(), err, http.StatusInternalServerError) - return - } - - // If we need to convert, use the last codec (strict dag- variant) - toCodec := codecs[len(codecs)-1] - - // If the requested content type has "dag-", ALWAYS go through the encoding - // process in order to validate the content. - if strings.Contains(requestedContentType, "dag-") { - i.serveCodecConverted(ctx, w, r, resolvedPath, contentPath, toCodec, modtime) - return - } - - // Otherwise, check if the data is encoded with the requested content type. - // If so, we can directly stream the raw data. serveRawBlock cannot be directly - // used here as it sets different headers. - for _, codec := range codecs { - if resolvedPath.Cid().Prefix().Codec == codec { - i.serveCodecRaw(ctx, w, r, resolvedPath, contentPath, name, modtime) - return - } - } - - // Finally, if nothing of the above is true, we have to actually convert the codec. - i.serveCodecConverted(ctx, w, r, resolvedPath, contentPath, toCodec, modtime) -} - -func (i *gatewayHandler) serveCodecHTML(ctx context.Context, w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path) { - // A HTML directory index will be presented, be sure to set the correct - // type instead of relying on autodetection (which may fail). - w.Header().Set("Content-Type", "text/html") - - // Clear Content-Disposition -- we want HTML to be rendered inline - w.Header().Del("Content-Disposition") - - // Generated index requires custom Etag (output may change between Kubo versions) - dagEtag := getDagIndexEtag(resolvedPath.Cid()) - w.Header().Set("Etag", dagEtag) - - // Remove Cache-Control for now to match UnixFS dir-index-html responses - // (we don't want browser to cache HTML forever) - // TODO: if we ever change behavior for UnixFS dir listings, same changes should be applied here - w.Header().Del("Cache-Control") - - cidCodec := mc.Code(resolvedPath.Cid().Prefix().Codec) - if err := dih.DagIndexTemplate.Execute(w, dih.DagIndexTemplateData{ - Path: contentPath.String(), - CID: resolvedPath.Cid().String(), - CodecName: cidCodec.String(), - CodecHex: fmt.Sprintf("0x%x", uint64(cidCodec)), - }); err != nil { - webError(w, "failed to generate HTML listing for this DAG: try fetching raw block with ?format=raw", err, http.StatusInternalServerError) - } -} - -func (i *gatewayHandler) serveCodecRaw(ctx context.Context, w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, name string, modtime time.Time) { - blockCid := resolvedPath.Cid() - blockReader, err := i.api.Block().Get(ctx, resolvedPath) - if err != nil { - webError(w, "ipfs block get "+blockCid.String(), err, http.StatusInternalServerError) - return - } - block, err := io.ReadAll(blockReader) - if err != nil { - webError(w, "ipfs block get "+blockCid.String(), err, http.StatusInternalServerError) - return - } - content := bytes.NewReader(block) - - // ServeContent will take care of - // If-None-Match+Etag, Content-Length and range requests - _, _, _ = ServeContent(w, r, name, modtime, content) -} - -func (i *gatewayHandler) serveCodecConverted(ctx context.Context, w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, toCodec uint64, modtime time.Time) { - obj, err := i.api.Dag().Get(ctx, resolvedPath.Cid()) - if err != nil { - webError(w, "ipfs dag get "+html.EscapeString(resolvedPath.String()), err, http.StatusInternalServerError) - return - } - - universal, ok := obj.(ipldlegacy.UniversalNode) - if !ok { - err = fmt.Errorf("%T is not a valid IPLD node", obj) - webError(w, err.Error(), err, http.StatusInternalServerError) - return - } - finalNode := universal.(ipld.Node) - - encoder, err := multicodec.LookupEncoder(toCodec) - if err != nil { - webError(w, err.Error(), err, http.StatusInternalServerError) - return - } - - // Ensure IPLD node conforms to the codec specification. - var buf bytes.Buffer - err = encoder(finalNode, &buf) - if err != nil { - webError(w, err.Error(), err, http.StatusInternalServerError) - return - } - - // Sets correct Last-Modified header. This code is borrowed from the standard - // library (net/http/server.go) as we cannot use serveFile. - if !(modtime.IsZero() || modtime.Equal(unixEpochTime)) { - w.Header().Set("Last-Modified", modtime.UTC().Format(http.TimeFormat)) - } - - _, _ = w.Write(buf.Bytes()) -} - -func setCodecContentDisposition(w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentType string) string { - var dispType, name string - - ext, ok := contentTypeToExtension[contentType] - if !ok { - // Should never happen. - ext = ".bin" - } - - if urlFilename := r.URL.Query().Get("filename"); urlFilename != "" { - name = urlFilename - } else { - name = resolvedPath.Cid().String() + ext - } - - // JSON should be inlined, but ?download=true should still override - if r.URL.Query().Get("download") == "true" { - dispType = "attachment" - } else { - switch ext { - case ".json": // codecs that serialize to JSON can be rendered by browsers - dispType = "inline" - default: // everything else is assumed binary / opaque bytes - dispType = "attachment" - } - } - - setContentDispositionHeader(w, name, dispType) - return name -} - -func getDagIndexEtag(dagCid cid.Cid) string { - return `"DagIndex-` + assets.AssetHash + `_CID-` + dagCid.String() + `"` -} diff --git a/core/corehttp/gateway_handler_tar.go b/core/corehttp/gateway_handler_tar.go deleted file mode 100644 index 532d88757..000000000 --- a/core/corehttp/gateway_handler_tar.go +++ /dev/null @@ -1,92 +0,0 @@ -package corehttp - -import ( - "context" - "html" - "net/http" - "time" - - files "github.com/ipfs/go-ipfs-files" - ipath "github.com/ipfs/interface-go-ipfs-core/path" - "github.com/ipfs/kubo/tracing" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" - "go.uber.org/zap" -) - -var unixEpochTime = time.Unix(0, 0) - -func (i *gatewayHandler) serveTAR(ctx context.Context, w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, begin time.Time, logger *zap.SugaredLogger) { - ctx, span := tracing.Span(ctx, "Gateway", "ServeTAR", trace.WithAttributes(attribute.String("path", resolvedPath.String()))) - defer span.End() - - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - // Get Unixfs file - file, err := i.api.Unixfs().Get(ctx, resolvedPath) - if err != nil { - webError(w, "ipfs cat "+html.EscapeString(contentPath.String()), err, http.StatusBadRequest) - return - } - defer file.Close() - - rootCid := resolvedPath.Cid() - - // Set Cache-Control and read optional Last-Modified time - modtime := addCacheControlHeaders(w, r, contentPath, rootCid) - - // Weak Etag W/ because we can't guarantee byte-for-byte identical - // responses, but still want to benefit from HTTP Caching. Two TAR - // responses for the same CID will be logically equivalent, - // but when TAR is streamed, then in theory, files and directories - // may arrive in different order (depends on TAR lib and filesystem/inodes). - etag := `W/` + getEtag(r, rootCid) - w.Header().Set("Etag", etag) - - // Finish early if Etag match - if r.Header.Get("If-None-Match") == etag { - w.WriteHeader(http.StatusNotModified) - return - } - - // Set Content-Disposition - var name string - if urlFilename := r.URL.Query().Get("filename"); urlFilename != "" { - name = urlFilename - } else { - name = rootCid.String() + ".tar" - } - setContentDispositionHeader(w, name, "attachment") - - // Construct the TAR writer - tarw, err := files.NewTarWriter(w) - if err != nil { - webError(w, "could not build tar writer", err, http.StatusInternalServerError) - return - } - defer tarw.Close() - - // Sets correct Last-Modified header. This code is borrowed from the standard - // library (net/http/server.go) as we cannot use serveFile without throwing the entire - // TAR into the memory first. - if !(modtime.IsZero() || modtime.Equal(unixEpochTime)) { - w.Header().Set("Last-Modified", modtime.UTC().Format(http.TimeFormat)) - } - - w.Header().Set("Content-Type", "application/x-tar") - w.Header().Set("X-Content-Type-Options", "nosniff") // no funny business in the browsers :^) - - // The TAR has a top-level directory (or file) named by the CID. - if err := tarw.WriteFile(file, rootCid.String()); err != nil { - w.Header().Set("X-Stream-Error", err.Error()) - // Trailer headers do not work in web browsers - // (see https://github.com/mdn/browser-compat-data/issues/14703) - // and we have limited options around error handling in browser contexts. - // To improve UX/DX, we finish response stream with error message, allowing client to - // (1) detect error by having corrupted TAR - // (2) be able to reason what went wrong by instecting the tail of TAR stream - _, _ = w.Write([]byte(err.Error())) - return - } -} diff --git a/core/corehttp/gateway_handler_unixfs.go b/core/corehttp/gateway_handler_unixfs.go deleted file mode 100644 index 75d51d93a..000000000 --- a/core/corehttp/gateway_handler_unixfs.go +++ /dev/null @@ -1,46 +0,0 @@ -package corehttp - -import ( - "context" - "fmt" - "html" - "net/http" - "time" - - files "github.com/ipfs/go-ipfs-files" - ipath "github.com/ipfs/interface-go-ipfs-core/path" - "github.com/ipfs/kubo/tracing" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" - "go.uber.org/zap" -) - -func (i *gatewayHandler) serveUnixFS(ctx context.Context, w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, begin time.Time, logger *zap.SugaredLogger) { - ctx, span := tracing.Span(ctx, "Gateway", "ServeUnixFS", trace.WithAttributes(attribute.String("path", resolvedPath.String()))) - defer span.End() - - // Handling UnixFS - dr, err := i.api.Unixfs().Get(ctx, resolvedPath) - if err != nil { - webError(w, "ipfs cat "+html.EscapeString(contentPath.String()), err, http.StatusBadRequest) - return - } - defer dr.Close() - - // Handling Unixfs file - if f, ok := dr.(files.File); ok { - logger.Debugw("serving unixfs file", "path", contentPath) - i.serveFile(ctx, w, r, resolvedPath, contentPath, f, begin) - return - } - - // Handling Unixfs directory - dir, ok := dr.(files.Directory) - if !ok { - internalWebError(w, fmt.Errorf("unsupported UnixFS type")) - return - } - - logger.Debugw("serving unixfs directory", "path", contentPath) - i.serveDirectory(ctx, w, r, resolvedPath, contentPath, dir, begin, logger) -} diff --git a/core/corehttp/gateway_handler_unixfs__redirects.go b/core/corehttp/gateway_handler_unixfs__redirects.go deleted file mode 100644 index 81cf05731..000000000 --- a/core/corehttp/gateway_handler_unixfs__redirects.go +++ /dev/null @@ -1,287 +0,0 @@ -package corehttp - -import ( - "fmt" - "io" - "net/http" - gopath "path" - "strconv" - "strings" - - files "github.com/ipfs/go-ipfs-files" - redirects "github.com/ipfs/go-ipfs-redirects-file" - ipath "github.com/ipfs/interface-go-ipfs-core/path" - "go.uber.org/zap" -) - -// Resolving a UnixFS path involves determining if the provided `path.Path` exists and returning the `path.Resolved` -// corresponding to that path. For UnixFS, path resolution is more involved. -// -// When a path under requested CID does not exist, Gateway will check if a `_redirects` file exists -// underneath the root CID of the path, and apply rules defined there. -// See sepcification introduced in: https://github.com/ipfs/specs/pull/290 -// -// Scenario 1: -// If a path exists, we always return the `path.Resolved` corresponding to that path, regardless of the existence of a `_redirects` file. -// -// Scenario 2: -// If a path does not exist, usually we should return a `nil` resolution path and an error indicating that the path -// doesn't exist. However, a `_redirects` file may exist and contain a redirect rule that redirects that path to a different path. -// We need to evaluate the rule and perform the redirect if present. -// -// Scenario 3: -// Another possibility is that the path corresponds to a rewrite rule (i.e. a rule with a status of 200). -// In this case, we don't perform a redirect, but do need to return a `path.Resolved` and `path.Path` corresponding to -// the rewrite destination path. -// -// Note that for security reasons, redirect rules are only processed when the request has origin isolation. -// See https://github.com/ipfs/specs/pull/290 for more information. -func (i *gatewayHandler) serveRedirectsIfPresent(w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, logger *zap.SugaredLogger) (newResolvedPath ipath.Resolved, newContentPath ipath.Path, continueProcessing bool, hadMatchingRule bool) { - redirectsFile := i.getRedirectsFile(r, contentPath, logger) - if redirectsFile != nil { - redirectRules, err := i.getRedirectRules(r, redirectsFile) - if err != nil { - internalWebError(w, err) - return nil, nil, false, true - } - - redirected, newPath, err := i.handleRedirectsFileRules(w, r, contentPath, redirectRules) - if err != nil { - err = fmt.Errorf("trouble processing _redirects file at %q: %w", redirectsFile.String(), err) - internalWebError(w, err) - return nil, nil, false, true - } - - if redirected { - return nil, nil, false, true - } - - // 200 is treated as a rewrite, so update the path and continue - if newPath != "" { - // Reassign contentPath and resolvedPath since the URL was rewritten - contentPath = ipath.New(newPath) - resolvedPath, err = i.api.ResolvePath(r.Context(), contentPath) - if err != nil { - internalWebError(w, err) - return nil, nil, false, true - } - - return resolvedPath, contentPath, true, true - } - } - // No matching rule, paths remain the same, continue regular processing - return resolvedPath, contentPath, true, false -} - -func (i *gatewayHandler) handleRedirectsFileRules(w http.ResponseWriter, r *http.Request, contentPath ipath.Path, redirectRules []redirects.Rule) (redirected bool, newContentPath string, err error) { - // Attempt to match a rule to the URL path, and perform the corresponding redirect or rewrite - pathParts := strings.Split(contentPath.String(), "/") - if len(pathParts) > 3 { - // All paths should start with /ipfs/cid/, so get the path after that - urlPath := "/" + strings.Join(pathParts[3:], "/") - rootPath := strings.Join(pathParts[:3], "/") - // Trim off the trailing / - urlPath = strings.TrimSuffix(urlPath, "/") - - for _, rule := range redirectRules { - // Error right away if the rule is invalid - if !rule.MatchAndExpandPlaceholders(urlPath) { - continue - } - - // We have a match! - - // Rewrite - if rule.Status == 200 { - // Prepend the rootPath - toPath := rootPath + rule.To - return false, toPath, nil - } - - // Or 4xx - if rule.Status == 404 || rule.Status == 410 || rule.Status == 451 { - toPath := rootPath + rule.To - content4xxPath := ipath.New(toPath) - err := i.serve4xx(w, r, content4xxPath, rule.Status) - return true, toPath, err - } - - // Or redirect - if rule.Status >= 301 && rule.Status <= 308 { - http.Redirect(w, r, rule.To, rule.Status) - return true, "", nil - } - } - } - - // No redirects matched - return false, "", nil -} - -func (i *gatewayHandler) getRedirectRules(r *http.Request, redirectsFilePath ipath.Resolved) ([]redirects.Rule, error) { - // Convert the path into a file node - node, err := i.api.Unixfs().Get(r.Context(), redirectsFilePath) - if err != nil { - return nil, fmt.Errorf("could not get _redirects: %w", err) - } - defer node.Close() - - // Convert the node into a file - f, ok := node.(files.File) - if !ok { - return nil, fmt.Errorf("could not parse _redirects: %w", err) - } - - // Parse redirect rules from file - redirectRules, err := redirects.Parse(f) - if err != nil { - return nil, fmt.Errorf("could not parse _redirects: %w", err) - } - - return redirectRules, nil -} - -// Returns a resolved path to the _redirects file located in the root CID path of the requested path -func (i *gatewayHandler) getRedirectsFile(r *http.Request, contentPath ipath.Path, logger *zap.SugaredLogger) ipath.Resolved { - // contentPath is the full ipfs path to the requested resource, - // regardless of whether path or subdomain resolution is used. - rootPath := getRootPath(contentPath) - - // Check for _redirects file. - // Any path resolution failures are ignored and we just assume there's no _redirects file. - // Note that ignoring these errors also ensures that the use of the empty CID (bafkqaaa) in tests doesn't fail. - path := ipath.Join(rootPath, "_redirects") - resolvedPath, err := i.api.ResolvePath(r.Context(), path) - if err != nil { - return nil - } - return resolvedPath -} - -// Returns the root CID Path for the given path -func getRootPath(path ipath.Path) ipath.Path { - parts := strings.Split(path.String(), "/") - return ipath.New(gopath.Join("/", path.Namespace(), parts[2])) -} - -func (i *gatewayHandler) serve4xx(w http.ResponseWriter, r *http.Request, content4xxPath ipath.Path, status int) error { - resolved4xxPath, err := i.api.ResolvePath(r.Context(), content4xxPath) - if err != nil { - return err - } - - node, err := i.api.Unixfs().Get(r.Context(), resolved4xxPath) - if err != nil { - return err - } - defer node.Close() - - f, ok := node.(files.File) - if !ok { - return fmt.Errorf("could not convert node for %d page to file", status) - } - - size, err := f.Size() - if err != nil { - return fmt.Errorf("could not get size of %d page", status) - } - - log.Debugf("using _redirects: custom %d file at %q", status, content4xxPath) - w.Header().Set("Content-Type", "text/html") - w.Header().Set("Content-Length", strconv.FormatInt(size, 10)) - addCacheControlHeaders(w, r, content4xxPath, resolved4xxPath.Cid()) - w.WriteHeader(status) - _, err = io.CopyN(w, f, size) - return err -} - -func hasOriginIsolation(r *http.Request) bool { - _, gw := r.Context().Value(requestContextKey("gw-hostname")).(string) - _, dnslink := r.Context().Value("dnslink-hostname").(string) - - if gw || dnslink { - return true - } - - return false -} - -func isUnixfsResponseFormat(responseFormat string) bool { - // The implicit response format is UnixFS - return responseFormat == "" -} - -// Deprecated: legacy ipfs-404.html files are superseded by _redirects file -// This is provided only for backward-compatibility, until websites migrate -// to 404s managed via _redirects file (https://github.com/ipfs/specs/pull/290) -func (i *gatewayHandler) serveLegacy404IfPresent(w http.ResponseWriter, r *http.Request, contentPath ipath.Path) bool { - resolved404Path, ctype, err := i.searchUpTreeFor404(r, contentPath) - if err != nil { - return false - } - - dr, err := i.api.Unixfs().Get(r.Context(), resolved404Path) - if err != nil { - return false - } - defer dr.Close() - - f, ok := dr.(files.File) - if !ok { - return false - } - - size, err := f.Size() - if err != nil { - return false - } - - log.Debugw("using pretty 404 file", "path", contentPath) - w.Header().Set("Content-Type", ctype) - w.Header().Set("Content-Length", strconv.FormatInt(size, 10)) - w.WriteHeader(http.StatusNotFound) - _, err = io.CopyN(w, f, size) - return err == nil -} - -func (i *gatewayHandler) searchUpTreeFor404(r *http.Request, contentPath ipath.Path) (ipath.Resolved, string, error) { - filename404, ctype, err := preferred404Filename(r.Header.Values("Accept")) - if err != nil { - return nil, "", err - } - - pathComponents := strings.Split(contentPath.String(), "/") - - for idx := len(pathComponents); idx >= 3; idx-- { - pretty404 := gopath.Join(append(pathComponents[0:idx], filename404)...) - parsed404Path := ipath.New("/" + pretty404) - if parsed404Path.IsValid() != nil { - break - } - resolvedPath, err := i.api.ResolvePath(r.Context(), parsed404Path) - if err != nil { - continue - } - return resolvedPath, ctype, nil - } - - return nil, "", fmt.Errorf("no pretty 404 in any parent folder") -} - -func preferred404Filename(acceptHeaders []string) (string, string, error) { - // If we ever want to offer a 404 file for a different content type - // then this function will need to parse q weightings, but for now - // the presence of anything matching HTML is enough. - for _, acceptHeader := range acceptHeaders { - accepted := strings.Split(acceptHeader, ",") - for _, spec := range accepted { - contentType := strings.SplitN(spec, ";", 1)[0] - switch contentType { - case "*/*", "text/*", "text/html": - return "ipfs-404.html", "text/html", nil - } - } - } - - return "", "", fmt.Errorf("there is no 404 file for the requested content types") -} diff --git a/core/corehttp/gateway_handler_unixfs_dir.go b/core/corehttp/gateway_handler_unixfs_dir.go deleted file mode 100644 index 1c803b13b..000000000 --- a/core/corehttp/gateway_handler_unixfs_dir.go +++ /dev/null @@ -1,222 +0,0 @@ -package corehttp - -import ( - "context" - "net/http" - "net/url" - gopath "path" - "strings" - "time" - - "github.com/dustin/go-humanize" - cid "github.com/ipfs/go-cid" - files "github.com/ipfs/go-ipfs-files" - path "github.com/ipfs/go-path" - "github.com/ipfs/go-path/resolver" - options "github.com/ipfs/interface-go-ipfs-core/options" - ipath "github.com/ipfs/interface-go-ipfs-core/path" - "github.com/ipfs/kubo/assets" - "github.com/ipfs/kubo/tracing" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" - "go.uber.org/zap" -) - -// serveDirectory returns the best representation of UnixFS directory -// -// It will return index.html if present, or generate directory listing otherwise. -func (i *gatewayHandler) serveDirectory(ctx context.Context, w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, dir files.Directory, begin time.Time, logger *zap.SugaredLogger) { - ctx, span := tracing.Span(ctx, "Gateway", "ServeDirectory", trace.WithAttributes(attribute.String("path", resolvedPath.String()))) - defer span.End() - - // HostnameOption might have constructed an IPNS/IPFS path using the Host header. - // In this case, we need the original path for constructing redirects - // and links that match the requested URL. - // For example, http://example.net would become /ipns/example.net, and - // the redirects and links would end up as http://example.net/ipns/example.net - requestURI, err := url.ParseRequestURI(r.RequestURI) - if err != nil { - webError(w, "failed to parse request path", err, http.StatusInternalServerError) - return - } - originalURLPath := requestURI.Path - - // Ensure directory paths end with '/' - if originalURLPath[len(originalURLPath)-1] != '/' { - // don't redirect to trailing slash if it's go get - // https://github.com/ipfs/kubo/pull/3963 - goget := r.URL.Query().Get("go-get") == "1" - if !goget { - suffix := "/" - // preserve query parameters - if r.URL.RawQuery != "" { - suffix = suffix + "?" + r.URL.RawQuery - } - // /ipfs/cid/foo?bar must be redirected to /ipfs/cid/foo/?bar - redirectURL := originalURLPath + suffix - logger.Debugw("directory location moved permanently", "status", http.StatusMovedPermanently) - http.Redirect(w, r, redirectURL, http.StatusMovedPermanently) - return - } - } - - // Check if directory has index.html, if so, serveFile - idxPath := ipath.Join(contentPath, "index.html") - idx, err := i.api.Unixfs().Get(ctx, idxPath) - switch err.(type) { - case nil: - f, ok := idx.(files.File) - if !ok { - internalWebError(w, files.ErrNotReader) - return - } - - logger.Debugw("serving index.html file", "path", idxPath) - // write to request - i.serveFile(ctx, w, r, resolvedPath, idxPath, f, begin) - return - case resolver.ErrNoLink: - logger.Debugw("no index.html; noop", "path", idxPath) - default: - internalWebError(w, err) - return - } - - // See statusResponseWriter.WriteHeader - // and https://github.com/ipfs/kubo/issues/7164 - // Note: this needs to occur before listingTemplate.Execute otherwise we get - // superfluous response.WriteHeader call from prometheus/client_golang - if w.Header().Get("Location") != "" { - logger.Debugw("location moved permanently", "status", http.StatusMovedPermanently) - w.WriteHeader(http.StatusMovedPermanently) - return - } - - // A HTML directory index will be presented, be sure to set the correct - // type instead of relying on autodetection (which may fail). - w.Header().Set("Content-Type", "text/html") - - // Generated dir index requires custom Etag (output may change between go-ipfs versions) - dirEtag := getDirListingEtag(resolvedPath.Cid()) - w.Header().Set("Etag", dirEtag) - - if r.Method == http.MethodHead { - logger.Debug("return as request's HTTP method is HEAD") - return - } - - // Optimization 1: - // List children without fetching their root blocks (fast, but no size info) - results, err := i.api.Unixfs().Ls(ctx, resolvedPath, options.Unixfs.ResolveChildren(false)) - if err != nil { - internalWebError(w, err) - return - } - - // storage for directory listing - dirListing := make([]directoryItem, 0, len(results)) - - for link := range results { - if link.Err != nil { - internalWebError(w, err) - return - } - hash := link.Cid.String() - di := directoryItem{ - Size: "", // no size because we did not fetch child nodes - Name: link.Name, - Path: gopath.Join(originalURLPath, link.Name), - Hash: hash, - ShortHash: shortHash(hash), - } - dirListing = append(dirListing, di) - } - - // Optimization 2: fetch sizes only for dirs below FastDirIndexThreshold - if len(dirListing) < i.config.FastDirIndexThreshold { - dirit := dir.Entries() - linkNo := 0 - for dirit.Next() { - size := "?" - if s, err := dirit.Node().Size(); err == nil { - // Size may not be defined/supported. Continue anyways. - size = humanize.Bytes(uint64(s)) - } - dirListing[linkNo].Size = size - linkNo++ - } - } - - // construct the correct back link - // https://github.com/ipfs/kubo/issues/1365 - backLink := originalURLPath - - // don't go further up than /ipfs/$hash/ - pathSplit := path.SplitList(contentPath.String()) - switch { - // skip backlink when listing a content root - case len(pathSplit) == 3: // url: /ipfs/$hash - backLink = "" - - // skip backlink when listing a content root - case len(pathSplit) == 4 && pathSplit[3] == "": // url: /ipfs/$hash/ - backLink = "" - - // add the correct link depending on whether the path ends with a slash - default: - if strings.HasSuffix(backLink, "/") { - backLink += ".." - } else { - backLink += "/.." - } - } - - size := "?" - if s, err := dir.Size(); err == nil { - // Size may not be defined/supported. Continue anyways. - size = humanize.Bytes(uint64(s)) - } - - hash := resolvedPath.Cid().String() - - // Gateway root URL to be used when linking to other rootIDs. - // This will be blank unless subdomain or DNSLink resolution is being used - // for this request. - var gwURL string - - // Get gateway hostname and build gateway URL. - if h, ok := r.Context().Value(requestContextKey("gw-hostname")).(string); ok { - gwURL = "//" + h - } else { - gwURL = "" - } - - dnslink := hasDNSLinkOrigin(gwURL, contentPath.String()) - - // See comment above where originalUrlPath is declared. - tplData := listingTemplateData{ - GatewayURL: gwURL, - DNSLink: dnslink, - Listing: dirListing, - Size: size, - Path: contentPath.String(), - Breadcrumbs: breadcrumbs(contentPath.String(), dnslink), - BackLink: backLink, - Hash: hash, - FastDirIndexThreshold: i.config.FastDirIndexThreshold, - } - - logger.Debugw("request processed", "tplDataDNSLink", dnslink, "tplDataSize", size, "tplDataBackLink", backLink, "tplDataHash", hash) - - if err := listingTemplate.Execute(w, tplData); err != nil { - internalWebError(w, err) - return - } - - // Update metrics - i.unixfsGenDirGetMetric.WithLabelValues(contentPath.Namespace()).Observe(time.Since(begin).Seconds()) -} - -func getDirListingEtag(dirCid cid.Cid) string { - return `"DirIndex-` + assets.AssetHash + `_CID-` + dirCid.String() + `"` -} diff --git a/core/corehttp/gateway_handler_unixfs_file.go b/core/corehttp/gateway_handler_unixfs_file.go deleted file mode 100644 index 9463be1ac..000000000 --- a/core/corehttp/gateway_handler_unixfs_file.go +++ /dev/null @@ -1,104 +0,0 @@ -package corehttp - -import ( - "context" - "fmt" - "io" - "mime" - "net/http" - gopath "path" - "strings" - "time" - - "github.com/gabriel-vasile/mimetype" - files "github.com/ipfs/go-ipfs-files" - ipath "github.com/ipfs/interface-go-ipfs-core/path" - "github.com/ipfs/kubo/tracing" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -// serveFile returns data behind a file along with HTTP headers based on -// the file itself, its CID and the contentPath used for accessing it. -func (i *gatewayHandler) serveFile(ctx context.Context, w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, file files.File, begin time.Time) { - _, span := tracing.Span(ctx, "Gateway", "ServeFile", trace.WithAttributes(attribute.String("path", resolvedPath.String()))) - defer span.End() - - // Set Cache-Control and read optional Last-Modified time - modtime := addCacheControlHeaders(w, r, contentPath, resolvedPath.Cid()) - - // Set Content-Disposition - name := addContentDispositionHeader(w, r, contentPath) - - // Prepare size value for Content-Length HTTP header (set inside of http.ServeContent) - size, err := file.Size() - if err != nil { - http.Error(w, "cannot serve files with unknown sizes", http.StatusBadGateway) - return - } - - if size == 0 { - // We override null files to 200 to avoid issues with fragment caching reverse proxies. - // Also whatever you are asking for, it's cheaper to just give you the complete file (nothing). - // TODO: remove this if clause once https://github.com/golang/go/issues/54794 is fixed in two latest releases of go - w.Header().Set("Content-Type", "text/plain") - w.WriteHeader(http.StatusOK) - return - } - - // Lazy seeker enables efficient range-requests and HTTP HEAD responses - content := &lazySeeker{ - size: size, - reader: file, - } - - // Calculate deterministic value for Content-Type HTTP header - // (we prefer to do it here, rather than using implicit sniffing in http.ServeContent) - var ctype string - if _, isSymlink := file.(*files.Symlink); isSymlink { - // We should be smarter about resolving symlinks but this is the - // "most correct" we can be without doing that. - ctype = "inode/symlink" - } else { - ctype = mime.TypeByExtension(gopath.Ext(name)) - if ctype == "" { - // uses https://github.com/gabriel-vasile/mimetype library to determine the content type. - // Fixes https://github.com/ipfs/kubo/issues/7252 - mimeType, err := mimetype.DetectReader(content) - if err != nil { - http.Error(w, fmt.Sprintf("cannot detect content-type: %s", err.Error()), http.StatusInternalServerError) - return - } - - ctype = mimeType.String() - _, err = content.Seek(0, io.SeekStart) - if err != nil { - http.Error(w, "seeker can't seek", http.StatusInternalServerError) - return - } - } - // Strip the encoding from the HTML Content-Type header and let the - // browser figure it out. - // - // Fixes https://github.com/ipfs/kubo/issues/2203 - if strings.HasPrefix(ctype, "text/html;") { - ctype = "text/html" - } - } - // Setting explicit Content-Type to avoid mime-type sniffing on the client - // (unifies behavior across gateways and web browsers) - w.Header().Set("Content-Type", ctype) - - // special fixup around redirects - w = &statusResponseWriter{w} - - // ServeContent will take care of - // If-None-Match+Etag, Content-Length and range requests - _, dataSent, _ := ServeContent(w, r, name, modtime, content) - - // Was response successful? - if dataSent { - // Update metrics - i.unixfsFileGetMetric.WithLabelValues(contentPath.Namespace()).Observe(time.Since(begin).Seconds()) - } -} diff --git a/core/corehttp/gateway_indexPage.go b/core/corehttp/gateway_indexPage.go deleted file mode 100644 index 19e444da3..000000000 --- a/core/corehttp/gateway_indexPage.go +++ /dev/null @@ -1,134 +0,0 @@ -package corehttp - -import ( - "html/template" - "net/url" - "path" - "strings" - - ipfspath "github.com/ipfs/go-path" - "github.com/ipfs/kubo/assets" -) - -// structs for directory listing -type listingTemplateData struct { - GatewayURL string - DNSLink bool - Listing []directoryItem - Size string - Path string - Breadcrumbs []breadcrumb - BackLink string - Hash string - FastDirIndexThreshold int -} - -type directoryItem struct { - Size string - Name string - Path string - Hash string - ShortHash string -} - -type breadcrumb struct { - Name string - Path string -} - -func breadcrumbs(urlPath string, dnslinkOrigin bool) []breadcrumb { - var ret []breadcrumb - - p, err := ipfspath.ParsePath(urlPath) - if err != nil { - // No breadcrumbs, fallback to bare Path in template - return ret - } - segs := p.Segments() - contentRoot := segs[1] - for i, seg := range segs { - if i == 0 { - ret = append(ret, breadcrumb{Name: seg}) - } else { - ret = append(ret, breadcrumb{ - Name: seg, - Path: "/" + strings.Join(segs[0:i+1], "/"), - }) - } - } - - // Drop the /ipns/ prefix from breadcrumb Paths when directory - // listing on a DNSLink website (loaded due to Host header in HTTP - // request). Necessary because the hostname most likely won't have a - // public gateway mounted. - if dnslinkOrigin { - prefix := "/ipns/" + contentRoot - for i, crumb := range ret { - if strings.HasPrefix(crumb.Path, prefix) { - ret[i].Path = strings.Replace(crumb.Path, prefix, "", 1) - } - } - // Make contentRoot breadcrumb link to the website root - ret[1].Path = "/" - } - - return ret -} - -func shortHash(hash string) string { - if len(hash) <= 8 { - return hash - } - return (hash[0:4] + "\u2026" + hash[len(hash)-4:]) -} - -// helper to detect DNSLink website context -// (when hostname from gwURL is matching /ipns/ in path) -func hasDNSLinkOrigin(gwURL string, path string) bool { - if gwURL != "" { - fqdn := stripPort(strings.TrimPrefix(gwURL, "//")) - return strings.HasPrefix(path, "/ipns/"+fqdn) - } - return false -} - -var listingTemplate *template.Template - -func init() { - knownIconsBytes, err := assets.Asset.ReadFile("dir-index-html/knownIcons.txt") - if err != nil { - panic(err) - } - knownIcons := make(map[string]struct{}) - for _, ext := range strings.Split(strings.TrimSuffix(string(knownIconsBytes), "\n"), "\n") { - knownIcons[ext] = struct{}{} - } - - // helper to guess the type/icon for it by the extension name - iconFromExt := func(name string) string { - ext := path.Ext(name) - _, ok := knownIcons[ext] - if !ok { - // default blank icon - return "ipfs-_blank" - } - return "ipfs-" + ext[1:] // slice of the first dot - } - - // custom template-escaping function to escape a full path, including '#' and '?' - urlEscape := func(rawUrl string) string { - pathURL := url.URL{Path: rawUrl} - return pathURL.String() - } - - // Directory listing template - dirIndexBytes, err := assets.Asset.ReadFile("dir-index-html/dir-index.html") - if err != nil { - panic(err) - } - - listingTemplate = template.Must(template.New("dir").Funcs(template.FuncMap{ - "iconFromExt": iconFromExt, - "urlEscape": urlEscape, - }).Parse(string(dirIndexBytes))) -} diff --git a/core/corehttp/gateway_test.go b/core/corehttp/gateway_test.go index 0d2f07dbe..49fa519fb 100644 --- a/core/corehttp/gateway_test.go +++ b/core/corehttp/gateway_test.go @@ -9,7 +9,6 @@ import ( "regexp" "strings" "testing" - "time" namesys "github.com/ipfs/go-namesys" version "github.com/ipfs/kubo" @@ -19,7 +18,7 @@ import ( datastore "github.com/ipfs/go-datastore" syncds "github.com/ipfs/go-datastore/sync" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" path "github.com/ipfs/go-path" iface "github.com/ipfs/interface-go-ipfs-core" nsopts "github.com/ipfs/interface-go-ipfs-core/options/namesys" @@ -68,11 +67,7 @@ func (m mockNamesys) ResolveAsync(ctx context.Context, name string, opts ...nsop return out } -func (m mockNamesys) Publish(ctx context.Context, name ci.PrivKey, value path.Path) error { - return errors.New("not implemented for mockNamesys") -} - -func (m mockNamesys) PublishWithEOL(ctx context.Context, name ci.PrivKey, value path.Path, _ time.Time) error { +func (m mockNamesys) Publish(ctx context.Context, name ci.PrivKey, value path.Path, opts ...nsopts.PublishOption) error { return errors.New("not implemented for mockNamesys") } @@ -656,28 +651,3 @@ func TestVersion(t *testing.T) { t.Fatalf("response doesn't contain protocol version:\n%s", s) } } - -func TestEtagMatch(t *testing.T) { - for _, test := range []struct { - header string // value in If-None-Match HTTP header - cidEtag string - dirEtag string - expected bool // expected result of etagMatch(header, cidEtag, dirEtag) - }{ - {"", `"etag"`, "", false}, // no If-None-Match - {"", "", `"etag"`, false}, // no If-None-Match - {`"etag"`, `"etag"`, "", true}, // file etag match - {`W/"etag"`, `"etag"`, "", true}, // file etag match - {`"foo", W/"bar", W/"etag"`, `"etag"`, "", true}, // file etag match (array) - {`"foo",W/"bar",W/"etag"`, `"etag"`, "", true}, // file etag match (compact array) - {`"etag"`, "", `W/"etag"`, true}, // dir etag match - {`"etag"`, "", `W/"etag"`, true}, // dir etag match - {`W/"etag"`, "", `W/"etag"`, true}, // dir etag match - {`*`, `"etag"`, "", true}, // wildcard etag match - } { - result := etagMatch(test.header, test.cidEtag, test.dirEtag) - if result != test.expected { - t.Fatalf("unexpected result of etagMatch(%q, %q, %q), got %t, expected %t", test.header, test.cidEtag, test.dirEtag, result, test.expected) - } - } -} diff --git a/core/corehttp/hostname.go b/core/corehttp/hostname.go index 39e857aad..adc47ab4d 100644 --- a/core/corehttp/hostname.go +++ b/core/corehttp/hostname.go @@ -10,6 +10,7 @@ import ( "strings" cid "github.com/ipfs/go-cid" + "github.com/ipfs/go-libipfs/gateway" namesys "github.com/ipfs/go-namesys" core "github.com/ipfs/kubo/core" coreapi "github.com/ipfs/kubo/core/coreapi" @@ -225,7 +226,7 @@ func HostnameOption() ServeOption { if !cfg.Gateway.NoDNSLink && isDNSLinkName(r.Context(), coreAPI, host) { // rewrite path and handle as DNSLink r.URL.Path = "/ipns/" + stripPort(host) + r.URL.Path - ctx := context.WithValue(r.Context(), requestContextKey("dnslink-hostname"), host) + ctx := context.WithValue(r.Context(), gateway.DNSLinkHostnameKey, host) childMux.ServeHTTP(w, withHostnameContext(r.WithContext(ctx), host)) return } @@ -247,8 +248,6 @@ type wildcardHost struct { spec *config.GatewaySpec } -type requestContextKey string - // Extends request context to include hostname of a canonical gateway root // (subdomain root or dnslink fqdn) func withHostnameContext(r *http.Request, hostname string) *http.Request { @@ -257,7 +256,7 @@ func withHostnameContext(r *http.Request, hostname string) *http.Request { // Host header, subdomain gateways have more comples rules (knownSubdomainDetails) // More: https://github.com/ipfs/dir-index-html/issues/42 // nolint: staticcheck // non-backward compatible change - ctx := context.WithValue(r.Context(), requestContextKey("gw-hostname"), hostname) + ctx := context.WithValue(r.Context(), gateway.GatewayHostnameKey, hostname) return r.WithContext(ctx) } diff --git a/core/corehttp/hostname_test.go b/core/corehttp/hostname_test.go index 6f0713528..b4a8b8d16 100644 --- a/core/corehttp/hostname_test.go +++ b/core/corehttp/hostname_test.go @@ -7,7 +7,7 @@ import ( "testing" cid "github.com/ipfs/go-cid" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" path "github.com/ipfs/go-path" config "github.com/ipfs/kubo/config" coreapi "github.com/ipfs/kubo/core/coreapi" diff --git a/core/corehttp/lazyseek.go b/core/corehttp/lazyseek.go deleted file mode 100644 index 2a379dc91..000000000 --- a/core/corehttp/lazyseek.go +++ /dev/null @@ -1,60 +0,0 @@ -package corehttp - -import ( - "fmt" - "io" -) - -// The HTTP server uses seek to determine the file size. Actually _seeking_ can -// be slow so we wrap the seeker in a _lazy_ seeker. -type lazySeeker struct { - reader io.ReadSeeker - - size int64 - offset int64 - realOffset int64 -} - -func (s *lazySeeker) Seek(offset int64, whence int) (int64, error) { - switch whence { - case io.SeekEnd: - return s.Seek(s.size+offset, io.SeekStart) - case io.SeekCurrent: - return s.Seek(s.offset+offset, io.SeekStart) - case io.SeekStart: - if offset < 0 { - return s.offset, fmt.Errorf("invalid seek offset") - } - s.offset = offset - return s.offset, nil - default: - return s.offset, fmt.Errorf("invalid whence: %d", whence) - } -} - -func (s *lazySeeker) Read(b []byte) (int, error) { - // If we're past the end, EOF. - if s.offset >= s.size { - return 0, io.EOF - } - - // actually seek - for s.offset != s.realOffset { - off, err := s.reader.Seek(s.offset, io.SeekStart) - if err != nil { - return 0, err - } - s.realOffset = off - } - off, err := s.reader.Read(b) - s.realOffset += int64(off) - s.offset += int64(off) - return off, err -} - -func (s *lazySeeker) Close() error { - if closer, ok := s.reader.(io.Closer); ok { - return closer.Close() - } - return nil -} diff --git a/core/corehttp/lazyseek_test.go b/core/corehttp/lazyseek_test.go deleted file mode 100644 index 49aca0a0e..000000000 --- a/core/corehttp/lazyseek_test.go +++ /dev/null @@ -1,136 +0,0 @@ -package corehttp - -import ( - "fmt" - "io" - "strings" - "testing" -) - -type badSeeker struct { - io.ReadSeeker -} - -var errBadSeek = fmt.Errorf("bad seeker") - -func (bs badSeeker) Seek(offset int64, whence int) (int64, error) { - off, err := bs.ReadSeeker.Seek(0, io.SeekCurrent) - if err != nil { - panic(err) - } - return off, errBadSeek -} - -func TestLazySeekerError(t *testing.T) { - underlyingBuffer := strings.NewReader("fubar") - s := &lazySeeker{ - reader: badSeeker{underlyingBuffer}, - size: underlyingBuffer.Size(), - } - off, err := s.Seek(0, io.SeekEnd) - if err != nil { - t.Fatal(err) - } - if off != s.size { - t.Fatal("expected to seek to the end") - } - - // shouldn't have actually seeked. - b, err := io.ReadAll(s) - if err != nil { - t.Fatal(err) - } - if len(b) != 0 { - t.Fatal("expected to read nothing") - } - - // shouldn't need to actually seek. - off, err = s.Seek(0, io.SeekStart) - if err != nil { - t.Fatal(err) - } - if off != 0 { - t.Fatal("expected to seek to the start") - } - b, err = io.ReadAll(s) - if err != nil { - t.Fatal(err) - } - if string(b) != "fubar" { - t.Fatal("expected to read string") - } - - // should fail the second time. - off, err = s.Seek(0, io.SeekStart) - if err != nil { - t.Fatal(err) - } - if off != 0 { - t.Fatal("expected to seek to the start") - } - // right here... - b, err = io.ReadAll(s) - if err == nil { - t.Fatalf("expected an error, got output %s", string(b)) - } - if err != errBadSeek { - t.Fatalf("expected a bad seek error, got %s", err) - } - if len(b) != 0 { - t.Fatalf("expected to read nothing") - } -} - -func TestLazySeeker(t *testing.T) { - underlyingBuffer := strings.NewReader("fubar") - s := &lazySeeker{ - reader: underlyingBuffer, - size: underlyingBuffer.Size(), - } - expectByte := func(b byte) { - t.Helper() - var buf [1]byte - n, err := io.ReadFull(s, buf[:]) - if err != nil { - t.Fatal(err) - } - if n != 1 { - t.Fatalf("expected to read one byte, read %d", n) - } - if buf[0] != b { - t.Fatalf("expected %b, got %b", b, buf[0]) - } - } - expectSeek := func(whence int, off, expOff int64, expErr string) { - t.Helper() - n, err := s.Seek(off, whence) - if expErr == "" { - if err != nil { - t.Fatal("unexpected seek error: ", err) - } - } else { - if err == nil || err.Error() != expErr { - t.Fatalf("expected %s, got %s", err, expErr) - } - } - if n != expOff { - t.Fatalf("expected offset %d, got, %d", expOff, n) - } - } - - expectSeek(io.SeekEnd, 0, s.size, "") - b, err := io.ReadAll(s) - if err != nil { - t.Fatal(err) - } - if len(b) != 0 { - t.Fatal("expected to read nothing") - } - expectSeek(io.SeekEnd, -1, s.size-1, "") - expectByte('r') - expectSeek(io.SeekStart, 0, 0, "") - expectByte('f') - expectSeek(io.SeekCurrent, 1, 2, "") - expectByte('b') - expectSeek(io.SeekCurrent, -100, 3, "invalid seek offset") -} diff --git a/core/corehttp/webui.go b/core/corehttp/webui.go index c196c0eef..f7b27c939 100644 --- a/core/corehttp/webui.go +++ b/core/corehttp/webui.go @@ -1,11 +1,13 @@ package corehttp // TODO: move to IPNS -const WebUIPath = "/ipfs/bafybeibjbq3tmmy7wuihhhwvbladjsd3gx3kfjepxzkq6wylik6wc3whzy" // v2.20.0 +const WebUIPath = "/ipfs/bafybeifeqt7mvxaniphyu2i3qhovjaf3sayooxbh5enfdqtiehxjv2ldte" // v2.22.0 // WebUIPaths is a list of all past webUI paths. var WebUIPaths = []string{ WebUIPath, + "/ipfs/bafybeiequgo72mrvuml56j4gk7crewig5bavumrrzhkqbim6b3s2yqi7ty", + "/ipfs/bafybeibjbq3tmmy7wuihhhwvbladjsd3gx3kfjepxzkq6wylik6wc3whzy", "/ipfs/bafybeiavrvt53fks6u32n5p2morgblcmck4bh4ymf4rrwu7ah5zsykmqqa", "/ipfs/bafybeiageaoxg6d7npaof6eyzqbwvbubyler7bq44hayik2hvqcggg7d2y", "/ipfs/bafybeidb5eryh72zajiokdggzo7yct2d6hhcflncji5im2y5w26uuygdsm", diff --git a/core/coreunix/add.go b/core/coreunix/add.go index 16ccbaefa..f895baf73 100644 --- a/core/coreunix/add.go +++ b/core/coreunix/add.go @@ -11,10 +11,10 @@ import ( "github.com/ipfs/go-cid" bstore "github.com/ipfs/go-ipfs-blockstore" chunker "github.com/ipfs/go-ipfs-chunker" - files "github.com/ipfs/go-ipfs-files" pin "github.com/ipfs/go-ipfs-pinner" posinfo "github.com/ipfs/go-ipfs-posinfo" ipld "github.com/ipfs/go-ipld-format" + "github.com/ipfs/go-libipfs/files" logging "github.com/ipfs/go-log" dag "github.com/ipfs/go-merkledag" "github.com/ipfs/go-mfs" diff --git a/core/coreunix/add_test.go b/core/coreunix/add_test.go index 6d5d941f7..e64d41001 100644 --- a/core/coreunix/add_test.go +++ b/core/coreunix/add_test.go @@ -14,14 +14,14 @@ import ( "github.com/ipfs/kubo/gc" "github.com/ipfs/kubo/repo" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" syncds "github.com/ipfs/go-datastore/sync" blockstore "github.com/ipfs/go-ipfs-blockstore" - files "github.com/ipfs/go-ipfs-files" pi "github.com/ipfs/go-ipfs-posinfo" + blocks "github.com/ipfs/go-libipfs/blocks" + "github.com/ipfs/go-libipfs/files" dag "github.com/ipfs/go-merkledag" coreiface "github.com/ipfs/interface-go-ipfs-core" config "github.com/ipfs/kubo/config" diff --git a/core/node/bitswap.go b/core/node/bitswap.go index 42b948f75..f78703039 100644 --- a/core/node/bitswap.go +++ b/core/node/bitswap.go @@ -4,10 +4,10 @@ import ( "context" "time" - "github.com/ipfs/go-bitswap" - "github.com/ipfs/go-bitswap/network" blockstore "github.com/ipfs/go-ipfs-blockstore" exchange "github.com/ipfs/go-ipfs-exchange-interface" + "github.com/ipfs/go-libipfs/bitswap" + "github.com/ipfs/go-libipfs/bitswap/network" "github.com/ipfs/kubo/config" irouting "github.com/ipfs/kubo/routing" "github.com/libp2p/go-libp2p/core/host" diff --git a/core/node/groups.go b/core/node/groups.go index 7bc4e894c..e640feff1 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -11,6 +11,7 @@ import ( "github.com/ipfs/go-log" "github.com/ipfs/kubo/config" pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/libp2p/go-libp2p-pubsub/timecache" "github.com/libp2p/go-libp2p/core/peer" "github.com/ipfs/kubo/core/node/libp2p" @@ -66,6 +67,18 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config) fx.Option { pubsub.WithSeenMessagesTTL(cfg.Pubsub.SeenMessagesTTL.WithDefault(pubsub.TimeCacheDuration)), ) + var seenMessagesStrategy timecache.Strategy + configSeenMessagesStrategy := cfg.Pubsub.SeenMessagesStrategy.WithDefault(config.DefaultSeenMessagesStrategy) + switch configSeenMessagesStrategy { + case config.LastSeenMessagesStrategy: + seenMessagesStrategy = timecache.Strategy_LastSeen + case config.FirstSeenMessagesStrategy: + seenMessagesStrategy = timecache.Strategy_FirstSeen + default: + return fx.Error(fmt.Errorf("unsupported Pubsub.SeenMessagesStrategy %q", configSeenMessagesStrategy)) + } + pubsubOptions = append(pubsubOptions, pubsub.WithSeenMessagesStrategy(seenMessagesStrategy)) + switch cfg.Pubsub.Router { case "": fallthrough @@ -291,7 +304,12 @@ func Online(bcfg *BuildCfg, cfg *config.Config) fx.Option { fx.Provide(p2p.New), LibP2P(bcfg, cfg), - OnlineProviders(cfg.Experimental.StrategicProviding, cfg.Experimental.AcceleratedDHTClient, cfg.Reprovider.Strategy, cfg.Reprovider.Interval), + OnlineProviders( + cfg.Experimental.StrategicProviding, + cfg.Experimental.AcceleratedDHTClient, + cfg.Reprovider.Strategy.WithDefault(config.DefaultReproviderStrategy), + cfg.Reprovider.Interval.WithDefault(config.DefaultReproviderInterval), + ), ) } @@ -304,7 +322,12 @@ func Offline(cfg *config.Config) fx.Option { fx.Provide(libp2p.Routing), fx.Provide(libp2p.ContentRouting), fx.Provide(libp2p.OfflineRouting), - OfflineProviders(cfg.Experimental.StrategicProviding, cfg.Experimental.AcceleratedDHTClient, cfg.Reprovider.Strategy, cfg.Reprovider.Interval), + OfflineProviders( + cfg.Experimental.StrategicProviding, + cfg.Experimental.AcceleratedDHTClient, + cfg.Reprovider.Strategy.WithDefault(config.DefaultReproviderStrategy), + cfg.Reprovider.Interval.WithDefault(config.DefaultReproviderInterval), + ), ) } diff --git a/core/node/libp2p/rcmgr.go b/core/node/libp2p/rcmgr.go index d705cd418..e0ce4693b 100644 --- a/core/node/libp2p/rcmgr.go +++ b/core/node/libp2p/rcmgr.go @@ -19,7 +19,7 @@ import ( "go.opencensus.io/stats/view" "go.uber.org/fx" - config "github.com/ipfs/kubo/config" + "github.com/ipfs/kubo/config" "github.com/ipfs/kubo/core/node/helpers" "github.com/ipfs/kubo/repo" ) @@ -52,7 +52,8 @@ func ResourceManager(cfg config.SwarmConfig) interface{} { return nil, opts, fmt.Errorf("opening IPFS_PATH: %w", err) } - limitConfig, err := createDefaultLimitConfig(cfg) + var limitConfig rcmgr.LimitConfig + defaultComputedLimitConfig, err := createDefaultLimitConfig(cfg) if err != nil { return nil, opts, err } @@ -61,10 +62,19 @@ func ResourceManager(cfg config.SwarmConfig) interface{} { // is documented in docs/config.md. // Any changes here should be reflected there. if cfg.ResourceMgr.Limits != nil { - l := *cfg.ResourceMgr.Limits - // This effectively overrides the computed default LimitConfig with any vlues from cfg.ResourceMgr.Limits - l.Apply(limitConfig) - limitConfig = l + userSuppliedOverrideLimitConfig := *cfg.ResourceMgr.Limits + // This effectively overrides the computed default LimitConfig with any non-zero values from cfg.ResourceMgr.Limits. + // Because of how how Apply works, any 0 value for a user supplied override + // will be overriden with a computed default value. + // There currently isn't a way for a user to supply a 0-value override. + userSuppliedOverrideLimitConfig.Apply(defaultComputedLimitConfig) + limitConfig = userSuppliedOverrideLimitConfig + } else { + limitConfig = defaultComputedLimitConfig + } + + if err := ensureConnMgrMakeSenseVsResourceMgr(limitConfig, cfg.ConnMgr); err != nil { + return nil, opts, err } limiter := rcmgr.NewFixedLimiter(limitConfig) @@ -113,7 +123,7 @@ func ResourceManager(cfg config.SwarmConfig) interface{} { manager = lrm } else { fmt.Println("go-libp2p resource manager protection disabled") - manager = network.NullResourceManager + manager = &network.NullResourceManager{} } opts.Opts = append(opts.Opts, libp2p.ResourceManager(manager)) @@ -598,3 +608,41 @@ func NetResetLimit(mgr network.ResourceManager, repo repo.Repo, scope string) (r return result, nil } + +func ensureConnMgrMakeSenseVsResourceMgr(rcm rcmgr.LimitConfig, cmgr config.ConnMgr) error { + if cmgr.Type.WithDefault(config.DefaultConnMgrType) == "none" { + return nil // none connmgr, no checks to do + } + highWater := cmgr.HighWater.WithDefault(config.DefaultConnMgrHighWater) + if rcm.System.ConnsInbound <= rcm.System.Conns { + if int64(rcm.System.ConnsInbound) <= highWater { + // nolint + return fmt.Errorf(` +Unable to initialize libp2p due to conflicting limit configuration: +ResourceMgr.Limits.System.ConnsInbound (%d) must be bigger than ConnMgr.HighWater (%d) +`, rcm.System.ConnsInbound, highWater) + } + } else if int64(rcm.System.Conns) <= highWater { + // nolint + return fmt.Errorf(` +Unable to initialize libp2p due to conflicting limit configuration: +ResourceMgr.Limits.System.Conns (%d) must be bigger than ConnMgr.HighWater (%d) +`, rcm.System.Conns, highWater) + } + if rcm.System.StreamsInbound <= rcm.System.Streams { + if int64(rcm.System.StreamsInbound) <= highWater { + // nolint + return fmt.Errorf(` +Unable to initialize libp2p due to conflicting limit configuration: +ResourceMgr.Limits.System.StreamsInbound (%d) must be bigger than ConnMgr.HighWater (%d) +`, rcm.System.StreamsInbound, highWater) + } + } else if int64(rcm.System.Streams) <= highWater { + // nolint + return fmt.Errorf(` +Unable to initialize libp2p due to conflicting limit configuration: +ResourceMgr.Limits.System.Streams (%d) must be bigger than ConnMgr.HighWater (%d) +`, rcm.System.Streams, highWater) + } + return nil +} diff --git a/core/node/libp2p/rcmgr_defaults.go b/core/node/libp2p/rcmgr_defaults.go index d3c294258..9a3825108 100644 --- a/core/node/libp2p/rcmgr_defaults.go +++ b/core/node/libp2p/rcmgr_defaults.go @@ -44,17 +44,18 @@ var noLimitIncrease = rcmgr.BaseLimitIncrease{ // This file defines implicit limit defaults used when Swarm.ResourceMgr.Enabled // createDefaultLimitConfig creates LimitConfig to pass to libp2p's resource manager. -// The defaults follow the documentation in docs/config.md. +// The defaults follow the documentation in docs/libp2p-resource-management.md. // Any changes in the logic here should be reflected there. func createDefaultLimitConfig(cfg config.SwarmConfig) (rcmgr.LimitConfig, error) { - maxMemoryDefaultString := humanize.Bytes(uint64(memory.TotalMemory()) / 4) + maxMemoryDefaultString := humanize.Bytes(uint64(memory.TotalMemory()) / 2) maxMemoryString := cfg.ResourceMgr.MaxMemory.WithDefault(maxMemoryDefaultString) maxMemory, err := humanize.ParseBytes(maxMemoryString) if err != nil { return rcmgr.LimitConfig{}, err } - numFD := cfg.ResourceMgr.MaxFileDescriptors.WithDefault(int64(fd.GetNumFDs()) / 2) + maxMemoryMB := maxMemory / (1024 * 1024) + maxFD := int(cfg.ResourceMgr.MaxFileDescriptors.WithDefault(int64(fd.GetNumFDs()) / 2)) // We want to see this message on startup, that's why we are using fmt instead of log. fmt.Printf(` @@ -65,65 +66,53 @@ Computing default go-libp2p Resource Manager limits based on: Applying any user-supplied overrides on top. Run 'ipfs swarm limit all' to see the resulting limits. -`, maxMemoryString, numFD) +`, maxMemoryString, maxFD) + + // At least as of 2023-01-25, it's possible to open a connection that + // doesn't ask for any memory usage with the libp2p Resource Manager/Accountant + // (see https://github.com/libp2p/go-libp2p/issues/2010#issuecomment-1404280736). + // As a result, we can't curretly rely on Memory limits to full protect us. + // Until https://github.com/libp2p/go-libp2p/issues/2010 is addressed, + // we take a proxy now of restricting to 1 inbound connection per MB. + // Note: this is more generous than go-libp2p's default autoscaled limits which do + // 64 connections per 1GB + // (see https://github.com/libp2p/go-libp2p/blob/master/p2p/host/resource-manager/limit_defaults.go#L357 ). + systemConnsInbound := int(1 * maxMemoryMB) scalingLimitConfig := rcmgr.ScalingLimitConfig{ SystemBaseLimit: rcmgr.BaseLimit{ Memory: int64(maxMemory), - FD: int(numFD), + FD: maxFD, // By default, we just limit connections on the inbound side. Conns: bigEnough, - ConnsInbound: rcmgr.DefaultLimits.SystemBaseLimit.ConnsInbound, // same as libp2p default + ConnsInbound: systemConnsInbound, ConnsOutbound: bigEnough, - // We limit streams since they not only take up memory and CPU. - // The Memory limit protects us on the memory side, - // but a StreamsInbound limit helps protect against unbound CPU consumption from stream processing. Streams: bigEnough, - StreamsInbound: rcmgr.DefaultLimits.SystemBaseLimit.StreamsInbound, + StreamsInbound: bigEnough, StreamsOutbound: bigEnough, }, - // Most limits don't see an increase because they're already infinite/bigEnough or at their max value. - // The values that should scale based on the amount of memory allocated to libp2p need to increase accordingly. - SystemLimitIncrease: rcmgr.BaseLimitIncrease{ - Memory: 0, - FDFraction: 0, - - Conns: 0, - ConnsInbound: rcmgr.DefaultLimits.SystemLimitIncrease.ConnsInbound, - ConnsOutbound: 0, - - Streams: 0, - StreamsInbound: rcmgr.DefaultLimits.SystemLimitIncrease.StreamsInbound, - StreamsOutbound: 0, - }, + SystemLimitIncrease: noLimitIncrease, + // Transient connections won't cause any memory to accounted for by the resource manager. + // Only established connections do. + // As a result, we can't rely on System.Memory to protect us from a bunch of transient connection being opened. + // We limit the same values as the System scope, but only allow the Transient scope to take 25% of what is allowed for the System scope. TransientBaseLimit: rcmgr.BaseLimit{ - Memory: rcmgr.DefaultLimits.TransientBaseLimit.Memory, - FD: rcmgr.DefaultLimits.TransientBaseLimit.FD, + Memory: int64(maxMemory / 4), + FD: maxFD / 4, Conns: bigEnough, - ConnsInbound: rcmgr.DefaultLimits.TransientBaseLimit.ConnsInbound, + ConnsInbound: systemConnsInbound / 4, ConnsOutbound: bigEnough, Streams: bigEnough, - StreamsInbound: rcmgr.DefaultLimits.TransientBaseLimit.StreamsInbound, + StreamsInbound: bigEnough, StreamsOutbound: bigEnough, }, - TransientLimitIncrease: rcmgr.BaseLimitIncrease{ - Memory: rcmgr.DefaultLimits.TransientLimitIncrease.Memory, - FDFraction: rcmgr.DefaultLimits.TransientLimitIncrease.FDFraction, - - Conns: 0, - ConnsInbound: rcmgr.DefaultLimits.TransientLimitIncrease.ConnsInbound, - ConnsOutbound: 0, - - Streams: 0, - StreamsInbound: rcmgr.DefaultLimits.TransientLimitIncrease.StreamsInbound, - StreamsOutbound: 0, - }, + TransientLimitIncrease: noLimitIncrease, // Lets get out of the way of the allow list functionality. // If someone specified "Swarm.ResourceMgr.Allowlist" we should let it go through. @@ -184,7 +173,26 @@ Run 'ipfs swarm limit all' to see the resulting limits. // Whatever limits libp2p has specifically tuned for its protocols/services we'll apply. libp2p.SetDefaultServiceLimits(&scalingLimitConfig) - defaultLimitConfig := scalingLimitConfig.Scale(int64(maxMemory), int(numFD)) + defaultLimitConfig := scalingLimitConfig.Scale(int64(maxMemory), maxFD) + + // Simple checks to overide autoscaling ensuring limits make sense versus the connmgr values. + // There are ways to break this, but this should catch most problems already. + // We might improve this in the future. + // See: https://github.com/ipfs/kubo/issues/9545 + if cfg.ConnMgr.Type.WithDefault(config.DefaultConnMgrType) != "none" { + maxInboundConns := int64(defaultLimitConfig.System.ConnsInbound) + if connmgrHighWaterTimesTwo := cfg.ConnMgr.HighWater.WithDefault(config.DefaultConnMgrHighWater) * 2; maxInboundConns < connmgrHighWaterTimesTwo { + maxInboundConns = connmgrHighWaterTimesTwo + } + + if maxInboundConns < config.DefaultResourceMgrMinInboundConns { + maxInboundConns = config.DefaultResourceMgrMinInboundConns + } + + // Scale System.StreamsInbound as well, but use the existing ratio of StreamsInbound to ConnsInbound + defaultLimitConfig.System.StreamsInbound = int(maxInboundConns * int64(defaultLimitConfig.System.StreamsInbound) / int64(defaultLimitConfig.System.ConnsInbound)) + defaultLimitConfig.System.ConnsInbound = int(maxInboundConns) + } return defaultLimitConfig, nil } diff --git a/core/node/libp2p/rcmgr_logging.go b/core/node/libp2p/rcmgr_logging.go index 6076a29b5..978222bfe 100644 --- a/core/node/libp2p/rcmgr_logging.go +++ b/core/node/libp2p/rcmgr_logging.go @@ -50,11 +50,11 @@ func (n *loggingResourceManager) start(ctx context.Context) { n.limitExceededErrs = make(map[string]int) for e, count := range errs { - n.logger.Warnf("Protected from exceeding resource limits %d times: %q.", count, e) + n.logger.Warnf("Protected from exceeding resource limits %d times. libp2p message: %q.", count, e) } if len(errs) != 0 { - n.logger.Warnf("Consider inspecting logs and raising the resource manager limits. Documentation: https://github.com/ipfs/kubo/blob/master/docs/config.md#swarmresourcemgr") + n.logger.Warnf("Learn more about potential actions to take at: https://github.com/ipfs/kubo/blob/master/docs/libp2p-resource-management.md") } n.mut.Unlock() diff --git a/core/node/libp2p/rcmgr_logging_test.go b/core/node/libp2p/rcmgr_logging_test.go index ca06fae12..512168d4a 100644 --- a/core/node/libp2p/rcmgr_logging_test.go +++ b/core/node/libp2p/rcmgr_logging_test.go @@ -55,7 +55,7 @@ func TestLoggingResourceManager(t *testing.T) { if oLogs.Len() == 0 { continue } - require.Equal(t, "Protected from exceeding resource limits 2 times: \"system: cannot reserve inbound connection: resource limit exceeded\".", oLogs.All()[0].Message) + require.Equal(t, "Protected from exceeding resource limits 2 times. libp2p message: \"system: cannot reserve inbound connection: resource limit exceeded\".", oLogs.All()[0].Message) return } } diff --git a/core/node/libp2p/routing.go b/core/node/libp2p/routing.go index 21afe292d..f16fec5a1 100644 --- a/core/node/libp2p/routing.go +++ b/core/node/libp2p/routing.go @@ -7,13 +7,9 @@ import ( "sort" "time" - "github.com/ipfs/kubo/core/node/helpers" - irouting "github.com/ipfs/kubo/routing" - + "github.com/cenkalti/backoff/v4" ds "github.com/ipfs/go-datastore" offroute "github.com/ipfs/go-ipfs-routing/offline" - config "github.com/ipfs/kubo/config" - "github.com/ipfs/kubo/repo" dht "github.com/libp2p/go-libp2p-kad-dht" ddht "github.com/libp2p/go-libp2p-kad-dht/dual" "github.com/libp2p/go-libp2p-kad-dht/fullrt" @@ -24,9 +20,12 @@ import ( "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/routing" - - "github.com/cenkalti/backoff/v4" "go.uber.org/fx" + + config "github.com/ipfs/kubo/config" + "github.com/ipfs/kubo/core/node/helpers" + "github.com/ipfs/kubo/repo" + irouting "github.com/ipfs/kubo/routing" ) type Router struct { @@ -77,6 +76,21 @@ func BaseRouting(experimentalDHTClient bool) interface{} { }) } + if pr, ok := in.Router.(routinghelpers.ComposableRouter); ok { + for _, r := range pr.Routers() { + if dht, ok := r.(*ddht.DHT); ok { + dr = dht + lc.Append(fx.Hook{ + OnStop: func(ctx context.Context) error { + return dr.Close() + }, + }) + + break + } + } + } + if dr != nil && experimentalDHTClient { cfg, err := in.Repo.Config() if err != nil { diff --git a/core/node/libp2p/routingopt.go b/core/node/libp2p/routingopt.go index 9f3ae5c06..bfb45971c 100644 --- a/core/node/libp2p/routingopt.go +++ b/core/node/libp2p/routingopt.go @@ -2,6 +2,9 @@ package libp2p import ( "context" + "os" + "strings" + "time" "github.com/ipfs/go-datastore" "github.com/ipfs/kubo/config" @@ -23,6 +26,79 @@ type RoutingOption func( ...peer.AddrInfo, ) (routing.Routing, error) +// Default HTTP routers used in parallel to DHT when Routing.Type = "auto" +var defaultHTTPRouters = []string{ + "https://cid.contact", // https://github.com/ipfs/kubo/issues/9422#issuecomment-1338142084 + // TODO: add an independent router from Cloudflare +} + +func init() { + // Override HTTP routers if custom ones were passed via env + if routers := os.Getenv("IPFS_HTTP_ROUTERS"); routers != "" { + defaultHTTPRouters = strings.Split(routers, " ") + } +} + +// ConstructDefaultRouting returns routers used when Routing.Type is unset or set to "auto" +func ConstructDefaultRouting(peerID string, addrs []string, privKey string) func( + ctx context.Context, + host host.Host, + dstore datastore.Batching, + validator record.Validator, + bootstrapPeers ...peer.AddrInfo, +) (routing.Routing, error) { + return func( + ctx context.Context, + host host.Host, + dstore datastore.Batching, + validator record.Validator, + bootstrapPeers ...peer.AddrInfo, + ) (routing.Routing, error) { + // Defined routers will be queried in parallel (optimizing for response speed) + // Different trade-offs can be made by setting Routing.Type = "custom" with own Routing.Routers + var routers []*routinghelpers.ParallelRouter + + // Run the default DHT routing (same as Routing.Type = "dht") + dhtRouting, err := DHTOption(ctx, host, dstore, validator, bootstrapPeers...) + if err != nil { + return nil, err + } + routers = append(routers, &routinghelpers.ParallelRouter{ + Router: dhtRouting, + IgnoreError: false, + Timeout: 5 * time.Minute, // https://github.com/ipfs/kubo/pull/9475#discussion_r1042501333 + ExecuteAfter: 0, + }) + + // Append HTTP routers for additional speed + for _, endpoint := range defaultHTTPRouters { + httpRouter, err := irouting.ConstructHTTPRouter(endpoint, peerID, addrs, privKey) + if err != nil { + return nil, err + } + + r := &irouting.Composer{ + GetValueRouter: routinghelpers.Null{}, + PutValueRouter: routinghelpers.Null{}, + ProvideRouter: routinghelpers.Null{}, // modify this when indexers supports provide + FindPeersRouter: routinghelpers.Null{}, + FindProvidersRouter: httpRouter, + } + + routers = append(routers, &routinghelpers.ParallelRouter{ + Router: r, + IgnoreError: true, // https://github.com/ipfs/kubo/pull/9475#discussion_r1042507387 + Timeout: 15 * time.Second, // 5x server value from https://github.com/ipfs/kubo/pull/9475#discussion_r1042428529 + ExecuteAfter: 0, + }) + } + + routing := routinghelpers.NewComposableParallel(routers) + return routing, nil + } +} + +// constructDHTRouting is used when Routing.Type = "dht" func constructDHTRouting(mode dht.ModeOpt) func( ctx context.Context, host host.Host, @@ -49,6 +125,7 @@ func constructDHTRouting(mode dht.ModeOpt) func( } } +// ConstructDelegatedRouting is used when Routing.Type = "custom" func ConstructDelegatedRouting(routers config.Routers, methods config.Methods, peerID string, addrs []string, privKey string) func( ctx context.Context, host host.Host, diff --git a/core/node/libp2p/smux.go b/core/node/libp2p/smux.go index 40c29d395..c906b6e02 100644 --- a/core/node/libp2p/smux.go +++ b/core/node/libp2p/smux.go @@ -19,7 +19,6 @@ func yamuxTransport() network.Multiplexer { if os.Getenv("YAMUX_DEBUG") != "" { tpt.LogOutput = os.Stderr } - return &tpt } @@ -27,9 +26,6 @@ func makeSmuxTransportOption(tptConfig config.Transports) (libp2p.Option, error) const yamuxID = "/yamux/1.0.0" const mplexID = "/mplex/6.7.0" - ymxtpt := *yamux.DefaultTransport - ymxtpt.AcceptBacklog = 512 - if prefs := os.Getenv("LIBP2P_MUX_PREFS"); prefs != "" { // Using legacy LIBP2P_MUX_PREFS variable. log.Error("LIBP2P_MUX_PREFS is now deprecated.") @@ -47,7 +43,7 @@ func makeSmuxTransportOption(tptConfig config.Transports) (libp2p.Option, error) } switch tpt { case yamuxID: - opts = append(opts, libp2p.Muxer(tpt, yamuxTransport)) + opts = append(opts, libp2p.Muxer(tpt, yamuxTransport())) case mplexID: opts = append(opts, libp2p.Muxer(tpt, mplex.DefaultTransport)) default: @@ -59,7 +55,7 @@ func makeSmuxTransportOption(tptConfig config.Transports) (libp2p.Option, error) return prioritizeOptions([]priorityOption{{ priority: tptConfig.Multiplexers.Yamux, defaultPriority: 100, - opt: libp2p.Muxer(yamuxID, yamuxTransport), + opt: libp2p.Muxer(yamuxID, yamuxTransport()), }, { priority: tptConfig.Multiplexers.Mplex, defaultPriority: 200, diff --git a/core/node/libp2p/transport.go b/core/node/libp2p/transport.go index d96891df2..f737c6086 100644 --- a/core/node/libp2p/transport.go +++ b/core/node/libp2p/transport.go @@ -36,12 +36,10 @@ func Transports(tptConfig config.Transports) interface{} { "QUIC transport does not support private networks, please disable Swarm.Transports.Network.QUIC", ) } - // TODO(9290): Make WithMetrics configurable - opts.Opts = append(opts.Opts, libp2p.Transport(quic.NewTransport, quic.WithMetrics())) + opts.Opts = append(opts.Opts, libp2p.Transport(quic.NewTransport)) } - // TODO(9292): Remove the false && to allows it enabled by default - if tptConfig.Network.WebTransport.WithDefault(false && !privateNetworkEnabled) { + if tptConfig.Network.WebTransport.WithDefault(!privateNetworkEnabled) { if privateNetworkEnabled { return opts, fmt.Errorf( "WebTransport transport does not support private networks, please disable Swarm.Transports.Network.WebTransport", diff --git a/core/node/provider.go b/core/node/provider.go index cf625b8c6..9110b41b2 100644 --- a/core/node/provider.go +++ b/core/node/provider.go @@ -18,8 +18,6 @@ import ( irouting "github.com/ipfs/kubo/routing" ) -const kReprovideFrequency = time.Hour * 12 - // SIMPLE // ProviderQueue creates new datastore backed provider queue @@ -61,20 +59,10 @@ func SimpleProviderSys(isOnline bool) interface{} { } // BatchedProviderSys creates new provider system -func BatchedProviderSys(isOnline bool, reprovideInterval string) interface{} { +func BatchedProviderSys(isOnline bool, reprovideInterval time.Duration) interface{} { return func(lc fx.Lifecycle, cr irouting.ProvideManyRouter, q *q.Queue, keyProvider simple.KeyChanFunc, repo repo.Repo) (provider.System, error) { - reprovideIntervalDuration := kReprovideFrequency - if reprovideInterval != "" { - dur, err := time.ParseDuration(reprovideInterval) - if err != nil { - return nil, err - } - - reprovideIntervalDuration = dur - } - sys, err := batched.New(cr, q, - batched.ReproviderInterval(reprovideIntervalDuration), + batched.ReproviderInterval(reprovideInterval), batched.Datastore(repo.Datastore()), batched.KeyProvider(keyProvider)) if err != nil { @@ -100,7 +88,7 @@ func BatchedProviderSys(isOnline bool, reprovideInterval string) interface{} { // ONLINE/OFFLINE // OnlineProviders groups units managing provider routing records online -func OnlineProviders(useStrategicProviding bool, useBatchedProviding bool, reprovideStrategy string, reprovideInterval string) fx.Option { +func OnlineProviders(useStrategicProviding bool, useBatchedProviding bool, reprovideStrategy string, reprovideInterval time.Duration) fx.Option { if useStrategicProviding { return fx.Provide(provider.NewOfflineProvider) } @@ -113,7 +101,7 @@ func OnlineProviders(useStrategicProviding bool, useBatchedProviding bool, repro } // OfflineProviders groups units managing provider routing records offline -func OfflineProviders(useStrategicProviding bool, useBatchedProviding bool, reprovideStrategy string, reprovideInterval string) fx.Option { +func OfflineProviders(useStrategicProviding bool, useBatchedProviding bool, reprovideStrategy string, reprovideInterval time.Duration) fx.Option { if useStrategicProviding { return fx.Provide(provider.NewOfflineProvider) } @@ -126,17 +114,7 @@ func OfflineProviders(useStrategicProviding bool, useBatchedProviding bool, repr } // SimpleProviders creates the simple provider/reprovider dependencies -func SimpleProviders(reprovideStrategy string, reprovideInterval string) fx.Option { - reproviderInterval := kReprovideFrequency - if reprovideInterval != "" { - dur, err := time.ParseDuration(reprovideInterval) - if err != nil { - return fx.Error(err) - } - - reproviderInterval = dur - } - +func SimpleProviders(reprovideStrategy string, reproviderInterval time.Duration) fx.Option { var keyProvider fx.Option switch reprovideStrategy { case "all": diff --git a/coverage/Rules.mk b/coverage/Rules.mk index e0935d880..7770ed69b 100644 --- a/coverage/Rules.mk +++ b/coverage/Rules.mk @@ -2,7 +2,7 @@ include mk/header.mk GOCC ?= go -$(d)/coverage_deps: $$(DEPS_GO) +$(d)/coverage_deps: $$(DEPS_GO) cmd/ipfs/ipfs rm -rf $(@D)/unitcover && mkdir $(@D)/unitcover rm -rf $(@D)/sharnesscover && mkdir $(@D)/sharnesscover @@ -46,7 +46,7 @@ endif export IPFS_COVER_DIR:= $(realpath $(d))/sharnesscover/ $(d)/sharness_tests.coverprofile: export TEST_NO_PLUGIN=1 -$(d)/sharness_tests.coverprofile: $(d)/ipfs cmd/ipfs/ipfs-test-cover $(d)/coverage_deps test_sharness_short +$(d)/sharness_tests.coverprofile: $(d)/ipfs cmd/ipfs/ipfs-test-cover $(d)/coverage_deps test_sharness (cd $(@D)/sharnesscover && find . -type f | gocovmerge -list -) > $@ diff --git a/docs/EARLY_TESTERS.md b/docs/EARLY_TESTERS.md index ee008c1a2..fb2fedc2a 100644 --- a/docs/EARLY_TESTERS.md +++ b/docs/EARLY_TESTERS.md @@ -27,7 +27,6 @@ We will ask early testers to participate at two points in the process: - [ ] Textile (@sanderpick) - [ ] Pinata (@obo20) - [ ] RTrade (@postables) -- [ ] QRI (@b5) - [ ] Siderus (@koalalorenzo) - [ ] Charity Engine (@rytiss, @tristanolive) - [ ] Fission (@bmann) diff --git a/docs/README.md b/docs/README.md index 78235622a..ab7ac9cc3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,11 +1,17 @@ # Developer Documentation and Guides -If you are looking for User Documentation & Guides, please visit [docs.ipfs.tech](https://docs.ipfs.tech/). +If you are looking for User Documentation & Guides, please visit [docs.ipfs.tech](https://docs.ipfs.tech/) or check [General Documentation](#general-documentation). If you’re experiencing an issue with IPFS, **please follow [our issue guide](github-issue-guide.md) when filing an issue!** Otherwise, check out the following guides to using and developing IPFS: +## General Documentation + +- [Configuration reference](config.md) + - [Datastore configuration](datastores.md) + - [Experimental features](experimental-features.md) + ## Developing `kubo` - First, please read the Contributing Guidelines [for IPFS projects](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md) and then the Contributing Guidelines for [Go code specifically](https://github.com/ipfs/community/blob/master/CONTRIBUTING_GO.md) @@ -22,9 +28,6 @@ Otherwise, check out the following guides to using and developing IPFS: ## Advanced User Guides - [Transferring a File Over IPFS](file-transfer.md) -- [Configuration reference](config.md) - - [Datastore configuration](datastores.md) - - [Experimental features](experimental-features.md) - [Installing command completion](command-completion.md) - [Mounting IPFS with FUSE](fuse.md) - [Installing plugins](plugins.md) diff --git a/docs/changelogs/v0.18.md b/docs/changelogs/v0.18.md index 4afa6793e..b9d023639 100644 --- a/docs/changelogs/v0.18.md +++ b/docs/changelogs/v0.18.md @@ -1,36 +1,207 @@ # Kubo changelog v0.18 +## v0.18.1 + +This release includes improvements around Pubsub message deduplication, libp2p resource management, and more. + + + +- [Overview](#overview) +- [🔦 Highlights](#-highlights) + - [New default Pubsub.SeenMessagesStrategy](#new-default-pubsubseenmessagesstrategy) + - [Improving libp2p resource management integration](#improving-libp2p-resource-management-integration) +- [📝 Changelog](#-changelog) +- [👨‍👩‍👧‍👦 Contributors](#-contributors) + + + +### 🔦 Highlights + +#### New default `Pubsub.SeenMessagesStrategy` + +A new optional [`Pubsub.SeenMessagesStrategy`](../config.md#pubsubseenmessagesstrategy) configuration option has been added. + +This option allows you to choose between two different strategies for +deduplicating messages: `first-seen` and `last-seen`. + +When unset, the default strategy is `last-seen`, which calculates the +time-to-live (TTL) countdown based on the last time a message is seen. This +means that if a message is received and then seen again within the specified +TTL window based on the last time it was seen, it won't be emitted. + +If you prefer the old behavior, which calculates the TTL countdown based on the +first time a message is seen, you can set `Pubsub.SeenMessagesStrategy` to +`first-seen`. + +#### Improving libp2p resource management integration + +This builds on the default protection nodes get against DoS (resource exhaustion) and eclipse attacks +with the [go-libp2p Network Resource Manager/Accountant](https://github.com/ipfs/kubo/blob/master/docs/libp2p-resource-management.md) +that was fine-tuned in [Kubo 0.18](https://github.com/ipfs/kubo/blob/biglep/resource-manager-example-of-what-want/docs/changelogs/v0.18.md#improving-libp2p-resource-management-integration). + +Adding default hard-limits from the Resource Manager/Accountant after the fact is tricky, +and some additional improvements have been made to improve the [computed defaults](https://github.com/ipfs/kubo/blob/master/docs/libp2p-resource-management.md#computed-default-limits). + +As much as possible, the aim is for a user to only think about how much memory they want to bound libp2p to, +and not need to think about translating that to hard numbers for connections, streams, etc. +More updates are likely in future Kubo releases, but with this release: +1. ``System.StreamsInbound`` is no longer bounded directly +2. ``System.ConnsInbound``, ``Transient.Memory``, ``Transiet.ConnsInbound`` have higher default computed values. + +### 📝 Changelog + +
Full Changelog + +- github.com/ipfs/kubo: + - Add overview section + - Adjust inbound connection limits depending on memory. + - feat: Pubsub.SeenMessagesStrategy (#9543) ([ipfs/kubo#9543](https://github.com/ipfs/kubo/pull/9543)) + - chore: update version +- github.com/libp2p/go-libp2p-pubsub (v0.8.2 -> v0.8.3): + - feat: expire messages from the cache based on last seen time (#513) ([libp2p/go-libp2p-pubsub#513](https://github.com/libp2p/go-libp2p-pubsub/pull/513)) + +
+ +### 👨‍👩‍👧‍👦 Contributors + +| Contributor | Commits | Lines ± | Files Changed | +|-------------|---------|---------|---------------| +| Mohsin Zaidi | 2 | +511/-55 | 12 | +| Antonio Navarro Perez | 2 | +57/-57 | 5 | +| galargh | 1 | +1/-1 | 1 | + ## v0.18.0 ### Overview Below is an outline of all that is in this release, so you get a sense of all that's included. -- [Kubo changelog v0.18](#kubo-changelog-v018) - - [v0.18.0](#v0180) + + - [Overview](#overview) - [🔦 Highlights](#-highlights) - - [(DAG-)JSON and (DAG-)CBOR Response Formats on Gateways](#dag-json-and-dag-cbor-response-formats-on-gateways) - - [Changelog](#changelog) - - [Contributors](#contributors) + - [Content routing](#content-routing) + - [Default InterPlanetary Network Indexer](#default-interplanetary-network-indexer) + - [Increase provider record republish interval and expiration](#increase-provider-record-republish-interval-and-expiration) + - [Gateways](#gateways) + - [(DAG-)JSON and (DAG-)CBOR response formats](#dag-json-and-dag-cbor-response-formats) + - [🐎 Fast directory listings with DAG sizes](#-fast-directory-listings-with-dag-sizes) + - [QUIC and WebTransport](#quic-and-webtransport) + - [WebTransport enabled by default](#webtransport-enabled-by-default) + - [QUIC and WebTransport share a single port](#quic-and-webtransport-share-a-single-port) + - [Differentiating QUIC versions](#differentiating-quic-versions) + - [QUICv1 and WebTransport config migration](#quicv1-and-webtransport-config-migration) + - [Improving libp2p resource management integration](#improving-libp2p-resource-management-integration) + - [📝 Changelog](#-changelog) + - [👨‍👩‍👧‍👦 Contributors](#-contributors) + + ### 🔦 Highlights -#### (DAG-)JSON and (DAG-)CBOR Response Formats on Gateways +#### Content routing -Implemented [IPIP-328](https://github.com/ipfs/specs/pull/328) which adds support -to DAG-JSON and DAG-CBOR, as well as their non-DAG variants, to the gateway. Now, -CIDs that encode JSON, CBOR, DAG-JSON and DAG-CBOR objects can be retrieved, and -traversed through IPLD Links. +##### Default InterPlanetary Network Indexer -HTTP clients can request JSON, CBOR, DAG-JSON, and DAG-CBOR responses by either -passing the query parameter `?format` or setting the `Accept` HTTP header to the -following values: +Content routing is the process of discovering which peers provide a piece of content. Kubo has traditionally only supported [libp2p's implementation of Kademlia DHT](https://github.com/libp2p/specs/tree/master/kad-dht) for content routing. -- JSON: `?format=json`, or `Accept: application/json` -- CBOR: `?format=cbor`, or `Accept: application/cbor` -- DAG-JSON: `?format=dag-json`, or `Accept: application/vnd.ipld.dag-json` -- DAG-JSON: `?format=dag-cbor`, or `Accept: application/vnd.ipld.dag-cbor` +Kubo can now bridge networks by including support for the [delegated routing HTTP API](https://github.com/ipfs/specs/pull/337). Users can compose content routers using the `Routing.Routers` config to pick content routers with different tradeoffs than a Kademlia DHT (e.g., high-performance and high-capacity centralized endpoints, dedicated Kademlia DHT nodes, routers with unique provider records, privacy-focused content routers). + +One example is [InterPlanetary Network Indexers](https://github.com/ipni/specs/blob/main/IPNI.md#readme), which are HTTP endpoints that cache records from both the IPFS network and other sources such as web3.storage and Filecoin. This improves not only content availability by enabling Kubo to transparently fetch content directly from Filecoin storage providers, but also improves IPFS content routing latency by an order of magnitude and decreases resource consumption. + +> *Note:* it's possible to retrieve content stored by Filecoin Storage Providers (SPs) from Kubo if the SPs service Bitswap requests. As of this release, some SPs are advertising Bitswap. You can follow the roadmap progress for IPNIs and Bitswap in SPs [here](https://www.starmaps.app/roadmap/github.com/protocol/bedrock/issues/1). + +In this release, the default content router is changed from `dht` to `auto`. The `auto` router includes the IPFS DHT in addition to the [cid.contact](https://cid.contact) IPNI instance. In future releases, we plan to expand the functionality of `auto` to encompass automatic discovery of content routers, which will improve performance and content availability (for example, see [IPIP-342](https://github.com/ipfs/specs/pull/342)). + +Previous behavior can be restored by setting `Routing.Type` to `dht`. + +Alternative routing rules, including alternative IPNI endpoints, can be configured in `Routing.Routers` after setting `Routing.Type` to `custom`. + +Learn more in the [`Routing` docs](https://github.com/ipfs/kubo/blob/master/docs/config.md#routing). + +##### Increase provider record republish interval and expiration + +Default `Reprovider.Interval` changed from 12h to 22h to match new defaults for the Provider Record Expiration (48h) in [go-libp2p-kad-dht v0.20.0](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.20.0). + +The rationale for increasing this can be found in +[RFM 17: Provider Record Livenes Report](https://github.com/protocol/network-measurements/blob/master/results/rfm17-provider-record-liveness.md), +[kubo#9326](https://github.com/ipfs/kubo/pull/9326), +and the upstream DHT specifications at [libp2p/specs#451](https://github.com/libp2p/specs/pull/451). + +Learn more in the [`Reprovider` config](https://github.com/ipfs/go-ipfs/blob/master/docs/config.md#reprovider). + +#### Gateways + +##### (DAG-)JSON and (DAG-)CBOR response formats + +The IPFS project has reserved the corresponding media types at IANA: +- [`application/vnd.ipld.dag-json`](https://www.iana.org/assignments/media-types/application/vnd.ipld.dag-json) +- [`application/vnd.ipld.dag-cbor`](https://www.iana.org/assignments/media-types/application/vnd.ipld.dag-cbor) + +This release implements them as part of [IPIP-328](https://github.com/ipfs/specs/pull/328) +and adds Gateway support for CIDs with `json` (0x0200), `cbor` (0x51), +[`dag-json`](https://ipld.io/specs/codecs/dag-json/) (0x0129) +and [`dag-cbor`](https://ipld.io/specs/codecs/dag-cbor/spec/) (0x71) codecs. + +To specify the response `Content-Type` explicitly, the HTTP client can override +the codec present in the CID by using the `format` parameter +or setting the `Accept` HTTP header: + +- Plain JSON: `?format=json` or `Accept: application/json` +- Plain CBOR: `?format=cbor` or `Accept: application/cbor` +- DAG-JSON: `?format=dag-json` or `Accept: application/vnd.ipld.dag-json` +- DAG-CBOR: `?format=dag-cbor` or `Accept: application/vnd.ipld.dag-cbor` + +In addition, when DAG-JSON or DAG-CBOR is requested with the `Accept` header +set to `text/html`, the Gateway will return a basic HTML page with download +options, improving the user experience in web browsers. + +###### Example 1: DAG-CBOR and DAG-JSON Conversion on Gateway + +The Gateway supports conversion between DAG-CBOR and DAG-JSON for efficient +end-to-end data structure management: author in CBOR or JSON, store as binary +CBOR and retrieve as JSON via HTTP: + +```console +$ echo '{"test": "json"}' | ipfs dag put # implicit --input-codec dag-json --store-codec dag-cbor +bafyreico7mjtqtqhvawro3yud5uqn6sc33nzqb7b5j2d7pdmzer5nab4t4 + +$ ipfs block get bafyreico7mjtqtqhvawro3yud5uqn6sc33nzqb7b5j2d7pdmzer5nab4t4 | xxd +00000000: a164 7465 7374 646a 736f 6e .dtestdjson + +$ ipfs dag get bafyreico7mjtqtqhvawro3yud5uqn6sc33nzqb7b5j2d7pdmzer5nab4t4 # implicit --output-codec dag-json +{"test":"json"} + +$ curl "http://127.0.0.1:8080/ipfs/bafyreico7mjtqtqhvawro3yud5uqn6sc33nzqb7b5j2d7pdmzer5nab4t4?format=dag-json" +{"test":"json"} +``` + +###### Example 2: Traversing CBOR DAGs + +Placing a CID in [CBOR Tag 42](https://github.com/ipld/cid-cbor/) enables the +creation of arbitrary DAGs. The equivalent DAG-JSON notation for linking +to different blocks is represented by `{ "/": "cid" }`. + +The Gateway supports traversing these links, enabling access to data +referenced by structures other than regular UnixFS directories: + +```console +$ echo '{"test.jpg": {"/": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi"}}' | ipfs dag put +bafyreihspwy3zlkzgphmec5d3xb5g5njrqwotd46lyubnelbzktnmsxkq4 # dag-cbor document linking to unixfs file + +$ ipfs resolve /ipfs/bafyreihspwy3zlkzgphmec5d3xb5g5njrqwotd46lyubnelbzktnmsxkq4/test.jpg +/ipfs/bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi + +$ ipfs dag stat bafyreihspwy3zlkzgphmec5d3xb5g5njrqwotd46lyubnelbzktnmsxkq4 +Size: 119827, NumBlocks: 2 + +$ curl "http://127.0.0.1:8080/ipfs/bafyreihspwy3zlkzgphmec5d3xb5g5njrqwotd46lyubnelbzktnmsxkq4/test.jpg" > test.jpg +``` + +###### Example 3: UnixFS directory listing as JSON + +Finally, Gateway now supports the same [logical format projection](https://ipld.io/specs/codecs/dag-pb/spec/#logical-format) from +DAG-PB to DAG-JSON as the `ipfs dag get` command, enabling the retrieval of directory listings as JSON instead of HTML: ```console $ export DIR_CID=bafybeigccimv3zqm5g4jt363faybagywkvqbrismoquogimy7kvz2sj7sq @@ -66,8 +237,601 @@ $ curl "http://127.0.0.1:8080/ipfs/$DIR_CID?format=dag-json" | jq } ] } +$ ipfs dag get $DIR_CID +{"Data":{"/":{"bytes":"CAE"}},"Links":[{"Hash":{"/":"Qmc3zqKcwzbbvw3MQm3hXdg8BQoFjGdZiGdAfXAyAGGdLi"},"Name":"1 - Barrel - Part 1 - alt.txt","Tsize":21},{"Hash":{"/":"QmdMxMx29KVYhHnaCc1icWYxQqXwUNCae6t1wS2NqruiHd"},"Name":"1 - Barrel - Part 1 - transcript.txt","Tsize":195},{"Hash":{"/":"QmawceGscqN4o8Y8Fv26UUmB454kn2bnkXV5tEQYc4jBd6"},"Name":"1 - Barrel - Part 1.png","Tsize":24862}]} ``` -### Changelog +##### 🐎 Fast directory listings with DAG sizes -### Contributors +Fast listings are now enabled for _all_ UnixFS directories: big and small. +There is no linear slowdown caused by reading size metadata from child nodes, +and the size of DAG representing child items is always present. + +As an example, the CID +`bafybeiggvykl7skb2ndlmacg2k5modvudocffxjesexlod2pfvg5yhwrqm` represents a UnixFS +directory with over 10k files. Listing big directories was fast +since Kubo 0.13, but in this release it will also include the size column. + +#### QUIC and WebTransport + +##### WebTransport enabled by default +[WebTransport](https://docs.libp2p.io/concepts/transports/webtransport/) is a new libp2p transport that [was introduced in v0.16](https://github.com/ipfs/kubo/blob/master/docs/changelogs/v0.16.md#-webtransport-new-experimental-transport) that is based on top of QUIC and HTTP3. + +This allows browser-based nodes to contact Kubo nodes, so now instead of just serving requests for other system-level application nodes, you can also serve requests directly to a node running inside a browser page. + +For the full story see [connectivity.libp2p.io](https://connectivity.libp2p.io/). + +##### QUIC and WebTransport share a single port +WebTransport is enabled by default in part because [go-libp2p now supports running WebTransport and QUIC transports on the same QUIC listener](https://github.com/libp2p/go-libp2p/issues/1759). No additional port needs to be opened. + +To use this feature, register two listen addresses on the same `/ipX/.../udp/XXX` prefix. + +##### Differentiating QUIC versions +go-libp2p now differentiates the first version of QUIC that was originally implemented, `Draft-29`, from the ratified protocol in [RFC9000](https://www.rfc-editor.org/rfc/rfc9000.html), `QUICv1`. +This was done for performance (time to first byte) reasons as [outlined here](https://github.com/multiformats/multiaddr/issues/145). + +This manifests as two different multiaddr components `/quic` (old Draft-29) and `/quic-v1`. +go-libp2p do supports listening with both QUIC versions on one single listener. +WebTransport has only supported QUICv1. +`/webtransport` now needs to be prefixed by a `/quic-v1` component instead of a `/quic` component. + +Support for QUIC Draft-29 will be removed at some point in 2023 ([tracking issue](https://github.com/ipfs/kubo/issues/9496)). As a result, new deployements should use `/quic-v1` instead of `/quic`. + +##### QUICv1 and WebTransport config migration +To support QUICv1 and WebTransport by default a new config migration (`v13`) is run which automatically adds entries in addresses-related fields: +- Replace all `/quic/webtransport` to `/quic-v1/webtransport`. +- For all `/quic` listeners, keep the Draft-29 listener, and on the same ip and port, add `/quic-v1` and `/quic-v1/webtransport` listeners. + +#### Improving libp2p resource management integration +To help protect nodes from DoS (resource exhaustion) and eclipse attacks, +Kubo enabled the [go-libp2p Network Resource Manager](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager) +by default in [Kubo 0.17](https://github.com/ipfs/kubo/blob/master/docs/changelogs/v0.17.md#libp2p-resource-management-enabled-by-default). + +Introducing limits like this by default after the fact is tricky, +and various improvements have been made to improve the UX including: +1. [Dedicated docs concerning the resource manager integration](https://github.com/ipfs/kubo/blob/master/docs/libp2p-resource-management.md). This is a great place to go to learn more or get your FAQs answered. +2. Increasing the default limits for the resource manager. +3. Enabling the [`Swarm.ConnMgr`](https://github.com/ipfs/kubo/blob/master/docs/config.md#swarmconnmgr) by default and reducing it thresholds so it can intelligently prune connections in many cases before the indiscriminate resource manager kicks in. +4. Adjusted log messages and levels to make clear that the resource manager is likely doing your node a favor by bounding resources. +5. [Other miscellaneous config and command bugs reported by users](https://github.com/ipfs/kubo/issues/9442). + +### 📝 Changelog + +
Full Changelog + +- github.com/ipfs/kubo: + - fix: clarity: no user supplied rcmgr limits of 0 (#9563) ([ipfs/kubo#9563](https://github.com/ipfs/kubo/pull/9563)) + - fix(gateway): undesired conversions to dag-json and friends (#9566) ([ipfs/kubo#9566](https://github.com/ipfs/kubo/pull/9566)) + - fix: ensure connmgr is smaller then autoscalled ressource limits + - fix: typo in ensureConnMgrMakeSenseVsResourcesMgr + - docs: clarify browser descriptions for webtransport + - fix: update saxon download path + - fix: refuse to start if connmgr is smaller than ressource limits and not using none connmgr + - fix: User-Agent sent to HTTP routers + - test: port gateway sharness tests to Go tests + - fix: do not download saxon in parallel + - docs: improve docs/README (#9539) ([ipfs/kubo#9539](https://github.com/ipfs/kubo/pull/9539)) + - test: port CircleCI to GH Actions and improve sharness reporting (#9355) ([ipfs/kubo#9355](https://github.com/ipfs/kubo/pull/9355)) + - chore: migrate from go-ipfs-files to go-libipfs/files (#9535) ([ipfs/kubo#9535](https://github.com/ipfs/kubo/pull/9535)) + - fix: stats dht command when Routing.Type=auto (#9538) ([ipfs/kubo#9538](https://github.com/ipfs/kubo/pull/9538)) + - fix: hint people to changing from RSA peer ids + - fix(gateway): JSON when Accept is a list + - fix(test): retry flaky t0125-twonode.sh + - docs: fix Router config Godoc (#9528) ([ipfs/kubo#9528](https://github.com/ipfs/kubo/pull/9528)) + - fix(ci): flaky sharness test + - docs(config): ProviderSearchDelay (#9526) ([ipfs/kubo#9526](https://github.com/ipfs/kubo/pull/9526)) + - docs: clarify debug environment variables + - chore: update version.go + - fix(test): stabilize flaky provider tests + - feat: port pins CLI test + - Removing QRI from early tester ([ipfs/kubo#9503](https://github.com/ipfs/kubo/pull/9503)) + - fix: disable provide over HTTP with Routing.Type=auto (#9511) ([ipfs/kubo#9511](https://github.com/ipfs/kubo/pull/9511)) + - Update version.go + - 'chore: update version.go' + - Clened up 0.18 changelog for release ([ipfs/kubo#9497](https://github.com/ipfs/kubo/pull/9497)) + - feat: turn on WebTransport by default ([ipfs/kubo#9492](https://github.com/ipfs/kubo/pull/9492)) + - feat: fast directory listings with DAG Size column (#9481) ([ipfs/kubo#9481](https://github.com/ipfs/kubo/pull/9481)) + - feat: add basic CLI tests using Go Test + - Changelog: v0.18.0 ([ipfs/kubo#9485](https://github.com/ipfs/kubo/pull/9485)) + - feat: go-libp2p-kad-dht with expiration 48h + - chore: update go-libp2p to v0.24.1 + - fix: remove the imports work-around + - fix: replace quic to quic-v1 for webtransport sharness + - fix: silence staticcheck warning for fx.Extract usage + - update go-libp2p to v0.24.0 + - stop using the deprecated go-libp2p-loggables package + - docs(readme): update package managers section (#9488) ([ipfs/kubo#9488](https://github.com/ipfs/kubo/pull/9488)) + - fix: support /quic-v1 in webui v0.21 + - feat: Routing.Type=auto (DHT+IPNI) (#9475) ([ipfs/kubo#9475](https://github.com/ipfs/kubo/pull/9475)) + - feat: adjust ConnMgr target to 32-96 (#9483) ([ipfs/kubo#9483](https://github.com/ipfs/kubo/pull/9483)) + - feat: increase default Reprovider.Interval (#9326) ([ipfs/kubo#9326](https://github.com/ipfs/kubo/pull/9326)) + - feat: add response body limiter to routing HTTP client (#9478) ([ipfs/kubo#9478](https://github.com/ipfs/kubo/pull/9478)) + - docs: libp2p resource management (#9468) ([ipfs/kubo#9468](https://github.com/ipfs/kubo/pull/9468)) + - chore: upgrade libipfs for routing HTTP API schema changes (#9477) ([ipfs/kubo#9477](https://github.com/ipfs/kubo/pull/9477)) + - feat: lower connection pool + - Add missing && + - Fix sharness test + - Added a message when RM is disabled. + - Requested changes. + - Fix sharness checking daemon output + - Update test/sharness/t0060-daemon.sh + - Try to fix sharness test. + - Fix: RM: Improve init RM message and fix final memory value. + - Fix: Resource Manager: Filter stats correctly by % + - Apply suggestions from code review + - Increase MaxMemory param to use half of total memory. + - Update libipfs dependency. + - Add sharness tests and documentation + - Fix variable name + - feature: delegated-routing: Add HTTP delegated routing. + - Fix: Change RM log output to WARN level + - Fix: RM: Set no-limit value to 1e9 (1000000000). + - Partial Revert "Revert "fix: ensure hasher is registered when using a hashing function"" + - Add logs to the routing system + - fix: apply agent-version-suffix to libp2p identify + - chore: migrate ipfs/tar-utils to libipfs + - feat(gateway): JSON and CBOR response formats (IPIP-328) (#9335) ([ipfs/kubo#9335](https://github.com/ipfs/kubo/pull/9335)) + - ([ipfs/kubo#9318](https://github.com/ipfs/kubo/pull/9318)) + - docs: release process updates from v0.17.0 ([ipfs/kubo#9391](https://github.com/ipfs/kubo/pull/9391)) + - fix(rcmgr): improve error phrasing + - docs: Update CHANGELOG.md adding 0.17 link + - feat(config): Pubsub.SeenMessagesTTL (#9372) ([ipfs/kubo#9372](https://github.com/ipfs/kubo/pull/9372)) + - docs: remove snap and chocolatey packages + - Merge release v0.17.0 ([ipfs/kubo#9431](https://github.com/ipfs/kubo/pull/9431)) + - docs: ipfs-http-client -> kubo-rpc-client (#9331) ([ipfs/kubo#9331](https://github.com/ipfs/kubo/pull/9331)) + - docs(readme): improve tldr + - Update config.md for resource management limits (#9421) ([ipfs/kubo#9421](https://github.com/ipfs/kubo/pull/9421)) + - Doc improvements and changelog for resource manager (#9413) ([ipfs/kubo#9413](https://github.com/ipfs/kubo/pull/9413)) + - Revert "Doc improvements for rcmgr" + - Doc improvements for rcmgr + - docs: document /wss fixes in 0.17 + - refactor(config): remove Swarm.ConnMgr defaults + - fix(config): skip nulls in ResourceMgr + - docs: replace tabcat with aphelionz in EARLY_TESTERS.md (#9404) ([ipfs/kubo#9404](https://github.com/ipfs/kubo/pull/9404)) + - docs: fix spoiler for 0.13.1 changelog + - fix(docs): typo + - chore: bump version to v0.18.0-dev ([ipfs/kubo#9393](https://github.com/ipfs/kubo/pull/9393)) +- github.com/ipfs/go-bitswap (v0.10.2 -> v0.11.0): + - chore: release v0.11.0 +- github.com/ipfs/go-blockservice (v0.4.0 -> v0.5.0): + - chore: release v0.5.0 +- github.com/ipfs/go-graphsync (v0.13.1 -> v0.14.1): + - chore: version 0.14.1 (#400) ([ipfs/go-graphsync#400](https://github.com/ipfs/go-graphsync/pull/400)) + - chore: migrate files (#399) ([ipfs/go-graphsync#399](https://github.com/ipfs/go-graphsync/pull/399)) + - docs(CHANGELOG): update for v0.14.0 release + - updates for libp2p v0.22 (#392) ([ipfs/go-graphsync#392](https://github.com/ipfs/go-graphsync/pull/392)) + - feat(ipld): use bindnode/registry (#386) ([ipfs/go-graphsync#386](https://github.com/ipfs/go-graphsync/pull/386)) + - Accept/Reject requests up front (#384) ([ipfs/go-graphsync#384](https://github.com/ipfs/go-graphsync/pull/384)) + - Remove protobuf protocol (#385) ([ipfs/go-graphsync#385](https://github.com/ipfs/go-graphsync/pull/385)) + - docs(CHANGELOG): update for v0.13.2 + - chore(deps): upgrade libp2p & ipld-prime (#389) ([ipfs/go-graphsync#389](https://github.com/ipfs/go-graphsync/pull/389)) + - chore(ipld): switch to using top-level ipld-prime codec helpers (#383) ([ipfs/go-graphsync#383](https://github.com/ipfs/go-graphsync/pull/383)) + - feat(requestmanager): read request from context (#381) ([ipfs/go-graphsync#381](https://github.com/ipfs/go-graphsync/pull/381)) + - fix: minor typo in error msg + - fix(panics): lift panic recovery up to top of network handling + - feat: expand use of panic handler to cover network and codec interaction + - feat(panics): capture panics from selector execution +- github.com/ipfs/go-ipfs-cmds (v0.8.1 -> v0.8.2): + - chore: version v0.8.2 (#235) ([ipfs/go-ipfs-cmds#235](https://github.com/ipfs/go-ipfs-cmds/pull/235)) + - chore: migrate files (#233) ([ipfs/go-ipfs-cmds#233](https://github.com/ipfs/go-ipfs-cmds/pull/233)) + - sync: update CI config files (#229) ([ipfs/go-ipfs-cmds#229](https://github.com/ipfs/go-ipfs-cmds/pull/229)) +- github.com/ipfs/go-ipfs-keystore (v0.0.2 -> v0.1.0): + - chore: release v0.1.0 + - chore: update go-libp2p + - sync: update CI config files ([ipfs/go-ipfs-keystore#10](https://github.com/ipfs/go-ipfs-keystore/pull/10)) + - sync: update CI config files ([ipfs/go-ipfs-keystore#8](https://github.com/ipfs/go-ipfs-keystore/pull/8)) + - Add link to pkg.go.dev + - README: this module does not use Gx +- github.com/ipfs/go-ipfs-provider (v0.7.1 -> v0.8.1): + - chore: release v0.8.1 + - fix: make queue 64bits on 32bits platforms too + - sync: update CI config files ([ipfs/go-ipfs-provider#36](https://github.com/ipfs/go-ipfs-provider/pull/36)) + - chore: update go-lib2p, avoid depending on go-libp2p-core, bump go.mod version +- github.com/ipfs/go-ipfs-routing (v0.2.1 -> v0.3.0): + - release v0.3.0 ([ipfs/go-ipfs-routing#36](https://github.com/ipfs/go-ipfs-routing/pull/36)) + - chore: update go-libp2p to v0.22.0 ([ipfs/go-ipfs-routing#35](https://github.com/ipfs/go-ipfs-routing/pull/35)) + - sync: update CI config files (#34) ([ipfs/go-ipfs-routing#34](https://github.com/ipfs/go-ipfs-routing/pull/34)) +- github.com/ipfs/go-ipld-cbor (v0.0.5 -> v0.0.6): + - Add contexts to IpldBlockstore ([ipfs/go-ipld-cbor#82](https://github.com/ipfs/go-ipld-cbor/pull/82)) + - sync: update CI config files (#81) ([ipfs/go-ipld-cbor#81](https://github.com/ipfs/go-ipld-cbor/pull/81)) + - sync: update CI config files ([ipfs/go-ipld-cbor#79](https://github.com/ipfs/go-ipld-cbor/pull/79)) + - Fix lint errors ([ipfs/go-ipld-cbor#78](https://github.com/ipfs/go-ipld-cbor/pull/78)) + - Add notice directing new projects to codec/dagcbor ([ipfs/go-ipld-cbor#77](https://github.com/ipfs/go-ipld-cbor/pull/77)) +- github.com/ipfs/go-merkledag (v0.6.0 -> v0.9.0): + - chore: bump version to 0.9.0 + - chore: bump version to 0.8.1 + - feat: remove panic() from non-error methods + - feat: improve broken cid.Builder testing for CidBuilder + - chore: bump version to 0.8.0 + - doc: document potential panics and how to avoid them + - fix: simplify Cid generation cache & usage + - feat: check links on setting and sanitise on encoding + - feat: check that the CidBuilder hasher is usable + - chore: bump version to 0.7.0 + - fix: remove use of ioutil + - run gofmt -s + - fix!: keep deserialised state stable until explicit mutation + - sync: update CI config files ([ipfs/go-merkledag#84](https://github.com/ipfs/go-merkledag/pull/84)) +- github.com/ipfs/go-namesys (v0.5.0 -> v0.6.0): + - chore: release v0.6.0 + - chore: update go-libp2p to v0.23.4, update go.mod version to 1.18 + - stop using the deprecated io/ioutil package +- github.com/ipfs/go-peertaskqueue (v0.7.1 -> v0.8.0): + - Release v0.8.0 ([ipfs/go-peertaskqueue#25](https://github.com/ipfs/go-peertaskqueue/pull/25)) + - chore: update go-libp2p to v0.22.0 ([ipfs/go-peertaskqueue#24](https://github.com/ipfs/go-peertaskqueue/pull/24)) + - sync: update CI config files (#23) ([ipfs/go-peertaskqueue#23](https://github.com/ipfs/go-peertaskqueue/pull/23)) + - sync: update CI config files (#21) ([ipfs/go-peertaskqueue#21](https://github.com/ipfs/go-peertaskqueue/pull/21)) +- github.com/ipfs/go-unixfs (v0.4.1 -> v0.4.2): + - chore: version 0.4.2 (#136) ([ipfs/go-unixfs#136](https://github.com/ipfs/go-unixfs/pull/136)) + - chore: migrate files (#134) ([ipfs/go-unixfs#134](https://github.com/ipfs/go-unixfs/pull/134)) + - ([ipfs/go-unixfs#128](https://github.com/ipfs/go-unixfs/pull/128)) +- github.com/ipfs/go-unixfsnode (v1.4.0 -> v1.5.1): + - v1.5.1 + - fix a possible `index out of range` crash ([ipfs/go-unixfsnode#39](https://github.com/ipfs/go-unixfsnode/pull/39)) + - add an ADL to preload hamt loading ([ipfs/go-unixfsnode#38](https://github.com/ipfs/go-unixfsnode/pull/38)) + - chore: bump version to 1.5.0 + - fix: remove use of ioutil + - run gofmt -s + - bump go.mod to Go 1.18 and run go fix + - test for reader / sizing behavior on large files ([ipfs/go-unixfsnode#34](https://github.com/ipfs/go-unixfsnode/pull/34)) + - add helper to approximate test creation patter from ipfs-files ([ipfs/go-unixfsnode#32](https://github.com/ipfs/go-unixfsnode/pull/32)) + - chore: remove Stebalien/go-bitfield in favour of ipfs/go-bitfield +- github.com/ipfs/interface-go-ipfs-core (v0.7.0 -> v0.8.2): + - chore: version 0.8.2 (#100) ([ipfs/interface-go-ipfs-core#100](https://github.com/ipfs/interface-go-ipfs-core/pull/100)) + - chore: migrate files (#97) ([ipfs/interface-go-ipfs-core#97](https://github.com/ipfs/interface-go-ipfs-core/pull/97)) + - chore: release v0.8.1 + - feat: add UseCumulativeSize UnixfsLs option (#95) ([ipfs/interface-go-ipfs-core#95](https://github.com/ipfs/interface-go-ipfs-core/pull/95)) + - chore: release v0.8.0 + - chore: update go-libp2p to v0.23.4 + - sync: update CI config files (#87) ([ipfs/interface-go-ipfs-core#87](https://github.com/ipfs/interface-go-ipfs-core/pull/87)) +- github.com/ipld/go-car/v2 (v2.4.0 -> v2.5.1): + - add a `SkipNext` method on block reader (#338) ([ipld/go-car#338](https://github.com/ipld/go-car/pull/338)) + - feat: Has() and Get() will respect StoreIdentityCIDs option + - chore: bump version to 0.5.0 + - fix: remove use of ioutil + - run gofmt -s + - bump go.mod to Go 1.18 and run go fix + - bump go.mod to Go 1.18 and run go fix + - OpenReadWriteFile: add test + - blockstore: allow to pass a file to write in (#323) ([ipld/go-car#323](https://github.com/ipld/go-car/pull/323)) + - feat: add `car inspect` command to cmd pkg (#320) ([ipld/go-car#320](https://github.com/ipld/go-car/pull/320)) + - Separate `index.ReadFrom` tests + - Only read index codec during inspection + - Upgrade to the latest `go-car/v2` + - Empty identity CID should be indexed when options are set +- github.com/ipld/go-codec-dagpb (v1.4.1 -> v1.5.0): + - chore: version bump to 1.5.0 + - fix: replace io/ioutil with io + - bump go.mod to Go 1.18 and run go fix + - v1.4.2 bump +- github.com/libp2p/go-libp2p (v0.23.4 -> v0.24.2): + - release v0.24.2 (#1969) ([libp2p/go-libp2p#1969](https://github.com/libp2p/go-libp2p/pull/1969)) + - webtransport: initialize a NullResourceManager if none is provided (#1962) ([libp2p/go-libp2p#1962](https://github.com/libp2p/go-libp2p/pull/1962)) + - release v0.24.1 (#1945) ([libp2p/go-libp2p#1945](https://github.com/libp2p/go-libp2p/pull/1945)) + - routed host: return Connect error if FindPeer doesn't yield new addresses (#1946) ([libp2p/go-libp2p#1946](https://github.com/libp2p/go-libp2p/pull/1946)) + - chore: update examples to v0.24.0 (#1936) ([libp2p/go-libp2p#1936](https://github.com/libp2p/go-libp2p/pull/1936)) + - webtransport: fix flaky accept queue test (#1938) ([libp2p/go-libp2p#1938](https://github.com/libp2p/go-libp2p/pull/1938)) + - quic: fix race condition in TestClientCanDialDifferentQUICVersions (#1937) ([libp2p/go-libp2p#1937](https://github.com/libp2p/go-libp2p/pull/1937)) + - quic: update quic-go to v0.31.1 (#1942) ([libp2p/go-libp2p#1942](https://github.com/libp2p/go-libp2p/pull/1942)) + - release v0.24.0 (#1934) ([libp2p/go-libp2p#1934](https://github.com/libp2p/go-libp2p/pull/1934)) + - Disable support for signed/static TLS certificates in WebTransport (#1927) ([libp2p/go-libp2p#1927](https://github.com/libp2p/go-libp2p/pull/1927)) + - webtransport: add PSK to constructor, and fail if it is used (#1929) ([libp2p/go-libp2p#1929](https://github.com/libp2p/go-libp2p/pull/1929)) + - use a different set of default transports when PSK is enabled (#1921) ([libp2p/go-libp2p#1921](https://github.com/libp2p/go-libp2p/pull/1921)) + - transport.Listener,quic: Support multiple QUIC versions with the same Listener. Only return a single multiaddr per listener. (#1923) ([libp2p/go-libp2p#1923](https://github.com/libp2p/go-libp2p/pull/1923)) + - quic / webtransport: make it possible to listen on the same address / port (#1905) ([libp2p/go-libp2p#1905](https://github.com/libp2p/go-libp2p/pull/1905)) + - autorelay: fix flaky TestReconnectToStaticRelays (#1903) ([libp2p/go-libp2p#1903](https://github.com/libp2p/go-libp2p/pull/1903)) + - swarm / rcmgr: synchronize the concurrent outbound dials with limits (#1898) ([libp2p/go-libp2p#1898](https://github.com/libp2p/go-libp2p/pull/1898)) + - add QUIC v1 addresses to the default listen addresses (#1914) ([libp2p/go-libp2p#1914](https://github.com/libp2p/go-libp2p/pull/1914)) + - webtransport: update webtransport-go to v0.3.0 (#1895) ([libp2p/go-libp2p#1895](https://github.com/libp2p/go-libp2p/pull/1895)) + - tls: fix flaky TestHandshakeConnectionCancellations test (#1896) ([libp2p/go-libp2p#1896](https://github.com/libp2p/go-libp2p/pull/1896)) + - holepunch: disable the resource manager in tests (#1897) ([libp2p/go-libp2p#1897](https://github.com/libp2p/go-libp2p/pull/1897)) + - transports: expose the name of the transport in the ConnectionState (#1911) ([libp2p/go-libp2p#1911](https://github.com/libp2p/go-libp2p/pull/1911)) + - respect the user's security protocol preference order ([libp2p/go-libp2p#1912](https://github.com/libp2p/go-libp2p/pull/1912)) + - circuitv2: disable the resource manager in tests (#1899) ([libp2p/go-libp2p#1899](https://github.com/libp2p/go-libp2p/pull/1899)) + - expose the security protocol on the ConnectionState ([libp2p/go-libp2p#1907](https://github.com/libp2p/go-libp2p/pull/1907)) + - fix: autorelay: treat static relays as just another peer source (#1875) ([libp2p/go-libp2p#1875](https://github.com/libp2p/go-libp2p/pull/1875)) + - feat: quic,webtransport: enable both quic-draft29 and quic-v1 addrs on quic. only quic-v1 on webtransport (#1881) ([libp2p/go-libp2p#1881](https://github.com/libp2p/go-libp2p/pull/1881)) + - holepunch: add multiaddress filter (#1839) ([libp2p/go-libp2p#1839](https://github.com/libp2p/go-libp2p/pull/1839)) + - README: remove broken links from table of contents (#1893) ([libp2p/go-libp2p#1893](https://github.com/libp2p/go-libp2p/pull/1893)) + - quic: update quic-go to v0.31.0 (#1882) ([libp2p/go-libp2p#1882](https://github.com/libp2p/go-libp2p/pull/1882)) + - add an integration test for muxer selection ([libp2p/go-libp2p#1887](https://github.com/libp2p/go-libp2p/pull/1887)) + - core/network: fix typo + - tls / noise: prefer the client's muxer preferences ([libp2p/go-libp2p#1888](https://github.com/libp2p/go-libp2p/pull/1888)) + - upgrader: absorb the muxer_multistream.Transport into the upgrader (#1885) ([libp2p/go-libp2p#1885](https://github.com/libp2p/go-libp2p/pull/1885)) + - Apply service peer default (#1878) ([libp2p/go-libp2p#1878](https://github.com/libp2p/go-libp2p/pull/1878)) + - webtransport: use deterministic TLS certificates (#1833) ([libp2p/go-libp2p#1833](https://github.com/libp2p/go-libp2p/pull/1833)) + - remove deprecated StaticRelays option (#1868) ([libp2p/go-libp2p#1868](https://github.com/libp2p/go-libp2p/pull/1868)) + - autorelay: remove the default static relay option (#1867) ([libp2p/go-libp2p#1867](https://github.com/libp2p/go-libp2p/pull/1867)) + - core/protocol: remove deprecated Negotiator.NegotiateLazy (#1869) ([libp2p/go-libp2p#1869](https://github.com/libp2p/go-libp2p/pull/1869)) + - config: use fx dependency injection to construct transports ([libp2p/go-libp2p#1858](https://github.com/libp2p/go-libp2p/pull/1858)) + - noise: add an option to allow unknown peer ID in SecureOutbound (#1823) ([libp2p/go-libp2p#1823](https://github.com/libp2p/go-libp2p/pull/1823)) + - Add some guard rails and docs (#1863) ([libp2p/go-libp2p#1863](https://github.com/libp2p/go-libp2p/pull/1863)) + - Fix concurrent map access in connmgr (#1860) ([libp2p/go-libp2p#1860](https://github.com/libp2p/go-libp2p/pull/1860)) + - fix: return filtered addrs (#1855) ([libp2p/go-libp2p#1855](https://github.com/libp2p/go-libp2p/pull/1855)) + - chore: preallocate slices (#1842) ([libp2p/go-libp2p#1842](https://github.com/libp2p/go-libp2p/pull/1842)) + - Close ping stream when we exit the loop (#1853) ([libp2p/go-libp2p#1853](https://github.com/libp2p/go-libp2p/pull/1853)) + - tls: don't set the deprecated tls.Config.PreferServerCipherSuites field (#1845) ([libp2p/go-libp2p#1845](https://github.com/libp2p/go-libp2p/pull/1845)) + - routed host: search for new multi addresses upon connect failure (#1835) ([libp2p/go-libp2p#1835](https://github.com/libp2p/go-libp2p/pull/1835)) + - core/peerstore: removed unused provider addr ttl constant (#1848) ([libp2p/go-libp2p#1848](https://github.com/libp2p/go-libp2p/pull/1848)) + - basichost: improve protocol negotiation debug message (#1846) ([libp2p/go-libp2p#1846](https://github.com/libp2p/go-libp2p/pull/1846)) + - noise: use Noise Extension to negotiate the muxer during the handshake (#1813) ([libp2p/go-libp2p#1813](https://github.com/libp2p/go-libp2p/pull/1813)) + - webtransport: use the rcmgr to control flow control window increases ([libp2p/go-libp2p#1832](https://github.com/libp2p/go-libp2p/pull/1832)) + - chore: update quic-go to v0.30.0 (#1838) ([libp2p/go-libp2p#1838](https://github.com/libp2p/go-libp2p/pull/1838)) + - roadmap: reorder priority, reorganize sections (#1831) ([libp2p/go-libp2p#1831](https://github.com/libp2p/go-libp2p/pull/1831)) + - websocket: set the HTTP host header in WSS(#1834) ([libp2p/go-libp2p#1834](https://github.com/libp2p/go-libp2p/pull/1834)) + - webtransport: make it possible to record qlogs (controlled by QLOGDIR env) ([libp2p/go-libp2p#1828](https://github.com/libp2p/go-libp2p/pull/1828)) + - ipfs /api/v0/id is post (#1819) ([libp2p/go-libp2p#1819](https://github.com/libp2p/go-libp2p/pull/1819)) + - examples: connect to all peers in example mdns chat app (#1798) ([libp2p/go-libp2p#1798](https://github.com/libp2p/go-libp2p/pull/1798)) + - roadmap: fix header level on "Mid Q4" (#1818) ([libp2p/go-libp2p#1818](https://github.com/libp2p/go-libp2p/pull/1818)) + - examples: use circuitv2 in relay example (#1795) ([libp2p/go-libp2p#1795](https://github.com/libp2p/go-libp2p/pull/1795)) + - add a roadmap for the next 6 months (#1784) ([libp2p/go-libp2p#1784](https://github.com/libp2p/go-libp2p/pull/1784)) + - tls: use ALPN to negotiate the stream multiplexer (#1772) ([libp2p/go-libp2p#1772](https://github.com/libp2p/go-libp2p/pull/1772)) + - tls: add tests for test vector from the spec (#1788) ([libp2p/go-libp2p#1788](https://github.com/libp2p/go-libp2p/pull/1788)) + - examples: update go-libp2p to v0.23.x (#1803) ([libp2p/go-libp2p#1803](https://github.com/libp2p/go-libp2p/pull/1803)) + - Try increasing timeouts if we're in CI for this test (#1796) ([libp2p/go-libp2p#1796](https://github.com/libp2p/go-libp2p/pull/1796)) + - Don't use rcmgr in this test (#1799) ([libp2p/go-libp2p#1799](https://github.com/libp2p/go-libp2p/pull/1799)) + - Bump timeout in CI for flaky test (#1800) ([libp2p/go-libp2p#1800](https://github.com/libp2p/go-libp2p/pull/1800)) + - Bump timeout in CI for flaky test (#1801) ([libp2p/go-libp2p#1801](https://github.com/libp2p/go-libp2p/pull/1801)) + - Fix comment in webtransport client auth handshake (#1793) ([libp2p/go-libp2p#1793](https://github.com/libp2p/go-libp2p/pull/1793)) + - examples: add basic pubsub-with-rendezvous example (#1738) ([libp2p/go-libp2p#1738](https://github.com/libp2p/go-libp2p/pull/1738)) + - quic: speed up the stateless reset test case (#1778) ([libp2p/go-libp2p#1778](https://github.com/libp2p/go-libp2p/pull/1778)) + - tls: fix flaky handshake cancellation test (#1779) ([libp2p/go-libp2p#1779](https://github.com/libp2p/go-libp2p/pull/1779)) +- github.com/libp2p/go-libp2p-gostream (v0.3.0 -> v0.5.0): + - release v0.5.0 (#74) ([libp2p/go-libp2p-gostream#74](https://github.com/libp2p/go-libp2p-gostream/pull/74)) + - update go-libp2p to v0.22.0 (#73) ([libp2p/go-libp2p-gostream#73](https://github.com/libp2p/go-libp2p-gostream/pull/73)) + - Expose some read-only methods on the underlying Stream interface (#67) ([libp2p/go-libp2p-gostream#67](https://github.com/libp2p/go-libp2p-gostream/pull/67)) + - Update libp2p ([libp2p/go-libp2p-gostream#69](https://github.com/libp2p/go-libp2p-gostream/pull/69)) + - sync: update CI config files (#65) ([libp2p/go-libp2p-gostream#65](https://github.com/libp2p/go-libp2p-gostream/pull/65)) + - sync: update CI config files ([libp2p/go-libp2p-gostream#62](https://github.com/libp2p/go-libp2p-gostream/pull/62)) + - fix staticcheck ([libp2p/go-libp2p-gostream#61](https://github.com/libp2p/go-libp2p-gostream/pull/61)) +- github.com/libp2p/go-libp2p-http (v0.2.1 -> v0.4.0): + - release v0.4.0 ([libp2p/go-libp2p-http#81](https://github.com/libp2p/go-libp2p-http/pull/81)) + - sync: update CI config files ([libp2p/go-libp2p-http#79](https://github.com/libp2p/go-libp2p-http/pull/79)) + - Update to latest go-libp2p ([libp2p/go-libp2p-http#80](https://github.com/libp2p/go-libp2p-http/pull/80)) + - Update to latest go-libp2p ([libp2p/go-libp2p-http#78](https://github.com/libp2p/go-libp2p-http/pull/78)) + - sync: update CI config files (#73) ([libp2p/go-libp2p-http#73](https://github.com/libp2p/go-libp2p-http/pull/73)) +- github.com/libp2p/go-libp2p-kad-dht (v0.18.0 -> v0.20.0): + - release v0.20.0 (#803) ([libp2p/go-libp2p-kad-dht#803](https://github.com/libp2p/go-libp2p-kad-dht/pull/803)) + - feat: increase the max record age to 48h (PUT_VALUE, RFM17) (#794) ([libp2p/go-libp2p-kad-dht#794](https://github.com/libp2p/go-libp2p-kad-dht/pull/794)) + - feat: increase expiration time for Provider Records to 48h (RFM17) + - release v0.19.0 (#801) ([libp2p/go-libp2p-kad-dht#801](https://github.com/libp2p/go-libp2p-kad-dht/pull/801)) + - define the ProviderAddrTTL in this repo (#797) ([libp2p/go-libp2p-kad-dht#797](https://github.com/libp2p/go-libp2p-kad-dht/pull/797)) +- github.com/libp2p/go-libp2p-kbucket (v0.4.7 -> v0.5.0): + - chore: release 0.5.0 (#111) ([libp2p/go-libp2p-kbucket#111](https://github.com/libp2p/go-libp2p-kbucket/pull/111)) + - deprecate go-libp2p-core and use go-libp2p instead (#109) ([libp2p/go-libp2p-kbucket#109](https://github.com/libp2p/go-libp2p-kbucket/pull/109)) + - sync: update CI config files (#108) ([libp2p/go-libp2p-kbucket#108](https://github.com/libp2p/go-libp2p-kbucket/pull/108)) + - sync: update CI config files ([libp2p/go-libp2p-kbucket#107](https://github.com/libp2p/go-libp2p-kbucket/pull/107)) + - sync: update CI config files (#104) ([libp2p/go-libp2p-kbucket#104](https://github.com/libp2p/go-libp2p-kbucket/pull/104)) + - sync: update CI config files ([libp2p/go-libp2p-kbucket#101](https://github.com/libp2p/go-libp2p-kbucket/pull/101)) + - sync: update CI config files ([libp2p/go-libp2p-kbucket#99](https://github.com/libp2p/go-libp2p-kbucket/pull/99)) + - fix staticcheck ([libp2p/go-libp2p-kbucket#98](https://github.com/libp2p/go-libp2p-kbucket/pull/98)) +- github.com/libp2p/go-libp2p-pubsub (v0.6.1 -> v0.8.2): + - Add docstring for WithAppSpecificRPCInspector (#510) ([libp2p/go-libp2p-pubsub#510](https://github.com/libp2p/go-libp2p-pubsub/pull/510)) + - Adds Application Specific RPC Inspector (#509) ([libp2p/go-libp2p-pubsub#509](https://github.com/libp2p/go-libp2p-pubsub/pull/509)) + - chore: ignore signing keys during WithLocalPublication publishing (#497) ([libp2p/go-libp2p-pubsub#497](https://github.com/libp2p/go-libp2p-pubsub/pull/497)) + - improve handling of dead peers (#508) ([libp2p/go-libp2p-pubsub#508](https://github.com/libp2p/go-libp2p-pubsub/pull/508)) + - perf: use pooled buffers for message writes (#507) ([libp2p/go-libp2p-pubsub#507](https://github.com/libp2p/go-libp2p-pubsub/pull/507)) + - perf: use msgio pooled buffers for received msgs (#500) ([libp2p/go-libp2p-pubsub#500](https://github.com/libp2p/go-libp2p-pubsub/pull/500)) + - Enables injectable GossipSub router (#503) ([libp2p/go-libp2p-pubsub#503](https://github.com/libp2p/go-libp2p-pubsub/pull/503)) + - Enables non-atomic validation for peer scoring parameters (#499) ([libp2p/go-libp2p-pubsub#499](https://github.com/libp2p/go-libp2p-pubsub/pull/499)) + - update go-libp2p to v0.22.0 (#498) ([libp2p/go-libp2p-pubsub#498](https://github.com/libp2p/go-libp2p-pubsub/pull/498)) + - fix handling of dead peers (#492) ([libp2p/go-libp2p-pubsub#492](https://github.com/libp2p/go-libp2p-pubsub/pull/492)) + - feat: WithLocalPublication option to enable local only publishing on a topic (#481) ([libp2p/go-libp2p-pubsub#481](https://github.com/libp2p/go-libp2p-pubsub/pull/481)) + - update pubsub deps (#491) ([libp2p/go-libp2p-pubsub#491](https://github.com/libp2p/go-libp2p-pubsub/pull/491)) + - Gossipsub: Unsubscribe backoff (#488) ([libp2p/go-libp2p-pubsub#488](https://github.com/libp2p/go-libp2p-pubsub/pull/488)) + - Adds exponential backoff to re-spawing new streams for supposedly dead peers (#483) ([libp2p/go-libp2p-pubsub#483](https://github.com/libp2p/go-libp2p-pubsub/pull/483)) + - Publishing option for signing a message with a custom private key (#486) ([libp2p/go-libp2p-pubsub#486](https://github.com/libp2p/go-libp2p-pubsub/pull/486)) + - fix unused GossipSubHistoryGossip, make seenMessages ttl configurable, make score params SeenMsgTTL configurable + - Update README.md + - Add in Backoff Check + - Modify comment + - Add Backoff For Pruned Peers + - tests: new test for WithTopicMsgIdFunction + - chore: better name + - feat: detach WithMsgIdFunction + - fix: use RawID in traceRPCMeta to avoid allocations + - feat: extract RawID from ID + - chore: hello mister mutex hat + - chore: go fmt and return timecache named import + - feat: new WithMsgIdFunction topic option to enable topics to have own msg id generation rules + - feat: integrate msgIdGenerator + - feat: introduce msgIdGenerator and add ID field to Message wrapper +- github.com/libp2p/go-libp2p-pubsub-router (v0.5.0 -> v0.6.0): + - release v0.6.0 (#99) ([libp2p/go-libp2p-pubsub-router#99](https://github.com/libp2p/go-libp2p-pubsub-router/pull/99)) + - sync: update CI config files (#93) ([libp2p/go-libp2p-pubsub-router#93](https://github.com/libp2p/go-libp2p-pubsub-router/pull/93)) +- github.com/libp2p/go-libp2p-routing-helpers (v0.4.0 -> v0.6.0): + - Update version.json + - Change interface name + - Add tests + - Feat: retrieve routers from composable routers + - Update version.json + - Update version.json + - chore: add regression test for compparallel deadlock + - Add logs to composable parallel + - Bump version to v0.4.1 + - ([libp2p/go-libp2p-routing-helpers#64](https://github.com/libp2p/go-libp2p-routing-helpers/pull/64)) +- github.com/lucas-clemente/quic-go (v0.29.1 -> v0.31.1): + - qerr: include role (remote / local) in error string representations (#3629) ([lucas-clemente/quic-go#3629](https://github.com/lucas-clemente/quic-go/pull/3629)) + - introduce a type for the stateless reset key (#3621) ([lucas-clemente/quic-go#3621](https://github.com/lucas-clemente/quic-go/pull/3621)) + - limit the exponential PTO backoff to 60s (#3595) ([lucas-clemente/quic-go#3595](https://github.com/lucas-clemente/quic-go/pull/3595)) + - expose the QUIC version of a connection (#3620) ([lucas-clemente/quic-go#3620](https://github.com/lucas-clemente/quic-go/pull/3620)) + - expose function to convert byte slice to a connection ID (#3614) ([lucas-clemente/quic-go#3614](https://github.com/lucas-clemente/quic-go/pull/3614)) + - use `go run` for mockgen, goimports and ginkgo (#3616) ([lucas-clemente/quic-go#3616](https://github.com/lucas-clemente/quic-go/pull/3616)) + - fix client SNI handling (#3613) ([lucas-clemente/quic-go#3613](https://github.com/lucas-clemente/quic-go/pull/3613)) + - chore: fix multiple typos in comments (#3612) ([lucas-clemente/quic-go#3612](https://github.com/lucas-clemente/quic-go/pull/3612)) + - use the new zero-allocation control message parsing function from x/sys (#3609) ([lucas-clemente/quic-go#3609](https://github.com/lucas-clemente/quic-go/pull/3609)) + - http3: add support for parsing and writing HTTP/3 capsules (#3607) ([lucas-clemente/quic-go#3607](https://github.com/lucas-clemente/quic-go/pull/3607)) + - http3: add request to response (#3608) ([lucas-clemente/quic-go#3608](https://github.com/lucas-clemente/quic-go/pull/3608)) + - fix availability signaling of the send queue (#3597) ([lucas-clemente/quic-go#3597](https://github.com/lucas-clemente/quic-go/pull/3597)) + - http3: add a ConnectionState method to the StreamCreator interface (#3600) ([lucas-clemente/quic-go#3600](https://github.com/lucas-clemente/quic-go/pull/3600)) + - http3: add a Context method to the StreamCreator interface (#3601) ([lucas-clemente/quic-go#3601](https://github.com/lucas-clemente/quic-go/pull/3601)) + - rename the variable in quic.Config.AllowConnectionWindowIncrease (#3602) ([lucas-clemente/quic-go#3602](https://github.com/lucas-clemente/quic-go/pull/3602)) + - migrate to Ginkgo v2, remove benchmark test ([lucas-clemente/quic-go#3589](https://github.com/lucas-clemente/quic-go/pull/3589)) + - don't drop more than 10 consecutive packets in drop test (#3584) ([lucas-clemente/quic-go#3584](https://github.com/lucas-clemente/quic-go/pull/3584)) + - use a monotonous timer for the connection (#3570) ([lucas-clemente/quic-go#3570](https://github.com/lucas-clemente/quic-go/pull/3570)) + - http3: add http3.Server.ServeQUICConn to serve a single QUIC connection (#3587) ([lucas-clemente/quic-go#3587](https://github.com/lucas-clemente/quic-go/pull/3587)) + - http3: expose ALPN values (#3580) ([lucas-clemente/quic-go#3580](https://github.com/lucas-clemente/quic-go/pull/3580)) + - log the size of buffered packets (#3571) ([lucas-clemente/quic-go#3571](https://github.com/lucas-clemente/quic-go/pull/3571)) + - ackhandler: reject duplicate packets in ReceivedPacket (#3568) ([lucas-clemente/quic-go#3568](https://github.com/lucas-clemente/quic-go/pull/3568)) + - reduce max DATAGRAM frame size, so that DATAGRAMs fit in IPv6 packets (#3581) ([lucas-clemente/quic-go#3581](https://github.com/lucas-clemente/quic-go/pull/3581)) + - use a Peek / Pop API for the datagram queue (#3582) ([lucas-clemente/quic-go#3582](https://github.com/lucas-clemente/quic-go/pull/3582)) + - http3: handle ErrAbortHandler when the handler panics (#3575) ([lucas-clemente/quic-go#3575](https://github.com/lucas-clemente/quic-go/pull/3575)) + - http3: fix double close of chan when using DontCloseRequestStream (#3561) ([lucas-clemente/quic-go#3561](https://github.com/lucas-clemente/quic-go/pull/3561)) + - qlog: rename key_retired to key_discarded (#3463) ([lucas-clemente/quic-go#3463](https://github.com/lucas-clemente/quic-go/pull/3463)) + - simplify packing of ACK-only packets ([lucas-clemente/quic-go#3545](https://github.com/lucas-clemente/quic-go/pull/3545)) + - use a sync.Pool for ACK frames ([lucas-clemente/quic-go#3547](https://github.com/lucas-clemente/quic-go/pull/3547)) + - prioritize sending ACKs over sending new DATAGRAM frames (#3544) ([lucas-clemente/quic-go#3544](https://github.com/lucas-clemente/quic-go/pull/3544)) + - http3: reduce usage of bytes.Buffer (#3539) ([lucas-clemente/quic-go#3539](https://github.com/lucas-clemente/quic-go/pull/3539)) + - use a single bytes.Reader for frame parsing (#3536) ([lucas-clemente/quic-go#3536](https://github.com/lucas-clemente/quic-go/pull/3536)) + - split code paths for packing 0-RTT and 1-RTT packets in packet packer (#3540) ([lucas-clemente/quic-go#3540](https://github.com/lucas-clemente/quic-go/pull/3540)) + - remove the wire.ShortHeader in favor of more return values (#3535) ([lucas-clemente/quic-go#3535](https://github.com/lucas-clemente/quic-go/pull/3535)) + - preallocate the message buffers of the ipv4.Message passed to ReadBatch (#3541) ([lucas-clemente/quic-go#3541](https://github.com/lucas-clemente/quic-go/pull/3541)) + - introduce a separate code paths for Short Header packet handling ([lucas-clemente/quic-go#3534](https://github.com/lucas-clemente/quic-go/pull/3534)) + - fix usage of ackhandler.Packet pool for non-ack-eliciting packets (#3538) ([lucas-clemente/quic-go#3538](https://github.com/lucas-clemente/quic-go/pull/3538)) + - return an error when parsing a too long connection ID from a header (#3533) ([lucas-clemente/quic-go#3533](https://github.com/lucas-clemente/quic-go/pull/3533)) + - speed up marshaling of transport parameters (#3531) ([lucas-clemente/quic-go#3531](https://github.com/lucas-clemente/quic-go/pull/3531)) + - use a struct containing an array to represent Connection IDs ([lucas-clemente/quic-go#3529](https://github.com/lucas-clemente/quic-go/pull/3529)) + - reduce allocations of ackhandler.Packet ([lucas-clemente/quic-go#3525](https://github.com/lucas-clemente/quic-go/pull/3525)) + - serialize frames by appending to a byte slice, not to a bytes.Buffer ([lucas-clemente/quic-go#3530](https://github.com/lucas-clemente/quic-go/pull/3530)) + - fix datagram RFC number in documentation for quic.Config (#3523) ([lucas-clemente/quic-go#3523](https://github.com/lucas-clemente/quic-go/pull/3523)) + - add DPLPMTUD (RFC 8899) to list of supported RFCs in README (#3520) ([lucas-clemente/quic-go#3520](https://github.com/lucas-clemente/quic-go/pull/3520)) + - use the null tracers in the tracer integration tests (#3528) ([lucas-clemente/quic-go#3528](https://github.com/lucas-clemente/quic-go/pull/3528)) +- github.com/marten-seemann/webtransport-go (v0.1.1 -> v0.4.3): + - release v0.4.3 (#57) ([marten-seemann/webtransport-go#57](https://github.com/marten-seemann/webtransport-go/pull/57)) + - return the correct error from OpenStreamSync when context is canceled (#55) ([marten-seemann/webtransport-go#55](https://github.com/marten-seemann/webtransport-go/pull/55)) + - release v0.4.2 (#54) ([marten-seemann/webtransport-go#54](https://github.com/marten-seemann/webtransport-go/pull/54)) + - use a buffered channel in the acceptQueue (#53) ([marten-seemann/webtransport-go#53](https://github.com/marten-seemann/webtransport-go/pull/53)) + - add a comment why using (a blocking) Read in the StreamHijacker is fine + - release v0.4.1 (#52) ([marten-seemann/webtransport-go#52](https://github.com/marten-seemann/webtransport-go/pull/52)) + - release session mutex when an error occurs when closing (#51) ([marten-seemann/webtransport-go#51](https://github.com/marten-seemann/webtransport-go/pull/51)) + - release v0.4.0 (#48) ([marten-seemann/webtransport-go#48](https://github.com/marten-seemann/webtransport-go/pull/48)) + - add a Server.ServeQUICConn method (#47) ([marten-seemann/webtransport-go#47](https://github.com/marten-seemann/webtransport-go/pull/47)) + - release v0.3.0 (#46) ([marten-seemann/webtransport-go#46](https://github.com/marten-seemann/webtransport-go/pull/46)) + - read and write CLOSE_WEBTRANSPORT_SESSION capsules ([marten-seemann/webtransport-go#40](https://github.com/marten-seemann/webtransport-go/pull/40)) + - implement the SetDeadline method on the stream (#44) ([marten-seemann/webtransport-go#44](https://github.com/marten-seemann/webtransport-go/pull/44)) + - expose the QUIC stream ID on the stream interfaces (#43) ([marten-seemann/webtransport-go#43](https://github.com/marten-seemann/webtransport-go/pull/43)) + - release v0.2.0 (#38) ([marten-seemann/webtransport-go#38](https://github.com/marten-seemann/webtransport-go/pull/38)) + - expose quic-go's connection tracing ID on the Session.Context (#35) ([marten-seemann/webtransport-go#35](https://github.com/marten-seemann/webtransport-go/pull/35)) + - add a ConnectionState method to the Session (#33) ([marten-seemann/webtransport-go#33](https://github.com/marten-seemann/webtransport-go/pull/33)) + - chore: update quic-go to v0.30.0 (#36) ([marten-seemann/webtransport-go#36](https://github.com/marten-seemann/webtransport-go/pull/36)) + - fix interop build (#37) ([marten-seemann/webtransport-go#37](https://github.com/marten-seemann/webtransport-go/pull/37)) + - rename session receiver variable (#34) ([marten-seemann/webtransport-go#34](https://github.com/marten-seemann/webtransport-go/pull/34)) + - fix double close of chan when using DontCloseRequestStream (#30) ([marten-seemann/webtransport-go#30](https://github.com/marten-seemann/webtransport-go/pull/30)) + - add a simple integration test using Selenium and a headless Chrome (#28) ([marten-seemann/webtransport-go#28](https://github.com/marten-seemann/webtransport-go/pull/28)) + - use a generic accept queue for uni- and bidirectional streams (#26) ([marten-seemann/webtransport-go#26](https://github.com/marten-seemann/webtransport-go/pull/26)) +- github.com/multiformats/go-base36 (v0.1.0 -> v0.2.0): + - v0.2.0 + - sync: update CI config files (#11) ([multiformats/go-base36#11](https://github.com/multiformats/go-base36/pull/11)) + - fix link to documentation (#9) ([multiformats/go-base36#9](https://github.com/multiformats/go-base36/pull/9)) + - sync: update CI config files (#8) ([multiformats/go-base36#8](https://github.com/multiformats/go-base36/pull/8)) + - Address `staticcheck` issue ([multiformats/go-base36#5](https://github.com/multiformats/go-base36/pull/5)) + - Feat/fasterer ([multiformats/go-base36#4](https://github.com/multiformats/go-base36/pull/4)) +- github.com/multiformats/go-multiaddr (v0.7.0 -> v0.8.0): + - release v0.8.0 ([multiformats/go-multiaddr#187](https://github.com/multiformats/go-multiaddr/pull/187)) + - Add quic-v1 component ([multiformats/go-multiaddr#186](https://github.com/multiformats/go-multiaddr/pull/186)) +- github.com/multiformats/go-varint (v0.0.6 -> v0.0.7): + - v0.0.7 ([multiformats/go-varint#18](https://github.com/multiformats/go-varint/pull/18)) + - feat: optimize decoding (#15) ([multiformats/go-varint#15](https://github.com/multiformats/go-varint/pull/15)) + - sync: update CI config files (#13) ([multiformats/go-varint#13](https://github.com/multiformats/go-varint/pull/13)) + - fix staticcheck ([multiformats/go-varint#9](https://github.com/multiformats/go-varint/pull/9)) + - tests for unbounded uvarint streams. ([multiformats/go-varint#7](https://github.com/multiformats/go-varint/pull/7)) +- github.com/whyrusleeping/cbor-gen (v0.0.0-20210219115102-f37d292932f2 -> v0.0.0-20221220214510-0333c149dec0): + - fix bug in consts code + - Allow 'const' fields to be declared ([whyrusleeping/cbor-gen#78](https://github.com/whyrusleeping/cbor-gen/pull/78)) + - support omitting empty fields on map encoders ([whyrusleeping/cbor-gen#77](https://github.com/whyrusleeping/cbor-gen/pull/77)) + - support string pointers + - feat: add the ability to encode a byte array (#76) ([whyrusleeping/cbor-gen#76](https://github.com/whyrusleeping/cbor-gen/pull/76)) + - support string slices (#73) ([whyrusleeping/cbor-gen#73](https://github.com/whyrusleeping/cbor-gen/pull/73)) + - Feat/size types ([whyrusleeping/cbor-gen#69](https://github.com/whyrusleeping/cbor-gen/pull/69)) + - Add CborReader and CborWriter (#67) ([whyrusleeping/cbor-gen#67](https://github.com/whyrusleeping/cbor-gen/pull/67)) + - Fix broken TestTimeIsh (#66) ([whyrusleeping/cbor-gen#66](https://github.com/whyrusleeping/cbor-gen/pull/66)) + - Return EOF and ErrUnexpectedEOF correctly (#64) ([whyrusleeping/cbor-gen#64](https://github.com/whyrusleeping/cbor-gen/pull/64)) + - fix: don't fail if we try to discard nothing at the end of an object ([whyrusleeping/cbor-gen#63](https://github.com/whyrusleeping/cbor-gen/pull/63)) + - Make peeker.ReadByte follow buffer.ReadByte semantics ([whyrusleeping/cbor-gen#61](https://github.com/whyrusleeping/cbor-gen/pull/61)) + - Fix read bug in readByteBuf ([whyrusleeping/cbor-gen#60](https://github.com/whyrusleeping/cbor-gen/pull/60)) + - support for cborgen struct field tags ([whyrusleeping/cbor-gen#58](https://github.com/whyrusleeping/cbor-gen/pull/58)) + - feat: take cbor adapters by-value when encoding ([whyrusleeping/cbor-gen#55](https://github.com/whyrusleeping/cbor-gen/pull/55)) + - fix: import "math" in generated code for uint8 unmarshalling ([whyrusleeping/cbor-gen#53](https://github.com/whyrusleeping/cbor-gen/pull/53)) + - doc: document Write*EncodersToFile functions ([whyrusleeping/cbor-gen#52](https://github.com/whyrusleeping/cbor-gen/pull/52)) + +
+ +### 👨‍👩‍👧‍👦 Contributors + +| Contributor | Commits | Lines ± | Files Changed | +|-------------|---------|---------|---------------| +| Marten Seemann | 154 | +8826/-6369 | 911 | +| Gus Eggert | 7 | +2792/-1444 | 40 | +| Marco Munizaga | 26 | +2324/-752 | 101 | +| hannahhoward | 7 | +695/-1587 | 50 | +| Rod Vagg | 30 | +1508/-668 | 106 | +| Henrique Dias | 13 | +1321/-431 | 85 | +| Yahya Hassanzadeh | 4 | +984/-158 | 9 | +| galargh | 17 | +519/-520 | 20 | +| Steve Loeppky | 11 | +612/-418 | 25 | +| Antonio Navarro Perez | 30 | +742/-88 | 47 | +| Marcin Rataj | 19 | +377/-407 | 52 | +| Ian Davis | 2 | +419/-307 | 7 | +| whyrusleeping | 5 | +670/-28 | 17 | +| Piotr Galar | 8 | +211/-417 | 25 | +| web3-bot | 28 | +282/-264 | 75 | +| Will Scott | 10 | +428/-103 | 19 | +| julian88110 | 2 | +367/-55 | 27 | +| Will | 5 | +282/-131 | 65 | +| Jorropo | 25 | +263/-94 | 38 | +| Wondertan | 10 | +203/-87 | 24 | +| Mohsin Zaidi | 1 | +269/-0 | 4 | +| Dennis Trautwein | 3 | +230/-21 | 7 | +| Prithvi Shahi | 1 | +116/-77 | 1 | +| Masih H. Derkani | 5 | +130/-37 | 11 | +| Iulian Pascalau | 1 | +151/-16 | 2 | +| Scott Martin | 1 | +166/-0 | 3 | +| Daniel Vernall | 1 | +92/-45 | 2 | +| Steven Allen | 7 | +114/-15 | 11 | +| Hlib Kanunnikov | 4 | +100/-28 | 6 | +| Peter Rabbitson | 4 | +59/-65 | 5 | +| Lucas Molas | 1 | +60/-57 | 7 | +| nisdas | 3 | +107/-6 | 5 | +| why | 2 | +80/-20 | 5 | +| ShengTao | 2 | +46/-45 | 16 | +| nisainan | 2 | +40/-50 | 12 | +| Mikel Cortes | 3 | +44/-36 | 10 | +| Chinmay Kousik | 1 | +64/-14 | 6 | +| ZenGround0 | 2 | +62/-15 | 6 | +| Antonio Navarro | 3 | +58/-3 | 8 | +| Michael Muré | 2 | +49/-2 | 2 | +| Dirk McCormick | 1 | +3/-42 | 1 | +| kixelated | 1 | +20/-20 | 4 | +| Russell Dempsey | 1 | +19/-17 | 3 | +| Karthik Nallabolu | 1 | +17/-17 | 1 | +| protolambda | 1 | +26/-4 | 4 | +| cliffc-spirent | 1 | +25/-5 | 2 | +| Raúl Kripalani | 1 | +29/-0 | 1 | +| Håvard Anda Estensen | 1 | +9/-19 | 6 | +| vyzo | 1 | +11/-12 | 1 | +| anorth | 1 | +15/-8 | 3 | +| shade34321 | 1 | +21/-1 | 2 | +| Toby | 2 | +9/-13 | 6 | +| Nishant Das | 1 | +9/-9 | 5 | +| Jeromy Johnson | 1 | +17/-0 | 3 | +| Oleg | 1 | +14/-1 | 1 | +| Hector Sanjuan | 6 | +4/-11 | 6 | +| Łukasz Magiera | 2 | +10/-4 | 2 | +| Aayush Rajasekaran | 1 | +7/-7 | 1 | +| Adin Schmahmann | 1 | +4/-3 | 1 | +| Stojan Dimitrovski | 1 | +6/-0 | 1 | +| Mathew Jacob | 1 | +3/-3 | 1 | +| Vladimir Ivanov | 1 | +2/-2 | 1 | +| Nex Zhu | 1 | +4/-0 | 2 | +| Michele Mastrogiovanni | 1 | +2/-2 | 1 | +| Louis Thibault | 1 | +4/-0 | 1 | +| Eric Myhre | 1 | +3/-1 | 1 | +| Kubo Mage | 2 | +2/-1 | 2 | +| tabcat | 1 | +1/-1 | 1 | +| Viacheslav | 1 | +1/-1 | 1 | +| Max Inden | 1 | +1/-1 | 1 | +| Manic Security | 1 | +1/-1 | 1 | +| Jc0803kevin | 1 | +1/-1 | 1 | +| David Brouwer | 1 | +2/-0 | 2 | +| Rong Zhou | 1 | +1/-0 | 1 | +| Neel Virdy | 1 | +1/-0 | 1 | diff --git a/docs/changelogs/v0.19.md b/docs/changelogs/v0.19.md new file mode 100644 index 000000000..e1c28482d --- /dev/null +++ b/docs/changelogs/v0.19.md @@ -0,0 +1,18 @@ +# Kubo changelog v0.19 + +- [v0.19.0](#v0190) + +## v0.19.0 + +- [Overview](#overview) +- [🔦 Highlights](#-highlights) +- [📝 Changelog](#-changelog) +- [👨‍👩‍👧‍👦 Contributors](#-contributors) + +### Overview + +### 🔦 Highlights + +### 📝 Changelog + +### 👨‍👩‍👧‍👦 Contributors diff --git a/docs/config.md b/docs/config.md index 2aba83291..995872c4f 100644 --- a/docs/config.md +++ b/docs/config.md @@ -71,6 +71,7 @@ config file at runtime. - [`Internal.Bitswap.EngineBlockstoreWorkerCount`](#internalbitswapengineblockstoreworkercount) - [`Internal.Bitswap.EngineTaskWorkerCount`](#internalbitswapenginetaskworkercount) - [`Internal.Bitswap.MaxOutstandingBytesPerPeer`](#internalbitswapmaxoutstandingbytesperpeer) + - [`Internal.Bitswap.ProviderSearchDelay`](#internalbitswapprovidersearchdelay) - [`Internal.UnixFSShardingSizeThreshold`](#internalunixfsshardingsizethreshold) - [`Ipns`](#ipns) - [`Ipns.RepublishPeriod`](#ipnsrepublishperiod) @@ -99,17 +100,18 @@ config file at runtime. - [`Pubsub.Router`](#pubsubrouter) - [`Pubsub.DisableSigning`](#pubsubdisablesigning) - [`Pubsub.SeenMessagesTTL`](#pubsubseenmessagesttl) + - [`Pubsub.SeenMessagesStrategy`](#pubsubseenmessagesstrategy) - [`Peering`](#peering) - [`Peering.Peers`](#peeringpeers) - [`Reprovider`](#reprovider) - [`Reprovider.Interval`](#reproviderinterval) - [`Reprovider.Strategy`](#reproviderstrategy) - [`Routing`](#routing) + - [`Routing.Type`](#routingtype) - [`Routing.Routers`](#routingrouters) - [`Routing.Routers: Type`](#routingrouters-type) - [`Routing.Routers: Parameters`](#routingrouters-parameters) - [`Routing: Methods`](#routing-methods) - - [`Routing.Type`](#routingtype) - [`Swarm`](#swarm) - [`Swarm.AddrFilters`](#swarmaddrfilters) - [`Swarm.DisableBandwidthMetrics`](#swarmdisablebandwidthmetrics) @@ -141,10 +143,6 @@ config file at runtime. - [`Swarm.ConnMgr.HighWater`](#swarmconnmgrhighwater) - [`Swarm.ConnMgr.GracePeriod`](#swarmconnmgrgraceperiod) - [`Swarm.ResourceMgr`](#swarmresourcemgr) - - [Levels of Configuration](#levels-of-configuration) - - [Default Limits](#default-limits) - - [Active Limits](#active-limits) - - [libp2p resource monitoring](#libp2p-resource-monitoring) - [`Swarm.ResourceMgr.Enabled`](#swarmresourcemgrenabled) - [`Swarm.ResourceMgr.MaxMemory`](#swarmresourcemgrmaxmemory) - [`Swarm.ResourceMgr.MaxFileDescriptors`](#swarmresourcemgrmaxfiledescriptors) @@ -157,7 +155,6 @@ config file at runtime. - [`Swarm.Transports.Network.QUIC`](#swarmtransportsnetworkquic) - [`Swarm.Transports.Network.Relay`](#swarmtransportsnetworkrelay) - [`Swarm.Transports.Network.WebTransport`](#swarmtransportsnetworkwebtransport) - - [How to enable WebTransport](#how-to-enable-webtransport) - [`Swarm.Transports.Security`](#swarmtransportssecurity) - [`Swarm.Transports.Security.TLS`](#swarmtransportssecuritytls) - [`Swarm.Transports.Security.SECIO`](#swarmtransportssecuritysecio) @@ -373,8 +370,9 @@ Supported Transports: * tcp/ip{4,6} - `/ipN/.../tcp/...` * websocket - `/ipN/.../tcp/.../ws` -* quic - `/ipN/.../udp/.../quic` -* webtransport (*experiemental*) - `/ipN/.../udp/.../quic/webtransport` - require using a different port than the QUIC listener for now +* quic (Draft-29) - `/ipN/.../udp/.../quic` - can share the same two tuple with `/quic-v1` and `/quic-v1/webtransport` +* quicv1 (RFC9000) - `/ipN/.../udp/.../quic-v1` - can share the same two tuple with `/quic` and `/quic-v1/webtransport` +* webtransport `/ipN/.../udp/.../quic-v1/webtransport` - can share the same two tuple with `/quic` and `/quic-v1` Default: ```json @@ -382,7 +380,11 @@ Default: "/ip4/0.0.0.0/tcp/4001", "/ip6/::/tcp/4001", "/ip4/0.0.0.0/udp/4001/quic", - "/ip6/::/udp/4001/quic" + "/ip4/0.0.0.0/udp/4001/quic-v1", + "/ip4/0.0.0.0/udp/4001/quic-v1/webtransport", + "/ip6/::/udp/4001/quic", + "/ip6/::/udp/4001/quic-v1", + "/ip6/::/udp/4001/quic-v1/webtransport" ] ``` @@ -676,17 +678,7 @@ Type: `string` (url) ### `Gateway.FastDirIndexThreshold` -The maximum number of items in a directory before the Gateway switches -to a shallow, faster listing which only requires the root node. - -This allows for fast listings of big directories, without the linear slowdown caused -by reading size metadata from child nodes. - -Setting to 0 will enable fast listings for all directories. - -Default: `100` - -Type: `optionalInteger` +**REMOVED**: this option is [no longer necessary](https://github.com/ipfs/kubo/pull/9481). Ignored since [Kubo 0.18](https://github.com/ipfs/kubo/blob/master/docs/changelogs/v0.18.md). ### `Gateway.Writable` @@ -979,6 +971,14 @@ deteriorate the quality provided to less aggressively-wanting peers. Type: `optionalInteger` (byte count, `null` means default which is 1MB) +### `Internal.Bitswap.ProviderSearchDelay` + +This parameter determines how long to wait before looking for providers outside of bitswap. +Other routing systems like the DHT are able to provide results in less than a second, so lowering +this number will allow faster peers lookups in some cases. + +Type: `optionalDuration` (`null` means default which is 1s) + ### `Internal.UnixFSShardingSizeThreshold` The sharding threshold used internally to decide whether a UnixFS directory should be sharded or not. @@ -1207,13 +1207,13 @@ Type: `bool` ### `Pubsub.SeenMessagesTTL` -Configures the duration after which a previously seen Pubsub Message ID can be -forgotten about. +Controls the time window within which duplicate messages, identified by Message +ID, will be identified and won't be emitted again. A smaller value for this parameter means that Pubsub messages in the cache will be garbage collected sooner, which can result in a smaller cache. At the same time, if there are slower nodes in the network that forward older messages, -this can cause more duplicates to be propagated through the network. +this can cause more duplicates to be propagated through the network. Conversely, a larger value for this parameter means that Pubsub messages in the cache will be garbage collected later, which can result in a larger cache for @@ -1224,6 +1224,29 @@ Default: see `TimeCacheDuration` from [go-libp2p-pubsub](https://github.com/libp Type: `optionalDuration` +### `Pubsub.SeenMessagesStrategy` + +Determines how the time-to-live (TTL) countdown for deduplicating Pubsub +messages is calculated. + +The Pubsub seen messages cache is a LRU cache that keeps messages for up to a +specified time duration. After this duration has elapsed, expired messages will +be purged from the cache. + +The `last-seen` cache is a sliding-window cache. Every time a message is seen +again with the SeenMessagesTTL duration, its timestamp slides forward. This +keeps frequently occurring messages cached and prevents them from being +continually propagated, especially because of issues that might increase the +number of duplicate messages in the network. + +The `first-seen` cache will store new messages and purge them after the +SeenMessagesTTL duration, even if they are seen multiple times within this +duration. + +Default: `last-seen` (see [go-libp2p-pubsub](https://github.com/libp2p/go-libp2p-pubsub)) + +Type: `optionalString` + ## `Peering` Configures the peering subsystem. The peering subsystem configures Kubo to @@ -1322,6 +1345,49 @@ Type: `string` (or unset for the default, which is "all") Contains options for content, peer, and IPNS routing mechanisms. +### `Routing.Type` + +There are multiple routing options: "auto", "none", "dht" and "custom". + +* **DEFAULT:** If unset, or set to "auto", your node will use the IPFS DHT + and parallel HTTP routers listed below for additional speed. + +* If set to "none", your node will use _no_ routing system. You'll have to + explicitly connect to peers that have the content you're looking for. + +* If set to "dht" (or "dhtclient"/"dhtserver"), your node will ONLY use the IPFS DHT (no HTTP routers). + +* If set to "custom", all default routers are disabled, and only ones defined in `Routing.Routers` will be used. + +When the DHT is enabled, it can operate in two modes: client and server. + +* In server mode, your node will query other peers for DHT records, and will + respond to requests from other peers (both requests to store records and + requests to retrieve records). + +* In client mode, your node will query the DHT as a client but will not respond + to requests from other peers. This mode is less resource-intensive than server + mode. + +When `Routing.Type` is set to `auto` or `dht`, your node will start as a DHT client, and +switch to a DHT server when and if it determines that it's reachable from the +public internet (e.g., it's not behind a firewall). + +To force a specific DHT-only mode, client or server, set `Routing.Type` to +`dhtclient` or `dhtserver` respectively. Please do not set this to `dhtserver` +unless you're sure your node is reachable from the public network. + +When `Routing.Type` is set to `auto` your node will accelerate some types of routing +by leveraging HTTP endpoints compatible with [IPIP-337](https://github.com/ipfs/specs/pull/337) +in addition to the IPFS DHT. +By default, an instance of [IPNI](https://github.com/ipni/specs/blob/main/IPNI.md#readme) +at https://cid.contact is used. +Alternative routing rules can be configured in `Routing.Routers` after setting `Routing.Type` to `custom`. + +Default: `auto` (DHT + IPNI) + +Type: `optionalString` (`null`/missing means the default) + ### `Routing.Routers` **EXPERIMENTAL: `Routing.Routers` configuration may change in future release** @@ -1345,9 +1411,8 @@ It specifies the routing type that will be created. Currently supported types: -- `reframe` **(DEPRECATED)** (delegated routing based on the [reframe protocol](https://github.com/ipfs/specs/tree/main/reframe#readme)) -- `http` simple delegated routing based on HTTP protocol. -- `dht` +- `http` simple delegated routing based on HTTP protocol from [IPIP-337](https://github.com/ipfs/specs/pull/337) +- `dht` provides decentralized routing based on [libp2p's kad-dht](https://github.com/libp2p/specs/tree/master/kad-dht) - `parallel` and `sequential`: Helpers that can be used to run several routers sequentially or in parallel. Type: `string` @@ -1358,9 +1423,6 @@ Type: `string` Parameters needed to create the specified router. Supported params per router type: -Reframe **(DEPRECATED)**: - - `Endpoint` (mandatory): URL that will be used to connect to a specified router. - HTTP: - `Endpoint` (mandatory): URL that will be used to connect to a specified router. - `MaxProvideBatchSize`: This number determines the maximum amount of CIDs sent per batch. Servers might not accept more than 100 elements per batch. 100 elements by default. @@ -1463,46 +1525,6 @@ ipfs config Routing.Methods --json '{ ``` -### `Routing.Type` - -There are three core routing options: "none", "dht" (default) and "custom". - -* If set to "none", your node will use _no_ routing system. You'll have to - explicitly connect to peers that have the content you're looking for. -* If set to "dht" (or "dhtclient"/"dhtserver"), your node will use the IPFS DHT. -* If set to "custom", `Routing.Routers` will be used. - -When the DHT is enabled, it can operate in two modes: client and server. - -* In server mode, your node will query other peers for DHT records, and will - respond to requests from other peers (both requests to store records and - requests to retrieve records). -* In client mode, your node will query the DHT as a client but will not respond - to requests from other peers. This mode is less resource-intensive than server - mode. - -When `Routing.Type` is set to `dht`, your node will start as a DHT client, and -switch to a DHT server when and if it determines that it's reachable from the -public internet (e.g., it's not behind a firewall). - -To force a specific DHT mode, client or server, set `Routing.Type` to -`dhtclient` or `dhtserver` respectively. Please do not set this to `dhtserver` -unless you're sure your node is reachable from the public network. - -**Example:** - -```json -{ - "Routing": { - "Type": "dhtclient" - } -} -``` - -Default: `dht` - -Type: `optionalString` (`null`/missing means the default) - ## `Swarm` Options for configuring the swarm. @@ -1778,7 +1800,7 @@ The connection manager considers a connection idle if: LowWater is the number of connections that the basic connection manager will trim down to. -Default: `50` +Default: `32` Type: `optionalInteger` @@ -1788,7 +1810,7 @@ HighWater is the number of connections that, when exceeded, will trigger a connection GC operation. Note: protected/recently formed connections don't count towards this limit. -Default: `150` +Default: `96` Type: `optionalInteger` @@ -1803,66 +1825,12 @@ Type: `optionalDuration` ### `Swarm.ResourceMgr` -The [libp2p Network Resource Manager](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#readme) allows setting limits per [Resource Scope](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#resource-scopes), -and tracking recource usage over time. - -##### Levels of Configuration - -libp2p's resource manager provides tremendous flexibility but also adds a lot of complexity. -There are these levels of limit configuration for resource management protection: -1. "The user who does nothing" - In this case they get some sane defaults discussed below - based on the amount of memory and file descriptors their system has. - This should protect the node from many attacks. -2. "Slightly more advanced user" - They can tweak the default limits discussed below. - Where the defaults aren't good enough, a good set of higher-level "knobs" are exposed to satisfy most use cases - without requiring users to wade into all the intricacies of libp2p's resource manager. - The "knobs"/inputs are `Swarm.ResourceMgr.MaxMemory` and `Swarm.ResourceMgr.MaxFileDescriptors` as described below. -3. "Power user" - They specify all the default limits from below they want override via `Swarm.ResourceMgr.Limits`; - -##### Default Limits - -With these inputs defined, [resource manager limits](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#limits) are created at the -[system](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#the-system-scope), -[transient](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#the-transient-scope), -and [peer](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#peer-scopes) scopes. -Other scopes are ignored (by being set to "~infinity". - -The reason these scopes are chosen is because: -- system - This gives us the coarse-grained control we want so we can reason about the system as a whole. - It is the backstop, and allows us to reason about resource consumption more easily - since don't have think about the interaction of many other scopes. -- transient - Limiting connections that are in process of being established provides backpressure so not too much work queues up. -- peer - The peer scope doesn't protect us against intentional DoS attacks. - It's just as easy for an attacker to send 100 requests/second with 1 peerId vs. 10 requests/second with 10 peers. - We are reliant on the system scope for protection here in the malicious case. - The reason for having a peer scope is to protect against unintentional DoS attacks - (e.g., bug in a peer which is causing it to "misbehave"). - In the unintional case, we want to make sure a "misbehaving" node doesn't consume more resources than necessary. - -Within these scopes, limits are just set on -[memory](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#memory), -[file descriptors (FD)](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#file-descriptors), [*inbound* connections](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#connections), -and [*inbound* streams](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#streams). -Limits are set based on the inputs above. -We trust this node to behave properly and thus don't limit *outbound* connection/stream limits. -We apply any limits that libp2p has for its protocols/services -since we assume libp2p knows best here. - -##### Active Limits -A dump of what limits were computed and are actually being used by the resource manager -can be obtained by `ipfs swarm limit all`. - -##### libp2p resource monitoring -For [monitoring libp2p resource usage](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#monitoring), -various `*rcmgr_*` metrics can be accessed as the prometheus endpoint at `{Addresses.API}/debug/metrics/prometheus` (default: `http://127.0.0.1:5001/debug/metrics/prometheus`). -There are also [pre-built Grafana dashboards](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager/obs/grafana-dashboards) that can be added to a Grafana instance. - -A textual view of current resource usage and a list of services, protocols, and peers can be -obtained via `ipfs swarm stats --help` +Learn more about Kubo's usage of libp2p Network Resource Manager +in the [dedicated resource management docs](./libp2p-resource-management.md). #### `Swarm.ResourceMgr.Enabled` -Enables the libp2p Resource Manager using limits based on the defaults and/or other configuration as discussed above. +Enables the libp2p Resource Manager using limits based on the defaults and/or other configuration as discussed in [libp2p resource management](./libp2p-resource-management.md). Default: `true` Type: `flag` @@ -1871,11 +1839,11 @@ Type: `flag` This is the max amount of memory to allow libp2p to use. libp2p's resource manager will prevent additional resource creation while this limit is reached. -This value is also used to scale the limit on various resources at various scopes -when the default limits (discuseed above) are used. +This value is also used to scale the limit on various resources at various scopes +when the default limits (discussed in [libp2p resource management](./libp2p-resource-management.md)) are used. For example, increasing this value will increase the default limit for incoming connections. -Default: `[TOTAL_SYSTEM_MEMORY]/4` +Default: `[TOTAL_SYSTEM_MEMORY]/2` Type: `optionalBytes` #### `Swarm.ResourceMgr.MaxFileDescriptors` @@ -1896,9 +1864,12 @@ The map supports fields from the [`LimitConfig` struct](https://github.com/libp2 [`BaseLimit`s](https://github.com/libp2p/go-libp2p/blob/master/p2p/host/resource-manager/limit.go#L89) can be set for any scope, and within the `BaseLimit`, all limit s are optional. -The `Swarm.ResourceMgr.Limits` override the default limits described above. +The `Swarm.ResourceMgr.Limits` override the default limits described above. Any override `BaseLimits` or limit s from `Swarm.ResourceMgr.Limits` -that aren't specified will use the default limits. +that aren't specified will use the [computed default limits](./libp2p-resource-management.md#computed-default-limits). + +Until [ipfs/kubo#9564](https://github.com/ipfs/kubo/issues/9564) is addressed, there isn't a way to set an override limit of zero. +0 is currently ignored. 0 currently means use to use the [computed default limits](./libp2p-resource-management.md#computed-default-limits). Example #1: setting limits for a specific scope ```json @@ -1937,10 +1908,10 @@ Example #2: setting a specific limit } ``` -It is also possible to adjust some runtime limits via `ipfs swarm limit --help`. +It is also possible to inspect and adjust some runtime limits via `ipfs swarm stats --help` and `ipfs swarm limit --help`. Changes made via `ipfs swarm limit` are persisted in `Swarm.ResourceMgr.Limits`. -Default: `{}` (use the safe implicit defaults described above) +Default: `{}` (use the [computed defaults](./libp2p-resource-management.md#computed-default-limits)) Type: `object[string->object]` @@ -2051,38 +2022,16 @@ Since this runs on top of `HTTP/3` it uses `QUIC` under the hood. We expect it to perform worst than `QUIC` because of the extra overhead, this transport is really meant at agents that cannot do `TCP` or `QUIC` (like browsers). -For now it is **disabled by default** and considered **experimental**. -If you find issues running it please [report them to us](https://github.com/ipfs/kubo/issues/new). - -In the future Kubo will listen on WebTransport by default for anyone already listening on QUIC addresses. - WebTransport is a new transport protocol currently under development by the IETF and the W3C, and already implemented by Chrome. Conceptually, it’s like WebSocket run over QUIC instead of TCP. Most importantly, it allows browsers to establish (secure!) connections to WebTransport servers without the need for CA-signed certificates, thereby enabling any js-libp2p node running in a browser to connect to any kubo node, with zero manual configuration involved. The previous alternative is websocket secure, which require installing a reverse proxy and TLS certificates manually. -Default: Disabled +Default: Enabled Type: `flag` - -##### How to enable WebTransport - -Thoses steps are temporary and wont be needed once we make it enabled by default. - -1. Enable the WebTransport transport: - `ipfs config Swarm.Transports.Network.WebTransport --json true` -1. Add a listener address for WebTransport to your `Addresses.Swarm` key, for example: - ```json - [ - "/ip4/0.0.0.0/tcp/4001", - "/ip4/0.0.0.0/udp/4001/quic", - "/ip4/0.0.0.0/udp/4002/quic/webtransport" - ] - ``` -1. Restart your daemon to apply the config changes. - ### `Swarm.Transports.Security` Configuration section for libp2p _security_ transports. Transports enabled in diff --git a/docs/environment-variables.md b/docs/environment-variables.md index 98b449054..ba1cce166 100644 --- a/docs/environment-variables.md +++ b/docs/environment-variables.md @@ -75,13 +75,13 @@ Warning: Enabling tracing will likely affect performance. ## `IPFS_FUSE_DEBUG` -Enables fuse debug logging. +If SET, enables fuse debug logging. Default: false ## `YAMUX_DEBUG` -Enables debug logging for the yamux stream muxer. +If SET, enables debug logging for the yamux stream muxer. Default: false @@ -114,6 +114,23 @@ $ ipfs resolve -r /ipns/dnslink-test2.example.com /ipfs/bafkreicysg23kiwv34eg2d7qweipxwosdo2py4ldv42nbauguluen5v6am ``` +## `IPFS_HTTP_ROUTERS` + +Overrides all implicit HTTP routers enabled when `Routing.Type=auto` with +the space-separated list of URLs provided in this variable. +Useful for testing and debugging in offline contexts. + +Example: + +```console +$ ipfs config Routing.Type auto +$ IPFS_HTTP_ROUTERS="http://127.0.0.1:7423" ipfs daemon +``` + +The above will replace implicit HTTP routers with single one, allowing for +inspection/debug of HTTP requests sent by Kubo via `while true ; do nc -l 7423; done` +or more advanced tools like [mitmproxy](https://docs.mitmproxy.org/stable/#mitmproxy). + ## `LIBP2P_TCP_REUSEPORT` Kubo tries to reuse the same source port for all connections to improve NAT diff --git a/docs/examples/kubo-as-a-library/go.mod b/docs/examples/kubo-as-a-library/go.mod index 8547eb31f..a74bfbf3e 100644 --- a/docs/examples/kubo-as-a-library/go.mod +++ b/docs/examples/kubo-as-a-library/go.mod @@ -7,17 +7,16 @@ go 1.18 replace github.com/ipfs/kubo => ./../../.. require ( - github.com/ipfs/go-ipfs-files v0.2.0 - github.com/ipfs/interface-go-ipfs-core v0.7.0 + github.com/ipfs/go-libipfs v0.4.1-0.20230130233950-a005a5006496 + github.com/ipfs/interface-go-ipfs-core v0.10.0 github.com/ipfs/kubo v0.0.0-00010101000000-000000000000 - github.com/libp2p/go-libp2p v0.23.4 + github.com/libp2p/go-libp2p v0.24.2 github.com/multiformats/go-multiaddr v0.8.0 ) require ( bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc // indirect github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect - github.com/Stebalien/go-bitfield v0.0.1 // indirect github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a // indirect github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect github.com/benbjohnson/clock v1.3.0 // indirect @@ -27,7 +26,7 @@ require ( github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/ceramicnetwork/go-dag-jose v0.1.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/containerd/cgroups v1.0.4 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect @@ -39,10 +38,10 @@ require ( github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect + github.com/emirpasic/gods v1.18.1 // indirect github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect @@ -52,6 +51,7 @@ require ( 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/google/pprof v0.0.0-20221203041831-ce31453925ec // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect @@ -63,9 +63,8 @@ require ( github.com/huin/goupnp v1.0.3 // 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-block-format v0.1.1 // indirect + github.com/ipfs/go-blockservice v0.5.0 // indirect github.com/ipfs/go-cid v0.3.2 // indirect github.com/ipfs/go-cidutil v0.1.0 // indirect github.com/ipfs/go-datastore v0.6.0 // indirect @@ -77,58 +76,56 @@ require ( github.com/ipfs/go-fetcher v1.6.1 // 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-graphsync v0.14.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-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-keystore v0.0.2 // indirect + github.com/ipfs/go-ipfs-keystore v0.1.0 // indirect github.com/ipfs/go-ipfs-pinner v0.2.1 // 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-provider v0.7.1 // indirect - github.com/ipfs/go-ipfs-routing v0.2.1 // indirect + github.com/ipfs/go-ipfs-provider v0.8.1 // indirect + github.com/ipfs/go-ipfs-routing v0.3.0 // indirect github.com/ipfs/go-ipfs-util v0.0.2 // indirect - github.com/ipfs/go-ipld-cbor v0.0.5 // indirect + github.com/ipfs/go-ipld-cbor v0.0.6 // indirect github.com/ipfs/go-ipld-format v0.4.0 // indirect github.com/ipfs/go-ipld-git v0.1.1 // indirect github.com/ipfs/go-ipld-legacy v0.1.1 // indirect github.com/ipfs/go-ipns v0.3.0 // indirect - github.com/ipfs/go-libipfs v0.0.0-20221207180439-c7e7738575f9 // indirect github.com/ipfs/go-log v1.0.5 // indirect github.com/ipfs/go-log/v2 v2.5.1 // indirect - github.com/ipfs/go-merkledag v0.8.1 // indirect + github.com/ipfs/go-merkledag v0.9.0 // indirect github.com/ipfs/go-metrics-interface v0.0.1 // indirect github.com/ipfs/go-mfs v0.2.1 // indirect - github.com/ipfs/go-namesys v0.5.0 // indirect + github.com/ipfs/go-namesys v0.7.0 // indirect github.com/ipfs/go-path v0.3.0 // indirect - github.com/ipfs/go-peertaskqueue v0.7.1 // indirect - github.com/ipfs/go-unixfs v0.4.1 // indirect - github.com/ipfs/go-unixfsnode v1.4.0 // indirect + github.com/ipfs/go-peertaskqueue v0.8.0 // indirect + github.com/ipfs/go-unixfs v0.4.2 // indirect + github.com/ipfs/go-unixfsnode v1.5.1 // indirect github.com/ipfs/go-verifcid v0.0.2 // indirect github.com/ipld/edelweiss v0.2.0 // indirect - github.com/ipld/go-codec-dagpb v1.4.1 // indirect + github.com/ipld/go-codec-dagpb v1.5.0 // indirect github.com/ipld/go-ipld-prime v0.19.0 // 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/klauspost/compress v1.15.12 // indirect - github.com/klauspost/cpuid/v2 v2.1.2 // indirect + github.com/klauspost/cpuid/v2 v2.2.1 // 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-doh-resolver v0.4.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-core v0.20.1 // indirect - github.com/libp2p/go-libp2p-kad-dht v0.18.0 // indirect - github.com/libp2p/go-libp2p-kbucket v0.4.7 // indirect - github.com/libp2p/go-libp2p-pubsub v0.8.1 // indirect - github.com/libp2p/go-libp2p-pubsub-router v0.5.0 // indirect + github.com/libp2p/go-libp2p-kad-dht v0.20.0 // indirect + github.com/libp2p/go-libp2p-kbucket v0.5.0 // indirect + github.com/libp2p/go-libp2p-pubsub v0.8.3 // indirect + github.com/libp2p/go-libp2p-pubsub-router v0.6.0 // indirect github.com/libp2p/go-libp2p-record v0.2.0 // indirect - github.com/libp2p/go-libp2p-routing-helpers v0.4.1 // indirect + github.com/libp2p/go-libp2p-routing-helpers v0.6.0 // indirect github.com/libp2p/go-libp2p-xor v0.1.0 // indirect github.com/libp2p/go-mplex v0.7.0 // indirect github.com/libp2p/go-msgio v0.2.0 // indirect @@ -138,13 +135,13 @@ require ( github.com/libp2p/go-reuseport v0.2.0 // indirect github.com/libp2p/go-yamux/v4 v4.0.0 // indirect github.com/libp2p/zeroconf/v2 v2.2.0 // indirect - github.com/lucas-clemente/quic-go v0.29.1 // indirect + github.com/lucas-clemente/quic-go v0.31.1 // indirect github.com/marten-seemann/qpack v0.3.0 // indirect github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect - github.com/marten-seemann/webtransport-go v0.1.1 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/marten-seemann/webtransport-go v0.4.3 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-pointer v0.0.1 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/miekg/dns v1.1.50 // indirect @@ -154,16 +151,15 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect - github.com/multiformats/go-base36 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.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.7.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/nxadm/tail v1.4.8 // indirect - github.com/onsi/ginkgo v1.16.5 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect + github.com/onsi/ginkgo/v2 v2.5.1 // indirect github.com/opencontainers/runtime-spec v1.0.2 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/openzipkin/zipkin-go v0.4.0 // indirect @@ -178,14 +174,13 @@ require ( github.com/samber/lo v1.36.0 // indirect github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/syndtr/goleveldb v1.0.0 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect - github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2 // indirect + github.com/whyrusleeping/cbor-gen v0.0.0-20221220214510-0333c149dec0 // 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/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect - github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect - go.opencensus.io v0.23.0 // indirect + go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel v1.7.0 // indirect go.opentelemetry.io/otel/exporters/jaeger v1.7.0 // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.7.0 // indirect @@ -198,24 +193,23 @@ require ( go.opentelemetry.io/otel/trace v1.7.0 // indirect go.opentelemetry.io/proto/otlp v0.16.0 // indirect go.uber.org/atomic v1.10.0 // indirect - go.uber.org/dig v1.14.1 // indirect - go.uber.org/fx v1.17.1 // indirect - go.uber.org/multierr v1.8.0 // indirect - go.uber.org/zap v1.23.0 // indirect + go.uber.org/dig v1.15.0 // indirect + go.uber.org/fx v1.18.2 // indirect + go.uber.org/multierr v1.9.0 // indirect + go.uber.org/zap v1.24.0 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect - golang.org/x/crypto v0.1.0 // indirect - golang.org/x/exp v0.0.0-20221106115401-f9659909a136 // indirect - golang.org/x/mod v0.6.0 // indirect - golang.org/x/net v0.1.0 // indirect + golang.org/x/crypto v0.3.0 // indirect + golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect + golang.org/x/mod v0.7.0 // indirect + golang.org/x/net v0.3.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.2.0 // indirect - golang.org/x/text v0.4.0 // indirect - golang.org/x/tools v0.2.0 // indirect - golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect + golang.org/x/sys v0.4.0 // indirect + golang.org/x/text v0.5.0 // indirect + golang.org/x/tools v0.3.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect - google.golang.org/grpc v1.47.0 // indirect + google.golang.org/grpc v1.46.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect - gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect lukechampine.com/blake3 v1.1.7 // indirect ) diff --git a/docs/examples/kubo-as-a-library/go.sum b/docs/examples/kubo-as-a-library/go.sum index 17252e076..eb37654f7 100644 --- a/docs/examples/kubo-as-a-library/go.sum +++ b/docs/examples/kubo-as-a-library/go.sum @@ -36,7 +36,6 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= 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= @@ -55,7 +54,6 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fTKCulPVs= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0= -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/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -81,8 +79,6 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l 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-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -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= @@ -100,12 +96,10 @@ github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcug 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/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= @@ -125,8 +119,9 @@ github.com/ceramicnetwork/go-dag-jose v0.1.0/go.mod h1:qYA1nYt0X8u4XoMAVoOV3upUV 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.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/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -150,11 +145,9 @@ github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO 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.2.1-0.20180108230905-e214231b295a/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/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= @@ -205,6 +198,8 @@ github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaB 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/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 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= @@ -218,7 +213,6 @@ github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 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/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= @@ -228,12 +222,10 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB 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.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= @@ -250,7 +242,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 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/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -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= @@ -343,6 +334,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/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/pprof v0.0.0-20221203041831-ce31453925ec h1:fR20TYVVwhK4O7r7y+McjRYyaTH6/vjwJOajE+XhlzM= +github.com/google/pprof v0.0.0-20221203041831-ce31453925ec/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= 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= @@ -380,7 +373,6 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QG github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= 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/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= @@ -392,7 +384,6 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-immutable-radix v1.0.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-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= @@ -415,7 +406,6 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 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= @@ -427,26 +417,21 @@ 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.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3UPrwvis= 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.1.8/go.mod h1:TOWoxllhccevbWFUR2N7B1MTSVVge1s6XSMiCSA4MzM= -github.com/ipfs/go-bitswap v0.3.4/go.mod h1:4T7fvNv/LmOys+21tnLzGKncMeeXUYUd1nUiJ2teMvI= 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-bitswap v0.11.0 h1:j1WVvhDX1yhG32NTC9xfxnqycqYIlhzEzLXG/cU1HyQ= 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.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbRhbvNSdgc/7So= +github.com/ipfs/go-block-format v0.1.1 h1:129vSO3zwbsYADcyQWcOYiuCpAqt462SFfqFHdFJhhI= +github.com/ipfs/go-block-format v0.1.1/go.mod h1:+McEIT+g52p+zz5xGAABGSOKrzmrdX97bc0USBdWPUs= github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= -github.com/ipfs/go-blockservice v0.1.4/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= 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-blockservice v0.5.0 h1:B2mwhhhVQl2ntW2EIpaWPwSCxSuqr5fFA93Ms4bYLEY= +github.com/ipfs/go-blockservice v0.5.0/go.mod h1:W6brZ5k20AehbmERplmERn8o2Ni3ZZubvAxaIUeaT6w= 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= @@ -457,7 +442,6 @@ github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqg github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o= github.com/ipfs/go-cid v0.3.2 h1:OGgOd+JCFM+y1DjWPmVH+2/4POtpDzwcr7VgnB7mZXc= github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svoupw= -github.com/ipfs/go-cidutil v0.0.2/go.mod h1:ewllrvrxG6AMYStla3GD7Cqn+XYSLqjK0vc+086tB6s= 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= @@ -481,7 +465,6 @@ github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaH github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= 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.2.7/go.mod h1:02rnztVKA4aZwDuaRPTf8mpqcKmXP7mLl6JPxd14JHA= 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-flatfs v0.5.1 h1:ZCIO/kQOS/PSh3vcF1H6a8fkRGS7pOfwfPdx4n/KJH4= @@ -494,20 +477,17 @@ github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUN 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.5.0/go.mod h1:5pDZ0393oRF/fHiLmtFZtpMNBQfHOYNPtryWedVuSWE= github.com/ipfs/go-fetcher v1.6.1 h1:UFuRVYX5AIllTiRhi5uK/iZkfhSpBCGX7L70nSZEmK8= 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.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-graphsync v0.14.1 h1:tvFpBY9LcehIB7zi5SZIa+7aoxBOrGbdekhOXdnlT70= +github.com/ipfs/go-graphsync v0.14.1/go.mod h1:S6O/c5iXOXqDgrQgiZSgOTRUSiVvpKEhrzqFHKnLVcs= 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.1.4/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86HgIYJW/D/MwqeYQ= 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= @@ -532,11 +512,8 @@ github.com/ipfs/go-ipfs-exchange-offline v0.2.0/go.mod h1:HjwBeW0dvZvfOMwDP0TSKX 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.8/go.mod h1:wiN/jSG8FKyk7N0WyctKSvq3ljIa2NNTiZB55kpTdOs= -github.com/ipfs/go-ipfs-files v0.2.0 h1:z6MCYHQSZpDWpUSK59Kf0ajP1fi4gLCf6fIulVsp8A8= -github.com/ipfs/go-ipfs-files v0.2.0/go.mod h1:vT7uaQfIsprKktzbTPLnIsd+NGw9ZbYwSq0g3N74u0M= -github.com/ipfs/go-ipfs-keystore v0.0.2 h1:Fa9xg9IFD1VbiZtrNLzsD0GuELVHUFXCWF64kCPfEXU= -github.com/ipfs/go-ipfs-keystore v0.0.2/go.mod h1:H49tRmibOEs7gLMgbOsjC4dqh1u5e0R/SWuc2ScfgSo= +github.com/ipfs/go-ipfs-keystore v0.1.0 h1:gfuQUO/cyGZgZIHE6OrJas4OnwuxXCqJG7tI0lrB5Qc= +github.com/ipfs/go-ipfs-keystore v0.1.0/go.mod h1:LvLw7Qhnb0RlMOfCzK6OmyWxICip6lQ06CCmdbee75U= github.com/ipfs/go-ipfs-pinner v0.2.1 h1:kw9hiqh2p8TatILYZ3WAfQQABby7SQARdrdA+5Z5QfY= github.com/ipfs/go-ipfs-pinner v0.2.1/go.mod h1:l1AtLL5bovb7opnG77sh4Y10waINz3Y1ni6CvTzx7oo= github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= @@ -544,20 +521,20 @@ github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqt 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-provider v0.7.1 h1:eKToBUAb6ZY8iiA6AYVxzW4G1ep67XUaaEBUIYpxhfw= -github.com/ipfs/go-ipfs-provider v0.7.1/go.mod h1:QwdDYRYnC5sYGLlOwVDY/0ZB6T3zcMtu+5+GdGeUuw8= -github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= +github.com/ipfs/go-ipfs-provider v0.8.1 h1:qt670pYmcNH3BCjyXDgg07o2WsTRsOdMwYc25ukCdjQ= +github.com/ipfs/go-ipfs-provider v0.8.1/go.mod h1:qCpwpoohIRVXvNzkygzsM3qdqP/sXlrogtA5I45tClc= 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-routing v0.3.0 h1:9W/W3N+g+y4ZDeffSgqhgo7BsBSJwPMcyssET9OWevc= +github.com/ipfs/go-ipfs-routing v0.3.0/go.mod h1:dKqtTFIql7e1zYsEuWLyuOU+E0WJWW8JjbTPLParDWo= 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 h1:ovz4CHKogtG2KB/h1zUp5U0c/IzZrL435rCh5+K/5G8= github.com/ipfs/go-ipld-cbor v0.0.5/go.mod h1:BkCduEx3XBCO6t2Sfo5BaHzuok7hbhdMm9Oh8B2Ftq4= +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= @@ -569,11 +546,10 @@ github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYD 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.1.2/go.mod h1:ioQ0j02o6jdIVW+bmi18f4k2gRf0AV3kZ9KeHYHICnQ= github.com/ipfs/go-ipns v0.3.0 h1:ai791nTgVo+zTuq2bLvEGmWP1M0A6kGTXUsgv/Yq67A= github.com/ipfs/go-ipns v0.3.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24= -github.com/ipfs/go-libipfs v0.0.0-20221207180439-c7e7738575f9 h1:rQkkhUmGyAMy1Pr/cSAmcp/0i+ur+koewOKfTD4UU3A= -github.com/ipfs/go-libipfs v0.0.0-20221207180439-c7e7738575f9/go.mod h1:blLqyfvHD86wgXMJ8GR4QQWYeg1ZvFHOhX3DT340Nj8= +github.com/ipfs/go-libipfs v0.4.1-0.20230130233950-a005a5006496 h1:RVI31GQCFODREpasIFyVFkS6PjJT2bMwr/Bgr9Ryql4= +github.com/ipfs/go-libipfs v0.4.1-0.20230130233950-a005a5006496/go.mod h1:AAPvZADZ80i+QhGCWNWCsx8IGY0t9C+IBEngLeYtySY= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= 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= @@ -588,62 +564,49 @@ github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Ax github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g= 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.0.6/go.mod h1:QYPdnlvkOg7GnQRofu9XZimC5ZW5Wi3bKys/4GQQfto= github.com/ipfs/go-merkledag v0.2.3/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/go.mod h1:9HSEwRd5sV+lbykiYP+2NC/3o6MZbKNaa4hfNcH5iH0= -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-merkledag v0.9.0 h1:DFC8qZ96Dz1hMT7dtIpcY524eFFDiEWAF8hNJHWW2pk= +github.com/ipfs/go-merkledag v0.9.0/go.mod h1:bPHqkHt5OZ0p1n3iqPeDiw2jIBkjAytRjS3WSBwjq90= 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-mfs v0.2.1 h1:5jz8+ukAg/z6jTkollzxGzhkl3yxm022Za9f2nL5ab8= github.com/ipfs/go-mfs v0.2.1/go.mod h1:Woj80iuw4ajDnIP6+seRaoHpPsc9hmL0pk/nDNDWP88= -github.com/ipfs/go-namesys v0.5.0 h1:vZEkdqxRiSnxBBJrvYTkwHYBFgibGUSpNtg9BHRyN+o= -github.com/ipfs/go-namesys v0.5.0/go.mod h1:zZOme8KDAUYDl4f5MnWSiTRhoxcM7kLkZIyps/HV/S0= -github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd2Sno= -github.com/ipfs/go-path v0.0.9/go.mod h1:VpDkSBKQ9EFQOUgi54Tq/O/tGi8n1RfYNks13M3DEs8= +github.com/ipfs/go-namesys v0.7.0 h1:xqosk71GIVRkFDtF2UNRcXn4LdNeo7tzuy8feHD6NbU= +github.com/ipfs/go-namesys v0.7.0/go.mod h1:KYSZBVZG3VJC34EfqqJPG7T48aWgxseoMPAPA5gLyyQ= github.com/ipfs/go-path v0.2.1/go.mod h1:NOScsVgxfC/eIw4nz6OiGwK42PjaSJ4Y/ZFPn1Xe07I= 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.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP1MX6Kd+aN+rMQ= github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= -github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= -github.com/ipfs/go-peertaskqueue v0.2.0/go.mod h1:5/eNrBEbtSKWCG+kQK8K8fGNixoYUnr+P7jivavs9lY= 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-peertaskqueue v0.8.0 h1:JyNO144tfu9bx6Hpo119zvbEL9iQ760FHOiJYsUjqaU= +github.com/ipfs/go-peertaskqueue v0.8.0/go.mod h1:cz8hEnnARq4Du5TGqiWKgMr/BOSQ5XOgMOh1K5YYKKM= github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= -github.com/ipfs/go-unixfs v0.4.1 h1:nmJFKvF+khK03PIWyCxxydD/nkQX315NZDcgvRqMXf0= -github.com/ipfs/go-unixfs v0.4.1/go.mod h1:2SUDFhUSzrcL408B1qpIkJJ5HznnyTzweViPXUAvkNg= +github.com/ipfs/go-unixfs v0.4.2 h1:hdQlsHHK5tek9gC9mjGVua8xyTqC+eopGseCRcbCZNg= +github.com/ipfs/go-unixfs v0.4.2/go.mod h1:L+x6JRlFE0PfyMqeoLYVOKLhn5IeZHvNT7ZI51Y9Qyc= 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-unixfsnode v1.5.1 h1:JcR3t5C2nM1V7PMzhJ/Qmo19NkoFIKweDSZyDx+CjkI= +github.com/ipfs/go-unixfsnode v1.5.1/go.mod h1:ed79DaG9IEuZITJVQn4U6MZDftv6I3ygUBLPfhEbHvk= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs= github.com/ipfs/go-verifcid v0.0.2/go.mod h1:40cD9x1y4OWnFXbLNJYRe7MpNvWlMn3LZAG5Wb4xnPU= -github.com/ipfs/interface-go-ipfs-core v0.4.0/go.mod h1:UJBcU6iNennuI05amq3FQ7g0JHUkibHFAfhfUIy927o= -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/interface-go-ipfs-core v0.10.0 h1:b/psL1oqJcySdQAsIBfW5ZJJkOAsYlhWtC0/Qvr4WiM= +github.com/ipfs/interface-go-ipfs-core v0.10.0/go.mod h1:F3EcmDy53GFkF0H3iEJpfJC320fZ/4G60eftnItrrJ0= github.com/ipld/edelweiss v0.2.0 h1:KfAZBP8eeJtrLxLhi7r3N0cBCo7JmwSRhOJp3WSpNjk= github.com/ipld/edelweiss v0.2.0/go.mod h1:FJAzJRCep4iI8FOFlRriN9n0b7OuX3T/S9++NpBDmA4= -github.com/ipld/go-car v0.4.0 h1:U6W7F1aKF/OJMHovnOVdst2cpQE5GhmHibQkAixgNcQ= -github.com/ipld/go-car/v2 v2.1.1/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= -github.com/ipld/go-car/v2 v2.4.0 h1:8jI6/iKlyLqRZzLz31jFWTqKvslaVzFsin305sOuqNQ= +github.com/ipld/go-car v0.5.0 h1:kcCEa3CvYMs0iE5BzD5sV7O2EwMiCIp3uF8tA6APQT8= +github.com/ipld/go-car/v2 v2.5.1 h1:U2ux9JS23upEgrJScW8VQuxmE94560kYxj9CQUpcfmk= 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.4.1 h1:CUQJaOPRgSZ27OUPgUWtvdvvd2d17/IGGAIMOo4yYp0= -github.com/ipld/go-codec-dagpb v1.4.1/go.mod h1:XdXTO/TUD/ra9RcK/NfmwBfr1JpFxM2uRKaB9oe4LxE= -github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= +github.com/ipld/go-codec-dagpb v1.5.0 h1:RspDRdsJpLfgCI0ONhTAnbHdySGD4t+LHSPK4X1+R0k= +github.com/ipld/go-codec-dagpb v1.5.0/go.mod h1:0yRIutEFD8o1DGVqw4RSHh+BUTlJA9XWldxaaWR/o4g= github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/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.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= -github.com/ipld/go-ipld-prime v0.16.0/go.mod h1:axSCuOCBPqrH+gvXr2w9uAOulJqBPhHPT2PjoiiU1qA= github.com/ipld/go-ipld-prime v0.19.0 h1:5axC7rJmPc17Emw6TelxGwnzALk0PdupZ2oj2roDj04= github.com/ipld/go-ipld-prime v0.19.0/go.mod h1:Q9j3BaVXwaA3o5JUDNvptDDr/x8+F7FG6XJ8WI3ILg4= -github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73/go.mod h1:2PJ0JgxyB08t0b2WKrcuqI3di0V+5n6RS/LTUJhkoxY= 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= @@ -652,7 +615,6 @@ github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4 github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= 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= @@ -692,20 +654,17 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL 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.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= 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.2 h1:XhdX4fqAJUA0yj+kUwMavO0hHrSPAecYdYf1ZmxHvak= -github.com/klauspost/cpuid/v2 v2.1.2/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.1 h1:U33DW0aiEj633gHYw3LoDNfkDiYnE5Q8M/TKJn2f2jI= +github.com/klauspost/cpuid/v2 v2.2.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= 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.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/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -721,66 +680,47 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 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 v0.0.1/go.mod h1:bGmu51N0KU9IEjX7kl2PQjgZa40JQWnayTvNMgD/vyk= -github.com/libp2p/go-conn-security-multistream v0.0.2/go.mod h1:nc9vud7inQ+d6SO0I/6dSWrdMnHnzZNHeyUQqrAJulE= 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-doh-resolver v0.4.0 h1:gUBa1f1XsPwtpE1du0O+nnZCUqtG7oYi7Bb+0S7FQqw= github.com/libp2p/go-doh-resolver v0.4.0/go.mod h1:v1/jwsFusgsWIGX/c6vCRrnJ60x7bhTiq/fs2qt0cAg= github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= -github.com/libp2p/go-eventbus v0.2.1 h1:VanAdErQnpTioN2TowqNcOijf6YwhuODe4pPKSDpxGc= 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.0.30/go.mod h1:XWT8FGHlhptAv1+3V/+J5mEpzyui/5bvFsNuWYs611A= 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.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.23.4 h1:hWi9XHSOVFR1oDWRk7rigfyA4XNMuYL20INNybP9LP8= -github.com/libp2p/go-libp2p v0.23.4/go.mod h1:s9DEa5NLR4g+LZS+md5uGU4emjMWFiqkZr6hBTY8UxI= -github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= -github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= +github.com/libp2p/go-libp2p v0.24.2 h1:iMViPIcLY0D6zr/f+1Yq9EavCZu2i7eDstsr1nEwSAk= +github.com/libp2p/go-libp2p v0.24.2/go.mod h1:WuxtL2V8yGjam03D93ZBC19tvOUiPpewYv1xdFGWu1k= 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.0.6/go.mod h1:uZneLdOkZHro35xIhpbtTzLlgYturpu4J5+0cZK3MqE= 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.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-blankhost v0.0.1/go.mod h1:Ibpbw/7cPPYwFb7PACIWdvxxv0t0XCCI10t7czjAjTc= 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.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= -github.com/libp2p/go-libp2p-blankhost v0.3.0 h1:kTnLArltMabZlzY63pgGDA4kkUcLkBFSM98zBssn/IY= -github.com/libp2p/go-libp2p-circuit v0.0.9/go.mod h1:uU+IBvEQzCu953/ps7bYzC/D/R0Ho2A9LfKVVCatlqU= 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.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-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= @@ -788,55 +728,32 @@ github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7O 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.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.6.1/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= 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.20.1 h1:fQz4BJyIFmSZAiTbKV8qoYhEH5Dtv/cVhZbG3Ib/+Cw= -github.com/libp2p/go-libp2p-core v0.20.1/go.mod h1:6zR8H7CvQWgYLsbG4on6oLNSGcyKaYFSEYyDt51+bIY= -github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE= -github.com/libp2p/go-libp2p-crypto v0.0.2/go.mod h1:eETI5OUfBnvARGOHrJz2eWNyTUxEGZnBxMcbUjfIj4I= github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= -github.com/libp2p/go-libp2p-discovery v0.0.5/go.mod h1:YtF20GUxjgoKZ4zmXj8j3Nb2TUSBHFlOCetzYdbZL5I= 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.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-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= -github.com/libp2p/go-libp2p-host v0.0.3/go.mod h1:Y/qPyA6C8j2coYyos1dfRm0I8+nvd4TGrDGt4tA7JR8= -github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= -github.com/libp2p/go-libp2p-interface-connmgr v0.0.4/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= -github.com/libp2p/go-libp2p-interface-connmgr v0.0.5/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= -github.com/libp2p/go-libp2p-interface-pnet v0.0.1/go.mod h1:el9jHpQAXK5dnTpKA4yfCNBZXvrzdOU75zz+C6ryp3k= -github.com/libp2p/go-libp2p-kad-dht v0.15.0/go.mod h1:rZtPxYu1TnHHz6n1RggdGrxUX/tA1C2/Wiw3ZMUDrU0= -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-kad-dht v0.20.0 h1:1bcMa74JFwExCHZMFEmjtHzxX5DovhJ07EtR6UOTEpc= +github.com/libp2p/go-libp2p-kad-dht v0.20.0/go.mod h1:qPIXdiZsLczhV4/+4EO1jE8ae0YCW4ZOogc4WVIyTEU= github.com/libp2p/go-libp2p-kbucket v0.3.1/go.mod h1:oyjT5O7tS9CQurok++ERgc46YLwEpuGoFq9ubvoUOio= -github.com/libp2p/go-libp2p-kbucket v0.4.7 h1:spZAcgxifvFZHBD8tErvppbnNiKA5uokDu3CV7axu70= -github.com/libp2p/go-libp2p-kbucket v0.4.7/go.mod h1:XyVo99AfQH0foSf176k4jY1xUJ2+jUJIZCSDm7r2YKk= -github.com/libp2p/go-libp2p-loggables v0.0.1/go.mod h1:lDipDlBNYbpyqyPX/KcoO+eq0sJYEVR2JgOexcivchg= +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-metrics v0.0.1/go.mod h1:jQJ95SXXA/K1VZi13h52WZMa9ja78zjyy5rspMsC/08= -github.com/libp2p/go-libp2p-mplex v0.1.1/go.mod h1:KUQWpGkCzfV7UIpi8SKsAVxyBgz1c9R5EvxgnwLsb/I= 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= @@ -846,19 +763,9 @@ github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryD 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-net v0.0.1/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= -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-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo= -github.com/libp2p/go-libp2p-peer v0.1.1/go.mod h1:jkF12jGB4Gk/IOo+yomm+7oLWxF278F7UnrYUQ1Q8es= github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= -github.com/libp2p/go-libp2p-peerstore v0.0.1/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= -github.com/libp2p/go-libp2p-peerstore v0.0.6/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= 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.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs= @@ -867,48 +774,27 @@ github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRj github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= 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.2.8/go.mod h1:gGiPlXdz7mIHd2vfAsHzBNAMqSDkt2UBFwgcITgw1lA= -github.com/libp2p/go-libp2p-peerstore v0.4.0/go.mod h1:rDJUFyzEWPpXpEwywkcTYYzDHlwza8riYMaUzaN6hX0= -github.com/libp2p/go-libp2p-peerstore v0.8.0 h1:bzTG693TA1Ju/zKmUCQzDLSqiJnyRFVwPpuloZ/OZtI= github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= -github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= -github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= -github.com/libp2p/go-libp2p-pubsub v0.6.0/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= -github.com/libp2p/go-libp2p-pubsub v0.8.1 h1:hSw09NauFUaA0FLgQPBJp6QOy0a2n+HSkb8IeOx8OnY= -github.com/libp2p/go-libp2p-pubsub v0.8.1/go.mod h1:e4kT+DYjzPUYGZeWk4I+oxCSYTXizzXii5LDRRhjKSw= -github.com/libp2p/go-libp2p-pubsub-router v0.5.0 h1:WuYdY42DVIJ+N0qMdq2du/E9poJH+xzsXL7Uptwj9tw= -github.com/libp2p/go-libp2p-pubsub-router v0.5.0/go.mod h1:TRJKskSem3C0aSb3CmRgPwq6IleVFzds6hS09fmZbGM= +github.com/libp2p/go-libp2p-pubsub v0.8.3 h1:T4+pcfcFm1K2v5oFyk68peSjVroaoM8zFygf6Y5WOww= +github.com/libp2p/go-libp2p-pubsub v0.8.3/go.mod h1:eje970FXxjhtFbVEoiae+VUw24ZoSlk67BsiZPLRzlw= +github.com/libp2p/go-libp2p-pubsub-router v0.6.0 h1:D30iKdlqDt5ZmLEYhHELCMRj8b4sFAqrUcshIUvVP/s= +github.com/libp2p/go-libp2p-pubsub-router v0.6.0/go.mod h1:FY/q0/RBTKsLA7l4vqC2cbRbOvyDotg8PJQ7j8FDudE= github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= -github.com/libp2p/go-libp2p-quic-transport v0.11.2/go.mod h1:wlanzKtIh6pHrq+0U3p3DY9PJfGqxMgPaGKaK5LifwQ= -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-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= -github.com/libp2p/go-libp2p-record v0.1.3/go.mod h1:yNUff/adKIfPnYQXgp6FQmNu3gLJ6EMg7+/vv2+9pY4= 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 v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= -github.com/libp2p/go-libp2p-routing-helpers v0.2.3/go.mod h1:795bh+9YeoFl99rMASoiVgHdi5bjack0N1+AFAdbvBw= -github.com/libp2p/go-libp2p-routing-helpers v0.4.1 h1:rOlZiFpUt7SgHm4w62MBvWaQ4UHh7bVJnSnor6RN7j8= -github.com/libp2p/go-libp2p-routing-helpers v0.4.1/go.mod h1:dYEAgkVhqho3/YKxfOEGdFMIcWfAFNlZX8iAIihYA2E= -github.com/libp2p/go-libp2p-secio v0.0.3/go.mod h1:hS7HQ00MgLhRO/Wyu1bTX6ctJKhVpm+j2/S2A5UqYb0= +github.com/libp2p/go-libp2p-routing-helpers v0.6.0 h1:Rfyd+wp/cU0PjNjCphGzLYzd7Q51fjOMs5Sjj6zWGT0= +github.com/libp2p/go-libp2p-routing-helpers v0.6.0/go.mod h1:wwK/XSLt6njjO7sRbjhf8w7PGBOfdntMQ2mOQPZ5s/Q= 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.0.6/go.mod h1:s5GZvzg9xXe8sbeESuFpjt8CJPTCa8mhEusweJqyFy8= 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.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.5.3/go.mod h1:NBn7eNW2lu568L7Ns9wdFrOhgRlkRnIDg0FLKbuu3i8= -github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= -github.com/libp2p/go-libp2p-swarm v0.11.0 h1:ITgsTEY2tA4OxFJGcWeugiMh2x5+VOEnI2JStT1EWxI= -github.com/libp2p/go-libp2p-testing v0.0.1/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= 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= @@ -917,28 +803,14 @@ github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eq 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.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-transport v0.0.1/go.mod h1:UzbUs9X+PHOSw7S3ZmeOxfnwaQY5vGDzZmKPod3N3tk= -github.com/libp2p/go-libp2p-transport v0.0.5/go.mod h1:StoY3sx6IqsP6XKoabsPnHCwqKXWUMWU7Rfcsubee/A= -github.com/libp2p/go-libp2p-transport-upgrader v0.0.4/go.mod h1:RGq+tupk+oj7PzL2kn/m1w6YXxcIAYJYeI90h6BGgUc= 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.4.6/go.mod h1:JE0WQuQdy+uLZ5zOaI3Nw9dWGYJIA7mywEtP2lMvnyk= -github.com/libp2p/go-libp2p-transport-upgrader v0.5.0/go.mod h1:Rc+XODlB3yce7dvFV4q/RmyJGsFcCZRkeZMu/Zdg0mo= -github.com/libp2p/go-libp2p-xor v0.0.0-20210714161855-5c005aca55db/go.mod h1:LSTM5yRnjGZbWNTA/hRwq2gGFrvRIbQJscoIL/u6InY= github.com/libp2p/go-libp2p-xor v0.1.0 h1:hhQwT4uGrBcuAkUGXADuPltalOdpf9aag9kaYNT2tLA= github.com/libp2p/go-libp2p-xor v0.1.0/go.mod h1:LSTM5yRnjGZbWNTA/hRwq2gGFrvRIbQJscoIL/u6InY= -github.com/libp2p/go-libp2p-yamux v0.1.2/go.mod h1:xUoV/RmYkg6BW/qGxA9XJyg+HzXFYkeXbnhjmnYzKp8= -github.com/libp2p/go-libp2p-yamux v0.1.3/go.mod h1:VGSQVrqkh6y4nm0189qqxMtvyBft44MOYYPpYKXiVt4= 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= @@ -947,15 +819,11 @@ 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-maddr-filter v0.0.1/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= 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/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= -github.com/libp2p/go-mplex v0.0.4/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= @@ -967,7 +835,6 @@ github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+ 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= @@ -990,40 +857,26 @@ github.com/libp2p/go-openssl v0.1.0 h1:LBkKEcUv6vtZIQLVTegAil8jbNpJErQ9AnT+bWV+O 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.0.5/go.mod h1:TC62hhPc8qs5c/RoXDZG6YmjK+/YWUPC0yYmeUecbjc= -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 v0.1.0/go.mod h1:8JAVsjeRBCWwPoZeH0W1imLOcriqXJyFvB0mR4A04sQ= -github.com/libp2p/go-stream-muxer-multistream v0.1.1/go.mod h1:zmGdfkQ1AzOECIAcccoL8L//laqawOsO03zX8Sa+eGw= 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.0.4/go.mod h1:+E8HvC8ezEVOxIo3V5vCK9l1y/19K427vCzQ+xHKH/o= 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.2.7/go.mod h1:lue9p1b3VmZj1MhhEGB/etmvF/nBQ0X9CW2DutBT3MM= -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= -github.com/libp2p/go-ws-transport v0.0.5/go.mod h1:Qbl4BxPfXXhhd/o0wcrgoaItHqA9tnZjoFZnxykuaXU= 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.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.1/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= 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= @@ -1032,22 +885,16 @@ 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/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ= github.com/libp2p/go-yamux/v4 v4.0.0/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= -github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= github.com/libp2p/zeroconf/v2 v2.2.0 h1:Cup06Jv6u81HLhIj1KasuNM/RHHrJ8T7wOTS4+Tv53Q= github.com/libp2p/zeroconf/v2 v2.2.0/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.19.3/go.mod h1:ADXpNbTQjq1hIzCpB+y/k5iz4n4z4IwqoLb94Kh5Hu8= -github.com/lucas-clemente/quic-go v0.21.2/go.mod h1:vF5M1XqhBAHgbjKcJOXY3JZz3GP0T3FQhz/uyOUS38Q= -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.29.1 h1:Z+WMJ++qMLhvpFkRZA+jl3BTxUjm415YBmWanXB8zP0= -github.com/lucas-clemente/quic-go v0.29.1/go.mod h1:CTcNfLYJS2UuRNB+zcNlgvkjBhxX6Hm3WUxxAQx2mgE= +github.com/lucas-clemente/quic-go v0.31.1 h1:O8Od7hfioqq0PMYHDyBkxU2aA7iZ2W9pjbrWuja2YR4= +github.com/lucas-clemente/quic-go v0.31.1/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g= 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/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -1058,19 +905,14 @@ github.com/marten-seemann/qpack v0.3.0 h1:UiWstOgT8+znlkDPOg2+3rIuYXJ2CnGDkGUXN6 github.com/marten-seemann/qpack v0.3.0/go.mod h1:cGfKPBiP4a9EQdxCwEwI/GEeWAsjSekBvx/X8mh58+g= 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-15 v0.1.5/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-17 v0.1.0-rc.1/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= -github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI= github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE= github.com/marten-seemann/qtls-go1-19 v0.1.1/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/marten-seemann/webtransport-go v0.1.1 h1:TnyKp3pEXcDooTaNn4s9dYpMJ7kMnTp7k5h+SgYP/mc= -github.com/marten-seemann/webtransport-go v0.1.1/go.mod h1:kBEh5+RSvOA4troP1vyOVBWK4MIMzDICXVrvCPrYcrM= +github.com/marten-seemann/webtransport-go v0.4.3 h1:vkt5o/Ci+luknRteWdYGYH1KcB7ziup+J+1PzZJIvmg= +github.com/marten-seemann/webtransport-go v0.4.3/go.mod h1:4xcfySgZMLP4aG5GBGj1egP7NlpfwgYJ1WJMvPPiVMU= 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= @@ -1080,8 +922,8 @@ github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 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-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/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= @@ -1093,7 +935,6 @@ 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= @@ -1135,8 +976,9 @@ github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjW github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= -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-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= 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= @@ -1148,7 +990,6 @@ github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u 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.8.0 h1:aqjksEcqK+iD/Foe1RRFsGZh8+XFiGo7FgUCZlpv3LU= github.com/multiformats/go-multiaddr v0.8.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= @@ -1172,29 +1013,21 @@ github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/g 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.2.0/go.mod h1:/y4YVwkfMyry5kFbMTbLJKErhycTIftytRV+llXdyS4= 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.7.0 h1:rTUjGOwjlhGHbEMbPoSUJowG1spZTVsITRANCjKTUAQ= github.com/multiformats/go-multicodec v0.7.0/go.mod h1:GUC8upxSBE4oG+q3kWZRw/+6yC1BqO550bjhWsJbZlw= 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.0.16/go.mod h1:zhfEIgVnB/rPMfxgFw15ZmGoNaKyNUIE4IWHG/kC+Ag= 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.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= -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= @@ -1202,8 +1035,9 @@ github.com/multiformats/go-multistream v0.3.3/go.mod h1:ODRoqamLUsETKS9BNcII4gcR 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/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= 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/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= @@ -1227,18 +1061,17 @@ github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W 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/ginkgo/v2 v2.5.0 h1:TRtrvv2vdQqzkwrQ1ke6vtXf7IK34RBUJafIy1wMwls= +github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw= +github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc= 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.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 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/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= @@ -1265,7 +1098,6 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 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/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/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -1288,7 +1120,6 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod 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.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/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= @@ -1307,10 +1138,8 @@ github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= 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.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= @@ -1320,7 +1149,6 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= 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= @@ -1335,8 +1163,6 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -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/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= @@ -1406,7 +1232,9 @@ github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3 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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 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= @@ -1414,9 +1242,12 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 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/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 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/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -1426,7 +1257,6 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT 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.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= @@ -1441,11 +1271,9 @@ github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvS github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4= github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= 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-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= -github.com/whyrusleeping/cbor-gen v0.0.0-20200710004633-5379fc63235d/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2 h1:bsUlNhdmbtlfdLVXAVfuvKQ01RnWAM09TVrJkI7NZs4= -github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20221220214510-0333c149dec0 h1:obKzQ1ey5AJg5NKjgtTo/CKwLImVP4ETLRcsmzFJ4Qw= +github.com/whyrusleeping/cbor-gen v0.0.0-20221220214510-0333c149dec0/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= @@ -1458,8 +1286,6 @@ github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84 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/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= @@ -1482,11 +1308,9 @@ 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.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= 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/exporters/jaeger v1.7.0 h1:wXgjiRldljksZkZrldGVe6XrG9u3kYDyQmkZwmm5dI0= @@ -1503,15 +1327,8 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0 h1:8hPcgCg0rUJiKE6V go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0/go.mod h1:K4GDXPY6TjUiwbOh+DkKaEdCF8y+lvMoM6SeAPyfCCM= go.opentelemetry.io/otel/exporters/zipkin v1.7.0 h1:X0FZj+kaIdLi29UiyrEGDhRTYsEXj9GdEW5Y39UQFEE= go.opentelemetry.io/otel/exporters/zipkin v1.7.0/go.mod h1:9YBXeOMFLQGwNEjsxMRiWPGoJX83usGMhbCmxUbNe5I= -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/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U= go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0= go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU= -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.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5fjhKeJGZPGFs= 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= @@ -1522,15 +1339,13 @@ 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.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.14.1 h1:fyakRgZDdi2F8FgwJJoRGangMSPTIxPSLGzR3Oh0/54= -go.uber.org/dig v1.14.1/go.mod h1:52EKx/Vjdpz9EzeNcweC4YMsTrDdFn9mS/+Uw5ZnVTI= -go.uber.org/fx v1.17.1 h1:S42dZ6Pok8hQ3jxKwo6ZMYcCgHQA/wAS/gnpRa1Pksg= -go.uber.org/fx v1.17.1/go.mod h1:yO7KN5rhlARljyo4LR047AjaV6J+KFzd/Z7rnTbEn0A= +go.uber.org/dig v1.15.0 h1:vq3YWr8zRj1eFGC7Gvf907hE0eRjPTZ1d3xHadD6liE= +go.uber.org/dig v1.15.0/go.mod h1:pKHs0wMynzL6brANhB2hLMro+zalv1osARTviTcqHLM= +go.uber.org/fx v1.18.2 h1:bUNI6oShr+OVFQeU8cDNbnN7VFsu+SsjHzUF51V/GAU= +go.uber.org/fx v1.18.2/go.mod h1:g0V1KMQ66zIRk8bLu3Ea5Jt2w/cHlOIp4wdRsgh0JaY= 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.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= @@ -1538,20 +1353,17 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/ go.uber.org/multierr v1.3.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/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 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.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.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -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.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY= -go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= 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= @@ -1563,7 +1375,6 @@ golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/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-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1577,7 +1388,6 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1586,16 +1396,12 @@ golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPh 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-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/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= @@ -1603,9 +1409,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 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-20221106115401-f9659909a136 h1:Fq7F/w7MAa1KJ5bt2aJ62ihqp9HDcRuyILskkpIAurw= -golang.org/x/exp v0.0.0-20221106115401-f9659909a136/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o= +golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= 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= @@ -1621,17 +1426,15 @@ golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/lint v0.0.0-20200302205851-738671d3881b/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 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 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= @@ -1675,8 +1478,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ 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= @@ -1687,12 +1490,11 @@ golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT 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-20210917221730-978cfadd31cf/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.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= 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= @@ -1741,7 +1543,6 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w 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-20190524152521-dbbf3f1254d4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/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= @@ -1756,7 +1557,6 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/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-20191210023423-ac6580df4449/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= @@ -1780,9 +1580,9 @@ golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7w 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-20200814200057-3d37ad5750ed/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= @@ -1795,19 +1595,15 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w 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-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-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= +golang.org/x/sys v0.4.0/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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1819,8 +1615,8 @@ 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/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 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= @@ -1858,7 +1654,6 @@ golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapK 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-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= @@ -1880,18 +1675,17 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc 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.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= 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= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= 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= @@ -1984,9 +1778,8 @@ google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.46.0 h1:oCjezcn6g6A75TGoKYBPgKmVBLexhYLM6MebdrPApP8= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= 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= @@ -2035,6 +1828,7 @@ 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= 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= @@ -2044,7 +1838,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh 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= 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= diff --git a/docs/examples/kubo-as-a-library/main.go b/docs/examples/kubo-as-a-library/main.go index 08a80bdef..8bd9f8f9c 100644 --- a/docs/examples/kubo-as-a-library/main.go +++ b/docs/examples/kubo-as-a-library/main.go @@ -11,7 +11,7 @@ import ( "strings" "sync" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" icore "github.com/ipfs/interface-go-ipfs-core" icorepath "github.com/ipfs/interface-go-ipfs-core/path" ma "github.com/multiformats/go-multiaddr" diff --git a/docs/libp2p-resource-management.md b/docs/libp2p-resource-management.md new file mode 100644 index 000000000..f15be20c5 --- /dev/null +++ b/docs/libp2p-resource-management.md @@ -0,0 +1,173 @@ +# libp2p Network Resource Manager (`Swarm.ResourceMgr`) + +## Purpose +The purpose of this document is to provide more information about the [libp2p Network Resource Manager](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#readme) and how it's integrated into Kubo so that Kubo users can understand and configure it appropriately. + +## 🙋 Help! The resource manager is protecting my node but I want to understand more +The resource manager is generally a *feature* to bound libp2p's resources, whether from bugs, unintentionally misbehaving peers, or intentional Denial of Service attacks. + +Good places to start are: +1. Understand [how the resource manager is configured](#levels-of-configuration). +2. Understand [how to read the log message](#what-do-these-protected-from-exceeding-resource-limits-log-messages-mean) +3. Understand [how to inspect and change limits](#user-supplied-override-limits) + +## Table of Contents + +- [libp2p Network Resource Manager (`Swarm.ResourceMgr`)](#libp2p-network-resource-manager-smallswarmresourcemgrsmall) + - [Purpose](#purpose) + - [Levels of Configuration](#levels-of-configuration) + - [Approach](#approach) + - [Computed Default Limits](#computed-default-limits) + - [User Supplied Override Limits](#user-supplied-override-limits) + - [Infinite limits](#infinite-limits) + - [FAQ](#faq) + - [What do these "Protected from exceeding resource limits" log messages mean?](#what-do-these-protected-from-exceeding-resource-limits-log-messages-mean) + - [What are the "Application error ... cannot reserve ..." messages?](#what-are-the-application-error--cannot-reserve--messages) + - [How does the resource manager (ResourceMgr) relate to the connection manager (ConnMgr)?](#how-does-the-resource-manager-resourcemgr-relate-to-the-connection-manager-connmgr) + - [How does one see the Active Limits?](#how-does-one-see-the-active-limits) + - [How does one see the Computed Default Limits?](#how-does-one-see-the-computed-default-limits) + - [How does one monitor libp2p resource usage?](#how-does-one-monitor-libp2p-resource-usage) + - [History](#history) + +## Levels of Configuration + +See also the [`Swarm.ResourceMgr` config docs](./config.md#swarmresourcemgr). + + +### Approach +libp2p's resource manager provides tremendous flexibility but also adds complexity. There are these levels of limit configuration for resource management protection: + +1. "The user who does nothing" - In this case Kubo attempts to give some sane defaults discussed below + based on the amount of memory and file descriptors their system has. + This should protect the node from many attacks. + +1. "Slightly more advanced user" - They can tweak the default limits discussed below. + Where the defaults aren't good enough, a good set of higher-level "knobs" are exposed to satisfy most use cases + without requiring users to wade into all the intricacies of libp2p's resource manager. + The "knobs"/inputs are `Swarm.ResourceMgr.MaxMemory` and `Swarm.ResourceMgr.MaxFileDescriptors` as described below. + +1. "Power user" - They specify overrides to computed default limits via `ipfs swarm limit` and `Swarm.ResourceMgr.Limits`; + +### Computed Default Limits +With the `Swarm.ResourceMgr.MaxMemory` and `Swarm.ResourceMgr.MaxFileDescriptors` inputs defined, +[resource manager limits](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#limits) are created at the +[system](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#the-system-scope), +[transient](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#the-transient-scope), +and [peer](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#peer-scopes) scopes. +Other scopes are ignored (by being set to "[~infinity](#infinite-limits])". + +The reason these scopes are chosen is because: +- `system` - This gives us the coarse-grained control we want so we can reason about the system as a whole. + It is the backstop, and allows us to reason about resource consumption more easily + since don't have think about the interaction of many other scopes. +- `transient` - Limiting connections that are in process of being established provides backpressure so not too much work queues up. +- `peer` - The peer scope doesn't protect us against intentional DoS attacks. + It's just as easy for an attacker to send 100 requests/second with 1 peerId vs. 10 requests/second with 10 peers. + We are reliant on the system scope for protection here in the malicious case. + The reason for having a peer scope is to protect against unintentional DoS attacks + (e.g., bug in a peer which is causing it to "misbehave"). + In the unintional case, we want to make sure a "misbehaving" node doesn't consume more resources than necessary. + +Within these scopes, limits are just set on +[memory](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#memory), +[file descriptors (FD)](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#file-descriptors), and [*inbound* connections](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#connections). +Limits are set based on the `Swarm.ResourceMgr.MaxMemory` and `Swarm.ResourceMgr.MaxFileDescriptors` inputs above. + +There are also some special cases where minimum values are enforced. +For example, Kubo maintainers have found in practice that it's a footgun to have too low of a value for `Swarm.ResourceMgr.Limits.System.ConnsInbound` and a default minimum is used. (See [core/node/libp2p/rcmgr_defaults.go](https://github.com/ipfs/kubo/blob/master/core/node/libp2p/rcmgr_defaults.go) for specifics.) + +We trust this node to behave properly and thus don't limit *outbound* connection/stream limits. +We apply any limits that libp2p has for its protocols/services +since we assume libp2p knows best here. + +Source: [core/node/libp2p/rcmgr_defaults.go](https://github.com/ipfs/kubo/blob/master/core/node/libp2p/rcmgr_defaults.go) + +### User Supplied Override Limits +Once Kubo has the [Computed Default Limits](#computed-default-limits), it then applies any user-supplied [`Swarm.ResourceMgr.Limits`](https://github.com/ipfs/kubo/blob/master/docs/config.md#swarmresourcemgrlimits) on top. +These become the [active limits](#how-does-one-see-the-active-limits). + +While `Swarm.ResourceMgr.Limits` can be edited directly, it is also possible to use `ipfs swarm limit` command to inspect and tweak specific limits at runtime. + +To see all resources that are close to hitting their respective limit: + +```console +$ ipfs swarm stats --min-used-limit-perc=90 all +``` + +To modify limits for specific scope (e.g. `system`): + +```console +$ ipfs swarm limit system > change.json +$ vi change.json +$ ipfs swarm limit system change.json +``` + +Learn more: `ipfs swarm limit --help` + +### Infinite limits +There isn't a way via config to specify infinite limits (see [go-libp2p#1935](https://github.com/libp2p/go-libp2p/issues/1935)). For example, "-1" is not infinity. To work around this, Kubo uses a magic number of "1000000000" to denote infinity since it's effectively infinite. + +## FAQ + +### What do these "Protected from exceeding resource limits" log messages mean? +"Protected from exceeding resource limits" log messages denote that the resource manager is working and that it prevented additional resources being used beyond the set limits. Per [libp2p code](https://github.com/libp2p/go-libp2p/blob/master/p2p/host/resource-manager/scope.go), these messages take the form of "$scope: cannot reserve $limitKey". + +As an example: + +> Protected from exceeding resource limits 2 times: "system: cannot reserve inbound connection: resource limit exceeded" + +This means that there were 2 recent occurences where the libp2p resource manager prevented an inbound connection at the "system" [scope](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#resource-scopes). +Specificaly the ``Swarm.ResourceMgr.Limits.System.ConnsInbound`` [active limit](#how-does-one-see-the-active-limits) was hit. + +This can be analyzed by viewing the limit with `ipfs swarm limit system` and comparing the usage with `ipfs swarm stats system`. +`ConnsInbound` is likely close or at the limit value. + +The simiplest way to identify all resources across all scopes that are close to exceeding their limit is with a command like `ipfs swarm stats --min-used-limit-perc=90 all`. + +Sources: +* [kubo resource manager logging](https://github.com/ipfs/kubo/blob/master/core/node/libp2p/rcmgr_logging.go) +* [libp2p resource manager messages](https://github.com/libp2p/go-libp2p/blob/master/p2p/host/resource-manager/scope.go) + +### What are the "Application error ... cannot reserve ..." messages? +These are messages from a *remote* go-libp2p peer (likely another Kubo node) with the resource manager enabled on why it failed to establish a connection. + +This can be confusing, but these `Application error ... cannot reserve ...` messages can occur even if your local node has the resoure manager disabled. + +You can distinguish resource manager messages originating from your local node if they're from the `resourcemanager` / `libp2p/rcmgr_logging.go` logger +or you see the string that is unique to Kubo (and not in go-libp2p): "Protected from exceeding resource limits". + +There is a go-libp2p issue ([#1928](https://github.com/libp2p/go-libp2p/issues/1928)) to make it clearer that this is an error message originating from a remote peer. + +### How does the resource manager (ResourceMgr) relate to the connection manager (ConnMgr)? +As discussed [here](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#connmanager-vs-resource-manager) +these are separate systems in go-libp2p. +Kubo performs sanity checks to ensure that some of the hard limits of the ResourceMgr are sufficiently greater than the soft limits of the ConnMgr. + +The soft limit of `Swarm.ConnMgr.HighWater` needs to be less than the hard limit `Swarm.ResourceMgr.Limits.System.ConnsInbound` for the configuration to make sense. +This ensures the ConnMgr cleans up connections based on connection priorities before the hard limits of the ResourceMgr are applied. +If `Swarm.ConnMgr.HighWater` is greater than `Swarm.ResourceMgr.Limits.System.ConnsInbound`, +existing low priority idle connections can prevent new high priority connections from being established. +The ResourceMgr doesn't know that the new connection is high priority and simply blocks it because of the limit its enforcing. + +To ensure the ConnMgr and ResourceMgr are congruent, the ResourceMgr [computed default limts](#computed-default-limits) are adjusted such that: +1. `Swarm.ResourceMgr.Limits.System.ConnsInbound` >= `max(Swarm.ConnMgr.HighWater * 2, DefaultResourceMgrMinInboundConns)` AND +2. `Swarm.ResourceMgr.Limits.System.StreamsInbound` is greater than any new/adjusted `Swarm.ResourceMgr.Limits.System.ConnsInbound` value so that there's enough streams per connection. + +### How does one see the Active Limits? +A dump of what limits are actually being used by the resource manager ([Computed Default Limits](#computed-default-limits) + [User Supplied Override Limits](#user-supplied-override-limits)) +can be obtained by `ipfs swarm limit all`. + +### How does one see the Computed Default Limits? +This can be observed with an empty [`Swarm.ResourceMgr.Limits`](https://github.com/ipfs/kubo/blob/master/docs/config.md#swarmresourcemgrlimits) +and then [seeing the active limits](#how-does-one-see-the-active-limits). + +### How does one monitor libp2p resource usage? +For [monitoring libp2p resource usage](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager#monitoring), +various `*rcmgr_*` metrics can be accessed as the prometheus endpoint at `{Addresses.API}/debug/metrics/prometheus` (default: `http://127.0.0.1:5001/debug/metrics/prometheus`). +There are also [pre-built Grafana dashboards](https://github.com/libp2p/go-libp2p/tree/master/p2p/host/resource-manager/obs/grafana-dashboards) that can be added to a Grafana instance. + +A textual view of current resource usage and a list of services, protocols, and peers can be +obtained via `ipfs swarm stats --help` + +## History +Kubo first [exposed this functionality in Kubo 0.13](./changelogs/v0.13.md#-libp2p-network-resource-manager-swarmresourcemgr), but it was disabled by default. It was then enabled by default in [Kubo 0.17](./changelogs/v0.17.md#libp2p-resource-management-enabled-by-default). Until that point, Kubo was vulnerable to unbound resource usage which could bring down nodes. Introducing limits like this by default after the fact is tricky, which is why there have been changes and improvements afterwards. diff --git a/fuse/readonly/ipfs_test.go b/fuse/readonly/ipfs_test.go index 7e79b9cf6..04fc07f73 100644 --- a/fuse/readonly/ipfs_test.go +++ b/fuse/readonly/ipfs_test.go @@ -24,9 +24,9 @@ import ( fstest "bazil.org/fuse/fs/fstestutil" chunker "github.com/ipfs/go-ipfs-chunker" - files "github.com/ipfs/go-ipfs-files" u "github.com/ipfs/go-ipfs-util" ipld "github.com/ipfs/go-ipld-format" + "github.com/ipfs/go-libipfs/files" dag "github.com/ipfs/go-merkledag" importer "github.com/ipfs/go-unixfs/importer" uio "github.com/ipfs/go-unixfs/io" diff --git a/go.mod b/go.mod index eb8be2b58..5edf9f68a 100644 --- a/go.mod +++ b/go.mod @@ -7,18 +7,16 @@ require ( github.com/blang/semver/v4 v4.0.0 github.com/cenkalti/backoff/v4 v4.1.3 github.com/ceramicnetwork/go-dag-jose v0.1.0 - github.com/cespare/xxhash v1.1.0 github.com/cheggaaa/pb v1.0.29 github.com/coreos/go-systemd/v22 v22.5.0 github.com/dustin/go-humanize v1.0.0 github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302 github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 github.com/fsnotify/fsnotify v1.6.0 - github.com/gabriel-vasile/mimetype v1.4.1 + github.com/gogo/protobuf v1.3.2 + github.com/google/uuid v1.3.0 github.com/hashicorp/go-multierror v1.1.1 - github.com/ipfs/go-bitswap v0.10.2 - github.com/ipfs/go-block-format v0.0.3 - github.com/ipfs/go-blockservice v0.4.0 + github.com/ipfs/go-blockservice v0.5.0 github.com/ipfs/go-cid v0.3.2 github.com/ipfs/go-cidutil v0.1.0 github.com/ipfs/go-datastore v0.6.0 @@ -31,55 +29,52 @@ require ( github.com/ipfs/go-fetcher v1.6.1 github.com/ipfs/go-filestore v1.2.0 github.com/ipfs/go-fs-lock v0.0.7 - github.com/ipfs/go-graphsync v0.13.1 + github.com/ipfs/go-graphsync v0.14.1 github.com/ipfs/go-ipfs-blockstore v1.2.0 github.com/ipfs/go-ipfs-chunker v0.0.5 - github.com/ipfs/go-ipfs-cmds v0.8.1 + github.com/ipfs/go-ipfs-cmds v0.8.2 github.com/ipfs/go-ipfs-exchange-interface v0.2.0 github.com/ipfs/go-ipfs-exchange-offline v0.3.0 - github.com/ipfs/go-ipfs-files v0.2.0 - github.com/ipfs/go-ipfs-keystore v0.0.2 + github.com/ipfs/go-ipfs-keystore v0.1.0 github.com/ipfs/go-ipfs-pinner v0.2.1 github.com/ipfs/go-ipfs-posinfo v0.0.1 - github.com/ipfs/go-ipfs-provider v0.7.1 - github.com/ipfs/go-ipfs-redirects-file v0.1.1 - github.com/ipfs/go-ipfs-routing v0.2.1 + github.com/ipfs/go-ipfs-provider v0.8.1 + github.com/ipfs/go-ipfs-routing v0.3.0 github.com/ipfs/go-ipfs-util v0.0.2 github.com/ipfs/go-ipld-format v0.4.0 github.com/ipfs/go-ipld-git v0.1.1 github.com/ipfs/go-ipld-legacy v0.1.1 github.com/ipfs/go-ipns v0.3.0 - github.com/ipfs/go-libipfs v0.0.0-20221207180439-c7e7738575f9 + github.com/ipfs/go-libipfs v0.4.1-0.20230130233950-a005a5006496 github.com/ipfs/go-log v1.0.5 github.com/ipfs/go-log/v2 v2.5.1 - github.com/ipfs/go-merkledag v0.8.1 + github.com/ipfs/go-merkledag v0.9.0 github.com/ipfs/go-metrics-interface v0.0.1 github.com/ipfs/go-metrics-prometheus v0.0.2 github.com/ipfs/go-mfs v0.2.1 - github.com/ipfs/go-namesys v0.5.0 + github.com/ipfs/go-namesys v0.7.0 github.com/ipfs/go-path v0.3.0 github.com/ipfs/go-pinning-service-http-client v0.1.2 - github.com/ipfs/go-unixfs v0.4.1 - github.com/ipfs/go-unixfsnode v1.4.0 + github.com/ipfs/go-unixfs v0.4.2 + github.com/ipfs/go-unixfsnode v1.5.1 github.com/ipfs/go-verifcid v0.0.2 - 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.0 - github.com/ipld/go-codec-dagpb v1.4.1 + github.com/ipfs/interface-go-ipfs-core v0.10.0 + github.com/ipld/go-car v0.5.0 + github.com/ipld/go-car/v2 v2.5.1 + github.com/ipld/go-codec-dagpb v1.5.0 github.com/ipld/go-ipld-prime v0.19.0 github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c github.com/jbenet/go-temp-err-catcher v0.1.0 github.com/jbenet/goprocess v0.1.4 github.com/libp2p/go-doh-resolver v0.4.0 - github.com/libp2p/go-libp2p v0.23.4 - github.com/libp2p/go-libp2p-http v0.2.1 - github.com/libp2p/go-libp2p-kad-dht v0.18.0 - github.com/libp2p/go-libp2p-kbucket v0.4.7 - github.com/libp2p/go-libp2p-loggables v0.1.0 - github.com/libp2p/go-libp2p-pubsub v0.8.1 - github.com/libp2p/go-libp2p-pubsub-router v0.5.0 + github.com/libp2p/go-libp2p v0.24.2 + github.com/libp2p/go-libp2p-http v0.4.0 + github.com/libp2p/go-libp2p-kad-dht v0.20.0 + github.com/libp2p/go-libp2p-kbucket v0.5.0 + github.com/libp2p/go-libp2p-pubsub v0.8.3 + github.com/libp2p/go-libp2p-pubsub-router v0.6.0 github.com/libp2p/go-libp2p-record v0.2.0 - github.com/libp2p/go-libp2p-routing-helpers v0.4.1 + github.com/libp2p/go-libp2p-routing-helpers v0.6.0 github.com/libp2p/go-libp2p-testing v0.12.0 github.com/libp2p/go-socket-activation v0.1.0 github.com/miekg/dns v1.1.50 @@ -94,10 +89,10 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.14.0 github.com/stretchr/testify v1.8.1 - github.com/syndtr/goleveldb v1.0.0 + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 - go.opencensus.io v0.23.0 + go.opencensus.io v0.24.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.32.0 go.opentelemetry.io/otel v1.7.0 go.opentelemetry.io/otel/exporters/jaeger v1.7.0 @@ -107,23 +102,24 @@ require ( go.opentelemetry.io/otel/exporters/zipkin v1.7.0 go.opentelemetry.io/otel/sdk v1.7.0 go.opentelemetry.io/otel/trace v1.7.0 - go.uber.org/dig v1.14.1 - go.uber.org/fx v1.17.1 - go.uber.org/zap v1.23.0 - golang.org/x/crypto v0.1.0 + go.uber.org/dig v1.15.0 + go.uber.org/fx v1.18.2 + go.uber.org/zap v1.24.0 + golang.org/x/crypto v0.3.0 + golang.org/x/mod v0.7.0 golang.org/x/sync v0.1.0 - golang.org/x/sys v0.2.0 + golang.org/x/sys v0.4.0 ) require ( github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect github.com/Kubuxu/go-os-helper v0.0.1 // indirect - github.com/Stebalien/go-bitfield v0.0.1 // indirect github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a // indirect github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/containerd/cgroups v1.0.4 // indirect github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect github.com/cskr/pubsub v1.0.2 // indirect @@ -134,22 +130,23 @@ require ( github.com/dgraph-io/ristretto v0.0.2 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect - github.com/felixge/httpsnoop v1.0.3 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/felixge/httpsnoop v1.0.2 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect + github.com/gabriel-vasile/mimetype v1.4.1 // 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-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/gogo/protobuf v1.3.2 // 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/google/uuid v1.3.0 // indirect + github.com/google/pprof v0.0.0-20221203041831-ce31453925ec // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect @@ -159,24 +156,23 @@ require ( github.com/huin/goupnp v1.0.3 // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-bitfield v1.0.0 // indirect + github.com/ipfs/go-block-format v0.1.1 // 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-pq v0.0.2 // indirect - github.com/ipfs/go-ipld-cbor v0.0.5 // indirect - github.com/ipfs/go-peertaskqueue v0.7.1 // indirect + github.com/ipfs/go-ipfs-redirects-file v0.1.1 // indirect + github.com/ipfs/go-ipld-cbor v0.0.6 // indirect + github.com/ipfs/go-peertaskqueue v0.8.0 // indirect github.com/ipld/edelweiss v0.2.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/klauspost/compress v1.15.12 // indirect - github.com/klauspost/cpuid/v2 v2.1.2 // indirect + github.com/klauspost/cpuid/v2 v2.2.1 // 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-blankhost v0.3.0 // indirect - github.com/libp2p/go-libp2p-core v0.20.1 // indirect - github.com/libp2p/go-libp2p-gostream v0.3.0 // indirect - github.com/libp2p/go-libp2p-swarm v0.11.0 // indirect + github.com/libp2p/go-libp2p-gostream v0.5.0 // indirect github.com/libp2p/go-libp2p-xor v0.1.0 // indirect github.com/libp2p/go-mplex v0.7.0 // indirect github.com/libp2p/go-msgio v0.2.0 // indirect @@ -186,14 +182,14 @@ require ( github.com/libp2p/go-reuseport v0.2.0 // indirect github.com/libp2p/go-yamux/v4 v4.0.0 // indirect github.com/libp2p/zeroconf/v2 v2.2.0 // indirect - github.com/lucas-clemente/quic-go v0.29.1 // indirect + github.com/lucas-clemente/quic-go v0.31.1 // indirect github.com/marten-seemann/qpack v0.3.0 // indirect github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect - github.com/marten-seemann/webtransport-go v0.1.1 // indirect + github.com/marten-seemann/webtransport-go v0.4.3 // indirect github.com/mattn/go-colorable v0.1.4 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-pointer v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.4 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect @@ -203,14 +199,11 @@ require ( github.com/minio/sha256-simd v1.0.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect - github.com/multiformats/go-base36 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect github.com/multiformats/go-multistream v0.3.3 // indirect - github.com/multiformats/go-varint v0.0.6 // indirect - github.com/nxadm/tail v1.4.8 // indirect - github.com/onsi/ginkgo v1.16.5 // indirect - github.com/onsi/ginkgo/v2 v2.5.0 // indirect - github.com/onsi/gomega v1.24.0 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect + github.com/onsi/ginkgo/v2 v2.5.1 // indirect github.com/opencontainers/runtime-spec v1.0.2 // indirect github.com/openzipkin/zipkin-go v0.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -227,31 +220,28 @@ require ( github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e // indirect github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb // indirect github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect - github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2 // indirect + github.com/whyrusleeping/cbor-gen v0.0.0-20221220214510-0333c149dec0 // 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/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.7.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.7.0 // indirect go.opentelemetry.io/otel/metric v0.30.0 // indirect go.opentelemetry.io/proto/otlp v0.16.0 // indirect go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.8.0 // indirect + go.uber.org/multierr v1.9.0 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect - golang.org/x/exp v0.0.0-20221106115401-f9659909a136 // indirect - golang.org/x/mod v0.6.0 // indirect - golang.org/x/net v0.1.0 // indirect + golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect + golang.org/x/net v0.3.0 // indirect golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect - golang.org/x/term v0.1.0 // indirect - golang.org/x/text v0.4.0 // indirect - golang.org/x/tools v0.2.0 // indirect - golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect + golang.org/x/term v0.4.0 // indirect + golang.org/x/text v0.5.0 // indirect + golang.org/x/tools v0.3.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/appengine v1.6.6 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect - google.golang.org/grpc v1.47.0 // indirect + google.golang.org/grpc v1.46.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // 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 lukechampine.com/blake3 v1.1.7 // indirect diff --git a/go.sum b/go.sum index 7a3c3e8ce..fefe9bf71 100644 --- a/go.sum +++ b/go.sum @@ -38,7 +38,6 @@ contrib.go.opencensus.io/exporter/prometheus v0.4.0 h1:0QfIkj9z/iVZgK31D9H9ohjjI 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= @@ -58,7 +57,6 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fTKCulPVs= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0= -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/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -84,8 +82,6 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l 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-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -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= @@ -103,12 +99,10 @@ github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcug 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/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= @@ -128,8 +122,9 @@ github.com/ceramicnetwork/go-dag-jose v0.1.0/go.mod h1:qYA1nYt0X8u4XoMAVoOV3upUV 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.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/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= @@ -155,11 +150,9 @@ github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO 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.2.1-0.20180108230905-e214231b295a/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/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= @@ -213,6 +206,8 @@ github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/ github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302 h1:QV0ZrfBLpFc2KDk+a4LJefDczXnonRwrYrQJY/9L4dA= github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302/go.mod h1:qBlWZqWeVx9BjvqBsnC/8RUlAYpIFmPvgROcw0n1scE= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 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= @@ -227,11 +222,9 @@ github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:Jp github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 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/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= @@ -241,7 +234,6 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB 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= @@ -267,7 +259,6 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V 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.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= @@ -361,6 +352,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/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/pprof v0.0.0-20221203041831-ce31453925ec h1:fR20TYVVwhK4O7r7y+McjRYyaTH6/vjwJOajE+XhlzM= +github.com/google/pprof v0.0.0-20221203041831-ce31453925ec/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= 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= @@ -398,7 +391,6 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QG github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= 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/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= @@ -410,7 +402,6 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-immutable-radix v1.0.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-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= @@ -433,7 +424,6 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 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= @@ -445,26 +435,21 @@ 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.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3UPrwvis= 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.1.8/go.mod h1:TOWoxllhccevbWFUR2N7B1MTSVVge1s6XSMiCSA4MzM= -github.com/ipfs/go-bitswap v0.3.4/go.mod h1:4T7fvNv/LmOys+21tnLzGKncMeeXUYUd1nUiJ2teMvI= 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-bitswap v0.11.0 h1:j1WVvhDX1yhG32NTC9xfxnqycqYIlhzEzLXG/cU1HyQ= 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.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbRhbvNSdgc/7So= +github.com/ipfs/go-block-format v0.1.1 h1:129vSO3zwbsYADcyQWcOYiuCpAqt462SFfqFHdFJhhI= +github.com/ipfs/go-block-format v0.1.1/go.mod h1:+McEIT+g52p+zz5xGAABGSOKrzmrdX97bc0USBdWPUs= github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= -github.com/ipfs/go-blockservice v0.1.4/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= 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-blockservice v0.5.0 h1:B2mwhhhVQl2ntW2EIpaWPwSCxSuqr5fFA93Ms4bYLEY= +github.com/ipfs/go-blockservice v0.5.0/go.mod h1:W6brZ5k20AehbmERplmERn8o2Ni3ZZubvAxaIUeaT6w= 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= @@ -475,7 +460,6 @@ github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqg github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o= github.com/ipfs/go-cid v0.3.2 h1:OGgOd+JCFM+y1DjWPmVH+2/4POtpDzwcr7VgnB7mZXc= github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svoupw= -github.com/ipfs/go-cidutil v0.0.2/go.mod h1:ewllrvrxG6AMYStla3GD7Cqn+XYSLqjK0vc+086tB6s= 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= @@ -499,7 +483,6 @@ github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaH github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= 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.2.7/go.mod h1:02rnztVKA4aZwDuaRPTf8mpqcKmXP7mLl6JPxd14JHA= 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-flatfs v0.5.1 h1:ZCIO/kQOS/PSh3vcF1H6a8fkRGS7pOfwfPdx4n/KJH4= @@ -512,20 +495,17 @@ github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUN 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.5.0/go.mod h1:5pDZ0393oRF/fHiLmtFZtpMNBQfHOYNPtryWedVuSWE= github.com/ipfs/go-fetcher v1.6.1 h1:UFuRVYX5AIllTiRhi5uK/iZkfhSpBCGX7L70nSZEmK8= 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.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-graphsync v0.14.1 h1:tvFpBY9LcehIB7zi5SZIa+7aoxBOrGbdekhOXdnlT70= +github.com/ipfs/go-graphsync v0.14.1/go.mod h1:S6O/c5iXOXqDgrQgiZSgOTRUSiVvpKEhrzqFHKnLVcs= 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.1.4/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86HgIYJW/D/MwqeYQ= 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= @@ -533,8 +513,8 @@ github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtL 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.8.1 h1:El661DBWqdqwgz7B9xwKyUpigwqk6BBBHb5B8DfJP00= -github.com/ipfs/go-ipfs-cmds v0.8.1/go.mod h1:y0bflH6m4g6ary4HniYt98UqbrVnRxmRarzeMdLIUn0= +github.com/ipfs/go-ipfs-cmds v0.8.2 h1:WmehvYWkxch8dTw0bdF51R8lqbyl+3H8e6pIACzT/ds= +github.com/ipfs/go-ipfs-cmds v0.8.2/go.mod h1:/b17Davff0E0Wh/hhXsN1Pgxxbkm26k3PV+G4EDiC/s= 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= @@ -552,11 +532,8 @@ github.com/ipfs/go-ipfs-exchange-offline v0.2.0/go.mod h1:HjwBeW0dvZvfOMwDP0TSKX 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.8/go.mod h1:wiN/jSG8FKyk7N0WyctKSvq3ljIa2NNTiZB55kpTdOs= -github.com/ipfs/go-ipfs-files v0.2.0 h1:z6MCYHQSZpDWpUSK59Kf0ajP1fi4gLCf6fIulVsp8A8= -github.com/ipfs/go-ipfs-files v0.2.0/go.mod h1:vT7uaQfIsprKktzbTPLnIsd+NGw9ZbYwSq0g3N74u0M= -github.com/ipfs/go-ipfs-keystore v0.0.2 h1:Fa9xg9IFD1VbiZtrNLzsD0GuELVHUFXCWF64kCPfEXU= -github.com/ipfs/go-ipfs-keystore v0.0.2/go.mod h1:H49tRmibOEs7gLMgbOsjC4dqh1u5e0R/SWuc2ScfgSo= +github.com/ipfs/go-ipfs-keystore v0.1.0 h1:gfuQUO/cyGZgZIHE6OrJas4OnwuxXCqJG7tI0lrB5Qc= +github.com/ipfs/go-ipfs-keystore v0.1.0/go.mod h1:LvLw7Qhnb0RlMOfCzK6OmyWxICip6lQ06CCmdbee75U= github.com/ipfs/go-ipfs-pinner v0.2.1 h1:kw9hiqh2p8TatILYZ3WAfQQABby7SQARdrdA+5Z5QfY= github.com/ipfs/go-ipfs-pinner v0.2.1/go.mod h1:l1AtLL5bovb7opnG77sh4Y10waINz3Y1ni6CvTzx7oo= github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= @@ -564,22 +541,22 @@ github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqt 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-provider v0.7.1 h1:eKToBUAb6ZY8iiA6AYVxzW4G1ep67XUaaEBUIYpxhfw= -github.com/ipfs/go-ipfs-provider v0.7.1/go.mod h1:QwdDYRYnC5sYGLlOwVDY/0ZB6T3zcMtu+5+GdGeUuw8= +github.com/ipfs/go-ipfs-provider v0.8.1 h1:qt670pYmcNH3BCjyXDgg07o2WsTRsOdMwYc25ukCdjQ= +github.com/ipfs/go-ipfs-provider v0.8.1/go.mod h1:qCpwpoohIRVXvNzkygzsM3qdqP/sXlrogtA5I45tClc= github.com/ipfs/go-ipfs-redirects-file v0.1.1 h1:Io++k0Vf/wK+tfnhEh63Yte1oQK5VGT2hIEYpD0Rzx8= github.com/ipfs/go-ipfs-redirects-file v0.1.1/go.mod h1:tAwRjCV0RjLTjH8DR/AU7VYvfQECg+lpUy2Mdzv7gyk= -github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= 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-routing v0.3.0 h1:9W/W3N+g+y4ZDeffSgqhgo7BsBSJwPMcyssET9OWevc= +github.com/ipfs/go-ipfs-routing v0.3.0/go.mod h1:dKqtTFIql7e1zYsEuWLyuOU+E0WJWW8JjbTPLParDWo= 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 h1:ovz4CHKogtG2KB/h1zUp5U0c/IzZrL435rCh5+K/5G8= github.com/ipfs/go-ipld-cbor v0.0.5/go.mod h1:BkCduEx3XBCO6t2Sfo5BaHzuok7hbhdMm9Oh8B2Ftq4= +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= @@ -591,11 +568,10 @@ github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYD 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.1.2/go.mod h1:ioQ0j02o6jdIVW+bmi18f4k2gRf0AV3kZ9KeHYHICnQ= github.com/ipfs/go-ipns v0.3.0 h1:ai791nTgVo+zTuq2bLvEGmWP1M0A6kGTXUsgv/Yq67A= github.com/ipfs/go-ipns v0.3.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24= -github.com/ipfs/go-libipfs v0.0.0-20221207180439-c7e7738575f9 h1:rQkkhUmGyAMy1Pr/cSAmcp/0i+ur+koewOKfTD4UU3A= -github.com/ipfs/go-libipfs v0.0.0-20221207180439-c7e7738575f9/go.mod h1:blLqyfvHD86wgXMJ8GR4QQWYeg1ZvFHOhX3DT340Nj8= +github.com/ipfs/go-libipfs v0.4.1-0.20230130233950-a005a5006496 h1:RVI31GQCFODREpasIFyVFkS6PjJT2bMwr/Bgr9Ryql4= +github.com/ipfs/go-libipfs v0.4.1-0.20230130233950-a005a5006496/go.mod h1:AAPvZADZ80i+QhGCWNWCsx8IGY0t9C+IBEngLeYtySY= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= 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= @@ -610,69 +586,56 @@ github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Ax github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g= 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.0.6/go.mod h1:QYPdnlvkOg7GnQRofu9XZimC5ZW5Wi3bKys/4GQQfto= github.com/ipfs/go-merkledag v0.2.3/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/go.mod h1:9HSEwRd5sV+lbykiYP+2NC/3o6MZbKNaa4hfNcH5iH0= -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-merkledag v0.9.0 h1:DFC8qZ96Dz1hMT7dtIpcY524eFFDiEWAF8hNJHWW2pk= +github.com/ipfs/go-merkledag v0.9.0/go.mod h1:bPHqkHt5OZ0p1n3iqPeDiw2jIBkjAytRjS3WSBwjq90= 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= github.com/ipfs/go-metrics-prometheus v0.0.2/go.mod h1:ELLU99AQQNi+zX6GCGm2lAgnzdSH3u5UVlCdqSXnEks= github.com/ipfs/go-mfs v0.2.1 h1:5jz8+ukAg/z6jTkollzxGzhkl3yxm022Za9f2nL5ab8= github.com/ipfs/go-mfs v0.2.1/go.mod h1:Woj80iuw4ajDnIP6+seRaoHpPsc9hmL0pk/nDNDWP88= -github.com/ipfs/go-namesys v0.5.0 h1:vZEkdqxRiSnxBBJrvYTkwHYBFgibGUSpNtg9BHRyN+o= -github.com/ipfs/go-namesys v0.5.0/go.mod h1:zZOme8KDAUYDl4f5MnWSiTRhoxcM7kLkZIyps/HV/S0= -github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd2Sno= -github.com/ipfs/go-path v0.0.9/go.mod h1:VpDkSBKQ9EFQOUgi54Tq/O/tGi8n1RfYNks13M3DEs8= +github.com/ipfs/go-namesys v0.7.0 h1:xqosk71GIVRkFDtF2UNRcXn4LdNeo7tzuy8feHD6NbU= +github.com/ipfs/go-namesys v0.7.0/go.mod h1:KYSZBVZG3VJC34EfqqJPG7T48aWgxseoMPAPA5gLyyQ= github.com/ipfs/go-path v0.2.1/go.mod h1:NOScsVgxfC/eIw4nz6OiGwK42PjaSJ4Y/ZFPn1Xe07I= 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.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP1MX6Kd+aN+rMQ= github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= -github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= -github.com/ipfs/go-peertaskqueue v0.2.0/go.mod h1:5/eNrBEbtSKWCG+kQK8K8fGNixoYUnr+P7jivavs9lY= 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-peertaskqueue v0.8.0 h1:JyNO144tfu9bx6Hpo119zvbEL9iQ760FHOiJYsUjqaU= +github.com/ipfs/go-peertaskqueue v0.8.0/go.mod h1:cz8hEnnARq4Du5TGqiWKgMr/BOSQ5XOgMOh1K5YYKKM= github.com/ipfs/go-pinning-service-http-client v0.1.2 h1:jdr7KelhL9gNHTU8jbqPMwIexSZXgZzxNGkycCwmbXI= github.com/ipfs/go-pinning-service-http-client v0.1.2/go.mod h1:6wd5mjYhXJTiWU8b4RSWPpWdlzE5/csoXV0dWWMjun4= github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= -github.com/ipfs/go-unixfs v0.4.1 h1:nmJFKvF+khK03PIWyCxxydD/nkQX315NZDcgvRqMXf0= -github.com/ipfs/go-unixfs v0.4.1/go.mod h1:2SUDFhUSzrcL408B1qpIkJJ5HznnyTzweViPXUAvkNg= +github.com/ipfs/go-unixfs v0.4.2 h1:hdQlsHHK5tek9gC9mjGVua8xyTqC+eopGseCRcbCZNg= +github.com/ipfs/go-unixfs v0.4.2/go.mod h1:L+x6JRlFE0PfyMqeoLYVOKLhn5IeZHvNT7ZI51Y9Qyc= 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-unixfsnode v1.5.1 h1:JcR3t5C2nM1V7PMzhJ/Qmo19NkoFIKweDSZyDx+CjkI= +github.com/ipfs/go-unixfsnode v1.5.1/go.mod h1:ed79DaG9IEuZITJVQn4U6MZDftv6I3ygUBLPfhEbHvk= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs= github.com/ipfs/go-verifcid v0.0.2/go.mod h1:40cD9x1y4OWnFXbLNJYRe7MpNvWlMn3LZAG5Wb4xnPU= -github.com/ipfs/interface-go-ipfs-core v0.4.0/go.mod h1:UJBcU6iNennuI05amq3FQ7g0JHUkibHFAfhfUIy927o= -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/interface-go-ipfs-core v0.10.0 h1:b/psL1oqJcySdQAsIBfW5ZJJkOAsYlhWtC0/Qvr4WiM= +github.com/ipfs/interface-go-ipfs-core v0.10.0/go.mod h1:F3EcmDy53GFkF0H3iEJpfJC320fZ/4G60eftnItrrJ0= github.com/ipld/edelweiss v0.2.0 h1:KfAZBP8eeJtrLxLhi7r3N0cBCo7JmwSRhOJp3WSpNjk= github.com/ipld/edelweiss v0.2.0/go.mod h1:FJAzJRCep4iI8FOFlRriN9n0b7OuX3T/S9++NpBDmA4= -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.0 h1:8jI6/iKlyLqRZzLz31jFWTqKvslaVzFsin305sOuqNQ= -github.com/ipld/go-car/v2 v2.4.0/go.mod h1:zjpRf0Jew9gHqSvjsKVyoq9OY9SWoEKdYCQUKVaaPT0= +github.com/ipld/go-car v0.5.0 h1:kcCEa3CvYMs0iE5BzD5sV7O2EwMiCIp3uF8tA6APQT8= +github.com/ipld/go-car v0.5.0/go.mod h1:ppiN5GWpjOZU9PgpAZ9HbZd9ZgSpwPMr48fGRJOWmvE= +github.com/ipld/go-car/v2 v2.5.1 h1:U2ux9JS23upEgrJScW8VQuxmE94560kYxj9CQUpcfmk= +github.com/ipld/go-car/v2 v2.5.1/go.mod h1:jKjGOqoCj5zn6KjnabD6JbnCsMntqU2hLiU6baZVO3E= 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.4.1 h1:CUQJaOPRgSZ27OUPgUWtvdvvd2d17/IGGAIMOo4yYp0= -github.com/ipld/go-codec-dagpb v1.4.1/go.mod h1:XdXTO/TUD/ra9RcK/NfmwBfr1JpFxM2uRKaB9oe4LxE= -github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= +github.com/ipld/go-codec-dagpb v1.5.0 h1:RspDRdsJpLfgCI0ONhTAnbHdySGD4t+LHSPK4X1+R0k= +github.com/ipld/go-codec-dagpb v1.5.0/go.mod h1:0yRIutEFD8o1DGVqw4RSHh+BUTlJA9XWldxaaWR/o4g= github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/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.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= -github.com/ipld/go-ipld-prime v0.16.0/go.mod h1:axSCuOCBPqrH+gvXr2w9uAOulJqBPhHPT2PjoiiU1qA= github.com/ipld/go-ipld-prime v0.19.0 h1:5axC7rJmPc17Emw6TelxGwnzALk0PdupZ2oj2roDj04= github.com/ipld/go-ipld-prime v0.19.0/go.mod h1:Q9j3BaVXwaA3o5JUDNvptDDr/x8+F7FG6XJ8WI3ILg4= 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/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= @@ -721,20 +684,17 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL 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.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= 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.2 h1:XhdX4fqAJUA0yj+kUwMavO0hHrSPAecYdYf1ZmxHvak= -github.com/klauspost/cpuid/v2 v2.1.2/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.1 h1:U33DW0aiEj633gHYw3LoDNfkDiYnE5Q8M/TKJn2f2jI= +github.com/klauspost/cpuid/v2 v2.2.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= 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.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/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -750,68 +710,47 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 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 v0.0.1/go.mod h1:bGmu51N0KU9IEjX7kl2PQjgZa40JQWnayTvNMgD/vyk= -github.com/libp2p/go-conn-security-multistream v0.0.2/go.mod h1:nc9vud7inQ+d6SO0I/6dSWrdMnHnzZNHeyUQqrAJulE= 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-doh-resolver v0.4.0 h1:gUBa1f1XsPwtpE1du0O+nnZCUqtG7oYi7Bb+0S7FQqw= github.com/libp2p/go-doh-resolver v0.4.0/go.mod h1:v1/jwsFusgsWIGX/c6vCRrnJ60x7bhTiq/fs2qt0cAg= github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= -github.com/libp2p/go-eventbus v0.2.1 h1:VanAdErQnpTioN2TowqNcOijf6YwhuODe4pPKSDpxGc= 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.0.30/go.mod h1:XWT8FGHlhptAv1+3V/+J5mEpzyui/5bvFsNuWYs611A= 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.12.0/go.mod h1:FpHZrfC1q7nA8jitvdjKBDF31hguaC676g/nT9PgQM0= -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.23.4 h1:hWi9XHSOVFR1oDWRk7rigfyA4XNMuYL20INNybP9LP8= -github.com/libp2p/go-libp2p v0.23.4/go.mod h1:s9DEa5NLR4g+LZS+md5uGU4emjMWFiqkZr6hBTY8UxI= -github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= -github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= +github.com/libp2p/go-libp2p v0.24.2 h1:iMViPIcLY0D6zr/f+1Yq9EavCZu2i7eDstsr1nEwSAk= +github.com/libp2p/go-libp2p v0.24.2/go.mod h1:WuxtL2V8yGjam03D93ZBC19tvOUiPpewYv1xdFGWu1k= 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.0.6/go.mod h1:uZneLdOkZHro35xIhpbtTzLlgYturpu4J5+0cZK3MqE= 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.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-blankhost v0.0.1/go.mod h1:Ibpbw/7cPPYwFb7PACIWdvxxv0t0XCCI10t7czjAjTc= 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.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= -github.com/libp2p/go-libp2p-blankhost v0.3.0 h1:kTnLArltMabZlzY63pgGDA4kkUcLkBFSM98zBssn/IY= -github.com/libp2p/go-libp2p-blankhost v0.3.0/go.mod h1:urPC+7U01nCGgJ3ZsV8jdwTp6Ji9ID0dMTvq+aJ+nZU= -github.com/libp2p/go-libp2p-circuit v0.0.9/go.mod h1:uU+IBvEQzCu953/ps7bYzC/D/R0Ho2A9LfKVVCatlqU= 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.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-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= @@ -819,83 +758,48 @@ github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7O 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.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.6.1/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= 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.20.1 h1:fQz4BJyIFmSZAiTbKV8qoYhEH5Dtv/cVhZbG3Ib/+Cw= -github.com/libp2p/go-libp2p-core v0.20.1/go.mod h1:6zR8H7CvQWgYLsbG4on6oLNSGcyKaYFSEYyDt51+bIY= -github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE= -github.com/libp2p/go-libp2p-crypto v0.0.2/go.mod h1:eETI5OUfBnvARGOHrJz2eWNyTUxEGZnBxMcbUjfIj4I= github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= -github.com/libp2p/go-libp2p-discovery v0.0.5/go.mod h1:YtF20GUxjgoKZ4zmXj8j3Nb2TUSBHFlOCetzYdbZL5I= 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.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.3.0 h1:rnas//vRdHYCr7bjraZJISPwZV8OGMjeX5k5fN5Ax44= -github.com/libp2p/go-libp2p-gostream v0.3.0/go.mod h1:pLBQu8db7vBMNINGsAwLL/ZCE8wng5V1FThoaE5rNjc= -github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= -github.com/libp2p/go-libp2p-host v0.0.3/go.mod h1:Y/qPyA6C8j2coYyos1dfRm0I8+nvd4TGrDGt4tA7JR8= -github.com/libp2p/go-libp2p-http v0.2.1 h1:h8kuv7ExPe0nDtWAexKQWbjnXqks1hwOdYLs84gMCpo= -github.com/libp2p/go-libp2p-http v0.2.1/go.mod h1:9KdioZ7XqNH0eZkZG9bulZLzHv11A7/12fT97agqWhg= -github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= -github.com/libp2p/go-libp2p-interface-connmgr v0.0.4/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= -github.com/libp2p/go-libp2p-interface-connmgr v0.0.5/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= -github.com/libp2p/go-libp2p-interface-pnet v0.0.1/go.mod h1:el9jHpQAXK5dnTpKA4yfCNBZXvrzdOU75zz+C6ryp3k= -github.com/libp2p/go-libp2p-kad-dht v0.15.0/go.mod h1:rZtPxYu1TnHHz6n1RggdGrxUX/tA1C2/Wiw3ZMUDrU0= -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-gostream v0.5.0 h1:niNGTUrFoUDP/8jxMgu97zngMO+UGYBpVpbCKwIJBls= +github.com/libp2p/go-libp2p-gostream v0.5.0/go.mod h1:rXrb0CqfcRRxa7m3RSKORQiKiWgk3IPeXWda66ZXKsA= +github.com/libp2p/go-libp2p-http v0.4.0 h1:V+f9Rhe/8GkColmXoyJyA0NVsN9F3TCLZgW2hwjoX5w= +github.com/libp2p/go-libp2p-http v0.4.0/go.mod h1:92tmLGrlBliQFDlZRpBXT3BJM7rGFONy0vsNrG/bMPg= +github.com/libp2p/go-libp2p-kad-dht v0.20.0 h1:1bcMa74JFwExCHZMFEmjtHzxX5DovhJ07EtR6UOTEpc= +github.com/libp2p/go-libp2p-kad-dht v0.20.0/go.mod h1:qPIXdiZsLczhV4/+4EO1jE8ae0YCW4ZOogc4WVIyTEU= github.com/libp2p/go-libp2p-kbucket v0.3.1/go.mod h1:oyjT5O7tS9CQurok++ERgc46YLwEpuGoFq9ubvoUOio= -github.com/libp2p/go-libp2p-kbucket v0.4.7 h1:spZAcgxifvFZHBD8tErvppbnNiKA5uokDu3CV7axu70= -github.com/libp2p/go-libp2p-kbucket v0.4.7/go.mod h1:XyVo99AfQH0foSf176k4jY1xUJ2+jUJIZCSDm7r2YKk= -github.com/libp2p/go-libp2p-loggables v0.0.1/go.mod h1:lDipDlBNYbpyqyPX/KcoO+eq0sJYEVR2JgOexcivchg= -github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= +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-metrics v0.0.1/go.mod h1:jQJ95SXXA/K1VZi13h52WZMa9ja78zjyy5rspMsC/08= -github.com/libp2p/go-libp2p-mplex v0.1.1/go.mod h1:KUQWpGkCzfV7UIpi8SKsAVxyBgz1c9R5EvxgnwLsb/I= 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.3.0/go.mod h1:l9QWxRbbb5/hQMECEb908GbS9Sm2UAR2KFZKUJEynEs= 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-net v0.0.1/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= -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-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo= -github.com/libp2p/go-libp2p-peer v0.1.1/go.mod h1:jkF12jGB4Gk/IOo+yomm+7oLWxF278F7UnrYUQ1Q8es= github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= -github.com/libp2p/go-libp2p-peerstore v0.0.1/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= -github.com/libp2p/go-libp2p-peerstore v0.0.6/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= 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.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs= @@ -904,50 +808,27 @@ github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRj github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= 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.2.8/go.mod h1:gGiPlXdz7mIHd2vfAsHzBNAMqSDkt2UBFwgcITgw1lA= -github.com/libp2p/go-libp2p-peerstore v0.4.0/go.mod h1:rDJUFyzEWPpXpEwywkcTYYzDHlwza8riYMaUzaN6hX0= -github.com/libp2p/go-libp2p-peerstore v0.8.0 h1:bzTG693TA1Ju/zKmUCQzDLSqiJnyRFVwPpuloZ/OZtI= github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= -github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= -github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= -github.com/libp2p/go-libp2p-pubsub v0.6.0/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= -github.com/libp2p/go-libp2p-pubsub v0.8.1 h1:hSw09NauFUaA0FLgQPBJp6QOy0a2n+HSkb8IeOx8OnY= -github.com/libp2p/go-libp2p-pubsub v0.8.1/go.mod h1:e4kT+DYjzPUYGZeWk4I+oxCSYTXizzXii5LDRRhjKSw= -github.com/libp2p/go-libp2p-pubsub-router v0.5.0 h1:WuYdY42DVIJ+N0qMdq2du/E9poJH+xzsXL7Uptwj9tw= -github.com/libp2p/go-libp2p-pubsub-router v0.5.0/go.mod h1:TRJKskSem3C0aSb3CmRgPwq6IleVFzds6hS09fmZbGM= +github.com/libp2p/go-libp2p-pubsub v0.8.3 h1:T4+pcfcFm1K2v5oFyk68peSjVroaoM8zFygf6Y5WOww= +github.com/libp2p/go-libp2p-pubsub v0.8.3/go.mod h1:eje970FXxjhtFbVEoiae+VUw24ZoSlk67BsiZPLRzlw= +github.com/libp2p/go-libp2p-pubsub-router v0.6.0 h1:D30iKdlqDt5ZmLEYhHELCMRj8b4sFAqrUcshIUvVP/s= +github.com/libp2p/go-libp2p-pubsub-router v0.6.0/go.mod h1:FY/q0/RBTKsLA7l4vqC2cbRbOvyDotg8PJQ7j8FDudE= github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= -github.com/libp2p/go-libp2p-quic-transport v0.11.2/go.mod h1:wlanzKtIh6pHrq+0U3p3DY9PJfGqxMgPaGKaK5LifwQ= -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-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= -github.com/libp2p/go-libp2p-record v0.1.3/go.mod h1:yNUff/adKIfPnYQXgp6FQmNu3gLJ6EMg7+/vv2+9pY4= 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 v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= -github.com/libp2p/go-libp2p-routing-helpers v0.2.3/go.mod h1:795bh+9YeoFl99rMASoiVgHdi5bjack0N1+AFAdbvBw= -github.com/libp2p/go-libp2p-routing-helpers v0.4.1 h1:rOlZiFpUt7SgHm4w62MBvWaQ4UHh7bVJnSnor6RN7j8= -github.com/libp2p/go-libp2p-routing-helpers v0.4.1/go.mod h1:dYEAgkVhqho3/YKxfOEGdFMIcWfAFNlZX8iAIihYA2E= -github.com/libp2p/go-libp2p-secio v0.0.3/go.mod h1:hS7HQ00MgLhRO/Wyu1bTX6ctJKhVpm+j2/S2A5UqYb0= +github.com/libp2p/go-libp2p-routing-helpers v0.6.0 h1:Rfyd+wp/cU0PjNjCphGzLYzd7Q51fjOMs5Sjj6zWGT0= +github.com/libp2p/go-libp2p-routing-helpers v0.6.0/go.mod h1:wwK/XSLt6njjO7sRbjhf8w7PGBOfdntMQ2mOQPZ5s/Q= 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.0.6/go.mod h1:s5GZvzg9xXe8sbeESuFpjt8CJPTCa8mhEusweJqyFy8= 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.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.3.1/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.5.3/go.mod h1:NBn7eNW2lu568L7Ns9wdFrOhgRlkRnIDg0FLKbuu3i8= -github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= -github.com/libp2p/go-libp2p-swarm v0.11.0 h1:ITgsTEY2tA4OxFJGcWeugiMh2x5+VOEnI2JStT1EWxI= -github.com/libp2p/go-libp2p-swarm v0.11.0/go.mod h1:sumjVYrC84gPSZOFKL8hNcnN6HZvJSwJ8ymaXeko4Lk= -github.com/libp2p/go-libp2p-testing v0.0.1/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= 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= @@ -956,29 +837,15 @@ github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eq 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.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= 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-transport v0.0.1/go.mod h1:UzbUs9X+PHOSw7S3ZmeOxfnwaQY5vGDzZmKPod3N3tk= -github.com/libp2p/go-libp2p-transport v0.0.5/go.mod h1:StoY3sx6IqsP6XKoabsPnHCwqKXWUMWU7Rfcsubee/A= -github.com/libp2p/go-libp2p-transport-upgrader v0.0.4/go.mod h1:RGq+tupk+oj7PzL2kn/m1w6YXxcIAYJYeI90h6BGgUc= 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.4.6/go.mod h1:JE0WQuQdy+uLZ5zOaI3Nw9dWGYJIA7mywEtP2lMvnyk= -github.com/libp2p/go-libp2p-transport-upgrader v0.5.0/go.mod h1:Rc+XODlB3yce7dvFV4q/RmyJGsFcCZRkeZMu/Zdg0mo= -github.com/libp2p/go-libp2p-xor v0.0.0-20210714161855-5c005aca55db/go.mod h1:LSTM5yRnjGZbWNTA/hRwq2gGFrvRIbQJscoIL/u6InY= github.com/libp2p/go-libp2p-xor v0.1.0 h1:hhQwT4uGrBcuAkUGXADuPltalOdpf9aag9kaYNT2tLA= github.com/libp2p/go-libp2p-xor v0.1.0/go.mod h1:LSTM5yRnjGZbWNTA/hRwq2gGFrvRIbQJscoIL/u6InY= -github.com/libp2p/go-libp2p-yamux v0.1.2/go.mod h1:xUoV/RmYkg6BW/qGxA9XJyg+HzXFYkeXbnhjmnYzKp8= -github.com/libp2p/go-libp2p-yamux v0.1.3/go.mod h1:VGSQVrqkh6y4nm0189qqxMtvyBft44MOYYPpYKXiVt4= 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= @@ -987,15 +854,11 @@ 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-maddr-filter v0.0.1/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= 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/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= -github.com/libp2p/go-mplex v0.0.4/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= @@ -1007,7 +870,6 @@ github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+ 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= @@ -1030,43 +892,28 @@ github.com/libp2p/go-openssl v0.1.0 h1:LBkKEcUv6vtZIQLVTegAil8jbNpJErQ9AnT+bWV+O 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.0.5/go.mod h1:TC62hhPc8qs5c/RoXDZG6YmjK+/YWUPC0yYmeUecbjc= -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-socket-activation v0.1.0 h1:OImQPhtbGlCNaF/KSTl6pBBy+chA5eBt5i9uMJNtEdY= github.com/libp2p/go-socket-activation v0.1.0/go.mod h1:gzda2dNkMG5Ti2OfWNNwW0FDIbj0g/aJJU320FcLfhk= github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= -github.com/libp2p/go-stream-muxer v0.1.0/go.mod h1:8JAVsjeRBCWwPoZeH0W1imLOcriqXJyFvB0mR4A04sQ= -github.com/libp2p/go-stream-muxer-multistream v0.1.1/go.mod h1:zmGdfkQ1AzOECIAcccoL8L//laqawOsO03zX8Sa+eGw= 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.0.4/go.mod h1:+E8HvC8ezEVOxIo3V5vCK9l1y/19K427vCzQ+xHKH/o= 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.2.7/go.mod h1:lue9p1b3VmZj1MhhEGB/etmvF/nBQ0X9CW2DutBT3MM= -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= -github.com/libp2p/go-ws-transport v0.0.5/go.mod h1:Qbl4BxPfXXhhd/o0wcrgoaItHqA9tnZjoFZnxykuaXU= 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.1/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= 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= @@ -1075,22 +922,16 @@ 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/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ= github.com/libp2p/go-yamux/v4 v4.0.0/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= -github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= github.com/libp2p/zeroconf/v2 v2.2.0 h1:Cup06Jv6u81HLhIj1KasuNM/RHHrJ8T7wOTS4+Tv53Q= github.com/libp2p/zeroconf/v2 v2.2.0/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.19.3/go.mod h1:ADXpNbTQjq1hIzCpB+y/k5iz4n4z4IwqoLb94Kh5Hu8= -github.com/lucas-clemente/quic-go v0.21.2/go.mod h1:vF5M1XqhBAHgbjKcJOXY3JZz3GP0T3FQhz/uyOUS38Q= -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.29.1 h1:Z+WMJ++qMLhvpFkRZA+jl3BTxUjm415YBmWanXB8zP0= -github.com/lucas-clemente/quic-go v0.29.1/go.mod h1:CTcNfLYJS2UuRNB+zcNlgvkjBhxX6Hm3WUxxAQx2mgE= +github.com/lucas-clemente/quic-go v0.31.1 h1:O8Od7hfioqq0PMYHDyBkxU2aA7iZ2W9pjbrWuja2YR4= +github.com/lucas-clemente/quic-go v0.31.1/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g= 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/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -1101,19 +942,14 @@ github.com/marten-seemann/qpack v0.3.0 h1:UiWstOgT8+znlkDPOg2+3rIuYXJ2CnGDkGUXN6 github.com/marten-seemann/qpack v0.3.0/go.mod h1:cGfKPBiP4a9EQdxCwEwI/GEeWAsjSekBvx/X8mh58+g= 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-15 v0.1.5/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-17 v0.1.0-rc.1/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= -github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI= github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE= github.com/marten-seemann/qtls-go1-19 v0.1.1/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/marten-seemann/webtransport-go v0.1.1 h1:TnyKp3pEXcDooTaNn4s9dYpMJ7kMnTp7k5h+SgYP/mc= -github.com/marten-seemann/webtransport-go v0.1.1/go.mod h1:kBEh5+RSvOA4troP1vyOVBWK4MIMzDICXVrvCPrYcrM= +github.com/marten-seemann/webtransport-go v0.4.3 h1:vkt5o/Ci+luknRteWdYGYH1KcB7ziup+J+1PzZJIvmg= +github.com/marten-seemann/webtransport-go v0.4.3/go.mod h1:4xcfySgZMLP4aG5GBGj1egP7NlpfwgYJ1WJMvPPiVMU= 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= @@ -1126,8 +962,8 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= 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-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/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= @@ -1142,7 +978,6 @@ 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= @@ -1184,8 +1019,9 @@ github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjW github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= -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-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= 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= @@ -1221,29 +1057,21 @@ github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/g 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.2.0/go.mod h1:/y4YVwkfMyry5kFbMTbLJKErhycTIftytRV+llXdyS4= 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.7.0 h1:rTUjGOwjlhGHbEMbPoSUJowG1spZTVsITRANCjKTUAQ= github.com/multiformats/go-multicodec v0.7.0/go.mod h1:GUC8upxSBE4oG+q3kWZRw/+6yC1BqO550bjhWsJbZlw= 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.0.16/go.mod h1:zhfEIgVnB/rPMfxgFw15ZmGoNaKyNUIE4IWHG/kC+Ag= 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.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= -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= @@ -1251,8 +1079,9 @@ github.com/multiformats/go-multistream v0.3.3/go.mod h1:ODRoqamLUsETKS9BNcII4gcR 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/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= 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/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= @@ -1276,22 +1105,19 @@ github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W 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/ginkgo/v2 v2.5.0 h1:TRtrvv2vdQqzkwrQ1ke6vtXf7IK34RBUJafIy1wMwls= -github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= +github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw= +github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc= 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.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 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/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg= -github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= 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= @@ -1316,7 +1142,6 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 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/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/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -1340,7 +1165,6 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod 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.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/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= @@ -1360,11 +1184,9 @@ github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= 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= @@ -1375,7 +1197,6 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= 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= @@ -1394,8 +1215,6 @@ github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBO github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 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/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= @@ -1478,8 +1297,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= 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/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e h1:T5PdfK/M1xyrHwynxMIVMWLS7f/qHwfslZphxtGnw7s= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= @@ -1494,7 +1314,6 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT 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.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= @@ -1509,11 +1328,9 @@ github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvS github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4= github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= 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-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= -github.com/whyrusleeping/cbor-gen v0.0.0-20200710004633-5379fc63235d/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2 h1:bsUlNhdmbtlfdLVXAVfuvKQ01RnWAM09TVrJkI7NZs4= -github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20221220214510-0333c149dec0 h1:obKzQ1ey5AJg5NKjgtTo/CKwLImVP4ETLRcsmzFJ4Qw= +github.com/whyrusleeping/cbor-gen v0.0.0-20221220214510-0333c149dec0/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= @@ -1528,8 +1345,6 @@ github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84 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/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= @@ -1552,13 +1367,11 @@ 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.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.32.0 h1:mac9BKRqwaX6zxHPDe3pvmWpwuuIM0vuXv2juCnQevE= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.32.0/go.mod h1:5eCOqeGphOyz6TsY3ZDNjE33SM/TFAK3RGuCL2naTgY= -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.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI= 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/exporters/jaeger v1.7.0 h1:wXgjiRldljksZkZrldGVe6XrG9u3kYDyQmkZwmm5dI0= @@ -1575,17 +1388,10 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0 h1:8hPcgCg0rUJiKE6V go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0/go.mod h1:K4GDXPY6TjUiwbOh+DkKaEdCF8y+lvMoM6SeAPyfCCM= go.opentelemetry.io/otel/exporters/zipkin v1.7.0 h1:X0FZj+kaIdLi29UiyrEGDhRTYsEXj9GdEW5Y39UQFEE= go.opentelemetry.io/otel/exporters/zipkin v1.7.0/go.mod h1:9YBXeOMFLQGwNEjsxMRiWPGoJX83usGMhbCmxUbNe5I= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= go.opentelemetry.io/otel/metric v0.30.0 h1:Hs8eQZ8aQgs0U49diZoaS6Uaxw3+bBE3lcMUKBFIk3c= go.opentelemetry.io/otel/metric v0.30.0/go.mod h1:/ShZ7+TS4dHzDFmfi1kSXMhMVubNoP0oIaBp70J6UXU= -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/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U= go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0= go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU= -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.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5fjhKeJGZPGFs= 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= @@ -1596,15 +1402,13 @@ 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.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.14.1 h1:fyakRgZDdi2F8FgwJJoRGangMSPTIxPSLGzR3Oh0/54= -go.uber.org/dig v1.14.1/go.mod h1:52EKx/Vjdpz9EzeNcweC4YMsTrDdFn9mS/+Uw5ZnVTI= -go.uber.org/fx v1.17.1 h1:S42dZ6Pok8hQ3jxKwo6ZMYcCgHQA/wAS/gnpRa1Pksg= -go.uber.org/fx v1.17.1/go.mod h1:yO7KN5rhlARljyo4LR047AjaV6J+KFzd/Z7rnTbEn0A= +go.uber.org/dig v1.15.0 h1:vq3YWr8zRj1eFGC7Gvf907hE0eRjPTZ1d3xHadD6liE= +go.uber.org/dig v1.15.0/go.mod h1:pKHs0wMynzL6brANhB2hLMro+zalv1osARTviTcqHLM= +go.uber.org/fx v1.18.2 h1:bUNI6oShr+OVFQeU8cDNbnN7VFsu+SsjHzUF51V/GAU= +go.uber.org/fx v1.18.2/go.mod h1:g0V1KMQ66zIRk8bLu3Ea5Jt2w/cHlOIp4wdRsgh0JaY= 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.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= @@ -1612,20 +1416,17 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/ go.uber.org/multierr v1.3.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/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 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.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.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -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.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY= -go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= 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= @@ -1637,7 +1438,6 @@ golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/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-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1651,7 +1451,6 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1660,16 +1459,12 @@ golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPh 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-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/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= @@ -1677,9 +1472,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 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-20221106115401-f9659909a136 h1:Fq7F/w7MAa1KJ5bt2aJ62ihqp9HDcRuyILskkpIAurw= -golang.org/x/exp v0.0.0-20221106115401-f9659909a136/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o= +golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= 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= @@ -1695,17 +1489,15 @@ golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/lint v0.0.0-20200302205851-738671d3881b/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 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 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= @@ -1749,8 +1541,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ 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= @@ -1761,13 +1553,12 @@ golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT 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-20210917221730-978cfadd31cf/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.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= 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= @@ -1817,7 +1608,6 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w 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-20190524152521-dbbf3f1254d4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/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= @@ -1832,7 +1622,6 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/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-20191210023423-ac6580df4449/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= @@ -1856,9 +1645,9 @@ golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7w 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-20200814200057-3d37ad5750ed/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= @@ -1871,25 +1660,22 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w 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-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-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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= +golang.org/x/sys v0.4.0/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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= 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= @@ -1898,8 +1684,8 @@ 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/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 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= @@ -1937,7 +1723,6 @@ golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapK 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-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= @@ -1959,18 +1744,17 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc 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.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= 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= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= 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= @@ -2064,9 +1848,8 @@ google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.46.0 h1:oCjezcn6g6A75TGoKYBPgKmVBLexhYLM6MebdrPApP8= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= 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= @@ -2125,7 +1908,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh 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= 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= diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index 219f136f7..99104b083 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -36,7 +36,7 @@ const LockFile = "repo.lock" var log = logging.Logger("fsrepo") // RepoVersion is the version number that we are currently expecting to see -var RepoVersion = 12 +var RepoVersion = 13 var migrationInstructions = `See https://github.com/ipfs/fs-repo-migrations/blob/master/run.md Sorry for the inconvenience. In the future, these will run automatically.` diff --git a/repo/fsrepo/migrations/fetcher.go b/repo/fsrepo/migrations/fetcher.go index 87fa95b8b..c174b5e77 100644 --- a/repo/fsrepo/migrations/fetcher.go +++ b/repo/fsrepo/migrations/fetcher.go @@ -11,7 +11,7 @@ import ( const ( // Current distribution to fetch migrations from - CurrentIpfsDist = "/ipfs/QmdaCHYBDHEhXCMoynH5UcohEay6m1XayZCcxWZzKAHNVN" // fs-repo-11-to-12 v1.0.2 + CurrentIpfsDist = "/ipfs/Qmf4yftD4LuMo8JMNPqqw3BtUwYd2VkXMiAThuPE6usrbQ" // fs-repo-12-to-13 v1.0.0 // Latest distribution path. Default for fetchers. LatestIpfsDist = "/ipns/dist.ipfs.tech" diff --git a/repo/fsrepo/migrations/ipfsfetcher/ipfsfetcher.go b/repo/fsrepo/migrations/ipfsfetcher/ipfsfetcher.go index ce7b490ef..52cd354d3 100644 --- a/repo/fsrepo/migrations/ipfsfetcher/ipfsfetcher.go +++ b/repo/fsrepo/migrations/ipfsfetcher/ipfsfetcher.go @@ -11,7 +11,7 @@ import ( "strings" "sync" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" iface "github.com/ipfs/interface-go-ipfs-core" "github.com/ipfs/interface-go-ipfs-core/options" ipath "github.com/ipfs/interface-go-ipfs-core/path" @@ -188,7 +188,7 @@ func initTempNode(ctx context.Context, bootstrap []string, peers []peer.AddrInfo } // configure the temporary node - cfg.Routing.Type = "dhtclient" + cfg.Routing.Type = config.NewOptionalString("dhtclient") // Disable listening for inbound connections cfg.Addresses.Gateway = []string{} diff --git a/routing/composer.go b/routing/composer.go index f2f1f65e6..f54d954bd 100644 --- a/routing/composer.go +++ b/routing/composer.go @@ -100,9 +100,18 @@ func (c *Composer) GetValue(ctx context.Context, key string, opts ...routing.Opt func (c *Composer) SearchValue(ctx context.Context, key string, opts ...routing.Option) (<-chan []byte, error) { log.Debug("composer: calling searchValue: ", key) ch, err := c.GetValueRouter.SearchValue(ctx, key, opts...) + + // avoid nil channels on implementations not supporting SearchValue method. + if err == routing.ErrNotFound && ch == nil { + out := make(chan []byte) + close(out) + return out, err + } + if err != nil { log.Debug("composer: calling searchValue error: ", key, err) } + return ch, err } diff --git a/routing/delegated.go b/routing/delegated.go index 953cfac00..1e8d7efa0 100644 --- a/routing/delegated.go +++ b/routing/delegated.go @@ -13,6 +13,7 @@ import ( drclient "github.com/ipfs/go-libipfs/routing/http/client" "github.com/ipfs/go-libipfs/routing/http/contentrouter" logging "github.com/ipfs/go-log" + version "github.com/ipfs/kubo" "github.com/ipfs/kubo/config" dht "github.com/libp2p/go-libp2p-kad-dht" "github.com/libp2p/go-libp2p-kad-dht/dual" @@ -157,6 +158,22 @@ type ExtraHTTPParams struct { PrivKeyB64 string } +func ConstructHTTPRouter(endpoint string, peerID string, addrs []string, privKey string) (routing.Routing, error) { + return httpRoutingFromConfig( + config.Router{ + Type: "http", + Parameters: &config.HTTPRouterParams{ + Endpoint: endpoint, + }, + }, + &ExtraHTTPParams{ + PeerID: peerID, + Addrs: addrs, + PrivKeyB64: privKey, + }, + ) +} + func httpRoutingFromConfig(conf config.Router, extraHTTP *ExtraHTTPParams) (routing.Routing, error) { params := conf.Parameters.(*config.HTTPRouterParams) if params.Endpoint == "" { @@ -171,7 +188,10 @@ func httpRoutingFromConfig(conf config.Router, extraHTTP *ExtraHTTPParams) (rout transport.MaxIdleConnsPerHost = 100 delegateHTTPClient := &http.Client{ - Transport: transport, + Transport: &drclient.ResponseBodyLimitedTransport{ + RoundTripper: transport, + LimitBytes: 1 << 20, + }, } key, err := decodePrivKey(extraHTTP.PrivKeyB64) @@ -189,6 +209,7 @@ func httpRoutingFromConfig(conf config.Router, extraHTTP *ExtraHTTPParams) (rout drclient.WithHTTPClient(delegateHTTPClient), drclient.WithIdentity(key), drclient.WithProviderInfo(addrInfo.ID, addrInfo.Addrs), + drclient.WithUserAgent(version.GetUserAgentVersion()), ) if err != nil { return nil, err diff --git a/test/cli/basic_commands_test.go b/test/cli/basic_commands_test.go new file mode 100644 index 000000000..30c1f1f9a --- /dev/null +++ b/test/cli/basic_commands_test.go @@ -0,0 +1,238 @@ +package cli + +import ( + "fmt" + "regexp" + "strings" + "testing" + + "github.com/blang/semver/v4" + "github.com/ipfs/kubo/test/cli/harness" + . "github.com/ipfs/kubo/test/cli/testutils" + "github.com/stretchr/testify/assert" + gomod "golang.org/x/mod/module" +) + +var versionRegexp = regexp.MustCompile(`^ipfs version (.+)$`) + +func parseVersionOutput(s string) semver.Version { + versString := versionRegexp.FindStringSubmatch(s)[1] + v, err := semver.Parse(versString) + if err != nil { + panic(err) + } + return v +} + +func TestCurDirIsWritable(t *testing.T) { + t.Parallel() + h := harness.NewT(t) + h.WriteFile("test.txt", "It works!") +} + +func TestIPFSVersionCommandMatchesFlag(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + commandVersionStr := node.IPFS("version").Stdout.String() + commandVersionStr = strings.TrimSpace(commandVersionStr) + commandVersion := parseVersionOutput(commandVersionStr) + + flagVersionStr := node.IPFS("--version").Stdout.String() + flagVersionStr = strings.TrimSpace(flagVersionStr) + flagVersion := parseVersionOutput(flagVersionStr) + + assert.Equal(t, commandVersion, flagVersion) +} + +func TestIPFSVersionAll(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + res := node.IPFS("version", "--all").Stdout.String() + res = strings.TrimSpace(res) + assert.Contains(t, res, "Kubo version") + assert.Contains(t, res, "Repo version") + assert.Contains(t, res, "System version") + assert.Contains(t, res, "Golang version") +} + +func TestIPFSVersionDeps(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + res := node.IPFS("version", "deps").Stdout.String() + res = strings.TrimSpace(res) + lines := SplitLines(res) + + assert.Equal(t, "github.com/ipfs/kubo@(devel)", lines[0]) + + for _, depLine := range lines[1:] { + split := strings.Split(depLine, " => ") + for _, moduleVersion := range split { + splitModVers := strings.Split(moduleVersion, "@") + modPath := splitModVers[0] + modVers := splitModVers[1] + assert.NoError(t, gomod.Check(modPath, modVers), "path: %s, version: %s", modPath, modVers) + } + } +} + +func TestIPFSCommands(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + cmds := node.IPFSCommands() + assert.Contains(t, cmds, "ipfs add") + assert.Contains(t, cmds, "ipfs daemon") + assert.Contains(t, cmds, "ipfs update") +} + +func TestAllSubcommandsAcceptHelp(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + for _, cmd := range node.IPFSCommands() { + t.Run(fmt.Sprintf("command %q accepts help", cmd), func(t *testing.T) { + t.Parallel() + splitCmd := strings.Split(cmd, " ")[1:] + node.IPFS(StrCat("help", splitCmd)...) + node.IPFS(StrCat(splitCmd, "--help")...) + }) + } +} + +func TestAllRootCommandsAreMentionedInHelpText(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + cmds := node.IPFSCommands() + var rootCmds []string + for _, cmd := range cmds { + splitCmd := strings.Split(cmd, " ") + if len(splitCmd) == 2 { + rootCmds = append(rootCmds, splitCmd[1]) + } + } + + // a few base commands are not expected to be in the help message + // but we default to requiring them to be in the help message, so that we + // have to make an conscious decision to exclude them + notInHelp := map[string]bool{ + "object": true, + "shutdown": true, + "tar": true, + "urlstore": true, + "dns": true, + } + + helpMsg := strings.TrimSpace(node.IPFS("--help").Stdout.String()) + for _, rootCmd := range rootCmds { + if _, ok := notInHelp[rootCmd]; ok { + continue + } + assert.Contains(t, helpMsg, fmt.Sprintf(" %s", rootCmd)) + } +} + +func TestCommandDocsWidth(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + + // require new commands to explicitly opt in to longer lines + allowList := map[string]bool{ + "ipfs add": true, + "ipfs block put": true, + "ipfs daemon": true, + "ipfs config profile": true, + "ipfs pin remote service": true, + "ipfs name pubsub": true, + "ipfs object patch": true, + "ipfs swarm connect": true, + "ipfs p2p forward": true, + "ipfs p2p close": true, + "ipfs swarm disconnect": true, + "ipfs swarm addrs listen": true, + "ipfs dag resolve": true, + "ipfs dag get": true, + "ipfs object stat": true, + "ipfs pin remote add": true, + "ipfs config show": true, + "ipfs config edit": true, + "ipfs pin remote rm": true, + "ipfs pin remote ls": true, + "ipfs pin verify": true, + "ipfs dht get": true, + "ipfs pin remote service add": true, + "ipfs file ls": true, + "ipfs pin update": true, + "ipfs pin rm": true, + "ipfs p2p": true, + "ipfs resolve": true, + "ipfs dag stat": true, + "ipfs name publish": true, + "ipfs object diff": true, + "ipfs object patch add-link": true, + "ipfs name": true, + "ipfs object patch append-data": true, + "ipfs object patch set-data": true, + "ipfs dht put": true, + "ipfs diag profile": true, + "ipfs diag cmds": true, + "ipfs swarm addrs local": true, + "ipfs files ls": true, + "ipfs stats bw": true, + "ipfs urlstore add": true, + "ipfs swarm peers": true, + "ipfs pubsub sub": true, + "ipfs repo fsck": true, + "ipfs files write": true, + "ipfs swarm limit": true, + "ipfs commands completion fish": true, + "ipfs key export": true, + "ipfs routing get": true, + "ipfs refs": true, + "ipfs refs local": true, + "ipfs cid base32": true, + "ipfs pubsub pub": true, + "ipfs repo ls": true, + "ipfs routing put": true, + "ipfs key import": true, + "ipfs swarm peering add": true, + "ipfs swarm peering rm": true, + "ipfs swarm peering ls": true, + "ipfs update": true, + "ipfs swarm stats": true, + } + for _, cmd := range node.IPFSCommands() { + if _, ok := allowList[cmd]; ok { + continue + } + t.Run(fmt.Sprintf("command %q conforms to docs width limit", cmd), func(t *testing.T) { + splitCmd := strings.Split(cmd, " ") + resStr := node.IPFS(StrCat(splitCmd[1:], "--help")...) + res := strings.TrimSpace(resStr.Stdout.String()) + for _, line := range SplitLines(res) { + assert.LessOrEqualf(t, len(line), 80, "expected width %d < 80 for %q", len(line), cmd) + } + + }) + } +} + +func TestAllCommandsFailWhenPassedBadFlag(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + + for _, cmd := range node.IPFSCommands() { + t.Run(fmt.Sprintf("command %q fails when passed a bad flag", cmd), func(t *testing.T) { + splitCmd := strings.Split(cmd, " ") + res := node.RunIPFS(StrCat(splitCmd, "--badflag")...) + assert.Equal(t, 1, res.Cmd.ProcessState.ExitCode()) + }) + } + +} + +func TestCommandsFlags(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + resStr := node.IPFS("commands", "--flags").Stdout.String() + assert.Contains(t, resStr, "ipfs pin add --recursive / ipfs pin add -r") + assert.Contains(t, resStr, "ipfs id --format / ipfs id -f") + assert.Contains(t, resStr, "ipfs repo gc --quiet / ipfs repo gc -q") +} diff --git a/test/cli/completion_test.go b/test/cli/completion_test.go new file mode 100644 index 000000000..0c40eb02b --- /dev/null +++ b/test/cli/completion_test.go @@ -0,0 +1,31 @@ +package cli + +import ( + "fmt" + "testing" + + "github.com/ipfs/kubo/test/cli/harness" + . "github.com/ipfs/kubo/test/cli/testutils" + "github.com/stretchr/testify/assert" +) + +func TestBashCompletion(t *testing.T) { + t.Parallel() + h := harness.NewT(t) + node := h.NewNode() + + res := node.IPFS("commands", "completion", "bash") + + length := len(res.Stdout.String()) + if length < 100 { + t.Fatalf("expected a long Bash completion file, but got one of length %d", length) + } + + t.Run("completion file can be loaded in bash", func(t *testing.T) { + RequiresLinux(t) + + completionFile := h.WriteToTemp(res.Stdout.String()) + res = h.Sh(fmt.Sprintf("source %s && type -t _ipfs", completionFile)) + assert.NoError(t, res.Err) + }) +} diff --git a/test/cli/delegated_routing_http_test.go b/test/cli/delegated_routing_http_test.go new file mode 100644 index 000000000..0b39a9b12 --- /dev/null +++ b/test/cli/delegated_routing_http_test.go @@ -0,0 +1,121 @@ +package cli + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/ipfs/kubo/config" + "github.com/ipfs/kubo/test/cli/harness" + . "github.com/ipfs/kubo/test/cli/testutils" + "github.com/stretchr/testify/assert" +) + +func TestHTTPDelegatedRouting(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode().Init().StartDaemon() + + fakeServer := func(resp string) *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _, err := w.Write([]byte(resp)) + if err != nil { + panic(err) + } + })) + } + + findProvsCID := "baeabep4vu3ceru7nerjjbk37sxb7wmftteve4hcosmyolsbsiubw2vr6pqzj6mw7kv6tbn6nqkkldnklbjgm5tzbi4hkpkled4xlcr7xz4bq" + prov := "12D3KooWARYacCc6eoCqvsS9RW9MA2vo51CV75deoiqssx3YgyYJ" + + t.Run("default routing config has no routers defined", func(t *testing.T) { + assert.Nil(t, node.ReadConfig().Routing.Routers) + }) + + t.Run("no routers means findprovs returns no results", func(t *testing.T) { + res := node.IPFS("routing", "findprovs", findProvsCID).Stdout.String() + assert.Empty(t, res) + }) + + t.Run("no routers means findprovs returns no results", func(t *testing.T) { + res := node.IPFS("routing", "findprovs", findProvsCID).Stdout.String() + assert.Empty(t, res) + }) + + node.StopDaemon() + + t.Run("missing method params make the daemon fail", func(t *testing.T) { + node.UpdateConfig(func(cfg *config.Config) { + cfg.Routing.Type = config.NewOptionalString("custom") + cfg.Routing.Methods = config.Methods{ + "find-peers": {RouterName: "TestDelegatedRouter"}, + "find-providers": {RouterName: "TestDelegatedRouter"}, + "get-ipns": {RouterName: "TestDelegatedRouter"}, + "provide": {RouterName: "TestDelegatedRouter"}, + } + }) + res := node.RunIPFS("daemon") + assert.Equal(t, 1, res.ExitErr.ProcessState.ExitCode()) + assert.Contains( + t, + res.Stderr.String(), + `method name "put-ipns" is missing from Routing.Methods config param`, + ) + }) + + t.Run("having wrong methods makes daemon fail", func(t *testing.T) { + node.UpdateConfig(func(cfg *config.Config) { + cfg.Routing.Type = config.NewOptionalString("custom") + cfg.Routing.Methods = config.Methods{ + "find-peers": {RouterName: "TestDelegatedRouter"}, + "find-providers": {RouterName: "TestDelegatedRouter"}, + "get-ipns": {RouterName: "TestDelegatedRouter"}, + "provide": {RouterName: "TestDelegatedRouter"}, + "put-ipns": {RouterName: "TestDelegatedRouter"}, + "NOT_SUPPORTED": {RouterName: "TestDelegatedRouter"}, + } + }) + res := node.RunIPFS("daemon") + assert.Equal(t, 1, res.ExitErr.ProcessState.ExitCode()) + assert.Contains( + t, + res.Stderr.String(), + `method name "NOT_SUPPORTED" is not a supported method on Routing.Methods config param`, + ) + }) + + t.Run("adding HTTP delegated routing endpoint to Routing.Routers config works", func(t *testing.T) { + server := fakeServer(ToJSONStr(JSONObj{ + "Providers": []JSONObj{{ + "Protocol": "transport-bitswap", + "Schema": "bitswap", + "ID": prov, + "Addrs": []string{"/ip4/0.0.0.0/tcp/4001", "/ip4/0.0.0.0/tcp/4002"}, + }}, + })) + t.Cleanup(server.Close) + + node.IPFS("config", "Routing.Type", "--json", `"custom"`) + node.IPFS("config", "Routing.Routers.TestDelegatedRouter", "--json", ToJSONStr(JSONObj{ + "Type": "http", + "Parameters": JSONObj{ + "Endpoint": server.URL, + }, + })) + node.IPFS("config", "Routing.Methods", "--json", ToJSONStr(JSONObj{ + "find-peers": JSONObj{"RouterName": "TestDelegatedRouter"}, + "find-providers": JSONObj{"RouterName": "TestDelegatedRouter"}, + "get-ipns": JSONObj{"RouterName": "TestDelegatedRouter"}, + "provide": JSONObj{"RouterName": "TestDelegatedRouter"}, + "put-ipns": JSONObj{"RouterName": "TestDelegatedRouter"}, + })) + + res := node.IPFS("config", "Routing.Routers.TestDelegatedRouter.Parameters.Endpoint") + assert.Equal(t, res.Stdout.Trimmed(), server.URL) + + node.StartDaemon() + + res = node.IPFS("routing", "findprovs", findProvsCID) + assert.Equal(t, prov, res.Stdout.Trimmed()) + }) + +} diff --git a/test/cli/gateway_test.go b/test/cli/gateway_test.go new file mode 100644 index 000000000..6e8ef516a --- /dev/null +++ b/test/cli/gateway_test.go @@ -0,0 +1,492 @@ +package cli + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "os" + "path/filepath" + "regexp" + "testing" + + "github.com/ipfs/kubo/config" + "github.com/ipfs/kubo/test/cli/harness" + . "github.com/ipfs/kubo/test/cli/testutils" + "github.com/multiformats/go-multiaddr" + manet "github.com/multiformats/go-multiaddr/net" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGateway(t *testing.T) { + t.Parallel() + h := harness.NewT(t) + node := h.NewNode().Init().StartDaemon("--offline") + cid := node.IPFSAddStr("Hello Worlds!") + + client := node.GatewayClient() + client.TemplateData = map[string]string{ + "CID": cid, + "PeerID": node.PeerID().String(), + } + + t.Run("GET IPFS path succeeds", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/{{.CID}}") + assert.Equal(t, 200, resp.StatusCode) + }) + + t.Run("GET IPFS path with explicit ?filename succeeds with proper header", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/{{.CID}}?filename=testтест.pdf") + assert.Equal(t, 200, resp.StatusCode) + assert.Equal(t, + `inline; filename="test____.pdf"; filename*=UTF-8''test%D1%82%D0%B5%D1%81%D1%82.pdf`, + resp.Headers.Get("Content-Disposition"), + ) + }) + + t.Run("GET IPFS path with explicit ?filename and &download=true succeeds with proper header", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/{{.CID}}?filename=testтест.mp4&download=true") + assert.Equal(t, 200, resp.StatusCode) + assert.Equal(t, + `attachment; filename="test____.mp4"; filename*=UTF-8''test%D1%82%D0%B5%D1%81%D1%82.mp4`, + resp.Headers.Get("Content-Disposition"), + ) + }) + + // https://github.com/ipfs/go-ipfs/issues/4025#issuecomment-342250616 + t.Run("GET for Server Worker registration outside of an IPFS content root errors", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/{{.CID}}?filename=sw.js", client.WithHeader("Service-Worker", "script")) + assert.Equal(t, 400, resp.StatusCode) + assert.Contains(t, resp.Body, "navigator.serviceWorker: registration is not allowed for this scope") + }) + + t.Run("GET IPFS directory path succeeds", func(t *testing.T) { + t.Parallel() + client := node.GatewayClient().DisableRedirects() + + pageContents := "hello i am a webpage" + fileContents := "12345" + h.WriteFile("dir/test", fileContents) + h.WriteFile("dir/dirwithindex/index.html", pageContents) + cids := node.IPFS("add", "-r", "-q", filepath.Join(h.Dir, "dir")).Stdout.Lines() + + rootCID := cids[len(cids)-1] + client.TemplateData = map[string]string{ + "IndexFileCID": cids[0], + "TestFileCID": cids[1], + "RootCID": rootCID, + } + + t.Run("GET IPFS the index file CID", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/{{.IndexFileCID}}") + assert.Equal(t, 200, resp.StatusCode) + assert.Equal(t, pageContents, resp.Body) + }) + + t.Run("GET IPFS the test file CID", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/{{.TestFileCID}}") + assert.Equal(t, 200, resp.StatusCode) + assert.Equal(t, fileContents, resp.Body) + }) + + t.Run("GET IPFS directory with index.html returns redirect to add trailing slash", func(t *testing.T) { + t.Parallel() + resp := client.Head("/ipfs/{{.RootCID}}/dirwithindex?query=to-remember") + assert.Equal(t, 301, resp.StatusCode) + assert.Equal(t, + fmt.Sprintf("/ipfs/%s/dirwithindex/?query=to-remember", rootCID), + resp.Headers.Get("Location"), + ) + }) + + // This enables go get to parse go-import meta tags from index.html files stored in IPFS + // https://github.com/ipfs/kubo/pull/3963 + t.Run("GET IPFS directory with index.html and no trailing slash returns expected output when go-get is passed", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/{{.RootCID}}/dirwithindex?go-get=1") + assert.Equal(t, pageContents, resp.Body) + }) + + t.Run("GET IPFS directory with index.html and trailing slash returns expected output", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/{{.RootCID}}/dirwithindex/?query=to-remember") + assert.Equal(t, pageContents, resp.Body) + }) + + t.Run("GET IPFS nonexistent file returns 404 (Not Found)", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/{{.RootCID}}/pleaseDontAddMe") + assert.Equal(t, 404, resp.StatusCode) + }) + + t.Run("GET IPFS invalid CID returns 400 (Bad Request)", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/QmInvalid/pleaseDontAddMe") + assert.Equal(t, 400, resp.StatusCode) + }) + + t.Run("GET IPFS inlined zero-length data object returns ok code (200)", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/bafkqaaa") + assert.Equal(t, 200, resp.StatusCode) + assert.Equal(t, "0", resp.Resp.Header.Get("Content-Length")) + assert.Equal(t, "", resp.Body) + }) + + t.Run("GET IPFS inlined zero-length data object with byte range returns ok code (200)", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/bafkqaaa", client.WithHeader("Range", "bytes=0-1048575")) + assert.Equal(t, 200, resp.StatusCode) + assert.Equal(t, "0", resp.Resp.Header.Get("Content-Length")) + assert.Equal(t, "text/plain", resp.Resp.Header.Get("Content-Type")) + }) + + t.Run("GET /ipfs/ipfs/{cid} returns redirect to the valid path", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/ipfs/bafkqaaa?query=to-remember") + assert.Contains(t, + resp.Body, + ``, + ) + assert.Contains(t, + resp.Body, + ``, + ) + }) + }) + + t.Run("IPNS", func(t *testing.T) { + t.Parallel() + node.IPFS("name", "publish", "--allow-offline", cid) + + t.Run("GET invalid IPNS root returns 400 (Bad Request)", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipns/QmInvalid/pleaseDontAddMe") + assert.Equal(t, 400, resp.StatusCode) + }) + + t.Run("GET IPNS path succeeds", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipns/{{.PeerID}}") + assert.Equal(t, 200, resp.StatusCode) + assert.Equal(t, "Hello Worlds!", resp.Body) + }) + + t.Run("GET /ipfs/ipns/{peerid} returns redirect to the valid path", func(t *testing.T) { + t.Parallel() + resp := client.Get("/ipfs/ipns/{{.PeerID}}?query=to-remember") + peerID := node.PeerID().String() + assert.Contains(t, + resp.Body, + fmt.Sprintf(``, peerID), + ) + assert.Contains(t, + resp.Body, + fmt.Sprintf(``, peerID), + ) + + }) + + }) + + t.Run("GET invalid IPFS path errors", func(t *testing.T) { + t.Parallel() + assert.Equal(t, 400, client.Get("/ipfs/12345").StatusCode) + }) + + t.Run("GET invalid path errors", func(t *testing.T) { + t.Parallel() + assert.Equal(t, 404, client.Get("/12345").StatusCode) + }) + + // TODO: these tests that use the API URL shouldn't be part of gateway tests... + t.Run("GET /webui returns 301 or 302", func(t *testing.T) { + t.Parallel() + resp := node.APIClient().DisableRedirects().Get("/webui") + assert.Contains(t, []int{302, 301}, resp.StatusCode) + }) + + t.Run("GET /webui/ returns 301 or 302", func(t *testing.T) { + t.Parallel() + resp := node.APIClient().DisableRedirects().Get("/webui/") + assert.Contains(t, []int{302, 301}, resp.StatusCode) + }) + + t.Run("GET /logs returns logs", func(t *testing.T) { + t.Parallel() + apiClient := node.APIClient() + reqURL := apiClient.BuildURL("/logs") + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil) + require.NoError(t, err) + + resp, err := apiClient.Client.Do(req) + require.NoError(t, err) + defer resp.Body.Close() + + // read the first line of the output and parse its JSON + dec := json.NewDecoder(resp.Body) + event := struct{ Event string }{} + err = dec.Decode(&event) + require.NoError(t, err) + + assert.Equal(t, "log API client connected", event.Event) + }) + + t.Run("POST /api/v0/version succeeds", func(t *testing.T) { + t.Parallel() + resp := node.APIClient().Post("/api/v0/version", nil) + assert.Equal(t, 200, resp.StatusCode) + + assert.Len(t, resp.Resp.TransferEncoding, 1) + assert.Equal(t, "chunked", resp.Resp.TransferEncoding[0]) + + vers := struct{ Version string }{} + err := json.Unmarshal([]byte(resp.Body), &vers) + require.NoError(t, err) + assert.NotEmpty(t, vers.Version) + }) + + t.Run("pprof", func(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode().Init().StartDaemon() + apiClient := node.APIClient() + t.Run("mutex", func(t *testing.T) { + t.Parallel() + t.Run("setting the mutex fraction works (negative so it doesn't enable)", func(t *testing.T) { + t.Parallel() + resp := apiClient.Post("/debug/pprof-mutex/?fraction=-1", nil) + assert.Equal(t, 200, resp.StatusCode) + }) + t.Run("mutex endpoint doesn't accept a string as an argument", func(t *testing.T) { + t.Parallel() + resp := apiClient.Post("/debug/pprof-mutex/?fraction=that_is_a_string", nil) + assert.Equal(t, 400, resp.StatusCode) + }) + t.Run("mutex endpoint returns 405 on GET", func(t *testing.T) { + t.Parallel() + resp := apiClient.Get("/debug/pprof-mutex/?fraction=-1") + assert.Equal(t, 405, resp.StatusCode) + }) + }) + t.Run("block", func(t *testing.T) { + t.Parallel() + t.Run("setting the block profiler rate works (0 so it doesn't enable)", func(t *testing.T) { + t.Parallel() + resp := apiClient.Post("/debug/pprof-block/?rate=0", nil) + assert.Equal(t, 200, resp.StatusCode) + }) + t.Run("block profiler endpoint doesn't accept a string as an argument", func(t *testing.T) { + t.Parallel() + resp := apiClient.Post("/debug/pprof-block/?rate=that_is_a_string", nil) + assert.Equal(t, 400, resp.StatusCode) + }) + t.Run("block profiler endpoint returns 405 on GET", func(t *testing.T) { + t.Parallel() + resp := apiClient.Get("/debug/pprof-block/?rate=0") + assert.Equal(t, 405, resp.StatusCode) + }) + }) + }) + + t.Run("index content types", func(t *testing.T) { + t.Parallel() + h := harness.NewT(t) + node := h.NewNode().Init().StartDaemon() + + h.WriteFile("index/index.html", "

") + cid := node.IPFS("add", "-Q", "-r", filepath.Join(h.Dir, "index")).Stderr.Trimmed() + + apiClient := node.APIClient() + apiClient.TemplateData = map[string]string{"CID": cid} + + t.Run("GET index.html has correct content type", func(t *testing.T) { + t.Parallel() + res := apiClient.Get("/ipfs/{{.CID}}/") + assert.Equal(t, "text/html; charset=utf-8", res.Resp.Header.Get("Content-Type")) + }) + + t.Run("HEAD index.html has no content", func(t *testing.T) { + t.Parallel() + res := apiClient.Head("/ipfs/{{.CID}}/") + assert.Equal(t, "", res.Body) + assert.Equal(t, "", res.Resp.Header.Get("Content-Length")) + }) + }) + + t.Run("readonly API", func(t *testing.T) { + t.Parallel() + + client := node.GatewayClient() + + fileContents := "12345" + h.WriteFile("readonly/dir/test", fileContents) + cids := node.IPFS("add", "-r", "-q", filepath.Join(h.Dir, "readonly/dir")).Stdout.Lines() + + rootCID := cids[len(cids)-1] + client.TemplateData = map[string]string{"RootCID": rootCID} + + t.Run("Get IPFS directory file through readonly API succeeds", func(t *testing.T) { + t.Parallel() + resp := client.Get("/api/v0/cat?arg={{.RootCID}}/test") + assert.Equal(t, 200, resp.StatusCode) + assert.Equal(t, fileContents, resp.Body) + }) + + t.Run("refs IPFS directory file through readonly API succeeds", func(t *testing.T) { + t.Parallel() + resp := client.Get("/api/v0/refs?arg={{.RootCID}}/test") + assert.Equal(t, 200, resp.StatusCode) + }) + + t.Run("test gateway API is sanitized", func(t *testing.T) { + t.Parallel() + for _, cmd := range []string{ + "add", + "block/put", + "bootstrap", + "config", + "dag/put", + "dag/import", + "dht", + "diag", + "id", + "mount", + "name/publish", + "object/put", + "object/new", + "object/patch", + "pin", + "ping", + "repo", + "stats", + "swarm", + "file", + "update", + "bitswap", + } { + t.Run(cmd, func(t *testing.T) { + cmd := cmd + t.Parallel() + assert.Equal(t, 404, client.Get("/api/v0/"+cmd).StatusCode) + }) + } + }) + }) + + t.Run("refs/local", func(t *testing.T) { + t.Parallel() + gatewayAddr := URLStrToMultiaddr(node.GatewayURL()) + res := node.RunIPFS("--api", gatewayAddr.String(), "refs", "local") + assert.Equal(t, + `Error: invalid path "local": selected encoding not supported`, + res.Stderr.Trimmed(), + ) + }) + + t.Run("raw leaves node", func(t *testing.T) { + t.Parallel() + contents := "This is RAW!" + cid := node.IPFSAddStr(contents, "--raw-leaves") + assert.Equal(t, contents, client.Get("/ipfs/"+cid).Body) + }) + + t.Run("compact blocks", func(t *testing.T) { + t.Parallel() + block1 := "\x0a\x09\x08\x02\x12\x03\x66\x6f\x6f\x18\x03" + block2 := "\x0a\x04\x08\x02\x18\x06\x12\x24\x0a\x22\x12\x20\xcf\x92\xfd\xef\xcd\xc3\x4c\xac\x00\x9c" + + "\x8b\x05\xeb\x66\x2b\xe0\x61\x8d\xb9\xde\x55\xec\xd4\x27\x85\xe9\xec\x67\x12\xf8\xdf\x65" + + "\x12\x24\x0a\x22\x12\x20\xcf\x92\xfd\xef\xcd\xc3\x4c\xac\x00\x9c\x8b\x05\xeb\x66\x2b\xe0" + + "\x61\x8d\xb9\xde\x55\xec\xd4\x27\x85\xe9\xec\x67\x12\xf8\xdf\x65" + + node.PipeStrToIPFS(block1, "block", "put") + block2CID := node.PipeStrToIPFS(block2, "block", "put", "--cid-codec=dag-pb").Stdout.Trimmed() + + resp := client.Get("/ipfs/" + block2CID) + assert.Equal(t, 200, resp.StatusCode) + assert.Equal(t, "foofoo", resp.Body) + }) + + t.Run("verify gateway file", func(t *testing.T) { + t.Parallel() + r := regexp.MustCompile(`Gateway \(readonly\) server listening on (?P.+)\s`) + matches := r.FindStringSubmatch(node.Daemon.Stdout.String()) + ma, err := multiaddr.NewMultiaddr(matches[1]) + require.NoError(t, err) + netAddr, err := manet.ToNetAddr(ma) + require.NoError(t, err) + expURL := "http://" + netAddr.String() + + b, err := os.ReadFile(filepath.Join(node.Dir, "gateway")) + require.NoError(t, err) + + assert.Equal(t, expURL, string(b)) + }) + + t.Run("verify gateway file diallable while on unspecified", func(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode().Init() + node.UpdateConfig(func(cfg *config.Config) { + cfg.Addresses.Gateway = config.Strings{"/ip4/127.0.0.1/tcp/32563"} + }) + node.StartDaemon() + + b, err := os.ReadFile(filepath.Join(node.Dir, "gateway")) + require.NoError(t, err) + + assert.Equal(t, "http://127.0.0.1:32563", string(b)) + }) + + t.Run("NoFetch", func(t *testing.T) { + t.Parallel() + nodes := harness.NewT(t).NewNodes(2).Init() + node1 := nodes[0] + node2 := nodes[1] + + node1.UpdateConfig(func(cfg *config.Config) { + cfg.Gateway.NoFetch = true + }) + + nodes.StartDaemons().Connect() + + t.Run("not present", func(t *testing.T) { + cidFoo := node2.IPFSAddStr("foo") + + t.Run("not present key from node 1", func(t *testing.T) { + t.Parallel() + assert.Equal(t, 404, node1.GatewayClient().Get("/ipfs/"+cidFoo).StatusCode) + }) + + t.Run("not present IPNS key from node 1", func(t *testing.T) { + t.Parallel() + assert.Equal(t, 400, node1.GatewayClient().Get("/ipns/"+node2.PeerID().String()).StatusCode) + }) + }) + + t.Run("present", func(t *testing.T) { + cidBar := node1.IPFSAddStr("bar") + + t.Run("present key from node 1", func(t *testing.T) { + t.Parallel() + assert.Equal(t, 200, node1.GatewayClient().Get("/ipfs/"+cidBar).StatusCode) + }) + + t.Run("present IPNS key from node 1", func(t *testing.T) { + t.Parallel() + node2.IPFS("name", "publish", "/ipfs/"+cidBar) + assert.Equal(t, 200, node1.GatewayClient().Get("/ipns/"+node2.PeerID().String()).StatusCode) + + }) + }) + }) +} diff --git a/test/cli/harness/buffer.go b/test/cli/harness/buffer.go new file mode 100644 index 000000000..b40e160b0 --- /dev/null +++ b/test/cli/harness/buffer.go @@ -0,0 +1,45 @@ +package harness + +import ( + "strings" + "sync" + + "github.com/ipfs/kubo/test/cli/testutils" +) + +// Buffer is a thread-safe byte buffer. +type Buffer struct { + b strings.Builder + m sync.Mutex +} + +func (b *Buffer) Write(p []byte) (n int, err error) { + b.m.Lock() + defer b.m.Unlock() + return b.b.Write(p) +} + +func (b *Buffer) String() string { + b.m.Lock() + defer b.m.Unlock() + return b.b.String() +} + +// Trimmed returns the bytes as a string, with leading and trailing whitespace removed. +func (b *Buffer) Trimmed() string { + b.m.Lock() + defer b.m.Unlock() + return strings.TrimSpace(b.b.String()) +} + +func (b *Buffer) Bytes() []byte { + b.m.Lock() + defer b.m.Unlock() + return []byte(b.b.String()) +} + +func (b *Buffer) Lines() []string { + b.m.Lock() + defer b.m.Unlock() + return testutils.SplitLines(b.b.String()) +} diff --git a/test/cli/harness/harness.go b/test/cli/harness/harness.go new file mode 100644 index 000000000..de962e1c1 --- /dev/null +++ b/test/cli/harness/harness.go @@ -0,0 +1,190 @@ +package harness + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "strings" + "testing" + "time" + + logging "github.com/ipfs/go-log/v2" + . "github.com/ipfs/kubo/test/cli/testutils" +) + +// Harness tracks state for a test, such as temp dirs and IFPS nodes, and cleans them up after the test. +type Harness struct { + Dir string + IPFSBin string + Runner *Runner + NodesRoot string + Nodes Nodes +} + +// TODO: use zaptest.NewLogger(t) instead +func EnableDebugLogging() { + err := logging.SetLogLevel("testharness", "DEBUG") + if err != nil { + panic(err) + } +} + +// NewT constructs a harness that cleans up after the given test is done. +func NewT(t *testing.T, options ...func(h *Harness)) *Harness { + h := New(options...) + t.Cleanup(h.Cleanup) + return h +} + +func New(options ...func(h *Harness)) *Harness { + h := &Harness{Runner: &Runner{Env: osEnviron()}} + + // walk up to find the root dir, from which we can locate the binary + wd, err := os.Getwd() + if err != nil { + panic(err) + } + goMod := FindUp("go.mod", wd) + if goMod == "" { + panic("unable to find root dir") + } + rootDir := filepath.Dir(goMod) + h.IPFSBin = filepath.Join(rootDir, "cmd", "ipfs", "ipfs") + + // setup working dir + tmpDir, err := os.MkdirTemp("", "") + if err != nil { + log.Panicf("error creating temp dir: %s", err) + } + h.Dir = tmpDir + h.Runner.Dir = h.Dir + + h.NodesRoot = filepath.Join(h.Dir, ".nodes") + + // apply any customizations + // this should happen after all initialization + for _, o := range options { + o(h) + } + + return h +} + +func osEnviron() map[string]string { + m := map[string]string{} + for _, entry := range os.Environ() { + split := strings.Split(entry, "=") + m[split[0]] = split[1] + } + return m +} + +func (h *Harness) NewNode() *Node { + nodeID := len(h.Nodes) + node := BuildNode(h.IPFSBin, h.NodesRoot, nodeID) + h.Nodes = append(h.Nodes, node) + return node +} + +func (h *Harness) NewNodes(count int) Nodes { + var newNodes []*Node + for i := 0; i < count; i++ { + newNodes = append(newNodes, h.NewNode()) + } + return newNodes +} + +// WriteToTemp writes the given contents to a guaranteed-unique temp file, returning its path. +func (h *Harness) WriteToTemp(contents string) string { + f := h.TempFile() + _, err := f.WriteString(contents) + if err != nil { + log.Panicf("writing to temp file: %s", err.Error()) + } + err = f.Close() + if err != nil { + log.Panicf("closing temp file: %s", err.Error()) + } + return f.Name() +} + +// TempFile creates a new unique temp file. +func (h *Harness) TempFile() *os.File { + f, err := os.CreateTemp(h.Dir, "") + if err != nil { + log.Panicf("creating temp file: %s", err.Error()) + } + return f +} + +// WriteFile writes a file given a filename and its contents. +// The filename must be a relative path, or this panics. +func (h *Harness) WriteFile(filename, contents string) { + if filepath.IsAbs(filename) { + log.Panicf("%s must be a relative path", filename) + } + absPath := filepath.Join(h.Runner.Dir, filename) + err := os.MkdirAll(filepath.Dir(absPath), 0777) + if err != nil { + log.Panicf("creating intermediate dirs for %q: %s", filename, err.Error()) + } + err = os.WriteFile(absPath, []byte(contents), 0644) + if err != nil { + log.Panicf("writing %q (%q): %s", filename, absPath, err.Error()) + } +} + +func WaitForFile(path string, timeout time.Duration) error { + start := time.Now() + timer := time.NewTimer(timeout) + ticker := time.NewTicker(1 * time.Millisecond) + defer timer.Stop() + defer ticker.Stop() + for { + select { + case <-timer.C: + return fmt.Errorf("timeout waiting for %s after %v", path, time.Since(start)) + case <-ticker.C: + _, err := os.Stat(path) + if err == nil { + return nil + } + if errors.Is(err, os.ErrNotExist) { + continue + } + return fmt.Errorf("error waiting for %s: %w", path, err) + } + } +} + +func (h *Harness) Mkdirs(paths ...string) { + for _, path := range paths { + if filepath.IsAbs(path) { + log.Panicf("%s must be a relative path when making dirs", path) + } + absPath := filepath.Join(h.Runner.Dir, path) + err := os.MkdirAll(absPath, 0777) + if err != nil { + log.Panicf("recursively making dirs under %s: %s", absPath, err) + } + } +} + +func (h *Harness) Sh(expr string) RunResult { + return h.Runner.Run(RunRequest{ + Path: "bash", + Args: []string{"-c", expr}, + }) +} + +func (h *Harness) Cleanup() { + log.Debugf("cleaning up cluster") + h.Nodes.StopDaemons() + // TODO: don't do this if test fails, not sure how? + log.Debugf("removing harness dir") + err := os.RemoveAll(h.Dir) + if err != nil { + log.Panicf("removing temp dir %s: %s", h.Dir, err) + } +} diff --git a/test/cli/harness/http_client.go b/test/cli/harness/http_client.go new file mode 100644 index 000000000..83aa1bff1 --- /dev/null +++ b/test/cli/harness/http_client.go @@ -0,0 +1,116 @@ +package harness + +import ( + "io" + "net/http" + "strings" + "text/template" + "time" +) + +// HTTPClient is an HTTP client with some conveniences for testing. +// URLs are constructed from a base URL. +// The response body is buffered into a string. +// Internal errors cause panics so that tests don't need to check errors. +// The paths are evaluated as Go templates for readable string interpolation. +type HTTPClient struct { + Client *http.Client + BaseURL string + + Timeout time.Duration + TemplateData any +} + +type HTTPResponse struct { + Body string + StatusCode int + Headers http.Header + + // The raw response. The body will be closed on this response. + Resp *http.Response +} + +func (c *HTTPClient) WithHeader(k, v string) func(h *http.Request) { + return func(h *http.Request) { + h.Header.Add(k, v) + } +} + +func (c *HTTPClient) DisableRedirects() *HTTPClient { + c.Client.CheckRedirect = func(req *http.Request, via []*http.Request) error { + return http.ErrUseLastResponse + } + return c +} + +// Do executes the request unchanged. +func (c *HTTPClient) Do(req *http.Request) *HTTPResponse { + log.Debugf("making HTTP req %s to %q with headers %+v", req.Method, req.URL.String(), req.Header) + resp, err := c.Client.Do(req) + if resp != nil && resp.Body != nil { + defer resp.Body.Close() + } + if err != nil { + panic(err) + } + bodyStr, err := io.ReadAll(resp.Body) + if err != nil { + panic(err) + } + + return &HTTPResponse{ + Body: string(bodyStr), + StatusCode: resp.StatusCode, + Headers: resp.Header, + Resp: resp, + } +} + +// BuildURL constructs a request URL from the given path by interpolating the string and then appending it to the base URL. +func (c *HTTPClient) BuildURL(urlPath string) string { + sb := &strings.Builder{} + err := template.Must(template.New("test").Parse(urlPath)).Execute(sb, c.TemplateData) + if err != nil { + panic(err) + } + renderedPath := sb.String() + return c.BaseURL + renderedPath +} + +func (c *HTTPClient) Get(urlPath string, opts ...func(*http.Request)) *HTTPResponse { + req, err := http.NewRequest(http.MethodGet, c.BuildURL(urlPath), nil) + if err != nil { + panic(err) + } + for _, o := range opts { + o(req) + } + return c.Do(req) +} + +func (c *HTTPClient) Post(urlPath string, body io.Reader, opts ...func(*http.Request)) *HTTPResponse { + req, err := http.NewRequest(http.MethodPost, c.BuildURL(urlPath), body) + if err != nil { + panic(err) + } + for _, o := range opts { + o(req) + } + return c.Do(req) +} + +func (c *HTTPClient) PostStr(urlpath, body string, opts ...func(*http.Request)) *HTTPResponse { + r := strings.NewReader(body) + return c.Post(urlpath, r, opts...) +} + +func (c *HTTPClient) Head(urlPath string, opts ...func(*http.Request)) *HTTPResponse { + req, err := http.NewRequest(http.MethodHead, c.BuildURL(urlPath), nil) + if err != nil { + panic(err) + } + for _, o := range opts { + o(req) + } + return c.Do(req) +} diff --git a/test/cli/harness/ipfs.go b/test/cli/harness/ipfs.go new file mode 100644 index 000000000..6ae7bdf94 --- /dev/null +++ b/test/cli/harness/ipfs.go @@ -0,0 +1,80 @@ +package harness + +import ( + "encoding/json" + "fmt" + "io" + "reflect" + "strings" + + . "github.com/ipfs/kubo/test/cli/testutils" +) + +func (n *Node) IPFSCommands() []string { + res := n.IPFS("commands").Stdout.String() + res = strings.TrimSpace(res) + split := SplitLines(res) + var cmds []string + for _, line := range split { + trimmed := strings.TrimSpace(line) + if trimmed == "ipfs" { + continue + } + cmds = append(cmds, trimmed) + } + return cmds +} + +func (n *Node) SetIPFSConfig(key string, val interface{}, flags ...string) { + valBytes, err := json.Marshal(val) + if err != nil { + log.Panicf("marshling config for key '%s': %s", key, err) + } + valStr := string(valBytes) + + args := []string{"config", "--json"} + args = append(args, flags...) + args = append(args, key, valStr) + n.IPFS(args...) + + // validate the config was set correctly + var newVal string + n.GetIPFSConfig(key, &newVal) + if val != newVal { + log.Panicf("key '%s' did not retain value '%s' after it was set, got '%s'", key, val, newVal) + } +} + +func (n *Node) GetIPFSConfig(key string, val interface{}) { + res := n.IPFS("config", key) + valStr := strings.TrimSpace(res.Stdout.String()) + // only when the result is a string is the result not well-formed JSON, + // so check the value type and add quotes if it's expected to be a string + reflectVal := reflect.ValueOf(val) + if reflectVal.Kind() == reflect.Ptr && reflectVal.Elem().Kind() == reflect.String { + valStr = fmt.Sprintf(`"%s"`, valStr) + } + err := json.Unmarshal([]byte(valStr), val) + if err != nil { + log.Fatalf("unmarshaling config for key '%s', value '%s': %s", key, valStr, err) + } +} + +func (n *Node) IPFSAddStr(content string, args ...string) string { + log.Debugf("node %d adding content '%s' with args: %v", n.ID, PreviewStr(content), args) + return n.IPFSAdd(strings.NewReader(content), args...) +} + +func (n *Node) IPFSAdd(content io.Reader, args ...string) string { + log.Debugf("node %d adding with args: %v", n.ID, args) + fullArgs := []string{"add", "-q"} + fullArgs = append(fullArgs, args...) + res := n.Runner.MustRun(RunRequest{ + Path: n.IPFSBin, + Args: fullArgs, + CmdOpts: []CmdOpt{RunWithStdin(content)}, + }) + out := strings.TrimSpace(res.Stdout.String()) + log.Debugf("add result: %q", out) + return out +} diff --git a/test/cli/harness/node.go b/test/cli/harness/node.go new file mode 100644 index 000000000..26a66ddd9 --- /dev/null +++ b/test/cli/harness/node.go @@ -0,0 +1,439 @@ +package harness + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "io/fs" + "net/http" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + "syscall" + "time" + + logging "github.com/ipfs/go-log/v2" + "github.com/ipfs/kubo/config" + serial "github.com/ipfs/kubo/config/serialize" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/multiformats/go-multiaddr" + manet "github.com/multiformats/go-multiaddr/net" +) + +var log = logging.Logger("testharness") + +// Node is a single Kubo node. +// Each node has its own config and can run its own Kubo daemon. +type Node struct { + ID int + Dir string + + APIListenAddr multiaddr.Multiaddr + GatewayListenAddr multiaddr.Multiaddr + SwarmAddr multiaddr.Multiaddr + EnableMDNS bool + + IPFSBin string + Runner *Runner + + Daemon *RunResult +} + +func BuildNode(ipfsBin, baseDir string, id int) *Node { + dir := filepath.Join(baseDir, strconv.Itoa(id)) + if err := os.MkdirAll(dir, 0755); err != nil { + panic(err) + } + + env := environToMap(os.Environ()) + env["IPFS_PATH"] = dir + + return &Node{ + ID: id, + Dir: dir, + IPFSBin: ipfsBin, + Runner: &Runner{ + Env: env, + Dir: dir, + }, + } +} + +func (n *Node) ReadConfig() *config.Config { + cfg, err := serial.Load(filepath.Join(n.Dir, "config")) + if err != nil { + panic(err) + } + return cfg +} + +func (n *Node) WriteConfig(c *config.Config) { + err := serial.WriteConfigFile(filepath.Join(n.Dir, "config"), c) + if err != nil { + panic(err) + } +} + +func (n *Node) UpdateConfig(f func(cfg *config.Config)) { + cfg := n.ReadConfig() + f(cfg) + n.WriteConfig(cfg) +} + +func (n *Node) IPFS(args ...string) RunResult { + res := n.RunIPFS(args...) + n.Runner.AssertNoError(res) + return res +} + +func (n *Node) PipeStrToIPFS(s string, args ...string) RunResult { + return n.PipeToIPFS(strings.NewReader(s), args...) +} + +func (n *Node) PipeToIPFS(reader io.Reader, args ...string) RunResult { + res := n.RunPipeToIPFS(reader, args...) + n.Runner.AssertNoError(res) + return res +} + +func (n *Node) RunPipeToIPFS(reader io.Reader, args ...string) RunResult { + return n.Runner.Run(RunRequest{ + Path: n.IPFSBin, + Args: args, + CmdOpts: []CmdOpt{RunWithStdin(reader)}, + }) +} + +func (n *Node) RunIPFS(args ...string) RunResult { + return n.Runner.Run(RunRequest{ + Path: n.IPFSBin, + Args: args, + }) +} + +// Init initializes and configures the IPFS node, after which it is ready to run. +func (n *Node) Init(ipfsArgs ...string) *Node { + n.Runner.MustRun(RunRequest{ + Path: n.IPFSBin, + Args: append([]string{"init"}, ipfsArgs...), + }) + + if n.SwarmAddr == nil { + swarmAddr, err := multiaddr.NewMultiaddr("/ip4/127.0.0.1/tcp/0") + if err != nil { + panic(err) + } + n.SwarmAddr = swarmAddr + } + + if n.APIListenAddr == nil { + apiAddr, err := multiaddr.NewMultiaddr("/ip4/127.0.0.1/tcp/0") + if err != nil { + panic(err) + } + n.APIListenAddr = apiAddr + } + + if n.GatewayListenAddr == nil { + gatewayAddr, err := multiaddr.NewMultiaddr("/ip4/127.0.0.1/tcp/0") + if err != nil { + panic(err) + } + n.GatewayListenAddr = gatewayAddr + } + + n.UpdateConfig(func(cfg *config.Config) { + cfg.Bootstrap = []string{} + cfg.Addresses.Swarm = []string{n.SwarmAddr.String()} + cfg.Addresses.API = []string{n.APIListenAddr.String()} + cfg.Addresses.Gateway = []string{n.GatewayListenAddr.String()} + cfg.Swarm.DisableNatPortMap = true + cfg.Discovery.MDNS.Enabled = n.EnableMDNS + }) + return n +} + +func (n *Node) StartDaemon(ipfsArgs ...string) *Node { + alive := n.IsAlive() + if alive { + log.Panicf("node %d is already running", n.ID) + } + + daemonArgs := append([]string{"daemon"}, ipfsArgs...) + log.Debugf("starting node %d", n.ID) + res := n.Runner.MustRun(RunRequest{ + Path: n.IPFSBin, + Args: daemonArgs, + RunFunc: (*exec.Cmd).Start, + }) + + n.Daemon = &res + + log.Debugf("node %d started, checking API", n.ID) + n.WaitOnAPI() + return n +} + +func (n *Node) signalAndWait(watch <-chan struct{}, signal os.Signal, t time.Duration) bool { + err := n.Daemon.Cmd.Process.Signal(signal) + if err != nil { + if errors.Is(err, os.ErrProcessDone) { + log.Debugf("process for node %d has already finished", n.ID) + return true + } + log.Panicf("error killing daemon for node %d with peer ID %s: %s", n.ID, n.PeerID(), err.Error()) + } + timer := time.NewTimer(t) + defer timer.Stop() + select { + case <-watch: + return true + case <-timer.C: + return false + } +} + +func (n *Node) StopDaemon() *Node { + log.Debugf("stopping node %d", n.ID) + if n.Daemon == nil { + log.Debugf("didn't stop node %d since no daemon present", n.ID) + return n + } + watch := make(chan struct{}, 1) + go func() { + _, _ = n.Daemon.Cmd.Process.Wait() + watch <- struct{}{} + }() + log.Debugf("signaling node %d with SIGTERM", n.ID) + if n.signalAndWait(watch, syscall.SIGTERM, 1*time.Second) { + return n + } + log.Debugf("signaling node %d with SIGTERM", n.ID) + if n.signalAndWait(watch, syscall.SIGTERM, 2*time.Second) { + return n + } + log.Debugf("signaling node %d with SIGQUIT", n.ID) + if n.signalAndWait(watch, syscall.SIGQUIT, 5*time.Second) { + return n + } + log.Debugf("signaling node %d with SIGKILL", n.ID) + if n.signalAndWait(watch, syscall.SIGKILL, 5*time.Second) { + return n + } + log.Panicf("timed out stopping node %d with peer ID %s", n.ID, n.PeerID()) + return n +} + +func (n *Node) APIAddr() multiaddr.Multiaddr { + ma, err := n.TryAPIAddr() + if err != nil { + panic(err) + } + return ma +} + +func (n *Node) APIURL() string { + apiAddr := n.APIAddr() + netAddr, err := manet.ToNetAddr(apiAddr) + if err != nil { + panic(err) + } + return "http://" + netAddr.String() +} + +func (n *Node) TryAPIAddr() (multiaddr.Multiaddr, error) { + b, err := os.ReadFile(filepath.Join(n.Dir, "api")) + if err != nil { + return nil, err + } + ma, err := multiaddr.NewMultiaddr(string(b)) + if err != nil { + return nil, err + } + return ma, nil +} + +func (n *Node) checkAPI() bool { + apiAddr, err := n.TryAPIAddr() + if err != nil { + log.Debugf("node %d API addr not available yet: %s", n.ID, err.Error()) + return false + } + ip, err := apiAddr.ValueForProtocol(multiaddr.P_IP4) + if err != nil { + panic(err) + } + port, err := apiAddr.ValueForProtocol(multiaddr.P_TCP) + if err != nil { + panic(err) + } + url := fmt.Sprintf("http://%s:%s/api/v0/id", ip, port) + log.Debugf("checking API for node %d at %s", n.ID, url) + httpResp, err := http.Post(url, "", nil) + if err != nil { + log.Debugf("node %d API check error: %s", err.Error()) + return false + } + defer httpResp.Body.Close() + resp := struct { + ID string + }{} + + respBytes, err := io.ReadAll(httpResp.Body) + if err != nil { + log.Debugf("error reading API check response for node %d: %s", n.ID, err.Error()) + return false + } + log.Debugf("got API check response for node %d: %s", n.ID, string(respBytes)) + + err = json.Unmarshal(respBytes, &resp) + if err != nil { + log.Debugf("error decoding API check response for node %d: %s", n.ID, err.Error()) + return false + } + if resp.ID == "" { + log.Debugf("API check response for node %d did not contain a Peer ID", n.ID) + return false + } + respPeerID, err := peer.Decode(resp.ID) + if err != nil { + panic(err) + } + + peerID := n.PeerID() + if respPeerID != peerID { + log.Panicf("expected peer ID %s but got %s", peerID, resp.ID) + } + + log.Debugf("API check for node %d successful", n.ID) + return true +} + +func (n *Node) PeerID() peer.ID { + cfg := n.ReadConfig() + id, err := peer.Decode(cfg.Identity.PeerID) + if err != nil { + panic(err) + } + return id +} + +func (n *Node) WaitOnAPI() *Node { + log.Debugf("waiting on API for node %d", n.ID) + for i := 0; i < 50; i++ { + if n.checkAPI() { + log.Debugf("daemon API found, daemon stdout: %s", n.Daemon.Stdout.String()) + return n + } + time.Sleep(400 * time.Millisecond) + } + log.Panicf("node %d with peer ID %s failed to come online: \n%s\n\n%s", n.ID, n.PeerID(), n.Daemon.Stderr.String(), n.Daemon.Stdout.String()) + return n +} + +func (n *Node) IsAlive() bool { + if n.Daemon == nil || n.Daemon.Cmd == nil || n.Daemon.Cmd.Process == nil { + return false + } + log.Debugf("signaling node %d daemon process for liveness check", n.ID) + err := n.Daemon.Cmd.Process.Signal(syscall.Signal(0)) + if err == nil { + log.Debugf("node %d daemon is alive", n.ID) + return true + } + log.Debugf("node %d daemon not alive: %s", err.Error()) + return false +} + +func (n *Node) SwarmAddrs() []multiaddr.Multiaddr { + res := n.Runner.MustRun(RunRequest{ + Path: n.IPFSBin, + Args: []string{"swarm", "addrs", "local"}, + }) + ipfsProtocol := multiaddr.ProtocolWithCode(multiaddr.P_IPFS).Name + peerID := n.PeerID() + out := strings.TrimSpace(res.Stdout.String()) + outLines := strings.Split(out, "\n") + var addrs []multiaddr.Multiaddr + for _, addrStr := range outLines { + ma, err := multiaddr.NewMultiaddr(addrStr) + if err != nil { + panic(err) + } + + // add the peer ID to the multiaddr if it doesn't have it + _, err = ma.ValueForProtocol(multiaddr.P_IPFS) + if errors.Is(err, multiaddr.ErrProtocolNotFound) { + comp, err := multiaddr.NewComponent(ipfsProtocol, peerID.String()) + if err != nil { + panic(err) + } + ma = ma.Encapsulate(comp) + } + addrs = append(addrs, ma) + } + return addrs +} + +func (n *Node) Connect(other *Node) *Node { + n.Runner.MustRun(RunRequest{ + Path: n.IPFSBin, + Args: []string{"swarm", "connect", other.SwarmAddrs()[0].String()}, + }) + return n +} + +func (n *Node) Peers() []multiaddr.Multiaddr { + res := n.Runner.MustRun(RunRequest{ + Path: n.IPFSBin, + Args: []string{"swarm", "peers"}, + }) + lines := strings.Split(strings.TrimSpace(res.Stdout.String()), "\n") + var addrs []multiaddr.Multiaddr + for _, line := range lines { + ma, err := multiaddr.NewMultiaddr(line) + if err != nil { + panic(err) + } + addrs = append(addrs, ma) + } + return addrs +} + +// GatewayURL waits for the gateway file and then returns its contents or times out. +func (n *Node) GatewayURL() string { + timer := time.NewTimer(1 * time.Second) + defer timer.Stop() + for { + select { + case <-timer.C: + panic("timeout waiting for gateway file") + default: + b, err := os.ReadFile(filepath.Join(n.Dir, "gateway")) + if err == nil { + return strings.TrimSpace(string(b)) + } + if !errors.Is(err, fs.ErrNotExist) { + panic(err) + } + time.Sleep(1 * time.Millisecond) + } + } +} + +func (n *Node) GatewayClient() *HTTPClient { + return &HTTPClient{ + Client: http.DefaultClient, + BaseURL: n.GatewayURL(), + } +} + +func (n *Node) APIClient() *HTTPClient { + return &HTTPClient{ + Client: http.DefaultClient, + BaseURL: n.APIURL(), + } +} diff --git a/test/cli/harness/nodes.go b/test/cli/harness/nodes.go new file mode 100644 index 000000000..dbc7de16b --- /dev/null +++ b/test/cli/harness/nodes.go @@ -0,0 +1,64 @@ +package harness + +import ( + "sync" + + "github.com/multiformats/go-multiaddr" +) + +// Nodes is a collection of Kubo nodes along with operations on groups of nodes. +type Nodes []*Node + +func (n Nodes) Init(args ...string) Nodes { + for _, node := range n { + node.Init() + } + return n +} + +func (n Nodes) Connect() Nodes { + wg := sync.WaitGroup{} + for i, node := range n { + for j, otherNode := range n { + if i == j { + continue + } + node := node + otherNode := otherNode + wg.Add(1) + go func() { + defer wg.Done() + node.Connect(otherNode) + }() + } + } + wg.Wait() + for _, node := range n { + firstPeer := node.Peers()[0] + if _, err := firstPeer.ValueForProtocol(multiaddr.P_P2P); err != nil { + log.Panicf("unexpected state for node %d with peer ID %s: %s", node.ID, node.PeerID(), err) + } + } + return n +} + +func (n Nodes) StartDaemons() Nodes { + wg := sync.WaitGroup{} + for _, node := range n { + wg.Add(1) + node := node + go func() { + defer wg.Done() + node.StartDaemon() + }() + } + wg.Wait() + return n +} + +func (n Nodes) StopDaemons() Nodes { + for _, node := range n { + node.StopDaemon() + } + return n +} diff --git a/test/cli/harness/run.go b/test/cli/harness/run.go new file mode 100644 index 000000000..1a6b32fc2 --- /dev/null +++ b/test/cli/harness/run.go @@ -0,0 +1,140 @@ +package harness + +import ( + "fmt" + "io" + "os/exec" + "strings" +) + +// Runner is a process runner which can run subprocesses and aggregate output. +type Runner struct { + Env map[string]string + Dir string + Verbose bool +} + +type CmdOpt func(*exec.Cmd) +type RunFunc func(*exec.Cmd) error + +var RunFuncStart = (*exec.Cmd).Start + +type RunRequest struct { + Path string + Args []string + // Options that are applied to the exec.Cmd just before running it + CmdOpts []CmdOpt + // Function to use to run the command. + // If not specified, defaults to cmd.Run + RunFunc func(*exec.Cmd) error + Verbose bool +} + +type RunResult struct { + Stdout *Buffer + Stderr *Buffer + Err error + ExitErr *exec.ExitError + Cmd *exec.Cmd +} + +func environToMap(environ []string) map[string]string { + m := map[string]string{} + for _, e := range environ { + kv := strings.Split(e, "=") + m[kv[0]] = kv[1] + } + return m +} + +func (r *Runner) Run(req RunRequest) RunResult { + cmd := exec.Command(req.Path, req.Args...) + stdout := &Buffer{} + stderr := &Buffer{} + cmd.Stdout = stdout + cmd.Stderr = stderr + cmd.Dir = r.Dir + + for k, v := range r.Env { + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", k, v)) + } + + for _, o := range req.CmdOpts { + o(cmd) + } + + if req.RunFunc == nil { + req.RunFunc = (*exec.Cmd).Run + } + + log.Debugf("running %v", cmd.Args) + + err := req.RunFunc(cmd) + + result := RunResult{ + Stdout: stdout, + Stderr: stderr, + Cmd: cmd, + Err: err, + } + + if exitErr, ok := err.(*exec.ExitError); ok { + result.ExitErr = exitErr + } + + return result +} + +// MustRun runs the command and fails the test if the command fails. +func (r *Runner) MustRun(req RunRequest) RunResult { + result := r.Run(req) + r.AssertNoError(result) + return result +} + +func (r *Runner) AssertNoError(result RunResult) { + if result.ExitErr != nil { + log.Panicf("'%s' returned error, code: %d, err: %s\nstdout:%s\nstderr:%s\n", + result.Cmd.Args, result.ExitErr.ExitCode(), result.ExitErr.Error(), result.Stdout.String(), result.Stderr.String()) + + } + if result.Err != nil { + log.Panicf("unable to run %s: %s", result.Cmd.Path, result.Err) + + } +} + +func RunWithEnv(env map[string]string) CmdOpt { + return func(cmd *exec.Cmd) { + for k, v := range env { + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", k, v)) + } + } +} + +func RunWithPath(path string) CmdOpt { + return func(cmd *exec.Cmd) { + var newEnv []string + for _, env := range cmd.Env { + e := strings.Split(env, "=") + if e[0] == "PATH" { + paths := strings.Split(e[1], ":") + paths = append(paths, path) + e[1] = strings.Join(paths, ":") + fmt.Printf("path: %s\n", strings.Join(e, "=")) + } + newEnv = append(newEnv, strings.Join(e, "=")) + } + cmd.Env = newEnv + } +} + +func RunWithStdin(reader io.Reader) CmdOpt { + return func(cmd *exec.Cmd) { + cmd.Stdin = reader + } +} + +func RunWithStdinStr(s string) CmdOpt { + return RunWithStdin(strings.NewReader(s)) +} diff --git a/test/cli/init_test.go b/test/cli/init_test.go new file mode 100644 index 000000000..359856e6b --- /dev/null +++ b/test/cli/init_test.go @@ -0,0 +1,164 @@ +package cli + +import ( + "fmt" + "os" + fp "path/filepath" + "strings" + "testing" + + "github.com/ipfs/kubo/test/cli/harness" + . "github.com/ipfs/kubo/test/cli/testutils" + pb "github.com/libp2p/go-libp2p/core/crypto/pb" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func validatePeerID(t *testing.T, peerID peer.ID, expErr error, expAlgo pb.KeyType) { + assert.NoError(t, peerID.Validate()) + pub, err := peerID.ExtractPublicKey() + assert.ErrorIs(t, expErr, err) + if expAlgo != 0 { + assert.Equal(t, expAlgo, pub.Type()) + } +} + +func testInitAlgo(t *testing.T, initFlags []string, expOutputName string, expPeerIDPubKeyErr error, expPeerIDPubKeyType pb.KeyType) { + t.Run("init", func(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + initRes := node.IPFS(StrCat("init", initFlags)...) + + lines := []string{ + fmt.Sprintf("generating %s keypair...done", expOutputName), + fmt.Sprintf("peer identity: %s", node.PeerID().String()), + fmt.Sprintf("initializing IPFS node at %s", node.Dir), + "to get started, enter:", + fmt.Sprintf("\n\tipfs cat /ipfs/%s/readme\n\n", CIDWelcomeDocs), + } + expectedInitOutput := strings.Join(lines, "\n") + assert.Equal(t, expectedInitOutput, initRes.Stdout.String()) + + assert.DirExists(t, node.Dir) + assert.FileExists(t, fp.Join(node.Dir, "config")) + assert.DirExists(t, fp.Join(node.Dir, "datastore")) + assert.DirExists(t, fp.Join(node.Dir, "blocks")) + assert.NoFileExists(t, fp.Join(node.Dir, "._check_writeable")) + + _, err := os.ReadDir(node.Dir) + assert.NoError(t, err, "ipfs dir should be listable") + + validatePeerID(t, node.PeerID(), expPeerIDPubKeyErr, expPeerIDPubKeyType) + + res := node.IPFS("config", "Mounts.IPFS") + assert.Equal(t, "/ipfs", res.Stdout.Trimmed()) + + node.IPFS("cat", fmt.Sprintf("/ipfs/%s/readme", CIDWelcomeDocs)) + }) + + t.Run("init empty repo", func(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + initRes := node.IPFS(StrCat("init", "--empty-repo", initFlags)...) + + validatePeerID(t, node.PeerID(), expPeerIDPubKeyErr, expPeerIDPubKeyType) + + lines := []string{ + fmt.Sprintf("generating %s keypair...done", expOutputName), + fmt.Sprintf("peer identity: %s", node.PeerID().String()), + fmt.Sprintf("initializing IPFS node at %s\n", node.Dir), + } + expectedEmptyInitOutput := strings.Join(lines, "\n") + assert.Equal(t, expectedEmptyInitOutput, initRes.Stdout.String()) + + catRes := node.RunIPFS("cat", fmt.Sprintf("/ipfs/%s/readme", CIDWelcomeDocs)) + assert.NotEqual(t, 0, catRes.ExitErr.ExitCode(), "welcome readme doesn't exist") + + idRes := node.IPFS("id", "-f", "") + version := node.IPFS("version", "-n").Stdout.Trimmed() + assert.Contains(t, idRes.Stdout.String(), version) + }) +} + +func TestInit(t *testing.T) { + t.Parallel() + + t.Run("init fails if the repo dir has no perms", func(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + badDir := fp.Join(node.Dir, ".badipfs") + err := os.Mkdir(badDir, 0000) + require.NoError(t, err) + + res := node.RunIPFS("init", "--repo-dir", badDir) + assert.NotEqual(t, 0, res.Cmd.ProcessState.ExitCode()) + assert.Contains(t, res.Stderr.String(), "permission denied") + + }) + + t.Run("init with ed25519", func(t *testing.T) { + t.Parallel() + testInitAlgo(t, []string{"--algorithm=ed25519"}, "ED25519", nil, pb.KeyType_Ed25519) + }) + + t.Run("init with rsa", func(t *testing.T) { + t.Parallel() + testInitAlgo(t, []string{"--bits=2048", "--algorithm=rsa"}, "2048-bit RSA", peer.ErrNoPublicKey, 0) + }) + + t.Run("init with default algorithm", func(t *testing.T) { + t.Parallel() + testInitAlgo(t, []string{}, "ED25519", nil, pb.KeyType_Ed25519) + }) + + t.Run("ipfs init --profile with invalid profile fails", func(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + res := node.RunIPFS("init", "--profile=invalid_profile") + assert.NotEqual(t, 0, res.ExitErr.ExitCode()) + assert.Equal(t, "Error: invalid configuration profile: invalid_profile", res.Stderr.Trimmed()) + }) + + t.Run("ipfs init --profile with valid profile succeeds", func(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode() + node.IPFS("init", "--profile=server") + }) + + t.Run("ipfs config looks good", func(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode().Init("--profile=server") + + lines := node.IPFS("config", "Swarm.AddrFilters").Stdout.Lines() + assert.Len(t, lines, 18) + + out := node.IPFS("config", "Bootstrap").Stdout.Trimmed() + assert.Equal(t, "[]", out) + + out = node.IPFS("config", "Addresses.API").Stdout.Trimmed() + assert.Equal(t, "/ip4/127.0.0.1/tcp/0", out) + }) + + t.Run("ipfs init from existing config succeeds", func(t *testing.T) { + t.Parallel() + nodes := harness.NewT(t).NewNodes(2) + node1 := nodes[0] + node2 := nodes[1] + + node1.Init("--profile=server") + + node2.IPFS("init", fp.Join(node1.Dir, "config")) + out := node2.IPFS("config", "Addresses.API").Stdout.Trimmed() + assert.Equal(t, "/ip4/127.0.0.1/tcp/0", out) + }) + + t.Run("ipfs init should not run while daemon is running", func(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode().Init().StartDaemon() + res := node.RunIPFS("init") + assert.NotEqual(t, 0, res.ExitErr.ExitCode()) + assert.Contains(t, res.Stderr.String(), "Error: ipfs daemon is running. please stop it to run this command") + }) + +} diff --git a/test/cli/ping_test.go b/test/cli/ping_test.go new file mode 100644 index 000000000..c4195024a --- /dev/null +++ b/test/cli/ping_test.go @@ -0,0 +1,73 @@ +package cli + +import ( + "fmt" + "testing" + + "github.com/ipfs/kubo/test/cli/harness" + "github.com/stretchr/testify/assert" +) + +func TestPing(t *testing.T) { + t.Parallel() + + t.Run("other", func(t *testing.T) { + t.Parallel() + nodes := harness.NewT(t).NewNodes(2).Init().StartDaemons().Connect() + node1 := nodes[0] + node2 := nodes[1] + + node1.IPFS("ping", "-n", "2", "--", node2.PeerID().String()) + node2.IPFS("ping", "-n", "2", "--", node1.PeerID().String()) + }) + + t.Run("ping unreachable peer", func(t *testing.T) { + t.Parallel() + nodes := harness.NewT(t).NewNodes(2).Init().StartDaemons().Connect() + node1 := nodes[0] + + badPeer := "QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJx" + res := node1.RunIPFS("ping", "-n", "2", "--", badPeer) + assert.Contains(t, res.Stdout.String(), fmt.Sprintf("Looking up peer %s", badPeer)) + assert.Contains(t, res.Stderr.String(), "Error: ping failed") + }) + + t.Run("self", func(t *testing.T) { + t.Parallel() + nodes := harness.NewT(t).NewNodes(2).Init().StartDaemons() + node1 := nodes[0] + node2 := nodes[1] + + res := node1.RunIPFS("ping", "-n", "2", "--", node1.PeerID().String()) + assert.Equal(t, 1, res.Cmd.ProcessState.ExitCode()) + assert.Contains(t, res.Stderr.String(), "can't ping self") + + res = node2.RunIPFS("ping", "-n", "2", "--", node2.PeerID().String()) + assert.Equal(t, 1, res.Cmd.ProcessState.ExitCode()) + assert.Contains(t, res.Stderr.String(), "can't ping self") + }) + + t.Run("0", func(t *testing.T) { + t.Parallel() + nodes := harness.NewT(t).NewNodes(2).Init().StartDaemons().Connect() + node1 := nodes[0] + node2 := nodes[1] + + res := node1.RunIPFS("ping", "-n", "0", "--", node2.PeerID().String()) + assert.Equal(t, 1, res.Cmd.ProcessState.ExitCode()) + assert.Contains(t, res.Stderr.String(), "ping count must be greater than 0") + }) + + t.Run("offline", func(t *testing.T) { + t.Parallel() + nodes := harness.NewT(t).NewNodes(2).Init().StartDaemons().Connect() + node1 := nodes[0] + node2 := nodes[1] + + node2.StopDaemon() + + res := node1.RunIPFS("ping", "-n", "2", "--", node2.PeerID().String()) + assert.Equal(t, 1, res.Cmd.ProcessState.ExitCode()) + assert.Contains(t, res.Stderr.String(), "ping failed") + }) +} diff --git a/test/cli/pins_test.go b/test/cli/pins_test.go new file mode 100644 index 000000000..14a3dc238 --- /dev/null +++ b/test/cli/pins_test.go @@ -0,0 +1,214 @@ +package cli + +import ( + "fmt" + "strings" + "testing" + + "github.com/ipfs/go-cid" + "github.com/ipfs/kubo/test/cli/harness" + . "github.com/ipfs/kubo/test/cli/testutils" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type testPinsArgs struct { + runDaemon bool + pinArg string + lsArg string + baseArg string +} + +func testPins(t *testing.T, args testPinsArgs) { + t.Run(fmt.Sprintf("test pins with args=%+v", args), func(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode().Init() + if args.runDaemon { + node.StartDaemon("--offline") + } + + strs := []string{"a", "b", "c", "d", "e", "f", "g"} + dataToCid := map[string]string{} + cids := []string{} + + ipfsAdd := func(t *testing.T, content string) string { + cidStr := node.IPFSAddStr(content, StrCat(args.baseArg, "--pin=false")...) + + _, err := cid.Decode(cidStr) + require.NoError(t, err) + dataToCid[content] = cidStr + cids = append(cids, cidStr) + return cidStr + } + + ipfsPinAdd := func(cids []string) []string { + input := strings.Join(cids, "\n") + return node.PipeStrToIPFS(input, StrCat("pin", "add", args.pinArg, args.baseArg)...).Stdout.Lines() + } + + ipfsPinLS := func() string { + return node.IPFS(StrCat("pin", "ls", args.lsArg, args.baseArg)...).Stdout.Trimmed() + } + + for _, s := range strs { + ipfsAdd(t, s) + } + + // these subtests run sequentially since they depend on state + + t.Run("check output of pin command", func(t *testing.T) { + resLines := ipfsPinAdd(cids) + + for i, s := range resLines { + assert.Equal(t, + fmt.Sprintf("pinned %s recursively", cids[i]), + s, + ) + } + }) + + t.Run("pin verify should succeed", func(t *testing.T) { + node.IPFS("pin", "verify") + }) + + t.Run("'pin verify --verbose' should include all the cids", func(t *testing.T) { + verboseVerifyOut := node.IPFS(StrCat("pin", "verify", "--verbose", args.baseArg)...).Stdout.String() + for _, cid := range cids { + assert.Contains(t, verboseVerifyOut, fmt.Sprintf("%s ok", cid)) + } + + }) + t.Run("ls output should contain the cids", func(t *testing.T) { + lsOut := ipfsPinLS() + for _, cid := range cids { + assert.Contains(t, lsOut, cid) + } + }) + + t.Run("check 'pin ls hash' output", func(t *testing.T) { + lsHashOut := node.IPFS(StrCat("pin", "ls", args.lsArg, args.baseArg, dataToCid["b"])...) + lsHashOutStr := lsHashOut.Stdout.String() + assert.Equal(t, fmt.Sprintf("%s recursive\n", dataToCid["b"]), lsHashOutStr) + }) + + t.Run("unpinning works", func(t *testing.T) { + node.PipeStrToIPFS(strings.Join(cids, "\n"), "pin", "rm") + }) + + t.Run("test pin update", func(t *testing.T) { + cidA := dataToCid["a"] + cidB := dataToCid["b"] + + ipfsPinAdd([]string{cidA}) + beforeUpdate := ipfsPinLS() + + assert.Contains(t, beforeUpdate, cidA) + assert.NotContains(t, beforeUpdate, cidB) + + node.IPFS("pin", "update", "--unpin=true", cidA, cidB) + afterUpdate := ipfsPinLS() + + assert.NotContains(t, afterUpdate, cidA) + assert.Contains(t, afterUpdate, cidB) + + node.IPFS("pin", "update", "--unpin=true", cidB, cidB) + afterIdempotentUpdate := ipfsPinLS() + + assert.Contains(t, afterIdempotentUpdate, cidB) + + node.IPFS("pin", "rm", cidB) + }) + }) +} + +func testPinsErrorReporting(t *testing.T, args testPinsArgs) { + t.Run(fmt.Sprintf("test pins error reporting with args=%+v", args), func(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode().Init() + if args.runDaemon { + node.StartDaemon("--offline") + } + randomCID := "Qme8uX5n9hn15pw9p6WcVKoziyyC9LXv4LEgvsmKMULjnV" + res := node.RunIPFS(StrCat("pin", "add", args.pinArg, randomCID)...) + assert.NotEqual(t, 0, res.ExitErr.ExitCode()) + assert.Contains(t, res.Stderr.String(), "ipld: could not find") + }) +} + +func testPinDAG(t *testing.T, args testPinsArgs) { + t.Run(fmt.Sprintf("test pin DAG with args=%+v", args), func(t *testing.T) { + t.Parallel() + h := harness.NewT(t) + node := h.NewNode().Init() + if args.runDaemon { + node.StartDaemon("--offline") + } + bytes := RandomBytes(1 << 20) // 1 MiB + tmpFile := h.WriteToTemp(string(bytes)) + cid := node.IPFS(StrCat("add", args.pinArg, "--pin=false", "-q", tmpFile)...).Stdout.Trimmed() + + node.IPFS("pin", "add", "--recursive=true", cid) + node.IPFS("pin", "rm", cid) + + // remove part of the DAG + part := node.IPFS("refs", cid).Stdout.Lines()[0] + node.IPFS("block", "rm", part) + + res := node.RunIPFS("pin", "add", "--recursive=true", cid) + assert.NotEqual(t, 0, res) + assert.Contains(t, res.Stderr.String(), "ipld: could not find") + }) +} + +func testPinProgress(t *testing.T, args testPinsArgs) { + t.Run(fmt.Sprintf("test pin progress with args=%+v", args), func(t *testing.T) { + t.Parallel() + h := harness.NewT(t) + node := h.NewNode().Init() + + if args.runDaemon { + node.StartDaemon("--offline") + } + + bytes := RandomBytes(1 << 20) // 1 MiB + tmpFile := h.WriteToTemp(string(bytes)) + cid := node.IPFS(StrCat("add", args.pinArg, "--pin=false", "-q", tmpFile)...).Stdout.Trimmed() + + res := node.RunIPFS("pin", "add", "--progress", cid) + node.Runner.AssertNoError(res) + + assert.Contains(t, res.Stderr.String(), " 5 nodes") + }) +} + +func TestPins(t *testing.T) { + t.Parallel() + t.Run("test pinning without daemon running", func(t *testing.T) { + t.Parallel() + testPinsErrorReporting(t, testPinsArgs{}) + testPinsErrorReporting(t, testPinsArgs{pinArg: "--progress"}) + testPinDAG(t, testPinsArgs{}) + testPinDAG(t, testPinsArgs{pinArg: "--raw-leaves"}) + testPinProgress(t, testPinsArgs{}) + testPins(t, testPinsArgs{}) + testPins(t, testPinsArgs{pinArg: "--progress"}) + testPins(t, testPinsArgs{pinArg: "--progress", lsArg: "--stream"}) + testPins(t, testPinsArgs{baseArg: "--cid-base=base32"}) + testPins(t, testPinsArgs{lsArg: "--stream", baseArg: "--cid-base=base32"}) + + }) + + t.Run("test pinning with daemon running without network", func(t *testing.T) { + t.Parallel() + testPinsErrorReporting(t, testPinsArgs{runDaemon: true}) + testPinsErrorReporting(t, testPinsArgs{runDaemon: true, pinArg: "--progress"}) + testPinDAG(t, testPinsArgs{runDaemon: true}) + testPinDAG(t, testPinsArgs{runDaemon: true, pinArg: "--raw-leaves"}) + testPinProgress(t, testPinsArgs{runDaemon: true}) + testPins(t, testPinsArgs{runDaemon: true}) + testPins(t, testPinsArgs{runDaemon: true, pinArg: "--progress"}) + testPins(t, testPinsArgs{runDaemon: true, pinArg: "--progress", lsArg: "--stream"}) + testPins(t, testPinsArgs{runDaemon: true, baseArg: "--cid-base=base32"}) + testPins(t, testPinsArgs{runDaemon: true, lsArg: "--stream", baseArg: "--cid-base=base32"}) + }) +} diff --git a/test/cli/stats_test.go b/test/cli/stats_test.go new file mode 100644 index 000000000..05c1702b4 --- /dev/null +++ b/test/cli/stats_test.go @@ -0,0 +1,24 @@ +package cli + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/ipfs/kubo/test/cli/harness" +) + +func TestStats(t *testing.T) { + t.Parallel() + + t.Run("stats dht", func(t *testing.T) { + t.Parallel() + nodes := harness.NewT(t).NewNodes(2).Init().StartDaemons().Connect() + node1 := nodes[0] + + res := node1.IPFS("stats", "dht") + assert.NoError(t, res.Err) + assert.Equal(t, 0, len(res.Stderr.Lines())) + assert.NotEqual(t, 0, len(res.Stdout.Lines())) + }) +} diff --git a/test/cli/testutils/cids.go b/test/cli/testutils/cids.go new file mode 100644 index 000000000..cae473e08 --- /dev/null +++ b/test/cli/testutils/cids.go @@ -0,0 +1,6 @@ +package testutils + +const ( + CIDWelcomeDocs = "QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc" + CIDEmptyDir = "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn" +) diff --git a/test/cli/testutils/files.go b/test/cli/testutils/files.go new file mode 100644 index 000000000..e17c98adf --- /dev/null +++ b/test/cli/testutils/files.go @@ -0,0 +1,37 @@ +package testutils + +import ( + "log" + "os" + "path/filepath" +) + +func MustOpen(name string) *os.File { + f, err := os.Open(name) + if err != nil { + log.Panicf("opening %s: %s", name, err) + } + return f +} + +// Searches for a file in a dir, then the parent dir, etc. +// If the file is not found, an empty string is returned. +func FindUp(name, dir string) string { + curDir := dir + for { + entries, err := os.ReadDir(curDir) + if err != nil { + panic(err) + } + for _, e := range entries { + if name == e.Name() { + return filepath.Join(curDir, name) + } + } + newDir := filepath.Dir(curDir) + if newDir == curDir { + return "" + } + curDir = newDir + } +} diff --git a/test/cli/testutils/json.go b/test/cli/testutils/json.go new file mode 100644 index 000000000..bc3093f13 --- /dev/null +++ b/test/cli/testutils/json.go @@ -0,0 +1,13 @@ +package testutils + +import "encoding/json" + +type JSONObj map[string]interface{} + +func ToJSONStr(m JSONObj) string { + b, err := json.Marshal(m) + if err != nil { + panic(err) + } + return string(b) +} diff --git a/test/cli/testutils/random.go b/test/cli/testutils/random.go new file mode 100644 index 000000000..00bb9de49 --- /dev/null +++ b/test/cli/testutils/random.go @@ -0,0 +1,12 @@ +package testutils + +import "crypto/rand" + +func RandomBytes(n int) []byte { + bytes := make([]byte, n) + _, err := rand.Read(bytes) + if err != nil { + panic(err) + } + return bytes +} diff --git a/test/cli/testutils/requires.go b/test/cli/testutils/requires.go new file mode 100644 index 000000000..d4b88cd6d --- /dev/null +++ b/test/cli/testutils/requires.go @@ -0,0 +1,37 @@ +package testutils + +import ( + "os" + "runtime" + "testing" +) + +func RequiresDocker(t *testing.T) { + if os.Getenv("TEST_NO_DOCKER") == "1" { + t.SkipNow() + } +} + +func RequiresFUSE(t *testing.T) { + if os.Getenv("TEST_NO_FUSE") == "1" { + t.SkipNow() + } +} + +func RequiresExpensive(t *testing.T) { + if os.Getenv("TEST_EXPENSIVE") == "1" || testing.Short() { + t.SkipNow() + } +} + +func RequiresPlugins(t *testing.T) { + if os.Getenv("TEST_NO_PLUGIN") == "1" { + t.SkipNow() + } +} + +func RequiresLinux(t *testing.T) { + if runtime.GOOS != "linux" { + t.SkipNow() + } +} diff --git a/test/cli/testutils/strings.go b/test/cli/testutils/strings.go new file mode 100644 index 000000000..1fb151248 --- /dev/null +++ b/test/cli/testutils/strings.go @@ -0,0 +1,77 @@ +package testutils + +import ( + "bufio" + "fmt" + "net" + "net/netip" + "net/url" + "strings" + + "github.com/multiformats/go-multiaddr" + manet "github.com/multiformats/go-multiaddr/net" +) + +// StrCat takes a bunch of strings or string slices +// and concats them all together into one string slice. +// If an arg is not one of those types, this panics. +// If an arg is an empty string, it is dropped. +func StrCat(args ...interface{}) []string { + res := make([]string, 0) + for _, a := range args { + if s, ok := a.(string); ok { + if s != "" { + res = append(res, s) + } + continue + } + if ss, ok := a.([]string); ok { + for _, s := range ss { + if s != "" { + res = append(res, s) + } + } + continue + } + panic(fmt.Sprintf("arg '%v' must be a string or string slice, but is '%T'", a, a)) + } + return res +} + +// PreviewStr returns a preview of s, which is a prefix for logging that avoids dumping a huge string to logs. +func PreviewStr(s string) string { + suffix := "..." + previewLength := 10 + if len(s) < previewLength { + previewLength = len(s) + suffix = "" + } + return s[0:previewLength] + suffix +} + +func SplitLines(s string) []string { + var lines []string + scanner := bufio.NewScanner(strings.NewReader(s)) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + return lines +} + +// URLStrToMultiaddr converts a URL string like http://localhost:80 to a multiaddr. +func URLStrToMultiaddr(u string) multiaddr.Multiaddr { + parsedURL, err := url.Parse(u) + if err != nil { + panic(err) + } + addrPort, err := netip.ParseAddrPort(parsedURL.Host) + if err != nil { + panic(err) + } + tcpAddr := net.TCPAddrFromAddrPort(addrPort) + ma, err := manet.FromNetAddr(tcpAddr) + if err != nil { + panic(err) + } + return ma +} diff --git a/test/integration/addcat_test.go b/test/integration/addcat_test.go index 45e8729ac..6f306d2bf 100644 --- a/test/integration/addcat_test.go +++ b/test/integration/addcat_test.go @@ -11,7 +11,7 @@ import ( "testing" "time" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" logging "github.com/ipfs/go-log" "github.com/ipfs/kubo/core" "github.com/ipfs/kubo/core/bootstrap" diff --git a/test/integration/bench_cat_test.go b/test/integration/bench_cat_test.go index d7e37dbb9..12c4d8dea 100644 --- a/test/integration/bench_cat_test.go +++ b/test/integration/bench_cat_test.go @@ -8,7 +8,7 @@ import ( "math" "testing" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" "github.com/ipfs/kubo/core" "github.com/ipfs/kubo/core/bootstrap" "github.com/ipfs/kubo/core/coreapi" diff --git a/test/integration/bitswap_wo_routing_test.go b/test/integration/bitswap_wo_routing_test.go index fa4e8d513..6a6fca4b7 100644 --- a/test/integration/bitswap_wo_routing_test.go +++ b/test/integration/bitswap_wo_routing_test.go @@ -5,8 +5,8 @@ import ( "context" "testing" - blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/ipfs/kubo/core" coremock "github.com/ipfs/kubo/core/mock" "github.com/ipfs/kubo/core/node/libp2p" diff --git a/test/integration/pubsub_msg_seen_cache_test.go b/test/integration/pubsub_msg_seen_cache_test.go index 394cda5b1..749508089 100644 --- a/test/integration/pubsub_msg_seen_cache_test.go +++ b/test/integration/pubsub_msg_seen_cache_test.go @@ -22,6 +22,7 @@ import ( "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p-pubsub/pb" + "github.com/libp2p/go-libp2p-pubsub/timecache" "github.com/libp2p/go-libp2p/core/peer" mock "github.com/ipfs/kubo/core/mock" @@ -76,7 +77,6 @@ func RunMessageSeenCacheTTLTest(t *testing.T, seenMessagesCacheTTL string) error var bootstrapNode, consumerNode, producerNode *core.IpfsNode var bootstrapPeerID, consumerPeerID, producerPeerID peer.ID - sendDupMsg := false mn := mocknet.New() bootstrapNode, err := mockNode(ctx, mn, false, "") // no need for PubSub configuration @@ -98,6 +98,12 @@ func RunMessageSeenCacheTTLTest(t *testing.T, seenMessagesCacheTTL string) error t.Fatal(err) } + // Used for logging the timeline + startTime := time.Time{} + + // Used for overriding the message ID + sendMsgID := "" + // Set up the pubsub message ID generation override for the producer core.RegisterFXOptionFunc(func(info core.FXNodeInfo) ([]fx.Option, error) { var pubsubOptions []pubsub.Option @@ -105,19 +111,23 @@ func RunMessageSeenCacheTTLTest(t *testing.T, seenMessagesCacheTTL string) error pubsubOptions, pubsub.WithSeenMessagesTTL(ttl), pubsub.WithMessageIdFn(func(pmsg *pubsub_pb.Message) string { - now := time.Now().Format(time.StampMilli) + now := time.Now() + if startTime.Second() == 0 { + startTime = now + } + timeElapsed := now.Sub(startTime).Seconds() msg := string(pmsg.Data) - var msgID string from, _ := peer.IDFromBytes(pmsg.From) - if (from == producerPeerID) && sendDupMsg { - msgID = "DupMsg" - t.Logf("sending [%s] with duplicate message ID at [%s]", msg, now) + var msgID string + if from == producerPeerID { + msgID = sendMsgID + t.Logf("sending [%s] with message ID [%s] at T%fs", msg, msgID, timeElapsed) } else { msgID = pubsub.DefaultMsgIdFn(pmsg) - t.Logf("sending [%s] with unique message ID at [%s]", msg, now) } return msgID }), + pubsub.WithSeenMessagesStrategy(timecache.Strategy_LastSeen), ) return append( info.FXOptions, @@ -165,8 +175,8 @@ func RunMessageSeenCacheTTLTest(t *testing.T, seenMessagesCacheTTL string) error t.Fatal(err) } // Utility functions defined inline to include context in closure - now := func() string { - return time.Now().Format(time.StampMilli) + now := func() float64 { + return time.Since(startTime).Seconds() } ctr := 0 msgGen := func() string { @@ -188,57 +198,87 @@ func RunMessageSeenCacheTTLTest(t *testing.T, seenMessagesCacheTTL string) error msg, err := consumerSubscription.Next(rxCtx) if shouldFind { if err != nil { - t.Logf("did not receive [%s] by [%s]", msgTxt, now()) + t.Logf("expected but did not receive [%s] at T%fs", msgTxt, now()) t.Fatal(err) } - t.Logf("received [%s] at [%s]", string(msg.Data()), now()) + t.Logf("received [%s] at T%fs", string(msg.Data()), now()) if !bytes.Equal(msg.Data(), []byte(msgTxt)) { t.Fatalf("consumed data [%s] does not match published data [%s]", string(msg.Data()), msgTxt) } } else { if err == nil { - t.Logf("received [%s] at [%s]", string(msg.Data()), now()) + t.Logf("not expected but received [%s] at T%fs", string(msg.Data()), now()) t.Fail() } - t.Logf("did not receive [%s] by [%s]", msgTxt, now()) + t.Logf("did not receive [%s] at T%fs", msgTxt, now()) } } - // Send message 1 with the message ID we're going to duplicate later - sendDupMsg = true + const MsgID1 = "MsgID1" + const MsgID2 = "MsgID2" + const MsgID3 = "MsgID3" + + // Send message 1 with the message ID we're going to duplicate + sentMsg1 := time.Now() + sendMsgID = MsgID1 msgTxt := produceMessage() - consumeMessage(msgTxt, true) // should find message + // Should find the message because it's new + consumeMessage(msgTxt, true) - // Send message 2 with the same message ID as before - sendDupMsg = true + // Send message 2 with a duplicate message ID + sendMsgID = MsgID1 msgTxt = produceMessage() - consumeMessage(msgTxt, false) // should NOT find message, because it got deduplicated (sent twice within the SeenMessagesTTL window) - - // Wait for seen cache TTL time to let seen cache entries time out - time.Sleep(ttl) + // Should NOT find message because it got deduplicated (sent 2 times within the SeenMessagesTTL window). + consumeMessage(msgTxt, false) // Send message 3 with a new message ID - // - // This extra step is necessary for testing the cache TTL because the PubSub code only garbage collects when a - // message ID was not already present in the cache. This means that message 2's cache entry, even though it has - // technically timed out, will still cause the message to be considered duplicate. When a message with a different - // ID passes through, it will be added to the cache and garbage collection will clean up message 2's entry. This is - // another bug in the pubsub/cache implementation that will be fixed once the code is refactored for this issue: - // https://github.com/libp2p/go-libp2p-pubsub/issues/502 - sendDupMsg = false + sendMsgID = MsgID2 msgTxt = produceMessage() - consumeMessage(msgTxt, true) // should find message + // Should find the message because it's new + consumeMessage(msgTxt, true) - // Send message 4 with the same message ID as before - sendDupMsg = true + // Wait till just before the SeenMessagesTTL window has passed since message 1 was sent + time.Sleep(time.Until(sentMsg1.Add(ttl - 100*time.Millisecond))) + + // Send message 4 with a duplicate message ID + sendMsgID = MsgID1 msgTxt = produceMessage() - consumeMessage(msgTxt, true) // should find message again (time since the last read > SeenMessagesTTL, so it looks like a new message). + // Should NOT find the message because it got deduplicated (sent 3 times within the SeenMessagesTTL window). This + // time, however, the expiration for the message should also get pushed out for a whole SeenMessagesTTL window since + // the default time cache now implements a sliding window algorithm. + consumeMessage(msgTxt, false) - // Send message 5 with a new message ID + // Send message 5 with a duplicate message ID. This will be a second after the last attempt above since NOT finding + // a message takes a second to determine. That would put this attempt at ~1 second after the SeenMessagesTTL window + // starting at message 1 has expired. + sentMsg5 := time.Now() + sendMsgID = MsgID1 + msgTxt = produceMessage() + // Should NOT find the message, because it got deduplicated (sent 2 times since the updated SeenMessagesTTL window + // started). This time again, the expiration should get pushed out for another SeenMessagesTTL window. + consumeMessage(msgTxt, false) + + // Send message 6 with a message ID that hasn't been seen within a SeenMessagesTTL window + sendMsgID = MsgID2 + msgTxt = produceMessage() + // Should find the message since last read > SeenMessagesTTL, so it looks like a new message. + consumeMessage(msgTxt, true) + + // Sleep for a full SeenMessagesTTL window to let cache entries time out + time.Sleep(time.Until(sentMsg5.Add(ttl + 100*time.Millisecond))) + + // Send message 7 with a duplicate message ID + sendMsgID = MsgID1 + msgTxt = produceMessage() + // Should find the message this time since last read > SeenMessagesTTL, so it looks like a new message. + consumeMessage(msgTxt, true) + + // Send message 8 with a brand new message ID // // This step is not strictly necessary, but has been added for good measure. - sendDupMsg = false + sendMsgID = MsgID3 msgTxt = produceMessage() - consumeMessage(msgTxt, true) // should find message + // Should find the message because it's new + consumeMessage(msgTxt, true) return nil } diff --git a/test/integration/three_legged_cat_test.go b/test/integration/three_legged_cat_test.go index f0358272b..c788bfb5e 100644 --- a/test/integration/three_legged_cat_test.go +++ b/test/integration/three_legged_cat_test.go @@ -14,7 +14,7 @@ import ( mock "github.com/ipfs/kubo/core/mock" "github.com/ipfs/kubo/thirdparty/unit" - files "github.com/ipfs/go-ipfs-files" + "github.com/ipfs/go-libipfs/files" testutil "github.com/libp2p/go-libp2p-testing/net" "github.com/libp2p/go-libp2p/core/peer" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" diff --git a/test/sharness/.gitignore b/test/sharness/.gitignore index c7ab08146..b9a5a21ae 100644 --- a/test/sharness/.gitignore +++ b/test/sharness/.gitignore @@ -1,5 +1,14 @@ +# symlinks to lib/sharness +/sharness.sh +/lib-sharness +# clone of sharness lib/sharness/ +# deps downloaded by lib/*.sh scripts +lib/dependencies/ +# sharness files test-results/ trash directory.*.sh/ +# makefile files plugins +# macos files *.DS_Store diff --git a/test/sharness/README.md b/test/sharness/README.md index 16cb508c1..9358fcf9c 100644 --- a/test/sharness/README.md +++ b/test/sharness/README.md @@ -1,4 +1,4 @@ -# ipfs whole tests using the [sharness framework](https://github.com/mlafeldt/sharness/) +# ipfs whole tests using the [sharness framework](https://github.com/pl-strflt/sharness/tree/feat/junit) ## Running all the tests diff --git a/test/sharness/Rules.mk b/test/sharness/Rules.mk index 49e41824c..20b2634db 100644 --- a/test/sharness/Rules.mk +++ b/test/sharness/Rules.mk @@ -42,10 +42,25 @@ $(d)/aggregate: $(T_$(d)) @(cd $(@D) && ./lib/test-aggregate-results.sh) .PHONY: $(d)/aggregate -$(d)/test-results/sharness.xml: export TEST_GENERATE_JUNIT=1 -$(d)/test-results/sharness.xml: test_sharness_expensive +$(d)/test-results/sharness.xml: $(T_$(d)) @echo "*** $@ ***" - @(cd $(@D)/.. && ./lib/gen-junit-report.sh) + @(cd $(@D)/.. && ./lib/test-aggregate-junit-reports.sh) +.PHONY: $(d)/test-results/sharness.xml + +$(d)/download-saxon: + @echo "*** $@ ***" + @(cd $(@D) && ./lib/download-saxon.sh) +.PHONY: $(d)/download-saxon + +$(d)/test-results/sharness-html: $(d)/test-results/sharness.xml $(d)/download-saxon + @echo "*** $@ ***" + @(cd $(@D)/.. && ./lib/test-generate-junit-html.sh frames) +.PHONY: $(d)/test-results/sharness-html + +$(d)/test-results/sharness.html: $(d)/test-results/sharness.xml $(d)/download-saxon + @echo "*** $@ ***" + @(cd $(@D)/.. && ./lib/test-generate-junit-html.sh no-frames) +.PHONY: $(d)/test-results/sharness.html $(d)/clean-test-results: rm -rf $(@D)/test-results @@ -62,16 +77,10 @@ $(d)/deps: $(SHARNESS_$(d)) $$(DEPS_$(d)) # use second expansion so coverage can test_sharness_deps: $(d)/deps .PHONY: test_sharness_deps -test_sharness_short: $(d)/aggregate -.PHONY: test_sharness_short +test_sharness: $(d)/aggregate +.PHONY: test_sharness - -test_sharness_expensive: export TEST_EXPENSIVE=1 -test_sharness_expensive: test_sharness_short -.PHONY: test_sharness_expensive - -TEST += test_sharness_expensive -TEST_SHORT += test_sharness_short +TEST += test_sharness include mk/footer.mk diff --git a/test/sharness/lib/0001-Generate-partial-JUnit-reports.patch b/test/sharness/lib/0001-Generate-partial-JUnit-reports.patch deleted file mode 100644 index 1a8b5f21b..000000000 --- a/test/sharness/lib/0001-Generate-partial-JUnit-reports.patch +++ /dev/null @@ -1,250 +0,0 @@ -From bc6bf844ef4e4cd468bc1ec96f2d6af738eb8d2f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C5=81ukasz=20Magiera?= -Date: Sat, 21 Apr 2018 22:01:45 +0200 -Subject: [PATCH] Generate partial JUnit reports - ---- - sharness.sh | 114 +++++++++++++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 108 insertions(+), 6 deletions(-) - -diff --git a/sharness.sh b/sharness.sh -index 6750ff7..336e426 100644 ---- a/sharness.sh -+++ b/sharness.sh -@@ -1,4 +1,4 @@ --#!/bin/sh -+#!/usr/bin/env bash - # - # Copyright (c) 2011-2012 Mathias Lafeldt - # Copyright (c) 2005-2012 Git project -@@ -106,6 +106,10 @@ if test -n "$color"; then - test -n "$quiet" && return;; - esac - shift -+ -+ if test -n "$TEST_GENERATE_JUNIT"; then -+ echo "$*" >> .junit/tout -+ fi - printf "%s" "$*" - tput sgr0 - echo -@@ -115,6 +119,10 @@ else - say_color() { - test -z "$1" && test -n "$quiet" && return - shift -+ -+ if test -n "$TEST_GENERATE_JUNIT"; then -+ echo "$*" >> .junit/tout -+ fi - printf "%s\n" "$*" - } - fi -@@ -129,6 +137,12 @@ say() { - say_color info "$*" - } - -+esc=$(printf '\033') -+ -+esc_xml() { -+ sed 's/&/\&/g; s//\>/g; s/"/\"/g; s/'"$esc"'//g; s///g;' -+} -+ - test -n "$test_description" || error "Test script did not set test_description." - - if test "$help" = "t"; then -@@ -251,30 +265,78 @@ test_have_prereq() { - test $total_prereq = $ok_prereq - } - -+# junit_testcase generates a testcase xml file after each test -+ -+junit_testcase() { -+ if test -z "$TEST_GENERATE_JUNIT"; then -+ return -+ fi -+ -+ test_name=$1 -+ tc_file=".junit/case-$(printf "%04d" $test_count)" -+ time_sec="$(cat .junit/time | xargs printf '%04d' | sed -e 's/\(...\)$/.\1/g')" -+ -+ echo "$(expr $(cat .junit/time_total) + $(cat .junit/time) )" > .junit/time_total -+ -+ shift -+ cat > "$tc_file" <<-EOF -+ -+ $@ -+ EOF -+ -+ if test -f .junit/tout; then -+ cat >> "$tc_file" <<-EOF -+ -+ $(cat .junit/tout | esc_xml) -+ -+ EOF -+ fi -+ -+ if test -f .junit/terr; then -+ cat >> "$tc_file" <<-EOF -+ -+ $(cat .junit/terr | esc_xml) -+ -+ EOF -+ fi -+ -+ echo "" >> "$tc_file" -+ rm -f .junit/tout .junit/terr .junit/time -+} -+ - # You are not expected to call test_ok_ and test_failure_ directly, use - # the text_expect_* functions instead. - - test_ok_() { - test_success=$(($test_success + 1)) - say_color "" "ok $test_count - $@" -+ -+ junit_testcase "$@" - } - - test_failure_() { - test_failure=$(($test_failure + 1)) - say_color error "not ok $test_count - $1" -+ test_name=$1 - shift - echo "$@" | sed -e 's/^/# /' -+ junit_testcase "$test_name" ''$(echo $@ | esc_xml)'' -+ - test "$immediate" = "" || { EXIT_OK=t; exit 1; } - } - - test_known_broken_ok_() { - test_fixed=$(($test_fixed + 1)) - say_color error "ok $test_count - $@ # TODO known breakage vanished" -+ -+ junit_testcase "$@" '' - } - - test_known_broken_failure_() { - test_broken=$(($test_broken + 1)) - say_color warn "not ok $test_count - $@ # TODO known breakage" -+ -+ junit_testcase "$@" - } - - # Public: Execute commands in debug mode. -@@ -310,15 +372,25 @@ test_pause() { - test_eval_() { - # This is a separate function because some tests use - # "return" to end a test_expect_success block early. -- eval &3 2>&4 "$*" -+ if test -n "$TEST_GENERATE_JUNIT"; then -+ eval >(tee -a .junit/tout >&3) 2> >(tee -a .junit/terr >&4) "$*" -+ else -+ eval &3 2>&4 "$*" -+ fi - } - - test_run_() { - test_cleanup=: - expecting_failure=$2 -+ -+ start_time_ms=$(date "+%s%3N"); - test_eval_ "$1" - eval_ret=$? - -+ if test -n "$TEST_GENERATE_JUNIT"; then -+ echo $(expr $(date "+%s%3N") - ${start_time_ms} ) > .junit/time; -+ fi -+ - if test "$chain_lint" = "t"; then - test_eval_ "(exit 117) && $1" - if test "$?" != 117; then -@@ -355,8 +427,18 @@ test_skip_() { - of_prereq=" of $test_prereq" - fi - -- say_color skip >&3 "skipping test: $@" -- say_color skip "ok $test_count # skip $1 (missing $missing_prereq${of_prereq})" -+ say_color skip >&3 "skipping test: $1" -+ say_color skip "ok $test_count # skip $1 (missing $missing_prereqm${of_prereq})" -+ -+ if test -n "$TEST_GENERATE_JUNIT"; then -+ cat > ".junit/case-$(printf "%04d" $test_count)" <<-EOF -+ -+ -+ skip $(echo $1 | esc_xml) (missing $missing_prereq${of_prereq}) -+ -+ -+ EOF -+ fi - : true - ;; - *) -@@ -403,7 +485,7 @@ test_expect_success() { - test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq= - test "$#" = 2 || error "bug in the test script: not 2 or 3 parameters to test_expect_success" - export test_prereq -- if ! test_skip_ "$@"; then -+ if ! test_skip_ "$@" "$1"; then - say >&3 "expecting success: $2" - if test_run_ "$2"; then - test_ok_ "$1" -@@ -442,7 +524,7 @@ test_expect_failure() { - test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq= - test "$#" = 2 || error "bug in the test script: not 2 or 3 parameters to test_expect_failure" - export test_prereq -- if ! test_skip_ "$@"; then -+ if ! test_skip_ "$@" "$1"; then - say >&3 "checking known breakage: $2" - if test_run_ "$2" expecting_failure; then - test_known_broken_ok_ "$1" -@@ -675,6 +757,7 @@ test_done() { - test_results_dir="$SHARNESS_TEST_DIRECTORY/test-results" - mkdir -p "$test_results_dir" - test_results_path="$test_results_dir/${SHARNESS_TEST_FILE%.$SHARNESS_TEST_EXTENSION}.$$.counts" -+ junit_results_path="$test_results_dir/${SHARNESS_TEST_FILE%.$SHARNESS_TEST_EXTENSION}.$$.xml.part" - - cat >>"$test_results_path" <<-EOF - total $test_count -@@ -684,6 +767,16 @@ test_done() { - failed $test_failure - - EOF -+ -+ if test -n "$TEST_GENERATE_JUNIT"; then -+ time_sec="$(cat .junit/time_total | xargs printf "%04d" | sed -e 's/\(...\)$/.\1/g')" -+ -+ cat >>"$junit_results_path" <<-EOF -+ -+ $(find .junit -name 'case-*' | sort | xargs cat) -+ -+ EOF -+ fi - fi - - if test "$test_fixed" != 0; then -@@ -745,6 +838,9 @@ export PATH SHARNESS_BUILD_DIRECTORY - SHARNESS_TEST_FILE="$0" - export SHARNESS_TEST_FILE - -+SHARNESS_TEST_NAME=$(basename ${SHARNESS_TEST_FILE} ".sh") -+export SHARNESS_TEST_NAME -+ - # Prepare test area. - test_dir="trash directory.$(basename "$SHARNESS_TEST_FILE" ".$SHARNESS_TEST_EXTENSION")" - test -n "$root" && test_dir="$root/$test_dir" -@@ -771,6 +867,12 @@ mkdir -p "$test_dir" || exit 1 - # in subprocesses like git equals our $PWD (for pathname comparisons). - cd -P "$test_dir" || exit 1 - -+# Prepare JUnit report dir -+if test -n "$TEST_GENERATE_JUNIT"; then -+ mkdir -p .junit -+ echo 0 > .junit/time_total -+fi -+ - this_test=${SHARNESS_TEST_FILE##*/} - this_test=${this_test%.$SHARNESS_TEST_EXTENSION} - for skp in $SKIP_TESTS; do --- -2.17.0 - diff --git a/test/sharness/lib/download-saxon.sh b/test/sharness/lib/download-saxon.sh new file mode 100755 index 000000000..cc645238f --- /dev/null +++ b/test/sharness/lib/download-saxon.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +dependencies=( + "url=https://raw.githubusercontent.com/pl-strflt/Saxon-HE/3e039cdbccf4efb9643736f34c839a3bae3402ae/11/Java/SaxonHE11-4J.zip;md5=8a4783d307c32c898f8995b8f337fd6b" + "url=https://raw.githubusercontent.com/pl-strflt/ant/c781f7d79b92cc55530245d9554682a47f46851e/src/etc/junit-frames-saxon.xsl;md5=6eb013566903a91e4959413f6ff144d0" + "url=https://raw.githubusercontent.com/pl-strflt/ant/c781f7d79b92cc55530245d9554682a47f46851e/src/etc/junit-noframes-saxon.xsl;md5=8d54882d5f9d32a7743ec675cc2e30ac" +) + +dependenciesdir="lib/dependencies" +mkdir -p "$dependenciesdir" + +get_md5() { + md5sum "$1" | cut -d ' ' -f 1 +} + +for dependency in "${dependencies[@]}"; do + url="$(echo "$dependency" | cut -d ';' -f 1 | cut -d '=' -f 2)" + md5="$(echo "$dependency" | cut -d ';' -f 2 | cut -d '=' -f 2)" + filename="$(basename "$url")" + if test -f "$dependenciesdir/$filename" && test "$(get_md5 "$dependenciesdir/$filename")" = "$md5"; then + echo "Using cached $filename" + else + echo "Downloading $filename" + curl -L --max-redirs 5 --retry 5 --no-progress-meter --output "$dependenciesdir/$filename" "$url" + actual_md5="$(get_md5 "$dependenciesdir/$filename")" + if test "$actual_md5" != "$md5"; then + echo "Downloaded $filename has wrong md5sum ('$actual_md5' != '$md5')" + exit 1 + fi + dirname=${filename%.*} + extension=${filename#$dirname.} + if test "$extension" = "zip"; then + echo "Removing old $dependenciesdir/$dirname" + rm -rf "$dependenciesdir/$dirname" + echo "Unzipping $dependenciesdir/$filename" + unzip "$dependenciesdir/$filename" -d "$dependenciesdir/$dirname" + fi + fi +done diff --git a/test/sharness/lib/gen-junit-report.sh b/test/sharness/lib/gen-junit-report.sh deleted file mode 100755 index c69f39adb..000000000 --- a/test/sharness/lib/gen-junit-report.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -cat > test-results/sharness.xml <<-EOF - - - $(find test-results -name '*.xml.part' | sort | xargs cat) - -EOF diff --git a/test/sharness/lib/install-sharness.sh b/test/sharness/lib/install-sharness.sh index ac6cb2f74..41b27188c 100755 --- a/test/sharness/lib/install-sharness.sh +++ b/test/sharness/lib/install-sharness.sh @@ -1,60 +1,50 @@ #!/bin/sh # install sharness.sh # -# Copyright (c) 2014 Juan Batiz-Benet +# Copyright (c) 2014, 2022 Juan Batiz-Benet, Piotr Galar # MIT Licensed; see the LICENSE file in this repository. # -# settings -version=5eee9b51b5621cec95a64018f0cc779963b230d2 -patch_version=17 +gitrepo=pl-strflt/sharness +githash=803df39d3cba16bb7d493dd6cd8bc5e29826da61 -urlprefix=https://github.com/mlafeldt/sharness.git if test ! -n "$clonedir" ; then clonedir=lib fi sharnessdir=sharness - -if test -f "$clonedir/$sharnessdir/SHARNESS_VERSION_${version}_p${patch_version}" -then - # There is the right version file. Great, we are done! - exit 0 -fi +gitdir="$clonedir/$sharnessdir/.git" die() { echo >&2 "$@" exit 1 } -apply_patches() { - git config --local user.email "noone@nowhere" - git config --local user.name "No One" - git am ../0001-Generate-partial-JUnit-reports.patch - - touch "SHARNESS_VERSION_${version}_p${patch_version}" || die "Could not create 'SHARNESS_VERSION_${version}_p${patch_version}'" -} - -checkout_version() { - git checkout "$version" || die "Could not checkout '$version'" - rm -f SHARNESS_VERSION_* || die "Could not remove 'SHARNESS_VERSION_*'" - echo "Sharness version $version is checked out!" - - apply_patches -} - -if test -d "$clonedir/$sharnessdir/.git" -then - # We need to update sharness! - cd "$clonedir/$sharnessdir" || die "Could not cd into '$clonedir/$sharnessdir' directory" - git fetch || die "Could not fetch to update sharness" - checkout_version -else - # We need to clone sharness! - mkdir -p "$clonedir" || die "Could not create '$clonedir' directory" - cd "$clonedir" || die "Could not cd into '$clonedir' directory" - - git clone "$urlprefix" || die "Could not clone '$urlprefix'" - cd "$sharnessdir" || die "Could not cd into '$sharnessdir' directory" - checkout_version +if test -d "$clonedir/$sharnessdir"; then + giturl="git@github.com:${gitrepo}.git" + echo "Checking if $giturl is already cloned (and if its origin is correct)" + if ! test -d "$gitdir" || test "$(git --git-dir "$gitdir" remote get-url origin)" != "$giturl"; then + echo "Removing $clonedir/$sharnessdir" + rm -rf "$clonedir/$sharnessdir" || die "Could not remove $clonedir/$sharnessdir" + fi fi + +if ! test -d "$clonedir/$sharnessdir"; then + giturl="https://github.com/${gitrepo}.git" + echo "Cloning $giturl into $clonedir/$sharnessdir" + git clone "$giturl" "$clonedir/$sharnessdir" || die "Could not clone $giturl into $clonedir/$sharnessdir" +fi + + +echo "Changing directory to $clonedir/$sharnessdir" +cd "$clonedir/$sharnessdir" || die "Could not cd into '$clonedir/$sharnessdir' directory" + +echo "Checking if $githash is already fetched" +if ! git show "$githash" >/dev/null 2>&1; then + echo "Fetching $githash" + git fetch origin "$githash" || die "Could not fetch $githash" +fi + +echo "Resetting to $githash" +git reset --hard "$githash" || die "Could not reset to $githash" + exit 0 diff --git a/test/sharness/lib/test-aggregate-junit-reports.sh b/test/sharness/lib/test-aggregate-junit-reports.sh new file mode 100755 index 000000000..ad39e5668 --- /dev/null +++ b/test/sharness/lib/test-aggregate-junit-reports.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# +# Script to aggregate results using Sharness +# +# Copyright (c) 2014, 2022 Christian Couder, Piotr Galar +# MIT Licensed; see the LICENSE file in this repository. +# + +SHARNESS_AGGREGATE_JUNIT="lib/sharness/aggregate-junit-reports.sh" + +test -f "$SHARNESS_AGGREGATE_JUNIT" || { + echo >&2 "Cannot find: $SHARNESS_AGGREGATE_JUNIT" + echo >&2 "Please check Sharness installation." + exit 1 +} + +ls test-results/t*-*.sh.*.xml.part | "$SHARNESS_AGGREGATE_JUNIT" > test-results/sharness.xml diff --git a/test/sharness/lib/test-generate-junit-html.sh b/test/sharness/lib/test-generate-junit-html.sh new file mode 100755 index 000000000..2790a7b9d --- /dev/null +++ b/test/sharness/lib/test-generate-junit-html.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +case "$1" in + "frames") + java -jar lib/dependencies/SaxonHE11-4J/saxon-he-11.4.jar \ + -s:test-results/sharness.xml \ + -xsl:lib/dependencies/junit-frames-saxon.xsl \ + output.dir=$(pwd)/test-results/sharness-html + ;; + "no-frames") + java -jar lib/dependencies/SaxonHE11-4J/saxon-he-11.4.jar \ + -s:test-results/sharness.xml \ + -xsl:lib/dependencies/junit-noframes-saxon.xsl \ + -o:test-results/sharness.html + ;; + *) + echo "Usage: $0 [frames|no-frames]" + exit 1 + ;; +esac diff --git a/test/sharness/lib/test-lib.sh b/test/sharness/lib/test-lib.sh index 0757c323c..3aecaec99 100644 --- a/test/sharness/lib/test-lib.sh +++ b/test/sharness/lib/test-lib.sh @@ -3,7 +3,7 @@ # Copyright (c) 2014 Christian Couder # MIT Licensed; see the LICENSE file in this repository. # -# We are using sharness (https://github.com/mlafeldt/sharness) +# We are using sharness (https://github.com/pl-strflt/sharness/tree/feat/junit) # which was extracted from the Git test framework. # use the ipfs tool to test against @@ -27,14 +27,17 @@ fi # to pass through in some cases. test "$TEST_VERBOSE" = 1 && verbose=t test "$TEST_IMMEDIATE" = 1 && immediate=t +test "$TEST_JUNIT" = 1 && junit=t +test "$TEST_NO_COLOR" = 1 && no_color=t # source the common hashes first. . lib/test-lib-hashes.sh -SHARNESS_LIB="lib/sharness/sharness.sh" +ln -sf lib/sharness/sharness.sh . +ln -sf lib/sharness/lib-sharness . -. "$SHARNESS_LIB" || { - echo >&2 "Cannot source: $SHARNESS_LIB" +. "sharness.sh" || { + echo >&2 "Cannot source: sharness.sh" echo >&2 "Please check Sharness installation." exit 1 } @@ -106,10 +109,15 @@ expr "$TEST_OS" : "CYGWIN_NT" >/dev/null || test_set_prereq STD_ERR_MSG if test "$TEST_VERBOSE" = 1; then echo '# TEST_VERBOSE='"$TEST_VERBOSE" + echo '# TEST_IMMEDIATE='"$TEST_IMMEDIATE" echo '# TEST_NO_FUSE='"$TEST_NO_FUSE" + echo '# TEST_NO_DOCKER='"$TEST_NO_DOCKER" echo '# TEST_NO_PLUGIN='"$TEST_NO_PLUGIN" echo '# TEST_EXPENSIVE='"$TEST_EXPENSIVE" echo '# TEST_OS='"$TEST_OS" + echo '# TEST_JUNIT='"$TEST_JUNIT" + echo '# TEST_NO_COLOR='"$TEST_NO_COLOR" + echo '# TEST_ULIMIT_PRESET='"$TEST_ULIMIT_PRESET" fi # source our generic test lib @@ -136,8 +144,8 @@ test_run_repeat_60_sec() { return 1 # failed } -test_wait_output_n_lines_60_sec() { - for i in $(test_seq 1 600) +test_wait_output_n_lines() { + for i in $(test_seq 1 3600) do test $(cat "$1" | wc -l | tr -d " ") -ge $2 && return go-sleep 100ms @@ -541,4 +549,3 @@ purge_blockstore() { [[ -z "$( ipfs repo gc )" ]] ' } - diff --git a/test/sharness/t0010-basic-commands.sh b/test/sharness/t0010-basic-commands.sh deleted file mode 100755 index 2b86466cf..000000000 --- a/test/sharness/t0010-basic-commands.sh +++ /dev/null @@ -1,149 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2014 Christian Couder -# MIT Licensed; see the LICENSE file in this repository. -# - -test_description="Test installation and some basic commands" - -. lib/test-lib.sh - -test_expect_success "current dir is writable" ' - echo "It works!" >test.txt -' - -test_expect_success "ipfs version succeeds" ' - ipfs version >version.txt -' - -test_expect_success "ipfs --version success" ' - ipfs --version -' - -test_expect_success "ipfs version output looks good" ' - egrep "^ipfs version [0-9]+\.[0-9]+\.[0-9]" version.txt >/dev/null || - test_fsh cat version.txt -' - -test_expect_success "ipfs versions matches ipfs --version" ' - ipfs version > version.txt && - ipfs --version > version2.txt && - diff version2.txt version.txt || - test_fsh ipfs --version - -' - -test_expect_success "ipfs version --all has all required fields" ' - ipfs version --all > version_all.txt && - grep "Kubo version" version_all.txt && - grep "Repo version" version_all.txt && - grep "System version" version_all.txt && - grep "Golang version" version_all.txt -' - -test_expect_success "ipfs version deps succeeds" ' - ipfs version deps >deps.txt -' - -test_expect_success "ipfs version deps output looks good ( set \$GOIPFSTEST_SKIP_LOCAL_DEVTREE_DEPS_CHECK to skip this test )" ' - head -1 deps.txt | grep "go-ipfs@(devel)" && - [[ "$GOIPFSTEST_SKIP_LOCAL_DEVTREE_DEPS_CHECK" == "1" ]] || - [[ $(tail -n +2 deps.txt | egrep -v -c "^[^ @]+@v[^ @]+( => [^ @]+@v[^ @]+)?$") -eq 0 ]] || - test_fsh cat deps.txt -' - -test_expect_success "'ipfs commands' succeeds" ' - ipfs commands >commands.txt -' - -test_expect_success "'ipfs commands' output looks good" ' - grep "ipfs add" commands.txt && - grep "ipfs daemon" commands.txt && - grep "ipfs update" commands.txt -' - -test_expect_success "All sub-commands accept help" ' - echo 0 > fail - while read -r cmd - do - ${cmd:0:4} help ${cmd:5} >/dev/null || - { echo "$cmd does not accept --help"; echo 1 > fail; } - echo stuff | $cmd --help >/dev/null || - { echo "$cmd does not accept --help when using stdin"; echo 1 > fail; } - done fail - while read -r cmd - do - $cmd --help >/dev/null || - { echo "$cmd does not accept --help"; echo 1 > fail; } - echo stuff | $cmd --help >/dev/null || - { echo "$cmd does not accept --help when using stdin"; echo 1 > fail; } - done fail - ipfs --help > help.txt - cut -d" " -f 2 commands.txt | grep -v ipfs | sort -u | \ - while read cmd - do - grep " $cmd" help.txt > /dev/null || - { echo "missing $cmd from helptext"; echo 1 > fail; } - done - - if [ $(cat fail) = 1 ]; then - return 1 - fi -' - -test_expect_failure "All ipfs commands docs are 80 columns or less" ' - echo 0 > fail - while read cmd - do - LENGTH="$($cmd --help | awk "{ print length }" | sort -nr | head -1)" - [ $LENGTH -gt 80 ] && - { echo "$cmd help text is longer than 79 chars ($LENGTH)"; echo 1 > fail; } - done fail - while read -r cmd - do - test_must_fail $cmd --badflag >/dev/null 2>&1 || - { echo "$cmd exit with code 0 when passed --badflag"; echo 1 > fail; } - done commands.txt -' - -test_expect_success "'ipfs commands --flags' output looks good" ' - grep "ipfs pin add --recursive / ipfs pin add -r" commands.txt && - grep "ipfs id --format / ipfs id -f" commands.txt && - grep "ipfs repo gc --quiet / ipfs repo gc -q" commands.txt -' - - - -test_done diff --git a/test/sharness/t0011-completion.sh b/test/sharness/t0011-completion.sh deleted file mode 100755 index cc1c3f0dc..000000000 --- a/test/sharness/t0011-completion.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -test_description="Test generated bash completions" - -. lib/test-lib.sh - -test_expect_success "'ipfs commands completion bash' succeeds" ' - ipfs commands completion bash > completions.bash -' - -test_expect_success "generated completions defines '_ipfs'" ' - bash -c "source completions.bash && type -t _ipfs" -' - -test_done diff --git a/test/sharness/t0020-init.sh b/test/sharness/t0020-init.sh deleted file mode 100755 index c1eb209a8..000000000 --- a/test/sharness/t0020-init.sh +++ /dev/null @@ -1,271 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2014 Christian Couder -# MIT Licensed; see the LICENSE file in this repository. -# - -test_description="Test init command" - -. lib/test-lib.sh - -# test that ipfs fails to init with BAD_IPFS_DIR that isn't writeable -test_expect_success "create dir and change perms succeeds" ' - export BAD_IPFS_DIR="$(pwd)/.badipfs" && - mkdir "$BAD_IPFS_DIR" && - chmod 000 "$BAD_IPFS_DIR" -' - -test_expect_success "ipfs init fails" ' - test_must_fail ipfs init --repo-dir "$BAD_IPFS_DIR" 2> init_fail_out -' - -# Under Windows/Cygwin the error message is different, -# so we use the STD_ERR_MSG prereq. -if test_have_prereq STD_ERR_MSG; then - init_err_msg="Error: error loading plugins: open $BAD_IPFS_DIR/config: permission denied" -else - init_err_msg="Error: error loading plugins: open $BAD_IPFS_DIR/config: The system cannot find the path specified." -fi - -test_expect_success "ipfs init output looks good" ' - echo "$init_err_msg" >init_fail_exp && - test_cmp init_fail_exp init_fail_out -' - -test_expect_success "cleanup dir with bad perms" ' - chmod 775 "$BAD_IPFS_DIR" && - rmdir "$BAD_IPFS_DIR" -' - -# test no repo error message -# this applies to `ipfs add sth`, `ipfs refs ` -test_expect_success "ipfs cat fails" ' - export IPFS_DIR="$(pwd)/.ipfs" && - test_must_fail ipfs cat --repo-dir "$IPFS_DIR" Qmaa4Rw81a3a1VEx4LxB7HADUAXvZFhCoRdBzsMZyZmqHD 2> cat_fail_out -' - -test_expect_success "ipfs cat no repo message looks good" ' - echo "Error: no IPFS repo found in $IPFS_DIR." > cat_fail_exp && - echo "please run: '"'"'ipfs init'"'"'" >> cat_fail_exp && - test_path_cmp cat_fail_exp cat_fail_out -' - -# $1 must be one of 'rsa', 'ed25519' or '' (for default key algorithm). -test_ipfs_init_flags() { - TEST_ALG=$1 - - # test that init succeeds - test_expect_success "ipfs init succeeds" ' - export IPFS_DIR="$(pwd)/.ipfs" && - echo "IPFS_DIR: \"$IPFS_DIR\"" && - RSA_BITS="2048" && - case $TEST_ALG in - "rsa") - ipfs init --repo-dir "$IPFS_DIR" --algorithm=rsa --bits="$RSA_BITS" >actual_init || test_fsh cat actual_init - ;; - "ed25519") - ipfs init --repo-dir "$IPFS_DIR" --algorithm=ed25519 >actual_init || test_fsh cat actual_init - ;; - *) - ipfs init --repo-dir "$IPFS_DIR" --algorithm=rsa --bits="$RSA_BITS" >actual_init || test_fsh cat actual_init - ;; - esac - ' - - test_expect_success ".ipfs/ has been created" ' - test -d "$IPFS_DIR" && - test -f "$IPFS_DIR/config" && - test -d "$IPFS_DIR/datastore" && - test -d "$IPFS_DIR/blocks" && - test ! -f ._check_writeable || - test_fsh ls -al $IPFS_DIR - ' - - test_expect_success "ipfs config succeeds" ' - echo /ipfs >expected_config && - ipfs config --repo-dir "$IPFS_DIR" Mounts.IPFS >actual_config && - test_cmp expected_config actual_config - ' - - test_expect_success "ipfs peer id looks good" ' - PEERID=$(ipfs config --repo-dir "$IPFS_DIR" Identity.PeerID) && - test_check_peerid "$PEERID" - ' - - test_expect_success "ipfs init output looks good" ' - STARTFILE="ipfs cat /ipfs/$HASH_WELCOME_DOCS/readme" && - - echo "generating $RSA_BITS-bit RSA keypair...done" >rsa_expected && - echo "peer identity: $PEERID" >>rsa_expected && - echo "initializing IPFS node at $IPFS_DIR" >>rsa_expected && - echo "to get started, enter:" >>rsa_expected && - printf "\\n\\t$STARTFILE\\n\\n" >>rsa_expected && - - echo "generating ED25519 keypair...done" >ed25519_expected && - echo "peer identity: $PEERID" >>ed25519_expected && - echo "initializing IPFS node at $IPFS_DIR" >>ed25519_expected && - echo "to get started, enter:" >>ed25519_expected && - printf "\\n\\t$STARTFILE\\n\\n" >>ed25519_expected && - - case $TEST_ALG in - rsa) - test_cmp rsa_expected actual_init - ;; - ed25519) - test_cmp ed25519_expected actual_init - ;; - *) - test_cmp rsa_expected actual_init - ;; - esac - ' - - test_expect_success "Welcome readme exists" ' - ipfs cat /ipfs/$HASH_WELCOME_DOCS/readme - ' - - test_expect_success "clean up ipfs dir" ' - rm -rf "$IPFS_DIR" - ' - - test_expect_success "'ipfs init --empty-repo' succeeds" ' - RSA_BITS="2048" && - case $TEST_ALG in - rsa) - ipfs init --repo-dir "$IPFS_DIR" --algorithm=rsa --bits="$RSA_BITS" --empty-repo >actual_init - ;; - ed25519) - ipfs init --repo-dir "$IPFS_DIR" --algorithm=ed25519 --empty-repo >actual_init - ;; - *) - ipfs init --repo-dir "$IPFS_DIR" --empty-repo >actual_init - ;; - esac - ' - - test_expect_success "ipfs peer id looks good" ' - PEERID=$(ipfs config --repo-dir "$IPFS_DIR" Identity.PeerID) && - test_check_peerid "$PEERID" - ' - - test_expect_success "'ipfs init --empty-repo' output looks good" ' - - echo "generating $RSA_BITS-bit RSA keypair...done" >rsa_expected && - echo "peer identity: $PEERID" >>rsa_expected && - echo "initializing IPFS node at $IPFS_DIR" >>rsa_expected && - - echo "generating ED25519 keypair...done" >ed25519_expected && - echo "peer identity: $PEERID" >>ed25519_expected && - echo "initializing IPFS node at $IPFS_DIR" >>ed25519_expected && - - case $TEST_ALG in - rsa) - test_cmp rsa_expected actual_init - ;; - ed25519) - test_cmp ed25519_expected actual_init - ;; - *) - test_cmp ed25519_expected actual_init - ;; - esac - ' - - test_expect_success "Welcome readme doesn't exist" ' - test_must_fail ipfs cat /ipfs/$HASH_WELCOME_DOCS/readme - ' - - test_expect_success "ipfs id agent string contains correct version" ' - ipfs id -f "" | grep $(ipfs version -n) - ' - - test_expect_success "clean up ipfs dir" ' - rm -rf "$IPFS_DIR" - ' -} -test_ipfs_init_flags 'ed25519' -test_ipfs_init_flags 'rsa' -test_ipfs_init_flags '' - -# test init profiles -test_expect_success "'ipfs init --profile' with invalid profile fails" ' - RSA_BITS="2048" && - test_must_fail ipfs init --repo-dir "$IPFS_DIR" --profile=nonexistent_profile 2> invalid_profile_out - EXPECT="Error: invalid configuration profile: nonexistent_profile" && - grep "$EXPECT" invalid_profile_out -' - -test_expect_success "'ipfs init --profile' succeeds" ' - RSA_BITS="2048" && - ipfs init --repo-dir "$IPFS_DIR" --profile=server -' - -test_expect_success "'ipfs config Swarm.AddrFilters' looks good" ' - ipfs config --repo-dir "$IPFS_DIR" Swarm.AddrFilters > actual_config && - test $(cat actual_config | wc -l) = 18 -' - -test_expect_success "clean up ipfs dir" ' - rm -rf "$IPFS_DIR" -' - -test_expect_success "'ipfs init --profile=test' succeeds" ' - RSA_BITS="2048" && - ipfs init --repo-dir "$IPFS_DIR" --profile=test -' - -test_expect_success "'ipfs config Bootstrap' looks good" ' - ipfs config --repo-dir "$IPFS_DIR" Bootstrap > actual_config && - test $(cat actual_config) = "[]" -' - -test_expect_success "'ipfs config Addresses.API' looks good" ' - ipfs config --repo-dir "$IPFS_DIR" Addresses.API > actual_config && - test $(cat actual_config) = "/ip4/127.0.0.1/tcp/0" -' - -test_expect_success "ipfs init from existing config succeeds" ' - export ORIG_PATH=$IPFS_DIR - export IPFS_DIR=$(pwd)/.ipfs-clone - - ipfs init --repo-dir "$IPFS_DIR" "$ORIG_PATH/config" && - ipfs config --repo-dir "$IPFS_DIR" Addresses.API > actual_config && - test $(cat actual_config) = "/ip4/127.0.0.1/tcp/0" -' - -test_expect_success "clean up ipfs clone dir and reset IPFS_DIR" ' - rm -rf "$IPFS_DIR" && - export IPFS_DIR=$ORIG_PATH -' - -test_expect_success "clean up ipfs dir" ' - rm -rf "$IPFS_DIR" -' - -test_expect_success "'ipfs init --profile=lowpower' succeeds" ' - RSA_BITS="2048" && - ipfs init --repo-dir "$IPFS_DIR" --profile=lowpower -' - -test_expect_success "'ipfs config Discovery.Routing' looks good" ' - ipfs config --repo-dir "$IPFS_DIR" Routing.Type > actual_config && - test $(cat actual_config) = "dhtclient" -' - -test_expect_success "clean up ipfs dir" ' - rm -rf "$IPFS_DIR" -' - -test_init_ipfs - -test_launch_ipfs_daemon - -test_expect_success "ipfs init should not run while daemon is running" ' - test_must_fail ipfs init --repo-dir "$IPFS_DIR" 2> daemon_running_err && - EXPECT="Error: ipfs daemon is running. please stop it to run this command" && - grep "$EXPECT" daemon_running_err -' - -test_kill_ipfs_daemon - -test_done diff --git a/test/sharness/t0041-ping.sh b/test/sharness/t0041-ping.sh index 8fdfe1797..14268989d 100755 --- a/test/sharness/t0041-ping.sh +++ b/test/sharness/t0041-ping.sh @@ -27,7 +27,7 @@ test_expect_success "test ping other" ' test_expect_success "test ping unreachable peer" ' printf "Looking up peer %s\n" "$BAD_PEER" > bad_ping_exp && - printf "PING QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJx.\nPing error: routing: not found\nError: ping failed\n" >> bad_ping_exp && + printf "PING QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJx.\nPing error: no addresses\nError: ping failed\n" >> bad_ping_exp && ! ipfsi 0 ping -n2 -- "$BAD_PEER" > bad_ping_actual 2>&1 && test_cmp bad_ping_exp bad_ping_actual ' diff --git a/test/sharness/t0085-pins.sh b/test/sharness/t0085-pins.sh deleted file mode 100755 index c83c51368..000000000 --- a/test/sharness/t0085-pins.sh +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2016 Jeromy Johnson -# MIT Licensed; see the LICENSE file in this repository. -# - -test_description="Test ipfs pinning operations" - -. lib/test-lib.sh - - -test_pins() { - PIN_ARGS="$1" - LS_ARGS="$2" - BASE=$3 - if [ -n "$BASE" ]; then - BASE_ARGS="--cid-base=$BASE" - fi - - test_expect_success "create some hashes $BASE" ' - HASH_A=$(echo "A" | ipfs add $BASE_ARGS -q --pin=false) && - HASH_B=$(echo "B" | ipfs add $BASE_ARGS -q --pin=false) && - HASH_C=$(echo "C" | ipfs add $BASE_ARGS -q --pin=false) && - HASH_D=$(echo "D" | ipfs add $BASE_ARGS -q --pin=false) && - HASH_E=$(echo "E" | ipfs add $BASE_ARGS -q --pin=false) && - HASH_F=$(echo "F" | ipfs add $BASE_ARGS -q --pin=false) && - HASH_G=$(echo "G" | ipfs add $BASE_ARGS -q --pin=false) - ' - - test_expect_success "put all those hashes in a file" ' - echo $HASH_A > hashes && - echo $HASH_B >> hashes && - echo $HASH_C >> hashes && - echo $HASH_D >> hashes && - echo $HASH_E >> hashes && - echo $HASH_F >> hashes && - echo $HASH_G >> hashes - ' - - if [ -n "$BASE" ]; then - test_expect_success "make sure hashes are in $BASE" ' - cat hashes | xargs cid-fmt %b | sort -u > actual - echo base32 > expected - test_cmp expected actual - ' - fi - - test_expect_success "'ipfs pin add $PIN_ARGS' via stdin" ' - cat hashes | ipfs pin add $PIN_ARGS $BASE_ARGS | tee actual - ' - - test_expect_success "'ipfs pin add $PIN_ARGS' output looks good" ' - sed -e "s/^/pinned /; s/$/ recursively/" hashes > expected && - test_cmp expected actual - ' - - test_expect_success "see if verify works" ' - ipfs pin verify - ' - - test_expect_success "see if verify --verbose $BASE_ARGS works" ' - ipfs pin verify --verbose $BASE_ARGS > verify_out && - test $(cat verify_out | wc -l) -ge 7 && - test_should_contain "$HASH_A ok" verify_out && - test_should_contain "$HASH_B ok" verify_out && - test_should_contain "$HASH_C ok" verify_out && - test_should_contain "$HASH_D ok" verify_out && - test_should_contain "$HASH_E ok" verify_out && - test_should_contain "$HASH_F ok" verify_out && - test_should_contain "$HASH_G ok" verify_out - ' - - test_expect_success "ipfs pin ls $LS_ARGS $BASE_ARGS works" ' - ipfs pin ls $LS_ARGS $BASE_ARGS > ls_out && - test_should_contain "$HASH_A" ls_out && - test_should_contain "$HASH_B" ls_out && - test_should_contain "$HASH_C" ls_out && - test_should_contain "$HASH_D" ls_out && - test_should_contain "$HASH_E" ls_out && - test_should_contain "$HASH_F" ls_out && - test_should_contain "$HASH_G" ls_out - ' - - test_expect_success "test pin ls $LS_ARGS $BASE_ARGS hash" ' - echo $HASH_B | test_must_fail grep /ipfs && # just to be sure - ipfs pin ls $LS_ARGS $BASE_ARGS $HASH_B > ls_hash_out && - echo "$HASH_B recursive" > ls_hash_exp && - test_cmp ls_hash_exp ls_hash_out - ' - - test_expect_success "unpin those hashes" ' - cat hashes | ipfs pin rm - ' - - test_expect_success "test pin update" ' - ipfs pin add "$HASH_A" && - ipfs pin ls $LS_ARGS $BASE_ARGS | tee before_update && - test_should_contain "$HASH_A" before_update && - test_must_fail grep -q "$HASH_B" before_update && - ipfs pin update --unpin=true "$HASH_A" "$HASH_B" && - ipfs pin ls $LS_ARGS $BASE_ARGS > after_update && - test_must_fail grep -q "$HASH_A" after_update && - test_should_contain "$HASH_B" after_update && - ipfs pin update --unpin=true "$HASH_B" "$HASH_B" && - ipfs pin ls $LS_ARGS $BASE_ARGS > after_idempotent_update && - test_should_contain "$HASH_B" after_idempotent_update && - ipfs pin rm "$HASH_B" - ' -} - -RANDOM_HASH=Qme8uX5n9hn15pw9p6WcVKoziyyC9LXv4LEgvsmKMULjnV - -test_pins_error_reporting() { - PIN_ARGS=$1 - - test_expect_success "'ipfs pin add $PIN_ARGS' on non-existent hash should fail" ' - test_must_fail ipfs pin add $PIN_ARGS $RANDOM_HASH 2> err && - grep -q "ipld: could not find" err - ' -} - -test_pin_dag_init() { - PIN_ARGS=$1 - - test_expect_success "'ipfs add $PIN_ARGS --pin=false' 1MB file" ' - random 1048576 56 > afile && - HASH=`ipfs add $PIN_ARGS --pin=false -q afile` - ' -} - -test_pin_dag() { - test_pin_dag_init $1 - - test_expect_success "'ipfs pin add --progress' file" ' - ipfs pin add --recursive=true $HASH - ' - - test_expect_success "'ipfs pin rm' file" ' - ipfs pin rm $HASH - ' - - test_expect_success "remove part of the dag" ' - PART=`ipfs refs $HASH | head -1` && - ipfs block rm $PART - ' - - test_expect_success "pin file, should fail" ' - test_must_fail ipfs pin add --recursive=true $HASH 2> err && - cat err && - grep -q "ipld: could not find" err - ' -} - -test_pin_progress() { - test_pin_dag_init - - test_expect_success "'ipfs pin add --progress' file" ' - ipfs pin add --progress $HASH 2> err - ' - - test_expect_success "pin progress reported correctly" ' - cat err - grep -q " 5 nodes" err - ' -} - -test_init_ipfs - -test_pins '' '' '' -test_pins --progress '' '' -test_pins --progress --stream '' -test_pins '' '' base32 -test_pins '' --stream base32 - -test_pins_error_reporting -test_pins_error_reporting --progress - -test_pin_dag -test_pin_dag --raw-leaves - -test_pin_progress - -test_launch_ipfs_daemon_without_network - -test_pins '' '' '' -test_pins --progress '' '' -test_pins --progress --stream '' -test_pins '' '' base32 -test_pins '' --stream base32 - -test_pins_error_reporting -test_pins_error_reporting --progress - -test_pin_dag -test_pin_dag --raw-leaves - -test_pin_progress - -test_kill_ipfs_daemon - -test_done diff --git a/test/sharness/t0100-name.sh b/test/sharness/t0100-name.sh index 934cc0127..44c2afb2d 100755 --- a/test/sharness/t0100-name.sh +++ b/test/sharness/t0100-name.sh @@ -225,6 +225,30 @@ test_name_with_self() { grep "argument \"ipfs-path\" is required" curl_out ' + # Test Publishing with TTL and Inspecting Records + test_expect_success "'ipfs name publish --ttl=30m' succeeds" ' + ipfs name publish --ttl=30m --allow-offline "/ipfs/$HASH_WELCOME_DOCS" + ' + + test_expect_success "retrieve IPNS key for further inspection" ' + ipfs routing get "/ipns/$PEERID" > ipns_record + ' + + test_expect_success "'ipfs name inspect' has correct TTL (30m)" ' + ipfs name inspect < ipns_record > verify_output && + test_should_contain "This record was not validated." verify_output && + test_should_contain "$HASH_WELCOME_DOCS" verify_output && + test_should_contain "1800000000000" verify_output + ' + + test_expect_success "'ipfs name inspect --verify' has '.Validation.Validity' set to 'true' with correct Peer ID" ' + ipfs name inspect --verify $PEERID --enc json < ipns_record | jq -e ".Validation.Valid == true and .Entry.TTL == .Entry.Data.TTL" + ' + + test_expect_success "'ipfs name inspect --verify' has '.Validation.Validity' set to 'false' with incorrect Peer ID" ' + ipfs name inspect --verify 12D3KooWRirYjmmQATx2kgHBfky6DADsLP7ex1t7BRxJ6nqLs9WH --enc json < ipns_record | jq -e ".Validation.Valid == false" + ' + test_kill_ipfs_daemon # Test daemon in offline mode diff --git a/test/sharness/t0110-gateway-data/foo.block b/test/sharness/t0110-gateway-data/foo.block deleted file mode 100644 index 39c7ef60b..000000000 --- a/test/sharness/t0110-gateway-data/foo.block +++ /dev/null @@ -1,2 +0,0 @@ - - foo \ No newline at end of file diff --git a/test/sharness/t0110-gateway-data/foofoo.block b/test/sharness/t0110-gateway-data/foofoo.block deleted file mode 100644 index 9e5177b18..000000000 Binary files a/test/sharness/t0110-gateway-data/foofoo.block and /dev/null differ diff --git a/test/sharness/t0110-gateway.sh b/test/sharness/t0110-gateway.sh deleted file mode 100755 index 87aa61c70..000000000 --- a/test/sharness/t0110-gateway.sh +++ /dev/null @@ -1,357 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2015 Matt Bell -# MIT Licensed; see the LICENSE file in this repository. -# - -test_description="Test HTTP Gateway" - -. lib/test-lib.sh - -test_init_ipfs -test_launch_ipfs_daemon - -port=$GWAY_PORT -apiport=$API_PORT - -# TODO check both 5001 and 5002. -# 5001 should have a readable gateway (part of the API) -# 5002 should have a readable gateway (using ipfs config Addresses.Gateway) -# but ideally we should only write the tests once. so maybe we need to -# define a function to test a gateway, and do so for each port. -# for now we check 5001 here as 5002 will be checked in gateway-writable. - -test_expect_success "Make a file to test with" ' - echo "Hello Worlds!" >expected && - HASH=$(ipfs add -q expected) || - test_fsh cat daemon_err -' - -test_expect_success "GET IPFS path succeeds" ' - curl -sfo actual "http://127.0.0.1:$port/ipfs/$HASH" -' - -test_expect_success "GET IPFS path with explicit ?filename succeeds with proper header" " - curl -fo actual -D actual_headers 'http://127.0.0.1:$port/ipfs/$HASH?filename=testтест.pdf' && - grep -F 'Content-Disposition: inline; filename=\"test____.pdf\"; filename*=UTF-8'\'\''test%D1%82%D0%B5%D1%81%D1%82.pdf' actual_headers -" - -test_expect_success "GET IPFS path with explicit ?filename and &download=true succeeds with proper header" " - curl -fo actual -D actual_headers 'http://127.0.0.1:$port/ipfs/$HASH?filename=testтест.mp4&download=true' && - grep -F 'Content-Disposition: attachment; filename=\"test____.mp4\"; filename*=UTF-8'\'\''test%D1%82%D0%B5%D1%81%D1%82.mp4' actual_headers -" - -# https://github.com/ipfs/go-ipfs/issues/4025#issuecomment-342250616 -test_expect_success "GET for Service Worker registration outside of an IPFS content root errors" " - curl -H 'Service-Worker: script' -svX GET 'http://127.0.0.1:$port/ipfs/$HASH?filename=sw.js' > curl_sw_out 2>&1 && - grep 'HTTP/1.1 400 Bad Request' curl_sw_out && - grep 'navigator.serviceWorker: registration is not allowed for this scope' curl_sw_out -" - -test_expect_success "GET IPFS path output looks good" ' - test_cmp expected actual && - rm actual -' - -test_expect_success "GET IPFS directory path succeeds" ' - mkdir -p dir/dirwithindex && - echo "12345" >dir/test && - echo "hello i am a webpage" >dir/dirwithindex/index.html && - ipfs add -r -q dir >actual && - HASH2=$(tail -n 1 actual) && - curl -sf "http://127.0.0.1:$port/ipfs/$HASH2" -' - -test_expect_success "GET IPFS directory file succeeds" ' - curl -sfo actual "http://127.0.0.1:$port/ipfs/$HASH2/test" -' - -test_expect_success "GET IPFS directory file output looks good" ' - test_cmp dir/test actual -' - -test_expect_success "GET IPFS directory with index.html returns redirect to add trailing slash" " - curl -sI -o response_without_slash \"http://127.0.0.1:$port/ipfs/$HASH2/dirwithindex?query=to-remember\" && - test_should_contain \"HTTP/1.1 301 Moved Permanently\" response_without_slash && - test_should_contain \"Location: /ipfs/$HASH2/dirwithindex/?query=to-remember\" response_without_slash -" - -# This enables go get to parse go-import meta tags from index.html files stored in IPFS -# https://github.com/ipfs/kubo/pull/3963 -test_expect_success "GET IPFS directory with index.html and no trailing slash returns expected output when go-get is passed" " - curl -s -o response_with_slash \"http://127.0.0.1:$port/ipfs/$HASH2/dirwithindex?go-get=1\" && - test_should_contain \"hello i am a webpage\" response_with_slash -" - -test_expect_success "GET IPFS directory with index.html and trailing slash returns expected output" " - curl -s -o response_with_slash \"http://127.0.0.1:$port/ipfs/$HASH2/dirwithindex/?query=to-remember\" && - test_should_contain \"hello i am a webpage\" response_with_slash -" - -test_expect_success "GET IPFS nonexistent file returns 404 (Not Found)" ' - test_curl_resp_http_code "http://127.0.0.1:$port/ipfs/$HASH2/pleaseDontAddMe" "HTTP/1.1 404 Not Found" -' - -test_expect_success "GET IPFS invalid CID returns 400 (Bad Request)" ' - test_curl_resp_http_code "http://127.0.0.1:$port/ipfs/QmInvalid/pleaseDontAddMe" "HTTP/1.1 400 Bad Request" -' - -# https://github.com/ipfs/go-ipfs/issues/8230 -test_expect_success "GET IPFS inlined zero-length data object returns ok code (200)" ' - curl -sD - "http://127.0.0.1:$port/ipfs/bafkqaaa" > empty_ok_response && - test_should_contain "HTTP/1.1 200 OK" empty_ok_response && - test_should_contain "Content-Length: 0" empty_ok_response -' - -# https://github.com/ipfs/kubo/issues/9238 -test_expect_success "GET IPFS inlined zero-length data object with byte range returns ok code (200)" ' - curl -sD - "http://127.0.0.1:$port/ipfs/bafkqaaa" -H "Range: bytes=0-1048575" > empty_ok_response && - test_should_contain "HTTP/1.1 200 OK" empty_ok_response && - test_should_contain "Content-Length: 0" empty_ok_response && - test_should_contain "Content-Type: text/plain" empty_ok_response -' - -test_expect_success "GET /ipfs/ipfs/{cid} returns redirect to the valid path" ' - curl -sD - "http://127.0.0.1:$port/ipfs/ipfs/bafkqaaa?query=to-remember" > response_with_double_ipfs_ns && - test_should_contain "" response_with_double_ipfs_ns && - test_should_contain "" response_with_double_ipfs_ns -' - -test_expect_success "GET invalid IPNS root returns 400 (Bad Request)" ' - test_curl_resp_http_code "http://127.0.0.1:$port/ipns/QmInvalid/pleaseDontAddMe" "HTTP/1.1 400 Bad Request" -' - -test_expect_failure "GET IPNS path succeeds" ' - ipfs name publish --allow-offline "$HASH" && - PEERID=$(ipfs config Identity.PeerID) && - test_check_peerid "$PEERID" && - curl -sfo actual "http://127.0.0.1:$port/ipns/$PEERID" -' - -test_expect_failure "GET IPNS path output looks good" ' - test_cmp expected actual -' - -test_expect_success "GET /ipfs/ipns/{peerid} returns redirect to the valid path" ' - PEERID=$(ipfs config Identity.PeerID) && - curl -sD - "http://127.0.0.1:$port/ipfs/ipns/${PEERID}?query=to-remember" > response_with_ipfs_ipns_ns && - test_should_contain "" response_with_ipfs_ipns_ns && - test_should_contain "" response_with_ipfs_ipns_ns -' - -test_expect_success "GET invalid IPFS path errors" ' - test_must_fail curl -sf "http://127.0.0.1:$port/ipfs/12345" -' - -test_expect_success "GET invalid path errors" ' - test_must_fail curl -sf "http://127.0.0.1:$port/12345" -' - -test_expect_success "GET /webui returns code expected" ' - test_curl_resp_http_code "http://127.0.0.1:$apiport/webui" "HTTP/1.1 302 Found" "HTTP/1.1 301 Moved Permanently" -' - -test_expect_success "GET /webui/ returns code expected" ' - test_curl_resp_http_code "http://127.0.0.1:$apiport/webui/" "HTTP/1.1 302 Found" "HTTP/1.1 301 Moved Permanently" -' - -test_expect_success "GET /logs returns logs" ' - test_expect_code 28 curl http://127.0.0.1:$apiport/logs -m1 > log_out -' - -test_expect_success "log output looks good" ' - grep "log API client connected" log_out -' - -test_expect_success "GET /api/v0/version succeeds" ' - curl -X POST -v "http://127.0.0.1:$apiport/api/v0/version" 2> version_out -' - -test_expect_success "output only has one transfer encoding header" ' - grep "Transfer-Encoding: chunked" version_out | wc -l | xargs echo > tecount_out && - echo "1" > tecount_exp && - test_cmp tecount_out tecount_exp -' - -curl_pprofmutex() { - curl -f -X POST "http://127.0.0.1:$apiport/debug/pprof-mutex/?fraction=$1" -} - -test_expect_success "set mutex fraction for pprof (negative so it doesn't enable)" ' - curl_pprofmutex -1 -' - -test_expect_success "test failure conditions of mutex pprof endpoint" ' - test_must_fail curl_pprofmutex && - test_must_fail curl_pprofmutex that_is_string && - test_must_fail curl -f -X GET "http://127.0.0.1:$apiport/debug/pprof-mutex/?fraction=-1" -' - -curl_pprofblock() { - curl -f -X POST "http://127.0.0.1:$apiport/debug/pprof-block/?rate=$1" -} - -test_expect_success "set blocking profiler rate for pprof (0 so it doesn't enable)" ' - curl_pprofblock 0 -' - -test_expect_success "test failure conditions of mutex block endpoint" ' - test_must_fail curl_pprofblock && - test_must_fail curl_pprofblock that_is_string && - test_must_fail curl -f -X GET "http://127.0.0.1:$apiport/debug/pprof-block/?rate=0" -' - -test_expect_success "setup index hash" ' - mkdir index && - echo "

" > index/index.html && - INDEXHASH=$(ipfs add -Q -r index) - echo index: $INDEXHASH -' - -test_expect_success "GET 'index.html' has correct content type" ' - curl -I "http://127.0.0.1:$port/ipfs/$INDEXHASH/" > indexout -' - -test_expect_success "output looks good" ' - grep "Content-Type: text/html" indexout -' - -test_expect_success "HEAD 'index.html' has no content" ' - curl -X HEAD --max-time 1 http://127.0.0.1:$port/ipfs/$INDEXHASH/ > output; - [ ! -s output ] -' - -# test ipfs readonly api - -test_curl_gateway_api() { - curl -sfo actual "http://127.0.0.1:$port/api/v0/$1" -} - -test_expect_success "get IPFS directory file through readonly API succeeds" ' - test_curl_gateway_api "cat?arg=$HASH2/test" -' - -test_expect_success "get IPFS directory file through readonly API output looks good" ' - test_cmp dir/test actual -' - -test_expect_success "refs IPFS directory file through readonly API succeeds" ' - test_curl_gateway_api "refs?arg=$HASH2/test" -' - -for cmd in add \ - block/put \ - bootstrap \ - config \ - dag/put \ - dag/import \ - dht \ - diag \ - id \ - mount \ - name/publish \ - object/put \ - object/new \ - object/patch \ - pin \ - ping \ - repo \ - stats \ - swarm \ - file \ - update \ - bitswap -do - test_expect_success "test gateway api is sanitized: $cmd" ' - test_curl_resp_http_code "http://127.0.0.1:$port/api/v0/$cmd" "HTTP/1.1 404 Not Found" - ' -done - -# This one is different. `local` will be interpreted as a path if the command isn't defined. -test_expect_success "test gateway api is sanitized: refs/local" ' - echo "Error: invalid path \"local\": selected encoding not supported" > refs_local_expected && - ! ipfs --api /ip4/127.0.0.1/tcp/$port refs local > refs_local_actual 2>&1 && - test_cmp refs_local_expected refs_local_actual - ' - -test_expect_success "create raw-leaves node" ' - echo "This is RAW!" > rfile && - echo "This is RAW!" | ipfs add --raw-leaves -q > rhash -' - -test_expect_success "try fetching it from gateway" ' - curl http://127.0.0.1:$port/ipfs/$(cat rhash) > ffile && - test_cmp rfile ffile -' - -test_expect_success "Add compact blocks" ' - ipfs block put ../t0110-gateway-data/foo.block && - FOO2_HASH=$(ipfs block put --cid-codec=dag-pb ../t0110-gateway-data/foofoo.block) && - printf "foofoo" > expected -' - -test_expect_success "GET compact blocks succeeds" ' - curl -o actual "http://127.0.0.1:$port/ipfs/$FOO2_HASH" && - test_cmp expected actual -' - -test_expect_success "Verify gateway file" ' - cat "$IPFS_PATH/gateway" > gateway_file_actual && - echo -n "http://$GWAY_ADDR" > gateway_daemon_actual && - test_cmp gateway_daemon_actual gateway_file_actual -' - -test_kill_ipfs_daemon - -GWPORT=32563 - -test_expect_success "Verify gateway file diallable while on unspecified" ' - ipfs config Addresses.Gateway /ip4/0.0.0.0/tcp/$GWPORT && - test_launch_ipfs_daemon && - cat "$IPFS_PATH/gateway" > gateway_file_actual && - echo -n "http://127.0.0.1:$GWPORT" > gateway_file_expected && - test_cmp gateway_file_expected gateway_file_actual -' - -test_kill_ipfs_daemon - -test_expect_success "set up iptb testbed" ' - iptb testbed create -type localipfs -count 5 -force -init && - ipfsi 0 config Addresses.Gateway /ip4/127.0.0.1/tcp/$GWPORT && - PEERID_1=$(iptb attr get 1 id) -' - -test_expect_success "set NoFetch to true in config of node 0" ' - ipfsi 0 config --bool=true Gateway.NoFetch true -' - -test_expect_success "start ipfs nodes" ' - iptb start -wait && - iptb connect 0 1 -' - -test_expect_success "try fetching not present key from node 0" ' - FOO=$(echo "foo" | ipfsi 1 add -Q) && - test_expect_code 22 curl -f "http://127.0.0.1:$GWPORT/ipfs/$FOO" -' - -test_expect_success "try fetching not present ipns key from node 0" ' - ipfsi 1 name publish /ipfs/$FOO && - test_expect_code 22 curl -f "http://127.0.0.1:$GWPORT/ipns/$PEERID_1" -' - -test_expect_success "try fetching present key from node 0" ' - BAR=$(echo "bar" | ipfsi 0 add -Q) && - curl -f "http://127.0.0.1:$GWPORT/ipfs/$BAR" -' - -test_expect_success "try fetching present ipns key from node 0" ' - ipfsi 1 name publish /ipfs/$BAR && - curl "http://127.0.0.1:$GWPORT/ipns/$PEERID_1" -' - -test_expect_success "stop testbed" ' - iptb stop -' - -test_done diff --git a/test/sharness/t0115-gateway-dir-listing.sh b/test/sharness/t0115-gateway-dir-listing.sh index 4b8cf7bc2..708e0c4cf 100755 --- a/test/sharness/t0115-gateway-dir-listing.sh +++ b/test/sharness/t0115-gateway-dir-listing.sh @@ -163,28 +163,6 @@ test_expect_success "dnslink gw: hash column should be a CID link to cid.ipfs.te test_should_contain "" list_response ' -## ============================================================================ -## Test dir listing of a big directory -## ============================================================================ - -test_expect_success "dir listing should resolve child sizes if under Gateway.FastDirIndexThreshold" ' - curl -sD - http://127.0.0.1:$GWAY_PORT/ipfs/${DIR_CID}/ą/ę/ | tee list_response && - test_should_contain "/ipfs/${FILE_CID}?filename" list_response && - test_should_contain ">${FILE_SIZE} B" list_response -' - -# force fast dir index for all responses -ipfs config --json Gateway.FastDirIndexThreshold 0 -# restart daemon to apply config changes -test_kill_ipfs_daemon -test_launch_ipfs_daemon - -test_expect_success "dir listing should not resolve child sizes beyond Gateway.FastDirIndexThreshold" ' - curl -sD - http://127.0.0.1:$GWAY_PORT/ipfs/${DIR_CID}/ą/ę/ | tee list_response && - test_should_contain "/ipfs/${FILE_CID}?filename" list_response && - test_should_not_contain ">${FILE_SIZE} B" list_response -' - ## ============================================================================ ## End of tests, cleanup ## ============================================================================ diff --git a/test/sharness/t0118-gateway-car.sh b/test/sharness/t0118-gateway-car.sh index 3d8d7b08f..62b2725d0 100755 --- a/test/sharness/t0118-gateway-car.sh +++ b/test/sharness/t0118-gateway-car.sh @@ -111,7 +111,7 @@ test_launch_ipfs_daemon_without_network ' test_expect_success "GET for application/vnd.ipld.car with query filename includes Content-Disposition with custom filename" ' - curl -svX GET -H "Accept: application/vnd.ipld.car" "http://127.0.0.1:$GWAY_PORT/ipfs/$ROOT_DIR_CID/subdir/ascii.txt?filename=foobar.car" > curl_output_filename 2>&1 && + curl -svX GET -H "Accept: application/vnd.ipld.car" "http://127.0.0.1:$GWAY_PORT/ipfs/$ROOT_DIR_CID/subdir/ascii.txt?filename=foobar.car" >/dev/null 2>curl_output_filename && cat curl_output_filename && grep "< Content-Disposition: attachment\; filename=\"foobar.car\"" curl_output_filename ' diff --git a/test/sharness/t0123-gateway-json-cbor.sh b/test/sharness/t0123-gateway-json-cbor.sh index 812d90f24..704d075f9 100755 --- a/test/sharness/t0123-gateway-json-cbor.sh +++ b/test/sharness/t0123-gateway-json-cbor.sh @@ -12,153 +12,150 @@ test_expect_success "Add the test directory" ' mkdir -p rootDir/ipns && mkdir -p rootDir/api && mkdir -p rootDir/ą/ę && + echo "{ \"test\": \"i am a plain json file\" }" > rootDir/ą/ę/t.json && echo "I am a txt file on path with utf8" > rootDir/ą/ę/file-źł.txt && echo "I am a txt file in confusing /api dir" > rootDir/api/file.txt && echo "I am a txt file in confusing /ipfs dir" > rootDir/ipfs/file.txt && echo "I am a txt file in confusing /ipns dir" > rootDir/ipns/file.txt && DIR_CID=$(ipfs add -Qr --cid-version 1 rootDir) && + FILE_JSON_CID=$(ipfs files stat --enc=json /ipfs/$DIR_CID/ą/ę/t.json | jq -r .Hash) && FILE_CID=$(ipfs files stat --enc=json /ipfs/$DIR_CID/ą/ę/file-źł.txt | jq -r .Hash) && FILE_SIZE=$(ipfs files stat --enc=json /ipfs/$DIR_CID/ą/ę/file-źł.txt | jq -r .Size) echo "$FILE_CID / $FILE_SIZE" ' -## Reading UnixFS (data encoded with dag-pb codec) as DAG-CBOR and DAG-JSON +## Quick regression check for JSON stored on UnixFS: +## it has nothing to do with DAG-JSON and JSON codecs, +## but a lot of JSON data is stored on UnixFS and is requested with or without various hints +## and we want to avoid surprises like https://github.com/protocol/bifrost-infra/issues/2290 +test_expect_success "GET UnixFS file with JSON bytes is returned with application/json Content-Type" ' + curl -sD headers "http://127.0.0.1:$GWAY_PORT/ipfs/$FILE_JSON_CID" > curl_output 2>&1 && + curl -sD headers_accept -H "Accept: application/json" "http://127.0.0.1:$GWAY_PORT/ipfs/$FILE_JSON_CID" > curl_output_accept 2>&1 && + ipfs cat $FILE_JSON_CID > ipfs_cat_output 2>&1 && + test_should_contain "Content-Type: application/json" headers && + test_should_contain "Content-Type: application/json" headers_accept && + test_cmp ipfs_cat_output curl_output && + test_cmp curl_output curl_output_accept +' -test_dag_pb_headers () { + +## Reading UnixFS (data encoded with dag-pb codec) as DAG-CBOR and DAG-JSON +## (returns representation defined in https://ipld.io/specs/codecs/dag-pb/spec/#logical-format) + +test_dag_pb_conversion () { name=$1 format=$2 disposition=$3 - test_expect_success "GET UnixFS as $name with format=dag-$format has expected Content-Type" ' - curl -sD - "http://127.0.0.1:$GWAY_PORT/ipfs/$FILE_CID?format=dag-$format" > curl_output 2>&1 && - test_should_contain "Content-Type: application/vnd.ipld.dag-$format" curl_output && - test_should_contain "Content-Disposition: ${disposition}\; filename=\"${FILE_CID}.${format}\"" curl_output && - test_should_not_contain "Content-Type: application/$format" curl_output + test_expect_success "GET UnixFS file as $name with format=dag-$format converts to the expected Content-Type" ' + curl -sD headers "http://127.0.0.1:$GWAY_PORT/ipfs/$FILE_CID?format=dag-$format" > curl_output 2>&1 && + ipfs dag get --output-codec dag-$format $FILE_CID > ipfs_dag_get_output 2>&1 && + test_cmp ipfs_dag_get_output curl_output && + test_should_contain "Content-Type: application/vnd.ipld.dag-$format" headers && + test_should_contain "Content-Disposition: ${disposition}\; filename=\"${FILE_CID}.${format}\"" headers && + test_should_not_contain "Content-Type: application/$format" headers ' - test_expect_success "GET UnixFS as $name with 'Accept: application/vnd.ipld.dag-$format' has expected Content-Type" ' + test_expect_success "GET UnixFS directory as $name with format=dag-$format converts to the expected Content-Type" ' + curl -sD headers "http://127.0.0.1:$GWAY_PORT/ipfs/$DIR_CID?format=dag-$format" > curl_output 2>&1 && + ipfs dag get --output-codec dag-$format $DIR_CID > ipfs_dag_get_output 2>&1 && + test_cmp ipfs_dag_get_output curl_output && + test_should_contain "Content-Type: application/vnd.ipld.dag-$format" headers && + test_should_contain "Content-Disposition: ${disposition}\; filename=\"${DIR_CID}.${format}\"" headers && + test_should_not_contain "Content-Type: application/$format" headers + ' + + test_expect_success "GET UnixFS as $name with 'Accept: application/vnd.ipld.dag-$format' converts to the expected Content-Type" ' curl -sD - -H "Accept: application/vnd.ipld.dag-$format" "http://127.0.0.1:$GWAY_PORT/ipfs/$FILE_CID" > curl_output 2>&1 && test_should_contain "Content-Disposition: ${disposition}\; filename=\"${FILE_CID}.${format}\"" curl_output && test_should_contain "Content-Type: application/vnd.ipld.dag-$format" curl_output && test_should_not_contain "Content-Type: application/$format" curl_output ' - test_expect_success "GET UnixFS as $name with format=$format has expected Content-Type" ' - curl -sD - "http://127.0.0.1:$GWAY_PORT/ipfs/$FILE_CID?format=$format" > curl_output 2>&1 && - test_should_contain "Content-Disposition: ${disposition}\; filename=\"${FILE_CID}.${format}\"" curl_output && - test_should_contain "Content-Type: application/$format" curl_output && - test_should_not_contain "Content-Type: application/vnd.ipld.dag-$format" curl_output + test_expect_success "GET UnixFS as $name with 'Accept: foo, application/vnd.ipld.dag-$format,bar' converts to the expected Content-Type" ' + curl -sD - -H "Accept: foo, application/vnd.ipld.dag-$format,text/plain" "http://127.0.0.1:$GWAY_PORT/ipfs/$FILE_CID" > curl_output 2>&1 && + test_should_contain "Content-Type: application/vnd.ipld.dag-$format" curl_output ' - test_expect_success "GET UnixFS as $name with 'Accept: application/$format' has expected Content-Type" ' - curl -sD - -H "Accept: application/$format" "http://127.0.0.1:$GWAY_PORT/ipfs/$FILE_CID" > curl_output 2>&1 && - test_should_contain "Content-Disposition: ${disposition}\; filename=\"${FILE_CID}.${format}\"" curl_output && - test_should_contain "Content-Type: application/$format" curl_output && - test_should_not_contain "Content-Type: application/vnd.ipld.dag-$format" curl_output + test_expect_success "GET UnixFS with format=$format (not dag-$format) is no-op (no conversion)" ' + curl -sD headers "http://127.0.0.1:$GWAY_PORT/ipfs/$FILE_CID?format=$format" > curl_output 2>&1 && + ipfs cat $FILE_CID > cat_output && + test_cmp cat_output curl_output && + test_should_contain "Content-Type: text/plain" headers && + test_should_not_contain "Content-Type: application/$format" headers && + test_should_not_contain "Content-Type: application/vnd.ipld.dag-$format" headers + ' + + test_expect_success "GET UnixFS with 'Accept: application/$format' (not dag-$format) is no-op (no conversion)" ' + curl -sD headers -H "Accept: application/$format" "http://127.0.0.1:$GWAY_PORT/ipfs/$FILE_CID" > curl_output 2>&1 && + ipfs cat $FILE_CID > cat_output && + test_cmp cat_output curl_output && + test_should_contain "Content-Type: text/plain" headers && + test_should_not_contain "Content-Type: application/$format" headers && + test_should_not_contain "Content-Type: application/vnd.ipld.dag-$format" headers ' } -test_dag_pb_headers "DAG-JSON" "json" "inline" -test_dag_pb_headers "DAG-CBOR" "cbor" "attachment" +test_dag_pb_conversion "DAG-JSON" "json" "inline" +test_dag_pb_conversion "DAG-CBOR" "cbor" "attachment" -test_dag_pb () { - name=$1 - format=$2 - test_expect_success "GET UnixFS as $name has expected output for file" ' - curl -s "http://127.0.0.1:$GWAY_PORT/ipfs/$FILE_CID?format=dag-$format" > curl_output 2>&1 && - ipfs dag get --output-codec dag-$format $FILE_CID > ipfs_dag_get_output 2>&1 && - test_cmp ipfs_dag_get_output curl_output - ' - - test_expect_success "GET UnixFS as $name has expected output for directory" ' - curl -s "http://127.0.0.1:$GWAY_PORT/ipfs/$DIR_CID?format=dag-$format" > curl_output 2>&1 && - ipfs dag get --output-codec dag-$format $DIR_CID > ipfs_dag_get_output 2>&1 && - test_cmp ipfs_dag_get_output curl_output - ' - - test_expect_success "GET UnixFS as $name with format=dag-$format and format=$format produce same output" ' - curl -s "http://127.0.0.1:$GWAY_PORT/ipfs/$DIR_CID?format=dag-$format" > curl_output_1 2>&1 && - curl -s "http://127.0.0.1:$GWAY_PORT/ipfs/$DIR_CID?format=$format" > curl_output_2 2>&1 && - test_cmp curl_output_1 curl_output_2 - ' -} - -test_dag_pb "DAG-JSON" "json" -test_dag_pb "DAG-CBOR" "cbor" - -## Content-Type response based on Accept header and ?format= parameter - -test_cmp_dag_get () { +# Requesting CID with plain json (0x0200) and cbor (0x51) codecs +# (note these are not UnixFS, not DAG-* variants, just raw block identified by a CID with a special codec) +test_plain_codec () { name=$1 format=$2 disposition=$3 - test_expect_success "GET $name without Accept or format= has expected Content-Type" ' - CID=$(echo "{ \"test\": \"json\" }" | ipfs dag put --input-codec json --store-codec $format) && - curl -sD - "http://127.0.0.1:$GWAY_PORT/ipfs/$CID" > curl_output 2>&1 && - test_should_contain "Content-Disposition: ${disposition}\; filename=\"${CID}.${format}\"" curl_output && - test_should_contain "Content-Type: application/$format" curl_output + # no explicit format, just codec in CID + test_expect_success "GET $name without Accept or format= has expected $format Content-Type and body as-is" ' + CID=$(echo "{ \"test\": \"plain json\" }" | ipfs dag put --input-codec json --store-codec $format) && + curl -sD headers "http://127.0.0.1:$GWAY_PORT/ipfs/$CID" > curl_output 2>&1 && + ipfs block get $CID > ipfs_block_output 2>&1 && + test_cmp ipfs_block_output curl_output && + test_should_contain "Content-Disposition: ${disposition}\; filename=\"${CID}.${format}\"" headers && + test_should_contain "Content-Type: application/$format" headers ' - test_expect_success "GET $name without Accept or format= produces correct output" ' - CID=$(echo "{ \"test\": \"json\" }" | ipfs dag put --input-codec json --store-codec $format) && - curl -s "http://127.0.0.1:$GWAY_PORT/ipfs/$CID" > curl_output 2>&1 && - ipfs dag get --output-codec $format $CID > ipfs_dag_get_output 2>&1 && - test_cmp ipfs_dag_get_output curl_output + # explicit format still gives correct output, just codec in CID + test_expect_success "GET $name with ?format= has expected $format Content-Type and body as-is" ' + CID=$(echo "{ \"test\": \"plain json\" }" | ipfs dag put --input-codec json --store-codec $format) && + curl -sD headers "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=$format" > curl_output 2>&1 && + ipfs block get $CID > ipfs_block_output 2>&1 && + test_cmp ipfs_block_output curl_output && + test_should_contain "Content-Disposition: ${disposition}\; filename=\"${CID}.${format}\"" headers && + test_should_contain "Content-Type: application/$format" headers ' - test_expect_success "GET $name with format=$format produces expected Content-Type" ' - CID=$(echo "{ \"test\": \"json\" }" | ipfs dag put --input-codec json --store-codec $format) && - curl -sD- "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=$format" > curl_output 2>&1 && - test_should_contain "Content-Disposition: ${disposition}\; filename=\"${CID}.${format}\"" curl_output && - test_should_contain "Content-Type: application/$format" curl_output + # explicit format still gives correct output, just codec in CID + test_expect_success "GET $name with Accept has expected $format Content-Type and body as-is" ' + CID=$(echo "{ \"test\": \"plain json\" }" | ipfs dag put --input-codec json --store-codec $format) && + curl -sD headers -H "Accept: application/$format" "http://127.0.0.1:$GWAY_PORT/ipfs/$CID" > curl_output 2>&1 && + ipfs block get $CID > ipfs_block_output 2>&1 && + test_cmp ipfs_block_output curl_output && + test_should_contain "Content-Disposition: ${disposition}\; filename=\"${CID}.${format}\"" headers && + test_should_contain "Content-Type: application/$format" headers ' - test_expect_success "GET $name with format=$format produces correct output" ' - CID=$(echo "{ \"test\": \"json\" }" | ipfs dag put --input-codec json --store-codec $format) && - curl -s "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=$format" > curl_output 2>&1 && - ipfs dag get --output-codec $format $CID > ipfs_dag_get_output 2>&1 && - test_cmp ipfs_dag_get_output curl_output - ' - - test_expect_success "GET $name with format=dag-$format produces expected Content-Type" ' - CID=$(echo "{ \"test\": \"json\" }" | ipfs dag put --input-codec json --store-codec $format) && - curl -sD- "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=dag-$format" > curl_output 2>&1 && - test_should_contain "Content-Disposition: ${disposition}\; filename=\"${CID}.${format}\"" curl_output && - test_should_contain "Content-Type: application/vnd.ipld.dag-$format" curl_output - ' - - test_expect_success "GET $name with format=dag-$format produces correct output" ' - CID=$(echo "{ \"test\": \"json\" }" | ipfs dag put --input-codec json --store-codec $format) && - curl -s "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=dag-$format" > curl_output 2>&1 && + # explicit dag-* format passed, attempt to parse as dag* variant + ## Note: this works only for simple JSON that can be upgraded to DAG-JSON. + test_expect_success "GET $name with format=dag-$format interprets $format as dag-* variant and produces expected Content-Type and body" ' + CID=$(echo "{ \"test\": \"plain-json-that-can-also-be-dag-json\" }" | ipfs dag put --input-codec json --store-codec $format) && + curl -sD headers "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=dag-$format" > curl_output_param 2>&1 && ipfs dag get --output-codec dag-$format $CID > ipfs_dag_get_output 2>&1 && - test_cmp ipfs_dag_get_output curl_output + test_cmp ipfs_dag_get_output curl_output_param && + test_should_contain "Content-Disposition: ${disposition}\; filename=\"${CID}.${format}\"" headers && + test_should_contain "Content-Type: application/vnd.ipld.dag-$format" headers && + curl -s -H "Accept: application/vnd.ipld.dag-$format" "http://127.0.0.1:$GWAY_PORT/ipfs/$CID" > curl_output_accept 2>&1 && + test_cmp curl_output_param curl_output_accept ' + } -test_cmp_dag_get "JSON" "json" "inline" -test_cmp_dag_get "CBOR" "cbor" "attachment" +test_plain_codec "plain JSON codec" "json" "inline" +test_plain_codec "plain CBOR codec" "cbor" "attachment" - -## Lossless conversion between JSON and CBOR - -test_expect_success "GET JSON as CBOR produces DAG-CBOR output" ' - CID=$(echo "{ \"test\": \"json\" }" | ipfs dag put --input-codec json --store-codec json) && - curl -s "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=cbor" > curl_output 2>&1 && - ipfs dag get --output-codec dag-cbor $CID > ipfs_dag_get_output 2>&1 && - test_cmp ipfs_dag_get_output curl_output -' - -test_expect_success "GET CBOR as JSON produces DAG-JSON output" ' - CID=$(echo "{ \"test\": \"json\" }" | ipfs dag put --input-codec json --store-codec cbor) && - curl -s "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=json" > curl_output 2>&1 && - ipfs dag get --output-codec dag-json $CID > ipfs_dag_get_output 2>&1 && - test_cmp ipfs_dag_get_output curl_output -' - - -## Pathing, traversal +## Pathing, traversal over DAG-JSON and DAG-CBOR DAG_CBOR_TRAVERSAL_CID="bafyreibs4utpgbn7uqegmd2goqz4bkyflre2ek2iwv743fhvylwi4zeeim" DAG_JSON_TRAVERSAL_CID="baguqeeram5ujjqrwheyaty3w5gdsmoz6vittchvhk723jjqxk7hakxkd47xq" @@ -199,17 +196,9 @@ test_expect_success "GET DAG-CBOR traverses multiple links" ' test_cmp expected actual ' -# test_expect_success "GET DAG-PB has expected output" ' -# curl -s "http://127.0.0.1:$GWAY_PORT/ipfs/$DAG_PB_CID?format=dag-json" > curl_output 2>&1 && -# jq --sort-keys . curl_output > actual && -# test_cmp ../t0123-gateway-json-cbor/dag-pb.json actual -# ' - - -## NATIVE TESTS: +## NATIVE TESTS for DAG-JSON (0x0129) and DAG-CBOR (0x71): ## DAG- regression tests for core behaviors when native DAG-(CBOR|JSON) is requested - test_native_dag () { name=$1 format=$2 @@ -232,10 +221,10 @@ test_native_dag () { test_cmp expected curl_ipfs_dag_param_output ' - test_expect_success "GET $name from /ipfs with format=$format returns the same payload as format=dag-$format" ' + test_expect_success "GET $name from /ipfs for application/$format returns the same payload as format=dag-$format" ' curl -sX GET "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=dag-$format" -o expected && - curl -sX GET "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=dag-$format" -o curl_ipfs_dag_param_output && - test_cmp expected curl_ipfs_dag_param_output + curl -sX GET "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=$format" -o plain_output && + test_cmp expected plain_output ' test_expect_success "GET $name from /ipfs with application/vnd.ipld.dag-$format returns the same payload as the raw block" ' @@ -244,6 +233,23 @@ test_native_dag () { test_cmp expected_block curl_ipfs_dag_block_accept_output ' + # Make sure DAG-* can be requested as plain JSON or CBOR and response has plain Content-Type for interop purposes + + test_expect_success "GET $name with format=$format returns same payload as format=dag-$format but with plain Content-Type" ' + curl -s "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=dag-$format" -o expected && + curl -sD plain_headers "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=$format" -o plain_output && + test_should_contain "Content-Type: application/$format" plain_headers && + test_cmp expected plain_output + ' + + test_expect_success "GET $name with Accept: application/$format returns same payload as application/vnd.ipld.dag-$format but with plain Content-Type" ' + curl -s -H "Accept: application/vnd.ipld.dag-$format" "http://127.0.0.1:$GWAY_PORT/ipfs/$CID" > expected && + curl -sD plain_headers -H "Accept: application/$format" "http://127.0.0.1:$GWAY_PORT/ipfs/$CID" > plain_output && + test_should_contain "Content-Type: application/$format" plain_headers && + test_cmp expected plain_output + ' + + # Make sure expected HTTP headers are returned with the dag- block test_expect_success "GET response for application/vnd.ipld.dag-$format has expected Content-Type" ' @@ -297,18 +303,11 @@ test_native_dag () { test_should_contain "Content-Type: application/vnd.ipld.dag-$format" output && test_should_contain "Content-Length: " output ' - test_expect_success "HEAD $name with an explicit JSON format returns HTTP 200" ' - curl -I "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=json" -o output && + test_expect_success "HEAD $name with an explicit DAG-JSON format returns HTTP 200" ' + curl -I "http://127.0.0.1:$GWAY_PORT/ipfs/$CID?format=dag-json" -o output && test_should_contain "HTTP/1.1 200 OK" output && - test_should_contain "Etag: \"$CID.json\"" output && - test_should_contain "Content-Type: application/json" output && - test_should_contain "Content-Length: " output - ' - test_expect_success "HEAD dag-pb with ?format=$format returns HTTP 200" ' - curl -I "http://127.0.0.1:$GWAY_PORT/ipfs/$FILE_CID?format=$format" -o output && - test_should_contain "HTTP/1.1 200 OK" output && - test_should_contain "Etag: \"$FILE_CID.$format\"" output && - test_should_contain "Content-Type: application/$format" output && + test_should_contain "Etag: \"$CID.dag-json\"" output && + test_should_contain "Content-Type: application/vnd.ipld.dag-json" output && test_should_contain "Content-Length: " output ' test_expect_success "HEAD $name with only-if-cached for missing block returns HTTP 412 Precondition Failed" ' diff --git a/test/sharness/t0124-gateway-ipns-record.sh b/test/sharness/t0124-gateway-ipns-record.sh new file mode 100755 index 000000000..cff00aa84 --- /dev/null +++ b/test/sharness/t0124-gateway-ipns-record.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +test_description="Test HTTP Gateway IPNS Record (application/vnd.ipfs.ipns-record) Support" + +. lib/test-lib.sh + +test_init_ipfs +test_launch_ipfs_daemon + +test_expect_success "Create and Publish IPNS Key" ' + FILE_CID=$(echo "Hello IPFS" | ipfs add --cid-version 1 -q) && + IPNS_KEY=$(ipfs key gen ipns-record) && + ipfs name publish /ipfs/$FILE_CID --key=ipns-record --ttl=30m && + curl "http://127.0.0.1:$GWAY_PORT/ipns/$IPNS_KEY" > curl_output_filename && + test_should_contain "Hello IPFS" curl_output_filename +' + +test_expect_success "GET KEY with format=ipns-record and validate key" ' + curl "http://127.0.0.1:$GWAY_PORT/ipns/$IPNS_KEY?format=ipns-record" > curl_output_filename && + ipfs name inspect --verify $IPNS_KEY < curl_output_filename > verify_output && + test_should_contain "$FILE_CID" verify_output +' + +test_expect_success "GET KEY with 'Accept: application/vnd.ipfs.ipns-record' and validate key" ' + curl -H "Accept: application/vnd.ipfs.ipns-record" "http://127.0.0.1:$GWAY_PORT/ipns/$IPNS_KEY" > curl_output_filename && + ipfs name inspect --verify $IPNS_KEY < curl_output_filename > verify_output && + test_should_contain "$FILE_CID" verify_output +' + +test_expect_success "GET KEY with format=ipns-record has expected HTTP headers" ' + curl -sD - "http://127.0.0.1:$GWAY_PORT/ipns/$IPNS_KEY?format=ipns-record" > curl_output_filename 2>&1 && + test_should_contain "Content-Disposition: attachment;" curl_output_filename && + test_should_contain "Content-Type: application/vnd.ipfs.ipns-record" curl_output_filename && + test_should_contain "Cache-Control: public, max-age=1800" curl_output_filename +' + +test_expect_success "GET KEY with 'Accept: application/vnd.ipfs.ipns-record' has expected HTTP headers" ' + curl -H "Accept: application/vnd.ipfs.ipns-record" -sD - "http://127.0.0.1:$GWAY_PORT/ipns/$IPNS_KEY" > curl_output_filename 2>&1 && + test_should_contain "Content-Disposition: attachment;" curl_output_filename && + test_should_contain "Content-Type: application/vnd.ipfs.ipns-record" curl_output_filename && + test_should_contain "Cache-Control: public, max-age=1800" curl_output_filename +' + +test_expect_success "GET KEY with expliciy ?filename= succeeds with modified Content-Disposition header" ' + curl -sD - "http://127.0.0.1:$GWAY_PORT/ipns/$IPNS_KEY?format=ipns-record&filename=testтест.ipns-record" > curl_output_filename 2>&1 && + grep -F "Content-Disposition: attachment; filename=\"test____.ipns-record\"; filename*=UTF-8'\'\''test%D1%82%D0%B5%D1%81%D1%82.ipns-record" curl_output_filename && + test_should_contain "Content-Type: application/vnd.ipfs.ipns-record" curl_output_filename +' + +test_kill_ipfs_daemon + +test_done diff --git a/test/sharness/t0125-twonode.sh b/test/sharness/t0125-twonode.sh index 6f819400a..8ea1c9e5d 100755 --- a/test/sharness/t0125-twonode.sh +++ b/test/sharness/t0125-twonode.sh @@ -52,7 +52,7 @@ run_random_dir_test() { check_dir_fetch 1 $DIR_HASH } -run_advanced_test() { +flaky_advanced_test() { startup_cluster 2 "$@" test_expect_success "clean repo before test" ' @@ -64,48 +64,78 @@ run_advanced_test() { run_random_dir_test - test_expect_success "node0 data transferred looks correct" ' - ipfsi 0 bitswap stat > stat0 && - grep "blocks sent: 126" stat0 > /dev/null && - grep "blocks received: 5" stat0 > /dev/null && - grep "data sent: 228113" stat0 > /dev/null && - grep "data received: 1000256" stat0 > /dev/null - ' - - test_expect_success "node1 data transferred looks correct" ' - ipfsi 1 bitswap stat > stat1 && - grep "blocks received: 126" stat1 > /dev/null && - grep "blocks sent: 5" stat1 > /dev/null && - grep "data received: 228113" stat1 > /dev/null && - grep "data sent: 1000256" stat1 > /dev/null + test_expect_success "gather bitswap stats" ' + ipfsi 0 bitswap stat -v > stat0 && + ipfsi 1 bitswap stat -v > stat1 ' test_expect_success "shut down nodes" ' iptb stop && iptb_wait_stop ' + + # NOTE: data transferred stats checks are flaky + # trying to debug them by printing out the stats hides the flakiness + # my theory is that the extra time cat calls take to print out the stats + # allow for proper cleanup to happen + go-sleep 1s +} + +run_advanced_test() { + # TODO: investigate why flaky_advanced_test is flaky + # Context: https://github.com/ipfs/kubo/pull/9486 + # sometimes, bitswap status returns unexpected block transfers + # and everyone has been re-running circleci until is passes for at least a year. + # this re-runs test until it passes or a timeout hits + + BLOCKS_0=126 + BLOCKS_1=5 + DATA_0=228113 + DATA_1=1000256 + for i in $(test_seq 1 600); do + flaky_advanced_test + (grep -q "$DATA_0" stat0 && grep -q "$DATA_1" stat1) && break + go-sleep 100ms + done + + test_expect_success "node0 data transferred looks correct" ' + test_should_contain "blocks sent: $BLOCKS_0" stat0 && + test_should_contain "blocks received: $BLOCKS_1" stat0 && + test_should_contain "data sent: $DATA_0" stat0 && + test_should_contain "data received: $DATA_1" stat0 + ' + + test_expect_success "node1 data transferred looks correct" ' + test_should_contain "blocks received: $BLOCKS_0" stat1 && + test_should_contain "blocks sent: $BLOCKS_1" stat1 && + test_should_contain "data received: $DATA_0" stat1 && + test_should_contain "data sent: $DATA_1" stat1 + ' + } test_expect_success "set up tcp testbed" ' iptb testbed create -type localipfs -count 2 -force -init ' -addrs='"[\"/ip4/127.0.0.1/tcp/0\", \"/ip4/127.0.0.1/udp/0/quic\"]"' -test_expect_success "configure addresses" ' - ipfsi 0 config --json Addresses.Swarm '"${addrs}"' && - ipfsi 1 config --json Addresses.Swarm '"${addrs}"' +test_expect_success "disable routing, use direct peering" ' + iptb run -- ipfs config Routing.Type none && + iptb run -- ipfs config --json Bootstrap "[]" ' # Test TCP transport echo "Testing TCP" +addrs='"[\"/ip4/127.0.0.1/tcp/0\"]"' test_expect_success "use TCP only" ' + iptb run -- ipfs config --json Addresses.Swarm '"${addrs}"' && iptb run -- ipfs config --json Swarm.Transports.Network.QUIC false && iptb run -- ipfs config --json Swarm.Transports.Network.Relay false && + iptb run -- ipfs config --json Swarm.Transports.Network.WebTransport false && iptb run -- ipfs config --json Swarm.Transports.Network.Websocket false ' run_advanced_test # test multiplex muxer -echo "Running advanced tests with mplex" +echo "Running TCP tests with mplex" test_expect_success "disable yamux" ' iptb run -- ipfs config --json Swarm.Transports.Multiplexers.Yamux false ' @@ -114,23 +144,35 @@ run_advanced_test test_expect_success "re-enable yamux" ' iptb run -- ipfs config --json Swarm.Transports.Multiplexers.Yamux null ' - # test Noise - -echo "Running advanced tests with NOISE" +echo "Running TCP tests with NOISE" test_expect_success "use noise only" ' iptb run -- ipfs config --json Swarm.Transports.Security.TLS false ' - run_advanced_test +test_expect_success "re-enable TLS" ' + iptb run -- ipfs config --json Swarm.Transports.Security.TLS null +' + # test QUIC echo "Running advanced tests over QUIC" +addrs='"[\"/ip4/127.0.0.1/udp/0/quic-v1\"]"' test_expect_success "use QUIC only" ' + iptb run -- ipfs config --json Addresses.Swarm '"${addrs}"' && iptb run -- ipfs config --json Swarm.Transports.Network.QUIC true && iptb run -- ipfs config --json Swarm.Transports.Network.TCP false ' +run_advanced_test +# test WebTransport +echo "Running advanced tests over WebTransport" +addrs='"[\"/ip4/127.0.0.1/udp/0/quic-v1/webtransport\"]"' +test_expect_success "use WebTransport only" ' + iptb run -- ipfs config --json Addresses.Swarm '"${addrs}"' && + iptb run -- ipfs config --json Swarm.Transports.Network.QUIC true && + iptb run -- ipfs config --json Swarm.Transports.Network.WebTransport true +' run_advanced_test test_done diff --git a/test/sharness/t0139-swarm-rcmgr.sh b/test/sharness/t0139-swarm-rcmgr.sh index c36ddd3d8..1b870abb7 100755 --- a/test/sharness/t0139-swarm-rcmgr.sh +++ b/test/sharness/t0139-swarm-rcmgr.sh @@ -40,9 +40,35 @@ test_expect_success 'disconnected: swarm stats requires running daemon' ' test_should_contain "missing ResourceMgr" actual ' +# test sanity scaling +test_expect_success 'set very high connmgr highwater' ' + ipfs config --json Swarm.ConnMgr.HighWater 1000 +' + +test_launch_ipfs_daemon + +test_expect_success 'conns and streams are above 2000' ' + ipfs swarm limit system --enc=json | tee json && + [ "$(jq -r .ConnsInbound < json)" -ge 2000 ] && + [ "$(jq -r .StreamsInbound < json)" -ge 2000 ] +' + +test_kill_ipfs_daemon + +test_expect_success 'set previous connmgr highwater' ' + ipfs config --json Swarm.ConnMgr.HighWater 96 +' + +test_launch_ipfs_daemon + +test_expect_success 'conns and streams are above 800' ' + ipfs swarm limit system --enc=json | tee json && + [ "$(jq -r .ConnsInbound < json)" -ge 800 ] && + [ "$(jq -r .StreamsInbound < json)" -ge 800 ] +' + # swarm limit|stats should succeed in online mode by default # because Resource Manager is opt-out -test_launch_ipfs_daemon # every scope has the same fields, so we only inspect System test_expect_success 'ResourceMgr enabled: swarm limit' ' @@ -227,4 +253,32 @@ test_expect_success 'stop iptb' ' iptb stop 2 ' +## Test daemon refuse to start if connmgr.highwater < ressources inbound + +test_expect_success "node refuse to start if Swarm.ResourceMgr.Limits.System.Conns <= Swarm.ConnMgr.HighWater" ' + ipfs config --json Swarm.ResourceMgr.Limits.System.Conns 128 && + ipfs config --json Swarm.ConnMgr.HighWater 128 && + ipfs config --json Swarm.ConnMgr.LowWater 64 && + test_expect_code 1 ipfs daemon && + ipfs config --json Swarm.ResourceMgr.Limits.System.Conns 256 +' + +test_expect_success "node refuse to start if Swarm.ResourceMgr.Limits.System.ConnsInbound <= Swarm.ConnMgr.HighWater" ' + ipfs config --json Swarm.ResourceMgr.Limits.System.ConnsInbound 128 && + test_expect_code 1 ipfs daemon && + ipfs config --json Swarm.ResourceMgr.Limits.System.ConnsInbound 256 +' + +test_expect_success "node refuse to start if Swarm.ResourceMgr.Limits.System.Streams <= Swarm.ConnMgr.HighWater" ' + ipfs config --json Swarm.ResourceMgr.Limits.System.Streams 128 && + test_expect_code 1 ipfs daemon && + ipfs config --json Swarm.ResourceMgr.Limits.System.Streams 256 +' + +test_expect_success "node refuse to start if Swarm.ResourceMgr.Limits.System.StreamsInbound <= Swarm.ConnMgr.HighWater" ' + ipfs config --json Swarm.ResourceMgr.Limits.System.StreamsInbound 128 && + test_expect_code 1 ipfs daemon && + ipfs config --json Swarm.ResourceMgr.Limits.System.StreamsInbound 256 +' + test_done diff --git a/test/sharness/t0160-resolve.sh b/test/sharness/t0160-resolve.sh index ca11947b0..f65b29c11 100755 --- a/test/sharness/t0160-resolve.sh +++ b/test/sharness/t0160-resolve.sh @@ -35,15 +35,6 @@ test_resolve_setup_name() { ' } -test_resolve_setup_name_fail() { - local key="$1" - local ref="$2" - - test_expect_failure "resolve: prepare $key" ' - ipfs name publish --key="$key" --allow-offline "$ref" - ' -} - test_resolve() { src=$1 dst=$2 @@ -129,23 +120,7 @@ test_resolve_cmd_b32() { ' } - -#todo remove this once the online resolve is fixed -test_resolve_fail() { - src=$1 - dst=$2 - - test_expect_failure "resolve succeeds: $src" ' - ipfs resolve "$src" >actual - ' - - test_expect_failure "resolved correctly: $src -> $dst" ' - printf "$dst" >expected && - test_cmp expected actual - ' -} - -test_resolve_cmd_fail() { +test_resolve_cmd_success() { test_resolve "/ipfs/$a_hash" "/ipfs/$a_hash" test_resolve "/ipfs/$a_hash/b" "/ipfs/$b_hash" test_resolve "/ipfs/$a_hash/b/c" "/ipfs/$c_hash" @@ -155,23 +130,16 @@ test_resolve_cmd_fail() { test_resolve "/ipld/$dag_hash/i/j" "/ipld/$dag_hash/i/j" test_resolve "/ipld/$dag_hash/i" "/ipld/$dag_hash/i" - # At the moment, publishing _fails_ because we fail to put to the DHT. - # However, resolving succeeds because we resolve the record we put to our own - # node. - # - # We should find a nice way to truly support offline publishing. But this - # behavior isn't terrible. - - test_resolve_setup_name_fail "self" "/ipfs/$a_hash" + test_resolve_setup_name "self" "/ipfs/$a_hash" test_resolve "/ipns/$self_hash" "/ipfs/$a_hash" test_resolve "/ipns/$self_hash/b" "/ipfs/$b_hash" test_resolve "/ipns/$self_hash/b/c" "/ipfs/$c_hash" - test_resolve_setup_name_fail "self" "/ipfs/$b_hash" + test_resolve_setup_name "self" "/ipfs/$b_hash" test_resolve "/ipns/$self_hash" "/ipfs/$b_hash" test_resolve "/ipns/$self_hash/c" "/ipfs/$c_hash" - test_resolve_setup_name_fail "self" "/ipfs/$c_hash" + test_resolve_setup_name "self" "/ipfs/$c_hash" test_resolve "/ipns/$self_hash" "/ipfs/$c_hash" } @@ -181,7 +149,7 @@ test_resolve_cmd_b32 # should work online test_launch_ipfs_daemon -test_resolve_cmd_fail +test_resolve_cmd_success test_kill_ipfs_daemon test_done diff --git a/test/sharness/t0170-legacy-dht.sh b/test/sharness/t0170-legacy-dht.sh index c18735b5b..fc11b9044 100755 --- a/test/sharness/t0170-legacy-dht.sh +++ b/test/sharness/t0170-legacy-dht.sh @@ -13,6 +13,10 @@ test_dht() { iptb testbed create -type localipfs -count $NUM_NODES -init ' + test_expect_success 'DHT-only routing' ' + iptb run -- ipfs config Routing.Type dht + ' + startup_cluster $NUM_NODES $@ test_expect_success 'peer ids' ' @@ -107,7 +111,7 @@ test_dht() { test_must_fail ipfsi 0 dht put "/ipns/$PEERID_2" "get_result" 2>err_put && test_should_contain "this command must be run in online mode" err_findprovs && test_should_contain "this command must be run in online mode" err_findpeer && - test_should_contain "this command must be run in online mode" err_put + test_should_contain "this action must be run in online mode" err_put ' } diff --git a/test/sharness/t0170-routing-dht.sh b/test/sharness/t0170-routing-dht.sh index 2eef692a8..85462dcc2 100755 --- a/test/sharness/t0170-routing-dht.sh +++ b/test/sharness/t0170-routing-dht.sh @@ -2,7 +2,7 @@ # This file does the same tests as t0170-dht.sh but uses 'routing' commands instead # (only exception is query, which lives only under dht) -test_description="Test routing command" +test_description="Test routing command for DHT queries" . lib/test-lib.sh @@ -14,6 +14,10 @@ test_dht() { iptb testbed create -type localipfs -count $NUM_NODES -init ' + test_expect_success 'DHT-only routing' ' + iptb run -- ipfs config Routing.Type dht + ' + startup_cluster $NUM_NODES $@ test_expect_success 'peer ids' ' @@ -108,7 +112,7 @@ test_dht() { test_must_fail ipfsi 0 routing put "/ipns/$PEERID_2" "get_result" 2>err_put && test_should_contain "this command must be run in online mode" err_findprovs && test_should_contain "this command must be run in online mode" err_findpeer && - test_should_contain "this command must be run in online mode" err_put + test_should_contain "this action must be run in online mode" err_put ' } diff --git a/test/sharness/t0172-content-routing-over-http.sh b/test/sharness/t0172-content-routing-over-http.sh new file mode 100755 index 000000000..2dac04e7d --- /dev/null +++ b/test/sharness/t0172-content-routing-over-http.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +test_description="Test content routing over HTTP" + +. lib/test-lib.sh + + +if ! test_have_prereq SOCAT; then + skip_all="skipping '$test_description': socat is not available" + test_done +fi + +test_init_ipfs + +# Run listener on a free port to log HTTP requests sent by Kubo in Routing.Type=auto mode +export ROUTER_PORT=$(comm -23 <(seq 49152 65535 | sort) <(ss -Htan | awk '{print $4}' | cut -d':' -f2) | head -n 1) +export IPFS_HTTP_ROUTERS="http://127.0.0.1:$ROUTER_PORT" + +test_launch_ipfs_daemon + +test_expect_success "start HTTP router proxy" ' + touch http_requests + socat -u TCP-LISTEN:$ROUTER_PORT,reuseaddr,fork,bind=127.0.0.1,retry=10 CREATE:http_requests & + NCPID=$! +' + +## HTTP GETs + +test_expect_success 'create unique CID without adding it to the local datastore' ' + WANT_CID=$(date +"%FT%T.%N%z" | ipfs add -qn) +' + +test_expect_success 'expect HTTP lookup when CID is not in the local datastore' ' + ipfs block stat "$WANT_CID" & + test_wait_output_n_lines http_requests 4 && + test_should_contain "GET /routing/v1/providers/$WANT_CID" http_requests +' + +test_expect_success 'expect HTTP request User-Agent to match Kubo version' ' + test_should_contain "User-Agent: $(ipfs id -f "")" http_requests +' + +## HTTP PUTs + +test_expect_success 'add new CID to the local datastore' ' + ADD_CID=$(date +"%FT%T.%N%z" | ipfs add -q) +' + +# cid.contact supports GET-only: https://github.com/ipfs/kubo/issues/9504 +# which means no announcements over HTTP should be made. +test_expect_success 'expect no HTTP requests to be sent with locally added CID' ' + test_should_not_contain "$ADD_CID" http_requests +' + +test_expect_success "stop nc" ' + kill "$NCPID" && wait "$NCPID" || true + rm -f http_requests || true +' + +test_kill_ipfs_daemon +test_done diff --git a/test/sharness/t0175-provider.sh b/test/sharness/t0175-provider.sh index 364df60e9..cca110fe1 100755 --- a/test/sharness/t0175-provider.sh +++ b/test/sharness/t0175-provider.sh @@ -22,7 +22,7 @@ test_expect_success 'use strategic providing' ' startup_cluster ${NUM_NODES} test_expect_success 'add test object' ' - HASH_0=$(echo "foo" | ipfsi 0 add -q) + HASH_0=$(date +"%FT%T.%N%z" | ipfsi 0 add -q) ' findprovs_expect '$HASH_0' '$PEERID_0' diff --git a/test/sharness/t0175-reprovider.sh b/test/sharness/t0175-reprovider.sh index 746aa6b0a..09535ecc4 100755 --- a/test/sharness/t0175-reprovider.sh +++ b/test/sharness/t0175-reprovider.sh @@ -34,7 +34,7 @@ reprovide() { init_strategy 'all' test_expect_success 'add test object' ' - HASH_0=$(echo "foo" | ipfsi 0 add -q --local) + HASH_0=$(date +"%FT%T.%N%z" | ipfsi 0 add -q --local) ' findprovs_empty '$HASH_0' @@ -49,8 +49,8 @@ test_expect_success 'Stop iptb' ' init_strategy 'pinned' test_expect_success 'prepare test files' ' - echo foo > f1 && - echo bar > f2 + date +"%FT%T.%N%z" > f1 && + date +"%FT%T.%N%z" > f2 ' test_expect_success 'add test objects' ' @@ -77,9 +77,9 @@ test_expect_success 'Stop iptb' ' init_strategy 'roots' test_expect_success 'prepare test files' ' - echo foo > f1 && - echo bar > f2 && - echo baz > f3 + date +"%FT%T.%N%z" > f1 && + date +"%FT%T.%N%z" > f2 && + date +"%FT%T.%N%z" > f3 ' test_expect_success 'add test objects' ' @@ -121,7 +121,7 @@ test_expect_success 'Disable reprovider ticking' ' startup_cluster ${NUM_NODES} test_expect_success 'add test object' ' - HASH_0=$(echo "foo" | ipfsi 0 add -q --offline) + HASH_0=$(date +"%FT%T.%N%z" | ipfsi 0 add -q --offline) ' findprovs_empty '$HASH_0' diff --git a/test/sharness/t0175-strategic-provider.sh b/test/sharness/t0175-strategic-provider.sh index 7bad38838..fafd6e538 100755 --- a/test/sharness/t0175-strategic-provider.sh +++ b/test/sharness/t0175-strategic-provider.sh @@ -22,7 +22,7 @@ test_expect_success 'use strategic providing' ' startup_cluster ${NUM_NODES} test_expect_success 'add test object' ' - HASH_0=$(echo "foo" | ipfsi 0 add -q) + HASH_0=$(date +"%FT%T.%N%z" | ipfsi 0 add -q) ' findprovs_empty '$HASH_0' diff --git a/test/sharness/t0191-webtransport-ping.sh b/test/sharness/t0191-webtransport-ping.sh index 82ef185e3..4b5d20ed0 100755 --- a/test/sharness/t0191-webtransport-ping.sh +++ b/test/sharness/t0191-webtransport-ping.sh @@ -11,8 +11,8 @@ test_expect_success 'init iptb' ' iptb testbed create -type localipfs -count 2 -init ' -addr1='"[\"/ip4/127.0.0.1/udp/0/quic/webtransport\"]"' -addr2='"[\"/ip4/127.0.0.1/udp/0/quic/webtransport\"]"' +addr1='"[\"/ip4/127.0.0.1/udp/0/quic-v1/webtransport\"]"' +addr2='"[\"/ip4/127.0.0.1/udp/0/quic-v1/webtransport\"]"' test_expect_success "add WebTransport swarm addresses" ' ipfsi 0 config --json Addresses.Swarm '$addr1' && ipfsi 0 config --json Swarm.Transports.Network.WebTransport true && diff --git a/test/sharness/t0195-noise.sh b/test/sharness/t0195-noise.sh index c68073d14..63e3703de 100755 --- a/test/sharness/t0195-noise.sh +++ b/test/sharness/t0195-noise.sh @@ -8,7 +8,7 @@ test_init_ipfs # start iptb + wait for peering test_expect_success 'init iptb' ' - iptb testbed create -type localipfs -count 3 -init + iptb testbed create -type localipfs -count 4 -init ' tcp_addr='"[\"/ip4/127.0.0.1/tcp/0\"]"' @@ -32,8 +32,11 @@ test_expect_success "test ping other" ' ipfsi 1 ping -n2 -- "$PEERID_0" ' +# bootstrap a working dht so 2 can find 0 but can't dial it test_expect_success "test tls incompatible" ' + iptb start --wait 3 && iptb start --wait 2 && + iptb connect [0-2] 3 && test_must_fail iptb connect 2 0 > connect_error 2>&1 && test_should_contain "failed to negotiate security protocol" connect_error || test_fsh cat connect_error diff --git a/test/sharness/t0240-republisher.sh b/test/sharness/t0240-republisher.sh index e498007a8..e52b8bee5 100755 --- a/test/sharness/t0240-republisher.sh +++ b/test/sharness/t0240-republisher.sh @@ -74,7 +74,7 @@ num_test_nodes=4 setup_iptb "$num_test_nodes" test_expect_success "publish succeeds" ' - HASH=$(echo "foobar" | ipfsi 1 add -q) && + HASH=$(date +"%FT%T.%N%z" | ipfsi 1 add -q) && ipfsi 1 name publish -t 10s $HASH ' @@ -99,7 +99,7 @@ KEY2=`ipfsi 1 key gen beepboop --type ed25519` ' test_expect_success "publish with new key succeeds" ' - HASH=$(echo "barfoo" | ipfsi 1 add -q) && + HASH=$(date +"%FT%T.%N%z" | ipfsi 1 add -q) && ipfsi 1 name publish -t 10s -k "$KEY2" $HASH ' diff --git a/test/sharness/t0300-docker-image.sh b/test/sharness/t0300-docker-image.sh index a3a802b28..3c390a453 100755 --- a/test/sharness/t0300-docker-image.sh +++ b/test/sharness/t0300-docker-image.sh @@ -79,9 +79,9 @@ test_expect_success "check that init script configs were applied" ' ' test_expect_success "simple ipfs add/cat can be run in docker container" ' - expected="Hello Worlds" && - HASH=$(docker_exec "$DOC_ID" "echo $(cat expected) | ipfs add | cut -d' ' -f2") && - docker_exec "$DOC_ID" "ipfs cat $HASH" >actual && + echo "Hello Worlds" | tr -d "[:cntrl:]" > expected && + HASH=$(docker_exec "$DOC_ID" "echo $(cat expected) | ipfs add -q" | tr -d "[:cntrl:]") && + docker_exec "$DOC_ID" "ipfs cat $HASH" | tr -d "[:cntrl:]" > actual && test_cmp expected actual ' @@ -102,4 +102,3 @@ test_expect_success "stop docker container" ' docker_rm "$DOC_ID" docker_rmi "$IMAGE_ID" test_done - diff --git a/test/sharness/t0600-issues-and-regressions-online.sh b/test/sharness/t0600-issues-and-regressions-online.sh index 315a9d117..3468f23d6 100755 --- a/test/sharness/t0600-issues-and-regressions-online.sh +++ b/test/sharness/t0600-issues-and-regressions-online.sh @@ -34,15 +34,15 @@ test_expect_success "metrics work" ' ' test_expect_success "pin add api looks right - #3753" ' - HASH=$(echo "foo" | ipfs add -q) && + HASH=$(date +"%FT%T.%N%z" | ipfs add -q) && curl -X POST "http://$API_ADDR/api/v0/pin/add/$HASH" > pinadd_out && - echo "{\"Pins\":[\"QmYNmQKp6SuaVrpgWRsPTgCQCnpxUYGq76YEKBXuj2N4H6\"]}" > pinadd_exp && + echo "{\"Pins\":[\"$HASH\"]}" > pinadd_exp && test_cmp pinadd_out pinadd_exp ' test_expect_success "pin add api looks right - #3753" ' curl -X POST "http://$API_ADDR/api/v0/pin/rm/$HASH" > pinrm_out && - echo "{\"Pins\":[\"QmYNmQKp6SuaVrpgWRsPTgCQCnpxUYGq76YEKBXuj2N4H6\"]}" > pinrm_exp && + echo "{\"Pins\":[\"$HASH\"]}" > pinrm_exp && test_cmp pinrm_out pinrm_exp ' diff --git a/test/sharness/t0702-delegated-routing-http.sh b/test/sharness/t0702-delegated-routing-http.sh deleted file mode 100755 index 03f452fd4..000000000 --- a/test/sharness/t0702-delegated-routing-http.sh +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/env bash - -test_description="Test delegated routing via HTTP endpoint" - -. lib/test-lib.sh - -if ! test_have_prereq SOCAT; then - skip_all="skipping '$test_description': socat is not available" - test_done -fi - -# simple http routing server mock -# local endpoint responds with deterministic application/vnd.ipfs.rpc+dag-json; version=1 -HTTP_ROUTING_PORT=5098 -function start_http_routing_mock_endpoint() { - REMOTE_SERVER_LOG="http-routing-server.log" - rm -f $REMOTE_SERVER_LOG - - touch response - socat tcp-listen:$HTTP_ROUTING_PORT,fork,bind=127.0.0.1,reuseaddr 'SYSTEM:cat response'!!CREATE:$REMOTE_SERVER_LOG & - REMOTE_SERVER_PID=$! - - socat /dev/null tcp:127.0.0.1:$HTTP_ROUTING_PORT,retry=10 - return $? -} -function serve_http_routing_response() { - local body=$1 - local status_code=${2:-"200 OK"} - local length=$((1 + ${#body})) - echo -e "HTTP/1.1 $status_code\nContent-Length: $length\nContent-Type: application/json\n\n$body" > response -} -function stop_http_routing_mock_endpoint() { - exec 7<&- - kill $REMOTE_SERVER_PID > /dev/null 2>&1 - wait $REMOTE_SERVER_PID || true -} - -# daemon running in online mode to ensure Pin.origins/PinStatus.delegates work -test_init_ipfs - -# based on static, synthetic http routing messages: -# t0702-delegated-routing-http/FindProvidersRequest -# t0702-delegated-routing-http/FindProvidersResponse -FINDPROV_CID="baeabep4vu3ceru7nerjjbk37sxb7wmftteve4hcosmyolsbsiubw2vr6pqzj6mw7kv6tbn6nqkkldnklbjgm5tzbi4hkpkled4xlcr7xz4bq" -EXPECTED_PROV="12D3KooWARYacCc6eoCqvsS9RW9MA2vo51CV75deoiqssx3YgyYJ" - -test_expect_success "default Routing config has no Routers defined" ' - echo null > expected && - ipfs config show | jq .Routing.Routers > actual && - test_cmp expected actual -' - -# turn off all implicit routers -ipfs config Routing.Type none || exit 1 -test_launch_ipfs_daemon -test_expect_success "disabling default router (dht) works" ' - ipfs config Routing.Type > actual && - echo none > expected && - test_cmp expected actual -' -test_expect_success "no routers means findprovs returns no results" ' - ipfs routing findprovs "$FINDPROV_CID" > actual && - echo -n > expected && - test_cmp expected actual -' - -test_kill_ipfs_daemon - -ipfs config Routing.Type --json '"custom"' || exit 1 -ipfs config Routing.Methods --json '{ - "find-peers": { - "RouterName": "TestDelegatedRouter" - }, - "find-providers": { - "RouterName": "TestDelegatedRouter" - }, - "get-ipns": { - "RouterName": "TestDelegatedRouter" - }, - "provide": { - "RouterName": "TestDelegatedRouter" - } - }' || exit 1 - -test_expect_success "missing method params makes daemon fails" ' - echo "Error: constructing the node (see log for full detail): method name \"put-ipns\" is missing from Routing.Methods config param" > expected_error && - GOLOG_LOG_LEVEL=fatal ipfs daemon 2> actual_error || exit 0 && - test_cmp expected_error actual_error -' - -ipfs config Routing.Methods --json '{ - "find-peers": { - "RouterName": "TestDelegatedRouter" - }, - "find-providers": { - "RouterName": "TestDelegatedRouter" - }, - "get-ipns": { - "RouterName": "TestDelegatedRouter" - }, - "provide": { - "RouterName": "TestDelegatedRouter" - }, - "put-ipns": { - "RouterName": "TestDelegatedRouter" - }, - "NOT_SUPPORTED": { - "RouterName": "TestDelegatedRouter" - } - }' || exit 1 - -test_expect_success "having wrong methods makes daemon fails" ' - echo "Error: constructing the node (see log for full detail): method name \"NOT_SUPPORTED\" is not a supported method on Routing.Methods config param" > expected_error && - GOLOG_LOG_LEVEL=fatal ipfs daemon 2> actual_error || exit 0 && - test_cmp expected_error actual_error -' - -# set Routing config to only use delegated routing via mocked http routing endpoint - -ipfs config Routing.Type --json '"custom"' || exit 1 -ipfs config Routing.Routers.TestDelegatedRouter --json '{ - "Type": "http", - "Parameters": { - "Endpoint": "http://127.0.0.1:5098/routing/v1" - } -}' || exit 1 -ipfs config Routing.Methods --json '{ - "find-peers": { - "RouterName": "TestDelegatedRouter" - }, - "find-providers": { - "RouterName": "TestDelegatedRouter" - }, - "get-ipns": { - "RouterName": "TestDelegatedRouter" - }, - "provide": { - "RouterName": "TestDelegatedRouter" - }, - "put-ipns": { - "RouterName": "TestDelegatedRouter" - } - }' || exit 1 - -test_expect_success "adding http delegated routing endpoint to Routing.Routers config works" ' - echo "http://127.0.0.1:5098/routing/v1" > expected && - ipfs config Routing.Routers.TestDelegatedRouter.Parameters.Endpoint > actual && - test_cmp expected actual -' - -test_launch_ipfs_daemon - -test_expect_success "start_http_routing_mock_endpoint" ' - start_http_routing_mock_endpoint -' - -test_expect_success "'ipfs routing findprovs' returns result from delegated http router" ' - serve_http_routing_response "$(<../t0702-delegated-routing-http/FindProvidersResponse)" && - echo "$EXPECTED_PROV" > expected && - ipfs routing findprovs "$FINDPROV_CID" > actual && - test_cmp expected actual -' - -test_expect_success "stop_http_routing_mock_endpoint" ' - stop_http_routing_mock_endpoint -' - - -test_kill_ipfs_daemon -test_done -# vim: ts=2 sw=2 sts=2 et: diff --git a/test/unit/Rules.mk b/test/unit/Rules.mk index 30f712a45..69404637c 100644 --- a/test/unit/Rules.mk +++ b/test/unit/Rules.mk @@ -2,7 +2,7 @@ include mk/header.mk CLEAN += $(d)/gotest.json $(d)/gotest.junit.xml -$(d)/gotest.junit.xml: clean test/bin/gotestsum coverage/unit_tests.coverprofile +$(d)/gotest.junit.xml: test/bin/gotestsum coverage/unit_tests.coverprofile gotestsum --no-color --junitfile $@ --raw-command cat $(@D)/gotest.json include mk/footer.mk diff --git a/testplans/bitswap/go.mod b/testplans/bitswap/go.mod index 3ae17384c..79925df14 100644 --- a/testplans/bitswap/go.mod +++ b/testplans/bitswap/go.mod @@ -2,17 +2,16 @@ module github.com/ipfs/go-ipfs/testplans/bitswap require ( github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect - github.com/ipfs/go-bitswap v0.10.1 - github.com/ipfs/go-block-format v0.0.3 - github.com/ipfs/go-cid v0.2.0 - github.com/ipfs/go-datastore v0.5.1 + github.com/ipfs/go-cid v0.3.2 + github.com/ipfs/go-datastore v0.6.0 github.com/ipfs/go-ipfs-blockstore v1.2.0 github.com/ipfs/go-ipfs-exchange-interface v0.2.0 github.com/ipfs/go-ipfs-regression v0.0.1 + github.com/ipfs/go-libipfs v0.4.0 github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db // indirect - github.com/libp2p/go-libp2p v0.22.0 + github.com/libp2p/go-libp2p v0.23.4 github.com/libp2p/go-libp2p-kad-dht v0.18.0 - github.com/multiformats/go-multiaddr v0.6.0 + github.com/multiformats/go-multiaddr v0.8.0 github.com/multiformats/go-multihash v0.2.1 github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e // indirect github.com/smartystreets/assertions v1.0.1 // indirect diff --git a/testplans/bitswap/go.sum b/testplans/bitswap/go.sum index c71296c05..5cb07e8c0 100644 --- a/testplans/bitswap/go.sum +++ b/testplans/bitswap/go.sum @@ -61,8 +61,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce 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/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -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-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.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= @@ -70,7 +68,6 @@ github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= 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.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -87,7 +84,6 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf 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/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -106,11 +102,14 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/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/go-systemd/v22 v22.4.0 h1:y9YHcjnjynCd/DVbg5j9L/33jQM3MxJlbj/zWskzfGU= +github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= +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/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -130,8 +129,9 @@ github.com/dgraph-io/badger v1.6.1/go.mod h1:FRmFw3uxvcpa8zG3Rxs0th+hCLIuaQg8HlN github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -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/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 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/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= @@ -262,6 +262,7 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/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/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 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= @@ -289,26 +290,27 @@ github.com/influxdata/influxdb1-client v0.0.0-20200515024757-02f0bf5dbca3 h1:k3/ github.com/influxdata/influxdb1-client v0.0.0-20200515024757-02f0bf5dbca3/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= 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-bitswap v0.10.1 h1:XaMmwMR8NgxpzB2hVtZsVLPJPTn2pfAA66GN8gZJTl8= -github.com/ipfs/go-bitswap v0.10.1/go.mod h1:+fZEvycxviZ7c+5KlKwTzLm0M28g2ukCPqiuLfJk4KA= 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-block-format v0.1.1 h1:129vSO3zwbsYADcyQWcOYiuCpAqt462SFfqFHdFJhhI= +github.com/ipfs/go-block-format v0.1.1/go.mod h1:+McEIT+g52p+zz5xGAABGSOKrzmrdX97bc0USBdWPUs= 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/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.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= -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-cid v0.3.2 h1:OGgOd+JCFM+y1DjWPmVH+2/4POtpDzwcr7VgnB7mZXc= +github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svoupw= 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.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.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-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk= +github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8= 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.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= @@ -324,7 +326,6 @@ github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtL 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.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.2.0 h1:8lMSJmKogZYNo2jjhUs0izT+dck05pqUw4mWNW9Pw6Y= @@ -333,15 +334,19 @@ 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-regression v0.0.1 h1:LX3lrYYgiCE9QmL/qlc4Mh0cewdOHRl5pArbeQRllsU= github.com/ipfs/go-ipfs-regression v0.0.1/go.mod h1:I9yKzBjbirC5D0ND0DBkiQ5PPSQ2R2YjhcqHPj8L28A= -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-routing v0.3.0 h1:9W/W3N+g+y4ZDeffSgqhgo7BsBSJwPMcyssET9OWevc= +github.com/ipfs/go-ipfs-routing v0.3.0/go.mod h1:dKqtTFIql7e1zYsEuWLyuOU+E0WJWW8JjbTPLParDWo= 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-format v0.3.0 h1:Mwm2oRLzIuUwEPewWAWyMuuBQUsn3awfFEYVb8akMOQ= github.com/ipfs/go-ipld-format v0.3.0/go.mod h1:co/SdBE8h99968X0hViiw1MNlh6fvxxnHpvVLnH7jSM= -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-ipns v0.3.0 h1:ai791nTgVo+zTuq2bLvEGmWP1M0A6kGTXUsgv/Yq67A= +github.com/ipfs/go-ipns v0.3.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24= +github.com/ipfs/go-libipfs v0.3.0/go.mod h1:pSUHZ5qPJTAidsxe9bAeHp3KIiw2ODEW2a2kM3v+iXI= +github.com/ipfs/go-libipfs v0.4.0 h1:TkUxJGjtPnSzAgkw7VjS0/DBay3MPjmTBa4dGdUQCDE= +github.com/ipfs/go-libipfs v0.4.0/go.mod h1:XsU2cP9jBhDrXoJDe0WxikB8XcVmD3k2MEZvB3dbYu8= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= 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= @@ -355,8 +360,8 @@ 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-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-peertaskqueue v0.7.0 h1:VyO6G4sbzX80K58N60cCaHsSsypbUNs1GjO5seGNsQ0= -github.com/ipfs/go-peertaskqueue v0.7.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= +github.com/ipfs/go-peertaskqueue v0.8.0 h1:JyNO144tfu9bx6Hpo119zvbEL9iQ760FHOiJYsUjqaU= +github.com/ipfs/go-peertaskqueue v0.8.0/go.mod h1:cz8hEnnARq4Du5TGqiWKgMr/BOSQ5XOgMOh1K5YYKKM= 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 h1:kFwGn8rXa/Z31ev1OFNQsYeNKNCdifnTPl/NvPy5L38= github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= @@ -390,12 +395,14 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL 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.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.10 h1:Ai8UzuomSCDw90e1qNMtb15msBXsNpH6gzkkENQNcJo= +github.com/klauspost/compress v1.15.10/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/cpuid/v2 v2.0.4/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/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0= +github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= 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.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= @@ -408,8 +415,9 @@ github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 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/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 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/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= @@ -421,13 +429,12 @@ github.com/libp2p/go-flow-metrics v0.0.2/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS 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.22.0 h1:2Tce0kHOp5zASFKJbNzRElvh0iZwdtG5uZheNW8chIw= github.com/libp2p/go-libp2p v0.22.0/go.mod h1:UDolmweypBSjQb2f7xutPnwZ/fxioLbMBxSjRksxxU4= +github.com/libp2p/go-libp2p v0.23.4 h1:hWi9XHSOVFR1oDWRk7rigfyA4XNMuYL20INNybP9LP8= +github.com/libp2p/go-libp2p v0.23.4/go.mod h1:s9DEa5NLR4g+LZS+md5uGU4emjMWFiqkZr6hBTY8UxI= github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= 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-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.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= @@ -446,12 +453,10 @@ github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVd github.com/libp2p/go-libp2p-peerstore v0.2.6/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s= 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-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/go.mod h1:795bh+9YeoFl99rMASoiVgHdi5bjack0N1+AFAdbvBw= -github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.11.0/go.mod h1:qG4sF27dfKFoK9KlVzK2y52LQKhp0VEmLjV5aDqr1Hg= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= @@ -475,19 +480,20 @@ github.com/libp2p/go-openssl v0.1.0/go.mod h1:OiOxwPpL3n4xlenjx2h7AwSGaFSC/KZvf6 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-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -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/go-yamux/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ= +github.com/libp2p/go-yamux/v4 v4.0.0/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= github.com/libp2p/zeroconf/v2 v2.2.0/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= -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/lucas-clemente/quic-go v0.29.1 h1:Z+WMJ++qMLhvpFkRZA+jl3BTxUjm415YBmWanXB8zP0= +github.com/lucas-clemente/quic-go v0.29.1/go.mod h1:CTcNfLYJS2UuRNB+zcNlgvkjBhxX6Hm3WUxxAQx2mgE= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 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/marten-seemann/qpack v0.2.1 h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= -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.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= @@ -496,6 +502,8 @@ github.com/marten-seemann/qtls-go1-19 v0.1.0 h1:rLFKD/9mp/uq1SYGYuVZhm83wkmU95pK 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/marten-seemann/webtransport-go v0.1.1 h1:TnyKp3pEXcDooTaNn4s9dYpMJ7kMnTp7k5h+SgYP/mc= +github.com/marten-seemann/webtransport-go v0.1.1/go.mod h1:kBEh5+RSvOA4troP1vyOVBWK4MIMzDICXVrvCPrYcrM= 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-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -521,7 +529,6 @@ github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdn github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= 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.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= @@ -534,18 +541,16 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN 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/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/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-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= +github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= 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.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= @@ -554,8 +559,10 @@ github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u 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.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= -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 v0.7.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs= +github.com/multiformats/go-multiaddr v0.8.0 h1:aqjksEcqK+iD/Foe1RRFsGZh8+XFiGo7FgUCZlpv3LU= +github.com/multiformats/go-multiaddr v0.8.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs= 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.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= @@ -568,10 +575,10 @@ github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPw 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.4.1/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-multicodec v0.6.0 h1:KhH2kSuCARyuJraYMFxrNO3DqIaYhOdS039kbhgVwpE= +github.com/multiformats/go-multicodec v0.6.0/go.mod h1:GUC8upxSBE4oG+q3kWZRw/+6yC1BqO550bjhWsJbZlw= 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= @@ -591,6 +598,7 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 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/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= @@ -634,8 +642,9 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= 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_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU= +github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/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= @@ -663,6 +672,7 @@ github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqn github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 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/samber/lo v1.36.0/go.mod h1:HLeWcJRRyLKp3+/XBJvOrerCQn9mhdKMHyd7IRlgeQ8= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 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= @@ -700,7 +710,6 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= 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= @@ -716,6 +725,7 @@ github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/ 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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 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= @@ -723,12 +733,14 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 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/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/testground/sdk-go v0.2.7 h1:SDLDukPZIaZOeG2gQjCNsh5EB3QL3mOhOM4p0BMpqlc= github.com/testground/sdk-go v0.2.7/go.mod h1:Q4dnWsUBH+dZ1u7aEGDBHWGUaLfhitjUq3UJQqxeTmk= +github.com/thoas/go-funk v0.9.1/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= @@ -746,6 +758,7 @@ 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/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -781,8 +794,9 @@ 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.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= +go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY= +go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= 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= @@ -790,12 +804,9 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf 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-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-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-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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -820,6 +831,10 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 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-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20220916125017-b168a2c6b86b h1:SCE/18RnFsLrjydh/R/s5EVvHoZprqEQUuoxK8q2Pc4= +golang.org/x/exp v0.0.0-20220916125017-b168a2c6b86b/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= 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= @@ -844,6 +859,9 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB 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.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= 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-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -892,14 +910,16 @@ golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT 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-20211015210444-4f30a5c0130f/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-20220425223048-2871e0cb64e4/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-20220722155237-a158d28d115b/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/net v0.0.0-20220920183852-bf014ff85ad5 h1:KafLifaRFIuSJ5C+7CyFJOF9haxKNC1CEIDk8GX6X0k= +golang.org/x/net v0.0.0-20220920183852-bf014ff85ad5/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= @@ -986,6 +1006,7 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc 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-20211019181941-9d821ace8654/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= @@ -1066,6 +1087,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f 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.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= 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= @@ -1166,6 +1189,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks 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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= diff --git a/testplans/bitswap/main.go b/testplans/bitswap/main.go index 95eb47f03..aa98d4f31 100644 --- a/testplans/bitswap/main.go +++ b/testplans/bitswap/main.go @@ -12,9 +12,9 @@ import ( "github.com/testground/sdk-go/runtime" "github.com/testground/sdk-go/sync" - bitswap "github.com/ipfs/go-bitswap" - bsnet "github.com/ipfs/go-bitswap/network" - block "github.com/ipfs/go-block-format" + bitswap "github.com/ipfs/go-libipfs/bitswap" + bsnet "github.com/ipfs/go-libipfs/bitswap/network" + block "github.com/ipfs/go-libipfs/blocks" "github.com/ipfs/go-cid" datastore "github.com/ipfs/go-datastore" blockstore "github.com/ipfs/go-ipfs-blockstore" diff --git a/thirdparty/verifbs/verifbs.go b/thirdparty/verifbs/verifbs.go index 7be5348a8..ca2f5d839 100644 --- a/thirdparty/verifbs/verifbs.go +++ b/thirdparty/verifbs/verifbs.go @@ -3,9 +3,9 @@ package verifbs import ( "context" - blocks "github.com/ipfs/go-block-format" cid "github.com/ipfs/go-cid" bstore "github.com/ipfs/go-ipfs-blockstore" + blocks "github.com/ipfs/go-libipfs/blocks" "github.com/ipfs/go-verifcid" ) diff --git a/version.go b/version.go index 2762442ee..1f0577fa3 100644 --- a/version.go +++ b/version.go @@ -11,7 +11,7 @@ import ( var CurrentCommit string // CurrentVersionNumber is the current application's version literal -const CurrentVersionNumber = "0.18.0-dev" +const CurrentVersionNumber = "0.19.0-dev" const ApiVersion = "/kubo/" + CurrentVersionNumber + "/" //nolint