diff --git a/.codespell-ignore b/.codespell-ignore
new file mode 100644
index 00000000000..4b7efa7c02d
--- /dev/null
+++ b/.codespell-ignore
@@ -0,0 +1,21 @@
+Adin
+nd
+Nd
+afile
+thirdparty
+receivedFrom
+origN
+hel
+TotalIn
+childs
+userA
+AssignT
+OT
+AssignT
+fo
+recusive
+raison
+Boddy
+ressource
+achin
+re-using
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000000..eeba0640dc6
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+custom: [ipshipyard.gitwallet.co]
diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml
index 9472db123b9..d89f921b889 100644
--- a/.github/ISSUE_TEMPLATE/bug-report.yml
+++ b/.github/ISSUE_TEMPLATE/bug-report.yml
@@ -18,7 +18,7 @@ body:
label: Checklist
description: Please verify that you've followed these steps
options:
- - label: This is a bug report, not a question. Ask questions on [discuss.ipfs.io](https://discuss.ipfs.io).
+ - label: This is a bug report, not a question. Ask questions on [discuss.ipfs.tech](https://discuss.ipfs.tech/c/help/13).
required: true
- label: I have searched on the [issue tracker](https://github.com/ipfs/kubo/issues?q=is%3Aissue) for my bug.
required: true
@@ -32,8 +32,9 @@ body:
label: Installation method
description: Please select your installation method
options:
+ - dist.ipfs.tech or ipfs-update
+ - docker image
- ipfs-desktop
- - ipfs-update or dist.ipfs.tech
- third-party binary
- built from source
- type: textarea
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index f3f53fe6cac..ec985b0bc36 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,7 +1,7 @@
blank_issues_enabled: false
contact_links:
- name: Getting Help on IPFS
- url: https://ipfs.io/help
+ url: https://ipfs.tech/help
about: All information about how and where to get help on IPFS.
- name: Kubo configuration reference
url: https://github.com/ipfs/kubo/blob/master/docs/config.md#readme
@@ -9,9 +9,9 @@ contact_links:
- name: Kubo experimental features docs
url: https://github.com/ipfs/kubo/blob/master/docs/experimental-features.md#readme
about: Documentation on Private Networks, Filestore and other experimental features.
- - name: RPC API Reference
+ - name: Kubo RPC API Reference
url: https://docs.ipfs.tech/reference/kubo/rpc/
about: Documentation of all Kubo RPC API endpoints.
- - name: IPFS Official Forum
- url: https://discuss.ipfs.io
+ - name: IPFS Official Discussion Forum
+ url: https://discuss.ipfs.tech
about: Please post general questions, support requests, and discussions here.
diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml
index 9bfeba5b516..a0b241b557b 100644
--- a/.github/ISSUE_TEMPLATE/enhancement.yml
+++ b/.github/ISSUE_TEMPLATE/enhancement.yml
@@ -6,11 +6,11 @@ body:
- type: markdown
attributes:
value: |
- Suggest an enhancement to Kubo (the program). If you'd like to suggest an improvement to the IPFS protocol, please discuss it on [the forum](https://discuss.ipfs.io).
+ Suggest an enhancement to Kubo (the program). If you'd like to suggest an improvement to the IPFS protocol, please discuss it on [the forum](https://discuss.ipfs.tech).
Issues in this repo must be specific, actionable, and well motivated. They should be starting points for _building_ new features, not brainstorming ideas.
- If you have an idea you'd like to discuss, please open a new thread on [the forum](https://discuss.ipfs.io).
+ If you have an idea you'd like to discuss, please open a new thread on [the forum](https://discuss.ipfs.tech).
**Example:**
diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml
index cf2fa81167f..d368588b419 100644
--- a/.github/ISSUE_TEMPLATE/feature.yml
+++ b/.github/ISSUE_TEMPLATE/feature.yml
@@ -6,11 +6,11 @@ body:
- type: markdown
attributes:
value: |
- Suggest a new feature in Kubo (the program). If you'd like to suggest an improvement to the IPFS protocol, please discuss it on [the forum](https://discuss.ipfs.io).
+ Suggest a new feature in Kubo (the program). If you'd like to suggest an improvement to the IPFS protocol, please discuss it on [the forum](https://discuss.ipfs.tech).
Issues in this repo must be specific, actionable, and well motivated. They should be starting points for _building_ new features, not brainstorming ideas.
- If you have an idea you'd like to discuss, please open a new thread on [the forum](https://discuss.ipfs.io).
+ If you have an idea you'd like to discuss, please open a new thread on [the forum](https://discuss.ipfs.tech).
**Example:**
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 60bc3c40976..4bc3665b692 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -31,14 +31,19 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
+ - name: Setup Go
+ uses: actions/setup-go@v5
+ with:
+ go-version: 1.24.x
+
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
languages: go
- name: Autobuild
- uses: github/codeql-action/autobuild@v2
+ uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v3
diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml
index 733dc2c0e0d..180f37963aa 100644
--- a/.github/workflows/docker-build.yml
+++ b/.github/workflows/docker-build.yml
@@ -28,7 +28,7 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
- go-version: 1.21.x
+ go-version: 1.24.x
- uses: actions/checkout@v4
- run: docker build -t $IMAGE_NAME:$WIP_IMAGE_TAG .
- run: docker run --rm $IMAGE_NAME:$WIP_IMAGE_TAG --version
diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml
index 33c5bb5491f..f8380924046 100644
--- a/.github/workflows/docker-image.yml
+++ b/.github/workflows/docker-image.yml
@@ -19,6 +19,7 @@ on:
push:
branches:
- 'master'
+ - 'staging'
- 'bifrost-*'
tags:
- 'v*'
@@ -31,7 +32,7 @@ jobs:
if: github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch'
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
- timeout-minutes: 90
+ timeout-minutes: 15
env:
IMAGE_NAME: ipfs/kubo
LEGACY_IMAGE_NAME: ipfs/go-ipfs
@@ -63,7 +64,7 @@ jobs:
shell: bash
- name: Log in to Docker Hub
- uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d
+ uses: docker/login-action@v3
with:
username: ${{ vars.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
@@ -72,7 +73,7 @@ jobs:
# builds, only one platform is being loaded into the cache. This would
# prevent us from testing the other platforms.
- name: Build Docker image (linux/amd64)
- uses: docker/build-push-action@v5
+ uses: docker/build-push-action@v6
with:
platforms: linux/amd64
context: .
@@ -84,7 +85,7 @@ jobs:
cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build Docker image (linux/arm/v7)
- uses: docker/build-push-action@v5
+ uses: docker/build-push-action@v6
with:
platforms: linux/arm/v7
context: .
@@ -96,7 +97,7 @@ jobs:
cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build Docker image (linux/arm64/v8)
- uses: docker/build-push-action@v5
+ uses: docker/build-push-action@v6
with:
platforms: linux/arm64/v8
context: .
@@ -109,14 +110,22 @@ jobs:
# We test all the images on amd64 host here. This uses QEMU to emulate
# the other platforms.
- - run: docker run --rm $IMAGE_NAME:linux-amd64 --version
- - run: docker run --rm $IMAGE_NAME:linux-arm-v7 --version
- - run: docker run --rm $IMAGE_NAME:linux-arm64-v8 --version
+ # NOTE: --version should finish instantly, but sometimes
+ # it hangs on github CI (could be qemu issue), so we retry to remove false negatives
+ - name: Smoke-test linux-amd64
+ run: for i in {1..3}; do timeout 15s docker run --rm $IMAGE_NAME:linux-amd64 version --all && break || [ $i = 3 ] && exit 1; done
+ timeout-minutes: 1
+ - name: Smoke-test linux-arm-v7
+ run: for i in {1..3}; do timeout 15s docker run --rm $IMAGE_NAME:linux-arm-v7 version --all && break || [ $i = 3 ] && exit 1; done
+ timeout-minutes: 1
+ - name: Smoke-test linux-arm64-v8
+ run: for i in {1..3}; do timeout 15s docker run --rm $IMAGE_NAME:linux-arm64-v8 version --all && break || [ $i = 3 ] && exit 1; done
+ timeout-minutes: 1
# This will only push the previously built images.
- if: github.event_name != 'workflow_dispatch' || github.event.inputs.push == 'true'
name: Publish to Docker Hub
- uses: docker/build-push-action@v5
+ uses: docker/build-push-action@v6
with:
platforms: linux/amd64,linux/arm/v7,linux/arm64/v8
context: .
diff --git a/.github/workflows/gateway-conformance.yml b/.github/workflows/gateway-conformance.yml
index 57563cfc272..b305a8fc71c 100644
--- a/.github/workflows/gateway-conformance.yml
+++ b/.github/workflows/gateway-conformance.yml
@@ -41,7 +41,7 @@ jobs:
steps:
# 1. Download the gateway-conformance fixtures
- name: Download gateway-conformance fixtures
- uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.5
+ uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.8
with:
output: fixtures
@@ -49,7 +49,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
- go-version: 1.21.x
+ go-version: 1.24.x
- uses: protocol/cache-go-action@v1
with:
name: ${{ github.job }}
@@ -84,9 +84,7 @@ jobs:
# Import dnslink records
# the IPFS_NS_MAP env will be used by the daemon
- export IPFS_NS_MAP=$(cat "./fixtures/dnslinks.json" | jq -r '.subdomains | to_entries | map("\(.key).example.com:\(.value)") | join(",")')
- export IPFS_NS_MAP="$(cat "./fixtures/dnslinks.json" | jq -r '.domains | to_entries | map("\(.key):\(.value)") | join(",")'),${IPFS_NS_MAP}"
- echo "IPFS_NS_MAP=${IPFS_NS_MAP}" >> $GITHUB_ENV
+ echo "IPFS_NS_MAP=$(cat ./fixtures/dnslinks.IPFS_NS_MAP)" >> $GITHUB_ENV
# 5. Start the kubo-gateway
- name: Start kubo-gateway
@@ -96,14 +94,15 @@ jobs:
# 6. Run the gateway-conformance tests
- name: Run gateway-conformance tests
- uses: ipfs/gateway-conformance/.github/actions/test@v0.5
+ uses: ipfs/gateway-conformance/.github/actions/test@v0.8
with:
gateway-url: http://127.0.0.1:8080
+ subdomain-url: http://localhost:8080
+ args: -skip 'TestGatewayCar/GET_response_for_application/vnd.ipld.car/Header_Content-Length'
json: output.json
xml: output.xml
html: output.html
markdown: output.md
- args: -skip 'TestGatewayCar/GET_response_for_application/vnd.ipld.car/Header_Content-Length'
# 7. Upload the results
- name: Upload MD summary
@@ -129,7 +128,7 @@ jobs:
steps:
# 1. Download the gateway-conformance fixtures
- name: Download gateway-conformance fixtures
- uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.5
+ uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.8
with:
output: fixtures
@@ -137,7 +136,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
- go-version: 1.20.x
+ go-version: 1.24.x
- uses: protocol/cache-go-action@v1
with:
name: ${{ github.job }}
@@ -202,14 +201,14 @@ jobs:
# 9. Run the gateway-conformance tests over libp2p
- name: Run gateway-conformance tests over libp2p
- uses: ipfs/gateway-conformance/.github/actions/test@v0.5
+ uses: ipfs/gateway-conformance/.github/actions/test@v0.8
with:
gateway-url: http://127.0.0.1:8092
+ args: --specs "trustless-gateway,-trustless-ipns-gateway" -skip 'TestGatewayCar/GET_response_for_application/vnd.ipld.car/Header_Content-Length'
json: output.json
xml: output.xml
html: output.html
markdown: output.md
- args: --specs "trustless-gateway,-trustless-ipns-gateway" -skip 'TestGatewayCar/GET_response_for_application/vnd.ipld.car/Header_Content-Length'
# 10. Upload the results
- name: Upload MD summary
diff --git a/.github/workflows/generated-pr.yml b/.github/workflows/generated-pr.yml
new file mode 100644
index 00000000000..b8c5cc63116
--- /dev/null
+++ b/.github/workflows/generated-pr.yml
@@ -0,0 +1,14 @@
+name: Close Generated PRs
+
+on:
+ schedule:
+ - cron: '0 0 * * *'
+ workflow_dispatch:
+
+permissions:
+ issues: write
+ pull-requests: write
+
+jobs:
+ stale:
+ uses: ipdxco/unified-github-workflows/.github/workflows/reusable-generated-pr.yml@v1
diff --git a/.github/workflows/gobuild.yml b/.github/workflows/gobuild.yml
index f5de9e5173f..32cefb4c138 100644
--- a/.github/workflows/gobuild.yml
+++ b/.github/workflows/gobuild.yml
@@ -30,7 +30,7 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
- go-version: 1.21.x
+ go-version: 1.24.x
- uses: actions/checkout@v4
- run: make cmd/ipfs-try-build
env:
diff --git a/.github/workflows/golang-analysis.yml b/.github/workflows/golang-analysis.yml
index 0643de16054..aef63584598 100644
--- a/.github/workflows/golang-analysis.yml
+++ b/.github/workflows/golang-analysis.yml
@@ -27,7 +27,7 @@ jobs:
submodules: recursive
- uses: actions/setup-go@v5
with:
- go-version: "1.21.x"
+ go-version: "1.24.x"
- name: Check that go.mod is tidy
uses: protocol/multiple-go-modules@v1.4
with:
diff --git a/.github/workflows/golint.yml b/.github/workflows/golint.yml
index 59150747150..5f6e0bb20cc 100644
--- a/.github/workflows/golint.yml
+++ b/.github/workflows/golint.yml
@@ -31,6 +31,6 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
- go-version: 1.21.x
+ go-version: 1.24.x
- uses: actions/checkout@v4
- run: make -O test_go_lint
diff --git a/.github/workflows/gotest.yml b/.github/workflows/gotest.yml
index c6b2cdc075d..e0815bf9040 100644
--- a/.github/workflows/gotest.yml
+++ b/.github/workflows/gotest.yml
@@ -32,7 +32,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
- go-version: 1.21.x
+ go-version: 1.24.x
- name: Check out Kubo
uses: actions/checkout@v4
- name: Install missing tools
@@ -45,7 +45,7 @@ jobs:
make -j "$PARALLEL" test/unit/gotest.junit.xml &&
[[ ! $(jq -s -c 'map(select(.Action == "fail")) | .[]' test/unit/gotest.json) ]]
- name: Upload coverage to Codecov
- uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4
+ uses: codecov/codecov-action@ad3126e916f78f00edff4ed0317cf185271ccc2d # v5.4.2
if: failure() || success()
with:
name: unittests
@@ -73,7 +73,7 @@ jobs:
mv go.sum.bak go.sum
working-directory: docs/examples/kubo-as-a-library
- name: Create a proper JUnit XML report
- uses: pl-strflt/gotest-json-to-junit-xml@v1
+ uses: ipdxco/gotest-json-to-junit-xml@v1
with:
input: test/unit/gotest.json
output: test/unit/gotest.junit.xml
@@ -85,7 +85,7 @@ jobs:
path: test/unit/gotest.junit.xml
if: failure() || success()
- name: Create a HTML report
- uses: pl-strflt/junit-xml-to-html@v1
+ uses: ipdxco/junit-xml-to-html@v1
with:
mode: no-frames
input: test/unit/gotest.junit.xml
@@ -98,7 +98,7 @@ jobs:
path: test/unit/gotest.html
if: failure() || success()
- name: Create a Markdown report
- uses: pl-strflt/junit-xml-to-html@v1
+ uses: ipdxco/junit-xml-to-html@v1
with:
mode: summary
input: test/unit/gotest.junit.xml
diff --git a/.github/workflows/build.yml b/.github/workflows/interop.yml
similarity index 99%
rename from .github/workflows/build.yml
rename to .github/workflows/interop.yml
index 2d1ce7dd2d7..e85e1f2fe36 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/interop.yml
@@ -10,7 +10,7 @@ on:
- 'master'
env:
- GO_VERSION: 1.21.x
+ GO_VERSION: 1.24.x
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.sha || github.ref }}
diff --git a/.github/workflows/sharness.yml b/.github/workflows/sharness.yml
index ec678e5ece5..86f08b2c101 100644
--- a/.github/workflows/sharness.yml
+++ b/.github/workflows/sharness.yml
@@ -17,7 +17,7 @@ jobs:
sharness-test:
if: github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch'
runs-on: ${{ fromJSON(github.repository == 'ipfs/kubo' && '["self-hosted", "linux", "x64", "4xlarge"]' || '"ubuntu-latest"') }}
- timeout-minutes: 20
+ timeout-minutes: ${{ github.repository == 'ipfs/kubo' && 15 || 60 }}
defaults:
run:
shell: bash
@@ -25,7 +25,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
- go-version: 1.21.x
+ go-version: 1.24.x
- name: Checkout Kubo
uses: actions/checkout@v4
with:
@@ -55,7 +55,7 @@ jobs:
# increasing parallelism beyond 10 doesn't speed up the tests much
PARALLEL: ${{ github.repository == 'ipfs/kubo' && 10 || 3 }}
- name: Upload coverage report
- uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4
+ uses: codecov/codecov-action@ad3126e916f78f00edff4ed0317cf185271ccc2d # v5.4.2
if: failure() || success()
with:
name: sharness
@@ -73,7 +73,7 @@ jobs:
echo >> $GITHUB_STEP_SUMMARY
cat kubo/test/sharness/test-results/summary.txt >> $GITHUB_STEP_SUMMARY
- name: Generate one-page HTML report
- uses: pl-strflt/junit-xml-to-html@v1
+ uses: ipdxco/junit-xml-to-html@v1
if: failure() || success()
with:
mode: no-frames
@@ -81,7 +81,7 @@ jobs:
output: kubo/test/sharness/test-results/sharness.html
- name: Upload one-page HTML report to S3
id: one-page
- uses: pl-strflt/tf-aws-gh-runner/.github/actions/upload-artifact@main
+ uses: ipdxco/custom-github-runners/.github/actions/upload-artifact@main
if: github.repository == 'ipfs/kubo' && (failure() || success())
with:
source: kubo/test/sharness/test-results/sharness.html
@@ -93,7 +93,7 @@ jobs:
name: sharness.html
path: kubo/test/sharness/test-results/sharness.html
- name: Generate full HTML report
- uses: pl-strflt/junit-xml-to-html@v1
+ uses: ipdxco/junit-xml-to-html@v1
if: failure() || success()
with:
mode: frames
@@ -101,7 +101,7 @@ jobs:
output: 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
+ uses: ipdxco/custom-github-runners/.github/actions/upload-artifact@main
if: github.repository == 'ipfs/kubo' && (failure() || success())
with:
source: kubo/test/sharness/test-results/sharness-html
diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml
new file mode 100644
index 00000000000..a34cc0798ab
--- /dev/null
+++ b/.github/workflows/spellcheck.yml
@@ -0,0 +1,21 @@
+name: Spell Check
+
+on: [push, pull_request]
+
+jobs:
+ spellcheck:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Install Codespell
+ run: pip install codespell==2.4.0
+
+ - name: Run Codespell
+ uses: codespell-project/actions-codespell@v2
+ with:
+ only_warn: 1
+ ignore_words_file: .codespell-ignore
+ skip: "*.mod,*.sum,*.pdf,./docs/AUTHORS,./test/sharness/t0275-cid-security-data,./test/sharness/t0280-plugin-dag-jose-data,./bin"
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index 16d65d72175..7c955c41430 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -1,8 +1,9 @@
-name: Close and mark stale issue
+name: Close Stale Issues
on:
schedule:
- cron: '0 0 * * *'
+ workflow_dispatch:
permissions:
issues: write
@@ -10,4 +11,4 @@ permissions:
jobs:
stale:
- uses: pl-strflt/.github/.github/workflows/reusable-stale-issue.yml@v0.3
+ uses: ipdxco/unified-github-workflows/.github/workflows/reusable-stale-issue.yml@v1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bfcf27bed31..67a776ee1ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Kubo Changelogs
+- [v0.36](docs/changelogs/v0.36.md)
+- [v0.35](docs/changelogs/v0.35.md)
+- [v0.34](docs/changelogs/v0.34.md)
+- [v0.33](docs/changelogs/v0.33.md)
+- [v0.32](docs/changelogs/v0.32.md)
+- [v0.31](docs/changelogs/v0.31.md)
+- [v0.30](docs/changelogs/v0.30.md)
+- [v0.29](docs/changelogs/v0.29.md)
+- [v0.28](docs/changelogs/v0.28.md)
- [v0.27](docs/changelogs/v0.27.md)
- [v0.26](docs/changelogs/v0.26.md)
- [v0.25](docs/changelogs/v0.25.md)
diff --git a/Dockerfile b/Dockerfile
index d68e525b9f8..98e44a1b647 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.21 AS builder
+FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.24 AS builder
ARG TARGETOS TARGETARCH
@@ -80,8 +80,8 @@ RUN mkdir -p $IPFS_PATH \
&& chown ipfs:users $IPFS_PATH
# Create mount points for `ipfs mount` command
-RUN mkdir /ipfs /ipns \
- && chown ipfs:users /ipfs /ipns
+RUN mkdir /ipfs /ipns /mfs \
+ && chown ipfs:users /ipfs /ipns /mfs
# Create the init scripts directory
RUN mkdir /container-init.d \
@@ -93,7 +93,7 @@ RUN mkdir /container-init.d \
VOLUME $IPFS_PATH
# The default logging level
-ENV IPFS_LOGGING ""
+ENV GOLOG_LOG_LEVEL ""
# This just makes sure that:
# 1. There's an fs-repo, and initializes one if there isn't.
diff --git a/FUNDING.json b/FUNDING.json
new file mode 100644
index 00000000000..9085792a636
--- /dev/null
+++ b/FUNDING.json
@@ -0,0 +1,5 @@
+{
+ "opRetro": {
+ "projectId": "0x7f330267969cf845a983a9d4e7b7dbcca5c700a5191269af377836d109e0bb69"
+ }
+}
diff --git a/README.md b/README.md
index 74b53c3ad6e..2e6766877b6 100644
--- a/README.md
+++ b/README.md
@@ -12,19 +12,19 @@
-
+
-
## What is Kubo?
-Kubo was the first IPFS implementation and is the most widely used one today. Implementing the *Interplanetary Filesystem* - the Web3 standard for content-addressing, interoperable with HTTP. Thus powered by IPLD's data models and the libp2p for network communication. Kubo is written in Go.
+Kubo was the first IPFS implementation and is the most widely used one today. Implementing the *Interplanetary Filesystem* - the standard for content-addressing on the Web, interoperable with HTTP. Thus powered by future-proof data models and the libp2p for network communication. Kubo is written in Go.
Featureset
- Runs an IPFS-Node as a network service that is part of LAN and WAN DHT
+- Native support for UnixFS (most popular way to represent files and directories on IPFS)
- [HTTP Gateway](https://specs.ipfs.tech/http-gateways/) (`/ipfs` and `/ipns`) functionality for trusted and [trustless](https://docs.ipfs.tech/reference/http/gateway/#trustless-verifiable-retrieval) content retrieval
- [HTTP Routing V1](https://specs.ipfs.tech/routing/http-routing-v1/) (`/routing/v1`) client and server implementation for [delegated routing](./docs/delegated-routing.md) lookups
- [HTTP Kubo RPC API](https://docs.ipfs.tech/reference/kubo/rpc/) (`/api/v0`) to access and control the daemon
@@ -64,20 +64,22 @@ Before opening an issue, consider using one of the following locations to ensure
- [Next milestones](#next-milestones)
- [Table of Contents](#table-of-contents)
- [Security Issues](#security-issues)
-- [Minimal System Requirements](#minimal-system-requirements)
- [Install](#install)
+ - [Minimal System Requirements](#minimal-system-requirements)
- [Docker](#docker)
- [Official prebuilt binaries](#official-prebuilt-binaries)
- [Updating](#updating)
- - [Using ipfs-update](#using-ipfs-update)
- [Downloading builds using IPFS](#downloading-builds-using-ipfs)
- [Unofficial Linux packages](#unofficial-linux-packages)
- [ArchLinux](#arch-linux)
+ - [Gentoo Linux](#gentoo-linux)
- [Nix](#nix)
- [Solus](#solus)
- [openSUSE](#opensuse)
- [Guix](#guix)
- [Snap](#snap)
+ - [Ubuntu PPA](#ubuntu-ppa)
+ - [Fedora](#fedora-copr)
- [Unofficial Windows packages](#unofficial-windows-packages)
- [Chocolatey](#chocolatey)
- [Scoop](#scoop)
@@ -109,21 +111,51 @@ Before opening an issue, consider using one of the following locations to ensure
Please follow [`SECURITY.md`](SECURITY.md).
+## Install
+
+The canonical download instructions for IPFS are over at: https://docs.ipfs.tech/install/. It is **highly recommended** you follow those instructions if you are not interested in working on IPFS development.
+
+For production use, Release Docker images (below) are recommended.
+
### Minimal System Requirements
-IPFS can run on most Linux, macOS, and Windows systems. We recommend running it on a machine with at least 4 GB of RAM and 2 CPU cores (kubo is highly parallel). On systems with less memory, it may not be completely stable, and you run on your own risk.
+Kubo runs on most Linux, macOS, and Windows systems. For optimal performance, we recommend at least 6 GB of RAM and 2 CPU cores (more is ideal, as Kubo is highly parallel).
-## Install
+> [!IMPORTANT]
+> Larger pinsets require additional memory, with an estimated ~1 GiB of RAM per 20 million items for reproviding to the Amino DHT.
-The canonical download instructions for IPFS are over at: https://docs.ipfs.tech/install/. It is **highly recommended** you follow those instructions if you are not interested in working on IPFS development.
+> [!CAUTION]
+> Systems with less than the recommended memory may experience instability, frequent OOM errors or restarts, and missing data announcement (reprovider window), which can make data fully or partially inaccessible to other peers. Running Kubo on underprovisioned hardware is at your own risk.
### Docker
-Official images are published at https://hub.docker.com/r/ipfs/kubo/:
+Official images are published at https://hub.docker.com/r/ipfs/kubo/: [](https://hub.docker.com/r/ipfs/kubo/)
-[](https://hub.docker.com/r/ipfs/kubo/)
+#### 🟢 Release Images
+ - These are production grade images. Use them.
+ - `latest` and [`release`](https://hub.docker.com/r/ipfs/kubo/tags?name=release) tags always point at [the latest stable release](https://github.com/ipfs/kubo/releases/latest). If you use this, remember to `docker pull` periodically to update.
+ - [`vN.N.N`](https://hub.docker.com/r/ipfs/kubo/tags?name=v) points at a specific [release tag](https://github.com/ipfs/kubo/releases)
-More info on how to run Kubo (go-ipfs) inside Docker can be found [here](https://docs.ipfs.tech/how-to/run-ipfs-inside-docker/).
+#### 🟠 Developer Preview Images
+ - These tags are used by developers for internal testing, not intended for end users or production use.
+ - [`master-latest`](https://hub.docker.com/r/ipfs/kubo/tags?name=master-latest) always points at the `HEAD` of the [`master`](https://github.com/ipfs/kubo/commits/master/) branch
+ - [`master-YYYY-DD-MM-GITSHA`](https://hub.docker.com/r/ipfs/kubo/tags?name=master-2) points at a specific commit from the `master` branch
+
+#### 🔴 Internal Staging Images
+ - We use `staging` for testing arbitrary commits and experimental patches.
+ - To build image for current HEAD, force push to `staging` via `git push origin HEAD:staging --force`)
+ - [`staging-latest`](https://hub.docker.com/r/ipfs/kubo/tags?name=staging-latest) always points at the `HEAD` of the [`staging`](https://github.com/ipfs/kubo/commits/staging/) branch
+ - [`staging-YYYY-DD-MM-GITSHA`](https://hub.docker.com/r/ipfs/kubo/tags?name=staging-2) points at a specific commit from the `staging` branch
+
+```console
+$ docker pull ipfs/kubo:latest
+$ docker run --rm -it --net=host ipfs/kubo:latest
+```
+
+To [customize your node](https://docs.ipfs.tech/install/run-ipfs-inside-docker/#customizing-your-node),
+pass necessary config via `-e` or by mounting scripts in the `/container-init.d`.
+
+Learn more at https://docs.ipfs.tech/install/run-ipfs-inside-docker/
### Official prebuilt binaries
@@ -142,12 +174,6 @@ If you are unable to access [dist.ipfs.tech](https://dist.ipfs.tech#kubo), you c
#### Updating
-##### Using ipfs-update
-
-IPFS has an updating tool that can be accessed through `ipfs update`. The tool is
-not installed alongside IPFS in order to keep that logic independent of the main
-codebase. To install `ipfs-update` tool, [download it here](https://dist.ipfs.tech/#ipfs-update).
-
##### Downloading builds using IPFS
List the available versions of Kubo (go-ipfs) implementation:
@@ -181,11 +207,14 @@ $ ipfs get /ipns/dist.ipfs.tech/kubo/$VERSION/kubo_$VERSION_windows-amd64.zip
- [ArchLinux](#arch-linux)
+- [Gentoo Linux](#gentoo-linux)
- [Nix](#nix-linux)
- [Solus](#solus)
- [openSUSE](#opensuse)
- [Guix](#guix)
- [Snap](#snap)
+- [Ubuntu PPA](#ubuntu-ppa)
+- [Fedora](#fedora-copr)
#### Arch Linux
@@ -197,6 +226,16 @@ $ ipfs get /ipns/dist.ipfs.tech/kubo/$VERSION/kubo_$VERSION_windows-amd64.zip
[](https://aur.archlinux.org/packages/kubo/)
+#### Gentoo Linux
+
+https://wiki.gentoo.org/wiki/Kubo
+
+```bash
+# emerge -a net-p2p/kubo
+```
+
+https://packages.gentoo.org/packages/net-p2p/kubo
+
#### Nix
With the purely functional package manager [Nix](https://nixos.org/nix/) you can install kubo (go-ipfs) like this:
@@ -223,12 +262,41 @@ You can also install it through the Solus software center.
#### Guix
-[Community Package for go-ipfs](https://packages.guix.gnu.org/packages/go-ipfs/0.11.0/) is no out-of-date.
+[Community Package for go-ipfs](https://packages.guix.gnu.org/packages/go-ipfs/0.11.0/) is now out-of-date.
#### Snap
No longer supported, see rationale in [kubo#8688](https://github.com/ipfs/kubo/issues/8688).
+#### Ubuntu PPA
+
+[PPA homepage](https://launchpad.net/~twdragon/+archive/ubuntu/ipfs) on Launchpad.
+
+##### Latest Ubuntu (>= 20.04 LTS)
+```sh
+sudo add-apt-repository ppa:twdragon/ipfs
+sudo apt update
+sudo apt install ipfs-kubo
+```
+
+### Fedora COPR
+
+[`taw00/ipfs-rpm`](https://github.com/taw00/ipfs-rpm)
+
+##### Any Ubuntu version
+
+```sh
+sudo su
+echo 'deb https://ppa.launchpadcontent.net/twdragon/ipfs/ubuntu <> main' >> /etc/apt/sources.list.d/ipfs
+echo 'deb-src https://ppa.launchpadcontent.net/twdragon/ipfs/ubuntu <> main' >> /etc/apt/sources.list.d/ipfs
+exit
+sudo apt update
+sudo apt install ipfs-kubo
+```
+where `<>` is the codename of your Ubuntu distribution (for example, `jammy` for 22.04 LTS). During the first installation the package maintenance script may automatically ask you about which networking profile, CPU accounting model, and/or existing node configuration file you want to use.
+
+**NOTE**: this method also may work with any compatible Debian-based distro which has `libc6` inside, and APT as a package manager.
+
### Unofficial Windows packages
- [Chocolatey](#chocolatey)
@@ -415,9 +483,11 @@ If you make changes to the protocol buffers, you will need to install the [proto
Find more documentation for developers on [docs](./docs)
## Maintainer Info
-* [Project Board for active and upcoming work](https://pl-strflt.notion.site/Kubo-GitHub-Project-Board-c68f9192e48e4e9eba185fa697bf0570)
-* [Release Process](https://pl-strflt.notion.site/Kubo-Release-Process-5a5d066264704009a28a79cff93062c4)
-* [Additional PL EngRes Kubo maintainer info](https://pl-strflt.notion.site/Kubo-go-ipfs-4a484aeeaa974dcf918027c300426c05)
+
+Kubo is maintained by [Shipyard](https://ipshipyard.com/).
+
+* This repository is part of [Shipyard's GO Triage triage](https://ipshipyard.notion.site/IPFS-Go-Triage-Boxo-Kubo-Rainbow-0ddee6b7f28d412da7dabe4f9107c29a).
+* [Release Process](https://ipshipyard.notion.site/Kubo-Release-Process-6dba4f5755c9458ab5685eeb28173778)
## Contributing
@@ -428,7 +498,9 @@ We ❤️ all [our contributors](docs/AUTHORS); this project wouldn’t be what
This repository falls under the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
-Please reach out to us in one [chat](https://docs.ipfs.tech/community/chat/) rooms.
+Members of IPFS community provide Kubo support on [discussion forum category here](https://discuss.ipfs.tech/c/help/help-kubo/23).
+
+Need help with IPFS itself? Learn where to get help and support at https://ipfs.tech/help.
## License
diff --git a/Rules.mk b/Rules.mk
index c3e662aa0e0..ef88bee0f74 100644
--- a/Rules.mk
+++ b/Rules.mk
@@ -123,7 +123,7 @@ help:
@echo ' build - Build binary at ./cmd/ipfs/ipfs'
@echo ' nofuse - Build binary with no fuse support'
@echo ' install - Build binary and install into $$GOBIN'
- @echo ' mod_tidy - Remove unused dependencis from go.mod files'
+ @echo ' mod_tidy - Remove unused dependencies from go.mod files'
# @echo ' dist_install - TODO: c.f. ./cmd/ipfs/dist/README.md'
@echo ''
@echo 'CLEANING TARGETS:'
diff --git a/assets/assets.go b/assets/assets.go
index 17bfa89413a..6196ed22f89 100644
--- a/assets/assets.go
+++ b/assets/assets.go
@@ -9,9 +9,7 @@ import (
"github.com/ipfs/kubo/core/coreapi"
"github.com/ipfs/boxo/files"
- "github.com/ipfs/boxo/path"
cid "github.com/ipfs/go-cid"
- options "github.com/ipfs/kubo/core/coreiface/options"
)
//go:embed init-doc
@@ -39,12 +37,7 @@ func addAssetList(nd *core.IpfsNode, l []string) (cid.Cid, error) {
return cid.Cid{}, err
}
- dirb, err := api.Object().New(nd.Context(), options.Object.Type("unixfs-dir"))
- if err != nil {
- return cid.Cid{}, err
- }
-
- basePath := path.FromCid(dirb.Cid())
+ dirMap := map[string]files.Node{}
for _, p := range l {
d, err := Asset.ReadFile(p)
@@ -52,17 +45,12 @@ func addAssetList(nd *core.IpfsNode, l []string) (cid.Cid, error) {
return cid.Cid{}, fmt.Errorf("assets: could load Asset '%s': %s", p, err)
}
- fp, err := api.Unixfs().Add(nd.Context(), files.NewBytesFile(d))
- if err != nil {
- return cid.Cid{}, err
- }
-
- fname := gopath.Base(p)
+ dirMap[gopath.Base(p)] = files.NewBytesFile(d)
+ }
- basePath, err = api.Object().AddLink(nd.Context(), basePath, fname, fp)
- if err != nil {
- return cid.Cid{}, err
- }
+ basePath, err := api.Unixfs().Add(nd.Context(), files.NewMapDirectory(dirMap))
+ if err != nil {
+ return cid.Cid{}, err
}
if err := api.Pin().Add(nd.Context(), basePath); err != nil {
diff --git a/bin/get-docker-tags.sh b/bin/get-docker-tags.sh
index e54da6482f7..1c4e184f222 100755
--- a/bin/get-docker-tags.sh
+++ b/bin/get-docker-tags.sh
@@ -18,7 +18,7 @@ set -euo pipefail
if [[ $# -lt 1 ]] ; then
echo 'At least 1 arg required.'
echo 'Usage:'
- echo './push-docker-tags.sh [git commit sha1] [git branch name] [git tag name]'
+ echo './get-docker-tags.sh [git commit sha1] [git branch name] [git tag name]'
exit 1
fi
@@ -50,9 +50,9 @@ elif [[ $GIT_BRANCH =~ ^bifrost-.* ]]; then
branch=$(echo "$GIT_BRANCH" | tr '/' '-' | tr --delete --complement '[:alnum:]-')
echoImageName "${branch}-${BUILD_NUM}-${GIT_SHA1_SHORT}"
-elif [ "$GIT_BRANCH" = "master" ]; then
- echoImageName "master-${BUILD_NUM}-${GIT_SHA1_SHORT}"
- echoImageName "master-latest"
+elif [ "$GIT_BRANCH" = "master" ] || [ "$GIT_BRANCH" = "staging" ]; then
+ echoImageName "${GIT_BRANCH}-${BUILD_NUM}-${GIT_SHA1_SHORT}"
+ echoImageName "${GIT_BRANCH}-latest"
else
echo "Nothing to do. No docker tag defined for branch: $GIT_BRANCH, tag: $GIT_TAG"
diff --git a/bin/ipns-republish b/bin/ipns-republish
index f5535ee4c4a..5fc81cd5724 100755
--- a/bin/ipns-republish
+++ b/bin/ipns-republish
@@ -19,7 +19,7 @@ if [ $? -ne 0 ]; then
fi
# check the object is there
-ipfs object stat "$1" >/dev/null
+ipfs dag stat "$1" >/dev/null
if [ $? -ne 0 ]; then
echo "error: ipfs cannot find $1"
exit 1
diff --git a/bin/push-docker-tags.sh b/bin/push-docker-tags.sh
index af809b989e5..a33948307ee 100755
--- a/bin/push-docker-tags.sh
+++ b/bin/push-docker-tags.sh
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
-
+#
+# TODO: this script is legacy, use get-docker-tags.sh instead.
+#
# push-docker-tags.sh
#
# Run from ci to tag images based on the current branch or tag name.
@@ -68,9 +70,9 @@ elif [[ $GIT_BRANCH =~ ^bifrost-.* ]]; then
branch=$(echo "$GIT_BRANCH" | tr '/' '-' | tr --delete --complement '[:alnum:]-')
pushTag "${branch}-${BUILD_NUM}-${GIT_SHA1_SHORT}"
-elif [ "$GIT_BRANCH" = "master" ]; then
- pushTag "master-${BUILD_NUM}-${GIT_SHA1_SHORT}"
- pushTag "master-latest"
+elif [ "$GIT_BRANCH" = "master" ] || [ "$GIT_BRANCH" = "staging" ]; then
+ pushTag "${GIT_BRANCH}-${BUILD_NUM}-${GIT_SHA1_SHORT}"
+ pushTag "${GIT_BRANCH}-latest"
else
echo "Nothing to do. No docker tag defined for branch: $GIT_BRANCH, tag: $GIT_TAG"
diff --git a/client/rpc/README.md b/client/rpc/README.md
index a020aa9da27..d9744e5b6e3 100644
--- a/client/rpc/README.md
+++ b/client/rpc/README.md
@@ -2,7 +2,7 @@
> IPFS CoreAPI implementation using HTTP API
-This packages implements [`coreiface.CoreAPI`](https://pkg.go.dev/github.com/ipfs/boxo/coreiface#CoreAPI) over the HTTP API.
+This package implements [`coreiface.CoreAPI`](https://pkg.go.dev/github.com/ipfs/kubo/core/coreiface#CoreAPI) over the HTTP API.
## Documentation
@@ -16,29 +16,33 @@ Pin file on your local IPFS node based on its CID:
package main
import (
- "context"
- "fmt"
+ "context"
+ "fmt"
- "github.com/ipfs/kubo/client/rpc"
- path "github.com/ipfs/boxo/coreiface/path"
+ "github.com/ipfs/boxo/path"
+ "github.com/ipfs/go-cid"
+ "github.com/ipfs/kubo/client/rpc"
)
func main() {
- // "Connect" to local node
- node, err := rpc.NewLocalApi()
- if err != nil {
- fmt.Printf(err)
- return
- }
- // Pin a given file by its CID
- ctx := context.Background()
- cid := "bafkreidtuosuw37f5xmn65b3ksdiikajy7pwjjslzj2lxxz2vc4wdy3zku"
- p := path.New(cid)
- err = node.Pin().Add(ctx, p)
- if err != nil {
- fmt.Printf(err)
- return
- }
- return
+ // "Connect" to local node
+ node, err := rpc.NewLocalApi()
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ // Pin a given file by its CID
+ ctx := context.Background()
+ c, err := cid.Decode("bafkreidtuosuw37f5xmn65b3ksdiikajy7pwjjslzj2lxxz2vc4wdy3zku")
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ p := path.FromCid(c)
+ err = node.Pin().Add(ctx, p)
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
}
```
diff --git a/client/rpc/api.go b/client/rpc/api.go
index 48a80388fd8..c4b73d387c2 100644
--- a/client/rpc/api.go
+++ b/client/rpc/api.go
@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "net"
"net/http"
"os"
"path/filepath"
@@ -19,10 +20,10 @@ import (
ipfs "github.com/ipfs/kubo"
iface "github.com/ipfs/kubo/core/coreiface"
caopts "github.com/ipfs/kubo/core/coreiface/options"
+ "github.com/ipfs/kubo/misc/fsutil"
dagpb "github.com/ipld/go-codec-dagpb"
_ "github.com/ipld/go-ipld-prime/codec/dagcbor"
"github.com/ipld/go-ipld-prime/node/basicnode"
- "github.com/mitchellh/go-homedir"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
)
@@ -81,7 +82,7 @@ func NewPathApi(ipfspath string) (*HttpApi, error) {
// ApiAddr reads api file in specified ipfs path.
func ApiAddr(ipfspath string) (ma.Multiaddr, error) {
- baseDir, err := homedir.Expand(ipfspath)
+ baseDir, err := fsutil.ExpandHome(ipfspath)
if err != nil {
return nil, err
}
@@ -98,11 +99,29 @@ func ApiAddr(ipfspath string) (ma.Multiaddr, error) {
// NewApi constructs HttpApi with specified endpoint.
func NewApi(a ma.Multiaddr) (*HttpApi, error) {
+ transport := &http.Transport{
+ Proxy: http.ProxyFromEnvironment,
+ DisableKeepAlives: true,
+ }
+
+ network, address, err := manet.DialArgs(a)
+ if err != nil {
+ return nil, err
+ }
+ if network == "unix" {
+ transport.DialContext = func(_ context.Context, _, _ string) (net.Conn, error) {
+ return net.Dial("unix", address)
+ }
+ c := &http.Client{
+ Transport: transport,
+ }
+ // This will create an API client which
+ // makes requests to `http://unix`.
+ return NewURLApiWithClient(network, c)
+ }
+
c := &http.Client{
- Transport: &http.Transport{
- Proxy: http.ProxyFromEnvironment,
- DisableKeepAlives: true,
- },
+ Transport: transport,
}
return NewApiWithClient(a, c)
@@ -227,10 +246,6 @@ func (api *HttpApi) Object() iface.ObjectAPI {
return (*ObjectAPI)(api)
}
-func (api *HttpApi) Dht() iface.DhtAPI {
- return (*DhtAPI)(api)
-}
-
func (api *HttpApi) Swarm() iface.SwarmAPI {
return (*SwarmAPI)(api)
}
diff --git a/client/rpc/api_test.go b/client/rpc/api_test.go
index 25bd26ceea6..c0da3d7b04e 100644
--- a/client/rpc/api_test.go
+++ b/client/rpc/api_test.go
@@ -46,7 +46,6 @@ func (np NodeProvider) MakeAPISwarm(t *testing.T, ctx context.Context, fullIdent
c := n.ReadConfig()
c.Experimental.FilestoreEnabled = true
n.WriteConfig(c)
-
n.StartDaemon("--enable-pubsub-experiment", "--offline="+strconv.FormatBool(!online))
if online {
diff --git a/client/rpc/apifile.go b/client/rpc/apifile.go
index 7a54995b181..57d82c5f712 100644
--- a/client/rpc/apifile.go
+++ b/client/rpc/apifile.go
@@ -1,10 +1,14 @@
package rpc
import (
+ "bytes"
"context"
"encoding/json"
"fmt"
"io"
+ "os"
+ "strconv"
+ "time"
"github.com/ipfs/boxo/files"
unixfs "github.com/ipfs/boxo/ipld/unixfs"
@@ -24,20 +28,35 @@ func (api *UnixfsAPI) Get(ctx context.Context, p path.Path) (files.Node, error)
}
var stat struct {
- Hash string
- Type string
- Size int64 // unixfs size
+ Hash string
+ Type string
+ Size int64 // unixfs size
+ Mode string
+ Mtime int64
+ MtimeNsecs int
}
err := api.core().Request("files/stat", p.String()).Exec(ctx, &stat)
if err != nil {
return nil, err
}
+ mode, err := stringToFileMode(stat.Mode)
+ if err != nil {
+ return nil, err
+ }
+
+ var modTime time.Time
+ if stat.Mtime != 0 {
+ modTime = time.Unix(stat.Mtime, int64(stat.MtimeNsecs)).UTC()
+ }
+
switch stat.Type {
case "file":
- return api.getFile(ctx, p, stat.Size)
+ return api.getFile(ctx, p, stat.Size, mode, modTime)
case "directory":
- return api.getDir(ctx, p, stat.Size)
+ return api.getDir(ctx, p, stat.Size, mode, modTime)
+ case "symlink":
+ return api.getSymlink(ctx, p, modTime)
default:
return nil, fmt.Errorf("unsupported file type '%s'", stat.Type)
}
@@ -49,6 +68,9 @@ type apiFile struct {
size int64
path path.Path
+ mode os.FileMode
+ mtime time.Time
+
r *Response
at int64
}
@@ -128,16 +150,37 @@ func (f *apiFile) Close() error {
return nil
}
+func (f *apiFile) Mode() os.FileMode {
+ return f.mode
+}
+
+func (f *apiFile) ModTime() time.Time {
+ return f.mtime
+}
+
func (f *apiFile) Size() (int64, error) {
return f.size, nil
}
-func (api *UnixfsAPI) getFile(ctx context.Context, p path.Path, size int64) (files.Node, error) {
+func stringToFileMode(mode string) (os.FileMode, error) {
+ if mode == "" {
+ return 0, nil
+ }
+ mode64, err := strconv.ParseUint(mode, 8, 32)
+ if err != nil {
+ return 0, fmt.Errorf("cannot parse mode %s: %s", mode, err)
+ }
+ return os.FileMode(uint32(mode64)), nil
+}
+
+func (api *UnixfsAPI) getFile(ctx context.Context, p path.Path, size int64, mode os.FileMode, mtime time.Time) (files.Node, error) {
f := &apiFile{
- ctx: ctx,
- core: api.core(),
- size: size,
- path: p,
+ ctx: ctx,
+ core: api.core(),
+ size: size,
+ path: p,
+ mode: mode,
+ mtime: mtime,
}
return f, f.reset()
@@ -195,13 +238,19 @@ func (it *apiIter) Next() bool {
switch it.cur.Type {
case unixfs.THAMTShard, unixfs.TMetadata, unixfs.TDirectory:
- it.curFile, err = it.core.getDir(it.ctx, path.FromCid(c), int64(it.cur.Size))
+ it.curFile, err = it.core.getDir(it.ctx, path.FromCid(c), int64(it.cur.Size), it.cur.Mode, it.cur.ModTime)
if err != nil {
it.err = err
return false
}
case unixfs.TFile:
- it.curFile, err = it.core.getFile(it.ctx, path.FromCid(c), int64(it.cur.Size))
+ it.curFile, err = it.core.getFile(it.ctx, path.FromCid(c), int64(it.cur.Size), it.cur.Mode, it.cur.ModTime)
+ if err != nil {
+ it.err = err
+ return false
+ }
+ case unixfs.TSymlink:
+ it.curFile, err = it.core.getSymlink(it.ctx, path.FromCid(c), it.cur.ModTime)
if err != nil {
it.err = err
return false
@@ -223,6 +272,9 @@ type apiDir struct {
size int64
path path.Path
+ mode os.FileMode
+ mtime time.Time
+
dec *json.Decoder
}
@@ -230,6 +282,14 @@ func (d *apiDir) Close() error {
return nil
}
+func (d *apiDir) Mode() os.FileMode {
+ return d.mode
+}
+
+func (d *apiDir) ModTime() time.Time {
+ return d.mtime
+}
+
func (d *apiDir) Size() (int64, error) {
return d.size, nil
}
@@ -242,7 +302,7 @@ func (d *apiDir) Entries() files.DirIterator {
}
}
-func (api *UnixfsAPI) getDir(ctx context.Context, p path.Path, size int64) (files.Node, error) {
+func (api *UnixfsAPI) getDir(ctx context.Context, p path.Path, size int64, mode os.FileMode, modTime time.Time) (files.Node, error) {
resp, err := api.core().Request("ls", p.String()).
Option("resolve-size", true).
Option("stream", true).Send(ctx)
@@ -253,18 +313,43 @@ func (api *UnixfsAPI) getDir(ctx context.Context, p path.Path, size int64) (file
return nil, resp.Error
}
- d := &apiDir{
- ctx: ctx,
- core: api,
- size: size,
- path: p,
+ data, _ := io.ReadAll(resp.Output)
+ rdr := bytes.NewReader(data)
- dec: json.NewDecoder(resp.Output),
+ d := &apiDir{
+ ctx: ctx,
+ core: api,
+ size: size,
+ path: p,
+ mode: mode,
+ mtime: modTime,
+
+ //dec: json.NewDecoder(resp.Output),
+ dec: json.NewDecoder(rdr),
}
return d, nil
}
+func (api *UnixfsAPI) getSymlink(ctx context.Context, p path.Path, modTime time.Time) (files.Node, error) {
+ resp, err := api.core().Request("cat", p.String()).
+ Option("resolve-size", true).
+ Option("stream", true).Send(ctx)
+ if err != nil {
+ return nil, err
+ }
+ if resp.Error != nil {
+ return nil, resp.Error
+ }
+
+ target, err := io.ReadAll(resp.Output)
+ if err != nil {
+ return nil, err
+ }
+
+ return files.NewSymlinkFile(string(target), modTime), nil
+}
+
var (
_ files.File = &apiFile{}
_ files.Directory = &apiDir{}
diff --git a/client/rpc/dht.go b/client/rpc/dht.go
deleted file mode 100644
index 1b2c863980d..00000000000
--- a/client/rpc/dht.go
+++ /dev/null
@@ -1,113 +0,0 @@
-package rpc
-
-import (
- "context"
- "encoding/json"
-
- "github.com/ipfs/boxo/path"
- caopts "github.com/ipfs/kubo/core/coreiface/options"
- "github.com/libp2p/go-libp2p/core/peer"
- "github.com/libp2p/go-libp2p/core/routing"
-)
-
-type DhtAPI HttpApi
-
-func (api *DhtAPI) FindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) {
- var out struct {
- Type routing.QueryEventType
- Responses []peer.AddrInfo
- }
- resp, err := api.core().Request("dht/findpeer", p.String()).Send(ctx)
- if err != nil {
- return peer.AddrInfo{}, err
- }
- if resp.Error != nil {
- return peer.AddrInfo{}, resp.Error
- }
- defer resp.Close()
- dec := json.NewDecoder(resp.Output)
- for {
- if err := dec.Decode(&out); err != nil {
- return peer.AddrInfo{}, err
- }
- if out.Type == routing.FinalPeer {
- return out.Responses[0], nil
- }
- }
-}
-
-func (api *DhtAPI) FindProviders(ctx context.Context, p path.Path, opts ...caopts.DhtFindProvidersOption) (<-chan peer.AddrInfo, error) {
- options, err := caopts.DhtFindProvidersOptions(opts...)
- if err != nil {
- return nil, err
- }
-
- rp, _, err := api.core().ResolvePath(ctx, p)
- if err != nil {
- return nil, err
- }
-
- resp, err := api.core().Request("dht/findprovs", rp.RootCid().String()).
- Option("num-providers", options.NumProviders).
- Send(ctx)
- if err != nil {
- return nil, err
- }
- if resp.Error != nil {
- return nil, resp.Error
- }
- res := make(chan peer.AddrInfo)
-
- go func() {
- defer resp.Close()
- defer close(res)
- dec := json.NewDecoder(resp.Output)
-
- for {
- var out struct {
- Extra string
- Type routing.QueryEventType
- Responses []peer.AddrInfo
- }
-
- if err := dec.Decode(&out); err != nil {
- return // todo: handle this somehow
- }
- if out.Type == routing.QueryError {
- return // usually a 'not found' error
- // todo: handle other errors
- }
- if out.Type == routing.Provider {
- for _, pi := range out.Responses {
- select {
- case res <- pi:
- case <-ctx.Done():
- return
- }
- }
- }
- }
- }()
-
- return res, nil
-}
-
-func (api *DhtAPI) Provide(ctx context.Context, p path.Path, opts ...caopts.DhtProvideOption) error {
- options, err := caopts.DhtProvideOptions(opts...)
- if err != nil {
- return err
- }
-
- rp, _, err := api.core().ResolvePath(ctx, p)
- if err != nil {
- return err
- }
-
- return api.core().Request("dht/provide", rp.RootCid().String()).
- Option("recursive", options.Recursive).
- Exec(ctx, nil)
-}
-
-func (api *DhtAPI) core() *HttpApi {
- return (*HttpApi)(api)
-}
diff --git a/client/rpc/errors.go b/client/rpc/errors.go
index 84340b550e2..29f5487d442 100644
--- a/client/rpc/errors.go
+++ b/client/rpc/errors.go
@@ -68,11 +68,11 @@ func parseErrNotFound(msg string) (error, bool) {
// Assume CIDs break on:
// - Whitespaces: " \t\n\r\v\f"
// - Semicolon: ";" this is to parse ipld.ErrNotFound wrapped in multierr
-// - Double Quotes: "\"" this is for parsing %q and %#v formating.
+// - Double Quotes: "\"" this is for parsing %q and %#v formatting.
const cidBreakSet = " \t\n\r\v\f;\""
func parseIPLDErrNotFound(msg string) (error, bool) {
- // The patern we search for is:
+ // The pattern we search for is:
const ipldErrNotFoundKey = "ipld: could not find " /*CID*/
// We try to parse the CID, if it's invalid we give up and return a simple text error.
// We also accept "node" in place of the CID because that means it's an Undefined CID.
@@ -138,7 +138,7 @@ func parseIPLDErrNotFound(msg string) (error, bool) {
// This is a simple error type that just return msg as Error().
// But that also match ipld.ErrNotFound when called with Is(err).
-// That is needed to keep compatiblity with code that use string.Contains(err.Error(), "blockstore: block not found")
+// That is needed to keep compatibility with code that use string.Contains(err.Error(), "blockstore: block not found")
// and code using ipld.ErrNotFound.
type blockstoreNotFoundMatchingIPLDErrNotFound struct {
msg string
diff --git a/client/rpc/object.go b/client/rpc/object.go
index 9e00bfb7711..5c9d323e87b 100644
--- a/client/rpc/object.go
+++ b/client/rpc/object.go
@@ -1,16 +1,10 @@
package rpc
import (
- "bytes"
"context"
- "fmt"
- "io"
- "github.com/ipfs/boxo/ipld/merkledag"
- ft "github.com/ipfs/boxo/ipld/unixfs"
"github.com/ipfs/boxo/path"
"github.com/ipfs/go-cid"
- ipld "github.com/ipfs/go-ipld-format"
iface "github.com/ipfs/kubo/core/coreiface"
caopts "github.com/ipfs/kubo/core/coreiface/options"
)
@@ -21,138 +15,6 @@ type objectOut struct {
Hash string
}
-func (api *ObjectAPI) New(ctx context.Context, opts ...caopts.ObjectNewOption) (ipld.Node, error) {
- options, err := caopts.ObjectNewOptions(opts...)
- if err != nil {
- return nil, err
- }
-
- var n ipld.Node
- switch options.Type {
- case "empty":
- n = new(merkledag.ProtoNode)
- case "unixfs-dir":
- n = ft.EmptyDirNode()
- default:
- return nil, fmt.Errorf("unknown object type: %s", options.Type)
- }
-
- return n, nil
-}
-
-func (api *ObjectAPI) Put(ctx context.Context, r io.Reader, opts ...caopts.ObjectPutOption) (path.ImmutablePath, error) {
- options, err := caopts.ObjectPutOptions(opts...)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- var out objectOut
- err = api.core().Request("object/put").
- Option("inputenc", options.InputEnc).
- Option("datafieldenc", options.DataType).
- Option("pin", options.Pin).
- FileBody(r).
- Exec(ctx, &out)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- c, err := cid.Parse(out.Hash)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- return path.FromCid(c), nil
-}
-
-func (api *ObjectAPI) Get(ctx context.Context, p path.Path) (ipld.Node, error) {
- r, err := api.core().Block().Get(ctx, p)
- if err != nil {
- return nil, err
- }
- b, err := io.ReadAll(r)
- if err != nil {
- return nil, err
- }
-
- return merkledag.DecodeProtobuf(b)
-}
-
-func (api *ObjectAPI) Data(ctx context.Context, p path.Path) (io.Reader, error) {
- resp, err := api.core().Request("object/data", p.String()).Send(ctx)
- if err != nil {
- return nil, err
- }
- if resp.Error != nil {
- return nil, resp.Error
- }
-
- // TODO: make Data return ReadCloser to avoid copying
- defer resp.Close()
- b := new(bytes.Buffer)
- if _, err := io.Copy(b, resp.Output); err != nil {
- return nil, err
- }
-
- return b, nil
-}
-
-func (api *ObjectAPI) Links(ctx context.Context, p path.Path) ([]*ipld.Link, error) {
- var out struct {
- Links []struct {
- Name string
- Hash string
- Size uint64
- }
- }
- if err := api.core().Request("object/links", p.String()).Exec(ctx, &out); err != nil {
- return nil, err
- }
- res := make([]*ipld.Link, len(out.Links))
- for i, l := range out.Links {
- c, err := cid.Parse(l.Hash)
- if err != nil {
- return nil, err
- }
-
- res[i] = &ipld.Link{
- Cid: c,
- Name: l.Name,
- Size: l.Size,
- }
- }
-
- return res, nil
-}
-
-func (api *ObjectAPI) Stat(ctx context.Context, p path.Path) (*iface.ObjectStat, error) {
- var out struct {
- Hash string
- NumLinks int
- BlockSize int
- LinksSize int
- DataSize int
- CumulativeSize int
- }
- if err := api.core().Request("object/stat", p.String()).Exec(ctx, &out); err != nil {
- return nil, err
- }
-
- c, err := cid.Parse(out.Hash)
- if err != nil {
- return nil, err
- }
-
- return &iface.ObjectStat{
- Cid: c,
- NumLinks: out.NumLinks,
- BlockSize: out.BlockSize,
- LinksSize: out.LinksSize,
- DataSize: out.DataSize,
- CumulativeSize: out.CumulativeSize,
- }, nil
-}
-
func (api *ObjectAPI) AddLink(ctx context.Context, base path.Path, name string, child path.Path, opts ...caopts.ObjectAddLinkOption) (path.ImmutablePath, error) {
options, err := caopts.ObjectAddLinkOptions(opts...)
if err != nil {
@@ -191,40 +53,6 @@ func (api *ObjectAPI) RmLink(ctx context.Context, base path.Path, link string) (
return path.FromCid(c), nil
}
-func (api *ObjectAPI) AppendData(ctx context.Context, p path.Path, r io.Reader) (path.ImmutablePath, error) {
- var out objectOut
- err := api.core().Request("object/patch/append-data", p.String()).
- FileBody(r).
- Exec(ctx, &out)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- c, err := cid.Parse(out.Hash)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- return path.FromCid(c), nil
-}
-
-func (api *ObjectAPI) SetData(ctx context.Context, p path.Path, r io.Reader) (path.ImmutablePath, error) {
- var out objectOut
- err := api.core().Request("object/patch/set-data", p.String()).
- FileBody(r).
- Exec(ctx, &out)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- c, err := cid.Parse(out.Hash)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- return path.FromCid(c), nil
-}
-
type change struct {
Type iface.ChangeType
Path string
diff --git a/client/rpc/pin.go b/client/rpc/pin.go
index a0469861c7e..2b1ef825801 100644
--- a/client/rpc/pin.go
+++ b/client/rpc/pin.go
@@ -3,6 +3,7 @@ package rpc
import (
"context"
"encoding/json"
+ "errors"
"io"
"strings"
@@ -10,7 +11,6 @@ import (
"github.com/ipfs/go-cid"
iface "github.com/ipfs/kubo/core/coreiface"
caopts "github.com/ipfs/kubo/core/coreiface/options"
- "github.com/pkg/errors"
)
type PinAPI HttpApi
@@ -62,10 +62,12 @@ type pinLsObject struct {
Type string
}
-func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) (<-chan iface.Pin, error) {
+func (api *PinAPI) Ls(ctx context.Context, pins chan<- iface.Pin, opts ...caopts.PinLsOption) error {
+ defer close(pins)
+
options, err := caopts.PinLsOptions(opts...)
if err != nil {
- return nil, err
+ return err
}
res, err := api.core().Request("pin/ls").
@@ -73,48 +75,32 @@ func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) (<-chan i
Option("stream", true).
Send(ctx)
if err != nil {
- return nil, err
+ return err
}
-
- pins := make(chan iface.Pin)
- go func(ch chan<- iface.Pin) {
- defer res.Output.Close()
- defer close(ch)
-
- dec := json.NewDecoder(res.Output)
- var out pinLsObject
- for {
- switch err := dec.Decode(&out); err {
- case nil:
- case io.EOF:
- return
- default:
- select {
- case ch <- pin{err: err}:
- return
- case <-ctx.Done():
- return
- }
+ defer res.Output.Close()
+
+ dec := json.NewDecoder(res.Output)
+ var out pinLsObject
+ for {
+ err := dec.Decode(&out)
+ if err != nil {
+ if err != io.EOF {
+ return err
}
+ return nil
+ }
- c, err := cid.Parse(out.Cid)
- if err != nil {
- select {
- case ch <- pin{err: err}:
- return
- case <-ctx.Done():
- return
- }
- }
+ c, err := cid.Parse(out.Cid)
+ if err != nil {
+ return err
+ }
- select {
- case ch <- pin{typ: out.Type, name: out.Name, path: path.FromCid(c)}:
- case <-ctx.Done():
- return
- }
+ select {
+ case pins <- pin{typ: out.Type, name: out.Name, path: path.FromCid(c)}:
+ case <-ctx.Done():
+ return ctx.Err()
}
- }(pins)
- return pins, nil
+ }
}
// IsPinned returns whether or not the given cid is pinned
diff --git a/client/rpc/routing.go b/client/rpc/routing.go
index 2ecf25f8b45..693f155c6b0 100644
--- a/client/rpc/routing.go
+++ b/client/rpc/routing.go
@@ -6,7 +6,9 @@ import (
"encoding/base64"
"encoding/json"
+ "github.com/ipfs/boxo/path"
"github.com/ipfs/kubo/core/coreiface/options"
+ "github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/routing"
)
@@ -58,6 +60,102 @@ func (api *RoutingAPI) Put(ctx context.Context, key string, value []byte, opts .
return nil
}
+func (api *RoutingAPI) FindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) {
+ var out struct {
+ Type routing.QueryEventType
+ Responses []peer.AddrInfo
+ }
+ resp, err := api.core().Request("routing/findpeer", p.String()).Send(ctx)
+ if err != nil {
+ return peer.AddrInfo{}, err
+ }
+ if resp.Error != nil {
+ return peer.AddrInfo{}, resp.Error
+ }
+ defer resp.Close()
+ dec := json.NewDecoder(resp.Output)
+ for {
+ if err := dec.Decode(&out); err != nil {
+ return peer.AddrInfo{}, err
+ }
+ if out.Type == routing.FinalPeer {
+ return out.Responses[0], nil
+ }
+ }
+}
+
+func (api *RoutingAPI) FindProviders(ctx context.Context, p path.Path, opts ...options.RoutingFindProvidersOption) (<-chan peer.AddrInfo, error) {
+ options, err := options.RoutingFindProvidersOptions(opts...)
+ if err != nil {
+ return nil, err
+ }
+
+ rp, _, err := api.core().ResolvePath(ctx, p)
+ if err != nil {
+ return nil, err
+ }
+
+ resp, err := api.core().Request("routing/findprovs", rp.RootCid().String()).
+ Option("num-providers", options.NumProviders).
+ Send(ctx)
+ if err != nil {
+ return nil, err
+ }
+ if resp.Error != nil {
+ return nil, resp.Error
+ }
+ res := make(chan peer.AddrInfo)
+
+ go func() {
+ defer resp.Close()
+ defer close(res)
+ dec := json.NewDecoder(resp.Output)
+
+ for {
+ var out struct {
+ Extra string
+ Type routing.QueryEventType
+ Responses []peer.AddrInfo
+ }
+
+ if err := dec.Decode(&out); err != nil {
+ return // todo: handle this somehow
+ }
+ if out.Type == routing.QueryError {
+ return // usually a 'not found' error
+ // todo: handle other errors
+ }
+ if out.Type == routing.Provider {
+ for _, pi := range out.Responses {
+ select {
+ case res <- pi:
+ case <-ctx.Done():
+ return
+ }
+ }
+ }
+ }
+ }()
+
+ return res, nil
+}
+
+func (api *RoutingAPI) Provide(ctx context.Context, p path.Path, opts ...options.RoutingProvideOption) error {
+ options, err := options.RoutingProvideOptions(opts...)
+ if err != nil {
+ return err
+ }
+
+ rp, _, err := api.core().ResolvePath(ctx, p)
+ if err != nil {
+ return err
+ }
+
+ return api.core().Request("routing/provide", rp.RootCid().String()).
+ Option("recursive", options.Recursive).
+ Exec(ctx, nil)
+}
+
func (api *RoutingAPI) core() *HttpApi {
return (*HttpApi)(api)
}
diff --git a/client/rpc/unixfs.go b/client/rpc/unixfs.go
index 501e8d02511..316cc21a8ec 100644
--- a/client/rpc/unixfs.go
+++ b/client/rpc/unixfs.go
@@ -6,6 +6,8 @@ import (
"errors"
"fmt"
"io"
+ "os"
+ "time"
"github.com/ipfs/boxo/files"
unixfs "github.com/ipfs/boxo/ipld/unixfs"
@@ -80,14 +82,13 @@ func (api *UnixfsAPI) Add(ctx context.Context, f files.Node, opts ...caopts.Unix
}
defer resp.Output.Close()
dec := json.NewDecoder(resp.Output)
-loop:
+
for {
var evt addEvent
- switch err := dec.Decode(&evt); err {
- case nil:
- case io.EOF:
- break loop
- default:
+ if err := dec.Decode(&evt); err != nil {
+ if errors.Is(err, io.EOF) {
+ break
+ }
return path.ImmutablePath{}, err
}
out = evt
@@ -129,6 +130,9 @@ type lsLink struct {
Size uint64
Type unixfs_pb.Data_DataType
Target string
+
+ Mode os.FileMode
+ ModTime time.Time
}
type lsObject struct {
@@ -140,10 +144,12 @@ type lsOutput struct {
Objects []lsObject
}
-func (api *UnixfsAPI) Ls(ctx context.Context, p path.Path, opts ...caopts.UnixfsLsOption) (<-chan iface.DirEntry, error) {
+func (api *UnixfsAPI) Ls(ctx context.Context, p path.Path, out chan<- iface.DirEntry, opts ...caopts.UnixfsLsOption) error {
+ defer close(out)
+
options, err := caopts.UnixfsLsOptions(opts...)
if err != nil {
- return nil, err
+ return err
}
resp, err := api.core().Request("ls", p.String()).
@@ -152,83 +158,64 @@ func (api *UnixfsAPI) Ls(ctx context.Context, p path.Path, opts ...caopts.Unixfs
Option("stream", true).
Send(ctx)
if err != nil {
- return nil, err
+ return err
}
if resp.Error != nil {
- return nil, resp.Error
+ return err
}
+ defer resp.Close()
dec := json.NewDecoder(resp.Output)
- out := make(chan iface.DirEntry)
- go func() {
- defer resp.Close()
- defer close(out)
-
- for {
- var link lsOutput
- if err := dec.Decode(&link); err != nil {
- if err == io.EOF {
- return
- }
- select {
- case out <- iface.DirEntry{Err: err}:
- case <-ctx.Done():
- }
- return
- }
-
- if len(link.Objects) != 1 {
- select {
- case out <- iface.DirEntry{Err: errors.New("unexpected Objects len")}:
- case <-ctx.Done():
- }
- return
+ for {
+ var link lsOutput
+ if err = dec.Decode(&link); err != nil {
+ if err != io.EOF {
+ return err
}
+ return nil
+ }
- if len(link.Objects[0].Links) != 1 {
- select {
- case out <- iface.DirEntry{Err: errors.New("unexpected Links len")}:
- case <-ctx.Done():
- }
- return
- }
+ if len(link.Objects) != 1 {
+ return errors.New("unexpected Objects len")
+ }
- l0 := link.Objects[0].Links[0]
+ if len(link.Objects[0].Links) != 1 {
+ return errors.New("unexpected Links len")
+ }
- c, err := cid.Decode(l0.Hash)
- if err != nil {
- select {
- case out <- iface.DirEntry{Err: err}:
- case <-ctx.Done():
- }
- return
- }
+ l0 := link.Objects[0].Links[0]
- var ftype iface.FileType
- switch l0.Type {
- case unixfs.TRaw, unixfs.TFile:
- ftype = iface.TFile
- case unixfs.THAMTShard, unixfs.TDirectory, unixfs.TMetadata:
- ftype = iface.TDirectory
- case unixfs.TSymlink:
- ftype = iface.TSymlink
- }
+ c, err := cid.Decode(l0.Hash)
+ if err != nil {
+ return err
+ }
- select {
- case out <- iface.DirEntry{
- Name: l0.Name,
- Cid: c,
- Size: l0.Size,
- Type: ftype,
- Target: l0.Target,
- }:
- case <-ctx.Done():
- }
+ var ftype iface.FileType
+ switch l0.Type {
+ case unixfs.TRaw, unixfs.TFile:
+ ftype = iface.TFile
+ case unixfs.THAMTShard, unixfs.TDirectory, unixfs.TMetadata:
+ ftype = iface.TDirectory
+ case unixfs.TSymlink:
+ ftype = iface.TSymlink
}
- }()
- return out, nil
+ select {
+ case out <- iface.DirEntry{
+ Name: l0.Name,
+ Cid: c,
+ Size: l0.Size,
+ Type: ftype,
+ Target: l0.Target,
+
+ Mode: l0.Mode,
+ ModTime: l0.ModTime,
+ }:
+ case <-ctx.Done():
+ return ctx.Err()
+ }
+ }
}
func (api *UnixfsAPI) core() *HttpApi {
diff --git a/cmd/ipfs/dist/README.md b/cmd/ipfs/dist/README.md
index 4517f655b7b..7ff65e9f2d2 100644
--- a/cmd/ipfs/dist/README.md
+++ b/cmd/ipfs/dist/README.md
@@ -1,6 +1,7 @@
# ipfs command line tool
-This is the [ipfs](http://ipfs.io) command line tool. It contains a full ipfs node.
+This is a [command line tool for interacting with Kubo](https://docs.ipfs.tech/install/command-line/),
+an [IPFS](https://ipfs.tech) implementation. It contains a full IPFS node.
## Install
diff --git a/cmd/ipfs/kubo/daemon.go b/cmd/ipfs/kubo/daemon.go
index 82f24089710..94b633f7941 100644
--- a/cmd/ipfs/kubo/daemon.go
+++ b/cmd/ipfs/kubo/daemon.go
@@ -1,20 +1,22 @@
package kubo
import (
+ "context"
"errors"
_ "expvar"
"fmt"
+ "math"
"net"
"net/http"
_ "net/http/pprof"
"os"
+ "regexp"
"runtime"
"sort"
+ "strings"
"sync"
"time"
- multierror "github.com/hashicorp/go-multierror"
-
cmds "github.com/ipfs/go-ipfs-cmds"
mprome "github.com/ipfs/go-metrics-prometheus"
version "github.com/ipfs/kubo"
@@ -43,6 +45,7 @@ import (
manet "github.com/multiformats/go-multiaddr/net"
prometheus "github.com/prometheus/client_golang/prometheus"
promauto "github.com/prometheus/client_golang/prometheus/promauto"
+ "go.uber.org/multierr"
)
const (
@@ -53,6 +56,7 @@ const (
initProfileOptionKwd = "init-profile"
ipfsMountKwd = "mount-ipfs"
ipnsMountKwd = "mount-ipns"
+ mfsMountKwd = "mount-mfs"
migrateKwd = "migrate"
mountKwd = "mount"
offlineKwd = "offline" // global option
@@ -87,7 +91,7 @@ running, calls to 'ipfs' commands will be sent over the network to
the daemon.
`,
LongDescription: `
-The daemon will start listening on ports on the network, which are
+The Kubo daemon will start listening on ports on the network, which are
documented in (and can be modified through) 'ipfs config Addresses'.
For example, to change the 'Gateway' port:
@@ -107,11 +111,16 @@ other computers in the network, use 0.0.0.0 as the ip address:
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).
+(firewall, authenticated proxy, etc), or at least set API.Authorizations.
+
+If you do not want to open any ports for RPC, and only want to use
+kubo CLI client, it is possible to expose the RPC over Unix socket:
+
+ ipfs config Addresses.API /unix/var/run/kubo.socket
HTTP Headers
-ipfs supports passing arbitrary headers to the RPC API and Gateway. You can
+Kubo 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:
@@ -122,7 +131,7 @@ Note that the value of the keys is an _array_ of strings. This is because
headers can have more than one value, and it is convenient to pass through
to other libraries.
-CORS Headers (for API)
+CORS Headers (for RPC API)
You can setup CORS headers the same way:
@@ -139,7 +148,7 @@ second signal.
IPFS_PATH environment variable
-ipfs uses a repository in the local file system. By default, the repo is
+Kubo uses a repository in the local file system. By default, the repo is
located at ~/.ipfs. To change the repo location, set the $IPFS_PATH
environment variable:
@@ -147,7 +156,7 @@ environment variable:
DEPRECATION NOTICE
-Previously, ipfs used an environment variable as seen below:
+Previously, Kubo used an environment variable as seen below:
export API_ORIGIN="http://localhost:8888/"
@@ -158,14 +167,15 @@ Headers.
},
Options: []cmds.Option{
- cmds.BoolOption(initOptionKwd, "Initialize ipfs with default settings if not already initialized"),
+ cmds.BoolOption(initOptionKwd, "Initialize Kubo with default settings if not already initialized"),
cmds.StringOption(initConfigOptionKwd, "Path to existing configuration file to be loaded during --init"),
cmds.StringOption(initProfileOptionKwd, "Configuration profiles to apply for --init. See ipfs init --help for more"),
cmds.StringOption(routingOptionKwd, "Overrides the routing option").WithDefault(routingOptionDefaultKwd),
cmds.BoolOption(mountKwd, "Mounts IPFS to the filesystem using FUSE (experimental)"),
cmds.StringOption(ipfsMountKwd, "Path to the mountpoint for IPFS (if using --mount). Defaults to config setting."),
cmds.StringOption(ipnsMountKwd, "Path to the mountpoint for IPNS (if using --mount). Defaults to config setting."),
- cmds.BoolOption(unrestrictedAPIAccessKwd, "Allow API access to unlisted hashes"),
+ cmds.StringOption(mfsMountKwd, "Path to the mountpoint for MFS (if using --mount). Defaults to config setting."),
+ cmds.BoolOption(unrestrictedAPIAccessKwd, "Allow RPC API access to unlisted hashes"),
cmds.BoolOption(unencryptTransportKwd, "Disable transport encryption (for debugging protocols)"),
cmds.BoolOption(enableGCKwd, "Enable automatic periodic repo garbage collection"),
cmds.BoolOption(adjustFDLimitKwd, "Check and raise file descriptor limits if needed").WithDefault(true),
@@ -286,7 +296,7 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment
if !domigrate {
fmt.Println("Not running migrations of fs-repo now.")
fmt.Println("Please get fs-repo-migrations from https://dist.ipfs.tech")
- return fmt.Errorf("fs-repo requires migration")
+ return errors.New("fs-repo requires migration")
}
// Read Migration section of IPFS config
@@ -371,6 +381,8 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment
return err
}
+ fmt.Printf("PeerID: %s\n", cfg.Identity.PeerID)
+
if !psSet {
pubsub = cfg.Pubsub.Enabled.WithDefault(false)
}
@@ -399,13 +411,28 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment
}
}
- // 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 {
+ if key, _ := repo.SwarmKey(); key != nil || pnet.ForcePrivateNetwork {
+ // 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 {
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
}
+
+ // Private setups should not use public AutoTLS infrastructure
+ // as it will leak their existence and PeerID identity to CA
+ // and they will show up at https://crt.sh/?q=libp2p.direct
+ enableAutoTLS := cfg.AutoTLS.Enabled.WithDefault(config.DefaultAutoTLSEnabled)
+ if enableAutoTLS {
+ if cfg.AutoTLS.Enabled != config.Default {
+ // hard fail if someone tries to explicitly enable both
+ return errors.New("private networking (swarm.key / LIBP2P_FORCE_PNET) does not work with AutoTLS.Enabled=true, update config to remove this message")
+ } else {
+ // print error and disable autotls if user runs on default settings
+ log.Error("private networking (swarm.key / LIBP2P_FORCE_PNET) is not compatible with AutoTLS. Set AutoTLS.Enabled=false in config to remove this message.")
+ cfg.AutoTLS.Enabled = config.False
+ }
+ }
}
switch routingOption {
@@ -424,8 +451,8 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment
case routingOptionNoneKwd:
ncfg.Routing = libp2p.NilRouterOption
case routingOptionCustomKwd:
- if cfg.Routing.AcceleratedDHTClient {
- return fmt.Errorf("Routing.AcceleratedDHTClient option is set even tho Routing.Type is custom, using custom .AcceleratedDHTClient needs to be set on DHT routers individually")
+ if cfg.Routing.AcceleratedDHTClient.WithDefault(config.DefaultAcceleratedDHTClient) {
+ return errors.New("Routing.AcceleratedDHTClient option is set even tho Routing.Type is custom, using custom .AcceleratedDHTClient needs to be set on DHT routers individually")
}
ncfg.Routing = libp2p.ConstructDelegatedRouting(
cfg.Routing.Routers,
@@ -433,14 +460,17 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment
cfg.Identity.PeerID,
cfg.Addresses,
cfg.Identity.PrivKey,
+ cfg.HTTPRetrieval.Enabled.WithDefault(config.DefaultHTTPRetrievalEnabled),
)
default:
return fmt.Errorf("unrecognized routing option: %s", routingOption)
}
- agentVersionSuffixString, _ := req.Options[agentVersionSuffix].(string)
- if agentVersionSuffixString != "" {
- version.SetUserAgentSuffix(agentVersionSuffixString)
+ // Set optional agent version suffix
+ versionSuffixFromCli, _ := req.Options[agentVersionSuffix].(string)
+ versionSuffix := cfg.Version.AgentSuffix.WithDefault(versionSuffixFromCli)
+ if versionSuffix != "" {
+ version.SetUserAgentSuffix(versionSuffix)
}
node, err := core.NewNode(req.Context, ncfg)
@@ -454,12 +484,20 @@ 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 {
+ if (pnet.ForcePrivateNetwork || node.PNetFingerprint != nil) && (routingOption == routingOptionAutoKwd || routingOption == routingOptionAutoClientKwd) {
// 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)")
}
+ if cfg.Provider.Strategy.WithDefault("") != "" && cfg.Reprovider.Strategy.IsDefault() {
+ log.Fatal("Invalid config. Remove unused Provider.Strategy and set Reprovider.Strategy instead. Documentation: https://github.com/ipfs/kubo/blob/master/docs/config.md#reproviderstrategy")
+ }
+ if cfg.Experimental.StrategicProviding {
+ log.Error("Experimental.StrategicProviding was removed. Remove it from your config and set Provider.Enabled=false to remove this message. Documentation: https://github.com/ipfs/kubo/blob/master/docs/experimental-features.md#strategic-providing")
+ cfg.Experimental.StrategicProviding = false
+ cfg.Provider.Enabled = config.False
+ }
- printSwarmAddrs(node)
+ printLibp2pPorts(node)
if node.PrivateKey.Type() == p2pcrypto.RSA {
fmt.Print(`
@@ -499,7 +537,11 @@ take effect.
if err != nil {
return err
}
- node.Process.AddChild(goprocess.WithTeardown(cctx.Plugins.Close))
+ select {
+ case <-node.Process.Closing():
+ default:
+ node.Process.AddChild(goprocess.WithTeardown(cctx.Plugins.Close))
+ }
// construct api endpoint - every time
apiErrc, err := serveHTTPApi(req, cctx)
@@ -559,7 +601,7 @@ take effect.
// Add ipfs version info to prometheus metrics
ipfsInfoMetric := promauto.NewGaugeVec(prometheus.GaugeOpts{
Name: "ipfs_info",
- Help: "IPFS version information.",
+ Help: "Kubo IPFS version information.",
}, []string{"version", "commit"})
// Setting to 1 lets us multiply it with other stats to add the version labels
@@ -573,7 +615,7 @@ take effect.
prometheus.MustRegister(&corehttp.IpfsNodeCollector{Node: node})
// start MFS pinning thread
- startPinMFS(daemonConfigPollInterval, cctx, &ipfsPinMFSNode{node})
+ startPinMFS(cctx, daemonConfigPollInterval, &ipfsPinMFSNode{node})
// The daemon is *finally* ready.
fmt.Printf("Daemon is ready\n")
@@ -587,12 +629,32 @@ take effect.
fmt.Println("(Hit ctrl-c again to force-shutdown the daemon.)")
}()
- // Give the user heads up if daemon running in online mode has no peers after 1 minute
if !offline {
+ // Warn users when provide systems are disabled
+ if !cfg.Provider.Enabled.WithDefault(config.DefaultProviderEnabled) {
+ fmt.Print(`
+
+⚠️ Provide and Reprovide systems are disabled due to 'Provide.Enabled=false'
+⚠️ Local CIDs will not be announced to Amino DHT, making them impossible to retrieve without manual peering
+⚠️ If this is not intentional, call 'ipfs config profile apply announce-on' or set Provide.Enabled=true'
+
+`)
+ } else if cfg.Reprovider.Interval.WithDefault(config.DefaultReproviderInterval) == 0 {
+ fmt.Print(`
+
+⚠️ Provide and Reprovide systems are disabled due to 'Reprovider.Interval=0'
+⚠️ Local CIDs will not be announced to Amino DHT, making them impossible to retrieve without manual peering
+⚠️ If this is not intentional, call 'ipfs config profile apply announce-on', or set 'Reprovider.Interval=22h'
+
+`)
+ }
+
+ // Give the user heads up if daemon running in online mode has no peers after 1 minute
time.AfterFunc(1*time.Minute, func() {
cfg, err := cctx.GetConfig()
if err != nil {
log.Errorf("failed to access config: %s", err)
+ return
}
if len(cfg.Bootstrap) == 0 && len(cfg.Peering.Peers) == 0 {
// Skip peer check if Bootstrap and Peering lists are empty
@@ -603,13 +665,24 @@ take effect.
ipfs, err := coreapi.NewCoreAPI(node)
if err != nil {
log.Errorf("failed to access CoreAPI: %v", err)
+ return
}
peers, err := ipfs.Swarm().Peers(cctx.Context())
if err != nil {
log.Errorf("failed to read swarm peers: %v", err)
+ return
}
if len(peers) == 0 {
log.Error("failed to bootstrap (no peers found): consider updating Bootstrap or Peering section of your config")
+ } else {
+ // After 1 minute we should have enough peers
+ // to run informed version check
+ startVersionChecker(
+ cctx.Context(),
+ node,
+ cfg.Version.SwarmCheckEnabled.WithDefault(true),
+ cfg.Version.SwarmCheckPercentThreshold.WithDefault(config.DefaultSwarmCheckPercentThreshold),
+ )
}
})
}
@@ -624,7 +697,7 @@ take effect.
var errs error
for err := range merge(apiErrc, gwErrc, gcErrc, p2pGwErrc) {
if err != nil {
- errs = multierror.Append(errs, err)
+ errs = multierr.Append(errs, err)
}
}
@@ -681,10 +754,18 @@ func serveHTTPApi(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, error
for _, listener := range listeners {
// we might have listened to /tcp/0 - let's see what we are listing on
fmt.Printf("RPC API server listening on %s\n", listener.Multiaddr())
- // Browsers require TCP.
+ // Browsers require TCP with explicit host.
switch listener.Addr().Network() {
case "tcp", "tcp4", "tcp6":
- fmt.Printf("WebUI: http://%s/webui\n", listener.Addr())
+ rpc := listener.Addr().String()
+ // replace catch-all with explicit localhost URL that works in browsers
+ // https://github.com/ipfs/kubo/issues/10515
+ if strings.Contains(rpc, "0.0.0.0:") {
+ rpc = strings.Replace(rpc, "0.0.0.0:", "127.0.0.1:", 1)
+ } else if strings.Contains(rpc, "[::]:") {
+ rpc = strings.Replace(rpc, "[::]:", "[::1]:", 1)
+ }
+ fmt.Printf("WebUI: http://%s/webui\n", rpc)
}
}
@@ -754,17 +835,17 @@ func rewriteMaddrToUseLocalhostIfItsAny(maddr ma.Multiaddr) ma.Multiaddr {
first, rest := ma.SplitFirst(maddr)
switch {
- case first.Equal(manet.IP4Unspecified):
+ case first.Equal(&manet.IP4Unspecified[0]):
return manet.IP4Loopback.Encapsulate(rest)
- case first.Equal(manet.IP6Unspecified):
+ case first.Equal(&manet.IP6Unspecified[0]):
return manet.IP6Loopback.Encapsulate(rest)
default:
return maddr // not ip
}
}
-// printSwarmAddrs prints the addresses of the host.
-func printSwarmAddrs(node *core.IpfsNode) {
+// printLibp2pPorts prints which ports are opened to facilitate swarm connectivity.
+func printLibp2pPorts(node *core.IpfsNode) {
if !node.IsOnline {
fmt.Println("Swarm not listening, running in offline mode.")
return
@@ -774,24 +855,49 @@ func printSwarmAddrs(node *core.IpfsNode) {
if err != nil {
log.Errorf("failed to read listening addresses: %s", err)
}
- lisAddrs := make([]string, len(ifaceAddrs))
- for i, addr := range ifaceAddrs {
- lisAddrs[i] = addr.String()
- }
- sort.Strings(lisAddrs)
- for _, addr := range lisAddrs {
- fmt.Printf("Swarm listening on %s\n", addr)
+
+ // Multiple libp2p transports can use same port.
+ // Deduplicate all listeners and collect unique IP:port (udp|tcp) combinations
+ // which is useful information for operator deploying Kubo in TCP/IP infra.
+ addrMap := make(map[string]map[string]struct{})
+ re := regexp.MustCompile(`^/(?:ip[46]|dns(?:[46])?)/([^/]+)/(tcp|udp)/(\d+)(/.*)?$`)
+ for _, addr := range ifaceAddrs {
+ matches := re.FindStringSubmatch(addr.String())
+ if matches != nil {
+ hostname := matches[1]
+ protocol := strings.ToUpper(matches[2])
+ port := matches[3]
+ var host string
+ if matches[0][:4] == "/ip6" {
+ host = fmt.Sprintf("[%s]:%s", hostname, port)
+ } else {
+ host = fmt.Sprintf("%s:%s", hostname, port)
+ }
+ if _, ok := addrMap[host]; !ok {
+ addrMap[host] = make(map[string]struct{})
+ }
+ addrMap[host][protocol] = struct{}{}
+ }
}
- nodePhostAddrs := node.PeerHost.Addrs()
- addrs := make([]string, len(nodePhostAddrs))
- for i, addr := range nodePhostAddrs {
- addrs[i] = addr.String()
+ // Produce a sorted host:port list
+ hosts := make([]string, 0, len(addrMap))
+ for host := range addrMap {
+ hosts = append(hosts, host)
}
- sort.Strings(addrs)
- for _, addr := range addrs {
- fmt.Printf("Swarm announcing %s\n", addr)
+ sort.Strings(hosts)
+
+ // Print listeners
+ for _, host := range hosts {
+ protocolsSet := addrMap[host]
+ protocols := make([]string, 0, len(protocolsSet))
+ for protocol := range protocolsSet {
+ protocols = append(protocols, protocol)
+ }
+ sort.Strings(protocols)
+ fmt.Printf("Swarm listening on %s (%s)\n", host, strings.Join(protocols, "+"))
}
+ fmt.Printf("Run 'ipfs id' to inspect announced and discovered multiaddrs of this node.\n")
}
// serveHTTPGateway collects options, creates listener, prints status message and starts serving requests.
@@ -850,8 +956,6 @@ func serveHTTPGateway(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, e
corehttp.GatewayOption("/ipfs", "/ipns"),
corehttp.VersionOption(),
corehttp.CheckVersionOption(),
- // TODO[api-on-gw]: remove for 0.28.0: https://github.com/ipfs/kubo/issues/10312
- corehttp.CommandsROOption(cmdctx),
}
if cfg.Experimental.P2pHttpProxy {
@@ -932,10 +1036,6 @@ func serveTrustlessGatewayOverLibp2p(cctx *oldcmds.Context) (<-chan error, error
StreamHost: node.PeerHost,
}
- tmpProtocol := protocol.ID("/kubo/delete-me")
- h.SetHTTPHandler(tmpProtocol, http.NotFoundHandler())
- h.WellKnownHandler.RemoveProtocolMeta(tmpProtocol)
-
h.WellKnownHandler.AddProtocolMeta(gatewayProtocolID, p2phttp.ProtocolMeta{Path: "/"})
h.ServeMux = http.NewServeMux()
h.ServeMux.Handle("/", handler)
@@ -965,23 +1065,58 @@ func mountFuse(req *cmds.Request, cctx *oldcmds.Context) error {
if !found {
fsdir = cfg.Mounts.IPFS
}
+ if err := checkFusePath("Mounts.IPFS", fsdir); err != nil {
+ return err
+ }
nsdir, found := req.Options[ipnsMountKwd].(string)
if !found {
nsdir = cfg.Mounts.IPNS
}
+ if err := checkFusePath("Mounts.IPNS", nsdir); err != nil {
+ return err
+ }
+
+ mfsdir, found := req.Options[mfsMountKwd].(string)
+ if !found {
+ mfsdir = cfg.Mounts.MFS
+ }
+ if err := checkFusePath("Mounts.MFS", mfsdir); err != nil {
+ return err
+ }
node, err := cctx.ConstructNode()
if err != nil {
return fmt.Errorf("mountFuse: ConstructNode() failed: %s", err)
}
- err = nodeMount.Mount(node, fsdir, nsdir)
+ err = nodeMount.Mount(node, fsdir, nsdir, mfsdir)
if err != nil {
return err
}
fmt.Printf("IPFS mounted at: %s\n", fsdir)
fmt.Printf("IPNS mounted at: %s\n", nsdir)
+ fmt.Printf("MFS mounted at: %s\n", mfsdir)
+ return nil
+}
+
+func checkFusePath(name, path string) error {
+ if path == "" {
+ return fmt.Errorf("%s path cannot be empty", name)
+ }
+
+ fileInfo, err := os.Stat(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return fmt.Errorf("%s path (%q) does not exist: %w", name, path, err)
+ }
+ return fmt.Errorf("error while inspecting %s path (%q): %w", name, path, err)
+ }
+
+ if !fileInfo.IsDir() {
+ return fmt.Errorf("%s path (%q) is not a directory", name, path)
+ }
+
return nil
}
@@ -1033,7 +1168,11 @@ func YesNoPrompt(prompt string) bool {
var s string
for i := 0; i < 3; i++ {
fmt.Printf("%s ", prompt)
- fmt.Scanf("%s", &s)
+ _, err := fmt.Scanf("%s", &s)
+ if err != nil {
+ fmt.Printf("Invalid input: %v. Please try again.\n", err)
+ continue
+ }
switch s {
case "y", "Y":
return true
@@ -1058,3 +1197,41 @@ func printVersion() {
fmt.Printf("System version: %s\n", runtime.GOARCH+"/"+runtime.GOOS)
fmt.Printf("Golang version: %s\n", runtime.Version())
}
+
+func startVersionChecker(ctx context.Context, nd *core.IpfsNode, enabled bool, percentThreshold int64) {
+ if !enabled {
+ return
+ }
+ ticker := time.NewTicker(time.Hour)
+ defer ticker.Stop()
+ go func() {
+ for {
+ o, err := commands.DetectNewKuboVersion(nd, percentThreshold)
+ if err != nil {
+ // The version check is best-effort, and may fail in custom
+ // configurations that do not run standard WAN DHT. If it
+ // errors here, no point in spamming logs: og once and exit.
+ log.Errorw("initial version check failed, will not be run again", "error", err)
+ return
+ }
+ if o.UpdateAvailable {
+ newerPercent := fmt.Sprintf("%.0f%%", math.Round(float64(o.WithGreaterVersion)/float64(o.PeersSampled)*100))
+ log.Errorf(`
+⚠️ A NEW VERSION OF KUBO DETECTED
+
+This Kubo node is running an outdated version (%s).
+%s of the sampled Kubo peers are running a higher version.
+Visit https://github.com/ipfs/kubo/releases or https://dist.ipfs.tech/#kubo and update to version %s or later.`,
+ o.RunningVersion, newerPercent, o.GreatestVersion)
+ }
+ select {
+ case <-ctx.Done():
+ return
+ case <-nd.Process.Closing():
+ return
+ case <-ticker.C:
+ continue
+ }
+ }
+ }()
+}
diff --git a/cmd/ipfs/kubo/init.go b/cmd/ipfs/kubo/init.go
index 986fe90c8b1..06312014884 100644
--- a/cmd/ipfs/kubo/init.go
+++ b/cmd/ipfs/kubo/init.go
@@ -88,11 +88,11 @@ environment variable:
if it.Err() != nil {
return it.Err()
}
- return fmt.Errorf("file argument was nil")
+ return errors.New("file argument was nil")
}
file := files.FileFromEntry(it)
if file == nil {
- return fmt.Errorf("expected a regular file")
+ return errors.New("expected a regular file")
}
conf = &config.Config{}
diff --git a/cmd/ipfs/kubo/pinmfs.go b/cmd/ipfs/kubo/pinmfs.go
index 846ee8a77af..a210f1b63b0 100644
--- a/cmd/ipfs/kubo/pinmfs.go
+++ b/cmd/ipfs/kubo/pinmfs.go
@@ -6,16 +6,14 @@ import (
"os"
"time"
- "github.com/libp2p/go-libp2p/core/host"
- peer "github.com/libp2p/go-libp2p/core/peer"
-
pinclient "github.com/ipfs/boxo/pinning/remote/client"
cid "github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
- logging "github.com/ipfs/go-log"
-
+ logging "github.com/ipfs/go-log/v2"
config "github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core"
+ "github.com/libp2p/go-libp2p/core/host"
+ peer "github.com/libp2p/go-libp2p/core/peer"
)
// mfslog is the logger for remote mfs pinning.
@@ -40,6 +38,7 @@ func init() {
d, err := time.ParseDuration(pollDurStr)
if err != nil {
mfslog.Error("error parsing MFS_PIN_POLL_INTERVAL, using default:", err)
+ return
}
daemonConfigPollInterval = d
}
@@ -74,87 +73,70 @@ func (x *ipfsPinMFSNode) PeerHost() host.Host {
return x.node.PeerHost
}
-func startPinMFS(configPollInterval time.Duration, cctx pinMFSContext, node pinMFSNode) {
- errCh := make(chan error)
- go pinMFSOnChange(configPollInterval, cctx, node, errCh)
- go func() {
- for {
- select {
- case err, isOpen := <-errCh:
- if !isOpen {
- return
- }
- mfslog.Errorf("%v", err)
- case <-cctx.Context().Done():
- return
- }
- }
- }()
+func startPinMFS(cctx pinMFSContext, configPollInterval time.Duration, node pinMFSNode) {
+ go pinMFSOnChange(cctx, configPollInterval, node)
}
-func pinMFSOnChange(configPollInterval time.Duration, cctx pinMFSContext, node pinMFSNode, errCh chan<- error) {
- defer close(errCh)
-
- var tmo *time.Timer
- defer func() {
- if tmo != nil {
- tmo.Stop()
- }
- }()
+func pinMFSOnChange(cctx pinMFSContext, configPollInterval time.Duration, node pinMFSNode) {
+ tmo := time.NewTimer(configPollInterval)
+ defer tmo.Stop()
lastPins := map[string]lastPin{}
for {
// polling sleep
- if tmo == nil {
- tmo = time.NewTimer(configPollInterval)
- } else {
- tmo.Reset(configPollInterval)
- }
select {
case <-cctx.Context().Done():
return
case <-tmo.C:
- }
-
- // reread the config, which may have changed in the meantime
- cfg, err := cctx.GetConfig()
- if err != nil {
- select {
- case errCh <- fmt.Errorf("pinning reading config (%v)", err):
- case <-cctx.Context().Done():
- return
+ // reread the config, which may have changed in the meantime
+ cfg, err := cctx.GetConfig()
+ if err != nil {
+ mfslog.Errorf("pinning reading config (%v)", err)
+ continue
}
- continue
- }
- mfslog.Debugf("pinning loop is awake, %d remote services", len(cfg.Pinning.RemoteServices))
+ mfslog.Debugf("pinning loop is awake, %d remote services", len(cfg.Pinning.RemoteServices))
- // get the most recent MFS root cid
- rootNode, err := node.RootNode()
- if err != nil {
- select {
- case errCh <- fmt.Errorf("pinning reading MFS root (%v)", err):
- case <-cctx.Context().Done():
- return
- }
- continue
+ // pin to all remote services in parallel
+ pinAllMFS(cctx.Context(), node, cfg, lastPins)
}
- rootCid := rootNode.Cid()
-
- // pin to all remote services in parallel
- pinAllMFS(cctx.Context(), node, cfg, rootCid, lastPins, errCh)
+ // pinAllMFS may take long. Reset interval only when we are done doing it
+ // so that we are not pinning constantly.
+ tmo.Reset(configPollInterval)
}
}
// pinAllMFS pins on all remote services in parallel to overcome DoS attacks.
-func pinAllMFS(ctx context.Context, node pinMFSNode, cfg *config.Config, rootCid cid.Cid, lastPins map[string]lastPin, errCh chan<- error) {
- ch := make(chan lastPin, len(cfg.Pinning.RemoteServices))
- for svcName_, svcConfig_ := range cfg.Pinning.RemoteServices {
+func pinAllMFS(ctx context.Context, node pinMFSNode, cfg *config.Config, lastPins map[string]lastPin) {
+ ch := make(chan lastPin)
+ var started int
+
+ // Bail out to mitigate issue below when not needing to do anything.
+ if len(cfg.Pinning.RemoteServices) == 0 {
+ return
+ }
+
+ // get the most recent MFS root cid.
+ // Warning! This can be super expensive.
+ // See https://github.com/ipfs/boxo/pull/751
+ // and https://github.com/ipfs/kubo/issues/8694
+ // Reading an MFS-directory nodes can take minutes due to
+ // ever growing cache being synced to unixfs.
+ rootNode, err := node.RootNode()
+ if err != nil {
+ mfslog.Errorf("pinning reading MFS root (%v)", err)
+ return
+ }
+ rootCid := rootNode.Cid()
+
+ for svcName, svcConfig := range cfg.Pinning.RemoteServices {
+ if ctx.Err() != nil {
+ break
+ }
+
// skip services where MFS is not enabled
- svcName, svcConfig := svcName_, svcConfig_
mfslog.Debugf("pinning MFS root considering service %q", svcName)
if !svcConfig.Policies.MFS.Enable {
mfslog.Debugf("pinning service %q is not enabled", svcName)
- ch <- lastPin{}
continue
}
// read mfs pin interval for this service
@@ -165,11 +147,7 @@ func pinAllMFS(ctx context.Context, node pinMFSNode, cfg *config.Config, rootCid
var err error
repinInterval, err = time.ParseDuration(svcConfig.Policies.MFS.RepinInterval)
if err != nil {
- select {
- case errCh <- fmt.Errorf("remote pinning service %q has invalid MFS.RepinInterval (%v)", svcName, err):
- case <-ctx.Done():
- }
- ch <- lastPin{}
+ mfslog.Errorf("remote pinning service %q has invalid MFS.RepinInterval (%v)", svcName, err)
continue
}
}
@@ -182,38 +160,30 @@ func pinAllMFS(ctx context.Context, node pinMFSNode, cfg *config.Config, rootCid
} else {
mfslog.Debugf("pinning MFS root to %q: skipped due to MFS.RepinInterval=%s (remaining: %s)", svcName, repinInterval.String(), (repinInterval - time.Since(last.Time)).String())
}
- ch <- lastPin{}
continue
}
}
mfslog.Debugf("pinning MFS root %q to %q", rootCid, svcName)
- go func() {
- if r, err := pinMFS(ctx, node, rootCid, svcName, svcConfig); err != nil {
- select {
- case errCh <- fmt.Errorf("pinning MFS root %q to %q (%v)", rootCid, svcName, err):
- case <-ctx.Done():
- }
- ch <- lastPin{}
- } else {
- ch <- r
+ go func(svcName string, svcConfig config.RemotePinningService) {
+ r, err := pinMFS(ctx, node, rootCid, svcName, svcConfig)
+ if err != nil {
+ mfslog.Errorf("pinning MFS root %q to %q (%v)", rootCid, svcName, err)
}
- }()
+ ch <- r
+ }(svcName, svcConfig)
+ started++
}
- for i := 0; i < len(cfg.Pinning.RemoteServices); i++ {
+
+ // Collect results from all started goroutines.
+ for i := 0; i < started; i++ {
if x := <-ch; x.IsValid() {
lastPins[x.ServiceName] = x
}
}
}
-func pinMFS(
- ctx context.Context,
- node pinMFSNode,
- cid cid.Cid,
- svcName string,
- svcConfig config.RemotePinningService,
-) (lastPin, error) {
+func pinMFS(ctx context.Context, node pinMFSNode, cid cid.Cid, svcName string, svcConfig config.RemotePinningService) (lastPin, error) {
c := pinclient.NewClient(svcConfig.API.Endpoint, svcConfig.API.Key)
pinName := svcConfig.Policies.MFS.PinName
@@ -223,7 +193,7 @@ func pinMFS(
// check if MFS pin exists (across all possible states) and inspect its CID
pinStatuses := []pinclient.Status{pinclient.StatusQueued, pinclient.StatusPinning, pinclient.StatusPinned, pinclient.StatusFailed}
- lsPinCh, lsErrCh := c.Ls(ctx, pinclient.PinOpts.FilterName(pinName), pinclient.PinOpts.FilterStatus(pinStatuses...))
+ lsPinCh, lsErrCh := c.GoLs(ctx, pinclient.PinOpts.FilterName(pinName), pinclient.PinOpts.FilterStatus(pinStatuses...))
existingRequestID := "" // is there any pre-existing MFS pin with pinName (for any CID)?
pinning := false // is CID for current MFS already being pinned?
pinTime := time.Now().UTC()
@@ -243,43 +213,46 @@ func pinMFS(
}
for range lsPinCh { // in case the prior loop exits early
}
- if err := <-lsErrCh; err != nil {
+ err := <-lsErrCh
+ if err != nil {
return lastPin{}, fmt.Errorf("error while listing remote pins: %v", err)
}
- // CID of the current MFS root is already being pinned, nothing to do
- if pinning {
- mfslog.Debugf("pinning MFS to %q: pin for %q exists since %s, skipping", svcName, cid, pinTime.String())
- return lastPin{Time: pinTime, ServiceName: svcName, ServiceConfig: svcConfig, CID: cid}, nil
- }
-
- // Prepare Pin.name
- addOpts := []pinclient.AddOption{pinclient.PinOpts.WithName(pinName)}
+ if !pinning {
+ // Prepare Pin.name
+ addOpts := []pinclient.AddOption{pinclient.PinOpts.WithName(pinName)}
- // Prepare Pin.origins
- // Add own multiaddrs to the 'origins' array, so Pinning Service can
- // use that as a hint and connect back to us (if possible)
- if node.PeerHost() != nil {
- addrs, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(node.PeerHost()))
- if err != nil {
- return lastPin{}, err
+ // Prepare Pin.origins
+ // Add own multiaddrs to the 'origins' array, so Pinning Service can
+ // use that as a hint and connect back to us (if possible)
+ if node.PeerHost() != nil {
+ addrs, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(node.PeerHost()))
+ if err != nil {
+ return lastPin{}, err
+ }
+ addOpts = append(addOpts, pinclient.PinOpts.WithOrigins(addrs...))
}
- addOpts = append(addOpts, pinclient.PinOpts.WithOrigins(addrs...))
- }
- // Create or replace pin for MFS root
- if existingRequestID != "" {
- mfslog.Debugf("pinning to %q: replacing existing MFS root pin with %q", svcName, cid)
- _, err := c.Replace(ctx, existingRequestID, cid, addOpts...)
- if err != nil {
- return lastPin{}, err
+ // Create or replace pin for MFS root
+ if existingRequestID != "" {
+ mfslog.Debugf("pinning to %q: replacing existing MFS root pin with %q", svcName, cid)
+ if _, err = c.Replace(ctx, existingRequestID, cid, addOpts...); err != nil {
+ return lastPin{}, err
+ }
+ } else {
+ mfslog.Debugf("pinning to %q: creating a new MFS root pin for %q", svcName, cid)
+ if _, err = c.Add(ctx, cid, addOpts...); err != nil {
+ return lastPin{}, err
+ }
}
} else {
- mfslog.Debugf("pinning to %q: creating a new MFS root pin for %q", svcName, cid)
- _, err := c.Add(ctx, cid, addOpts...)
- if err != nil {
- return lastPin{}, err
- }
+ mfslog.Debugf("pinning MFS to %q: pin for %q exists since %s, skipping", svcName, cid, pinTime.String())
}
- return lastPin{Time: pinTime, ServiceName: svcName, ServiceConfig: svcConfig, CID: cid}, nil
+
+ return lastPin{
+ Time: pinTime,
+ ServiceName: svcName,
+ ServiceConfig: svcConfig,
+ CID: cid,
+ }, nil
}
diff --git a/cmd/ipfs/kubo/pinmfs_test.go b/cmd/ipfs/kubo/pinmfs_test.go
index da71d362cdb..6b171cd638e 100644
--- a/cmd/ipfs/kubo/pinmfs_test.go
+++ b/cmd/ipfs/kubo/pinmfs_test.go
@@ -1,14 +1,19 @@
package kubo
import (
+ "bufio"
"context"
+ "encoding/json"
+ "errors"
"fmt"
+ "io"
"strings"
"testing"
"time"
merkledag "github.com/ipfs/boxo/ipld/merkledag"
ipld "github.com/ipfs/go-ipld-format"
+ logging "github.com/ipfs/go-log/v2"
config "github.com/ipfs/kubo/config"
"github.com/libp2p/go-libp2p/core/host"
peer "github.com/libp2p/go-libp2p/core/peer"
@@ -60,39 +65,68 @@ func isErrorSimilar(e1, e2 error) bool {
}
func TestPinMFSConfigError(t *testing.T) {
- ctx := &testPinMFSContext{
- ctx: context.Background(),
+ ctx, cancel := context.WithTimeout(context.Background(), 2*testConfigPollInterval)
+ defer cancel()
+
+ cctx := &testPinMFSContext{
+ ctx: ctx,
cfg: nil,
err: fmt.Errorf("couldn't read config"),
}
node := &testPinMFSNode{}
- errCh := make(chan error)
- go pinMFSOnChange(testConfigPollInterval, ctx, node, errCh)
- if !isErrorSimilar(<-errCh, ctx.err) {
- t.Errorf("error did not propagate")
+
+ logReader := logging.NewPipeReader()
+ go func() {
+ pinMFSOnChange(cctx, testConfigPollInterval, node)
+ logReader.Close()
+ }()
+
+ level, msg := readLogLine(t, logReader)
+ if level != "error" {
+ t.Error("expected error to be logged")
}
- if !isErrorSimilar(<-errCh, ctx.err) {
+ if !isErrorSimilar(errors.New(msg), cctx.err) {
t.Errorf("error did not propagate")
}
}
func TestPinMFSRootNodeError(t *testing.T) {
- ctx := &testPinMFSContext{
- ctx: context.Background(),
- cfg: &config.Config{
- Pinning: config.Pinning{},
+ ctx, cancel := context.WithTimeout(context.Background(), 2*testConfigPollInterval)
+ defer cancel()
+
+ // need at least one config to trigger
+ cfg := &config.Config{
+ Pinning: config.Pinning{
+ RemoteServices: map[string]config.RemotePinningService{
+ "A": {
+ Policies: config.RemotePinningServicePolicies{
+ MFS: config.RemotePinningServiceMFSPolicy{
+ Enable: false,
+ },
+ },
+ },
+ },
},
+ }
+
+ cctx := &testPinMFSContext{
+ ctx: ctx,
+ cfg: cfg,
err: nil,
}
node := &testPinMFSNode{
err: fmt.Errorf("cannot create root node"),
}
- errCh := make(chan error)
- go pinMFSOnChange(testConfigPollInterval, ctx, node, errCh)
- if !isErrorSimilar(<-errCh, node.err) {
- t.Errorf("error did not propagate")
+ logReader := logging.NewPipeReader()
+ go func() {
+ pinMFSOnChange(cctx, testConfigPollInterval, node)
+ logReader.Close()
+ }()
+ level, msg := readLogLine(t, logReader)
+ if level != "error" {
+ t.Error("expected error to be logged")
}
- if !isErrorSimilar(<-errCh, node.err) {
+ if !isErrorSimilar(errors.New(msg), node.err) {
t.Errorf("error did not propagate")
}
}
@@ -155,7 +189,8 @@ func TestPinMFSService(t *testing.T) {
}
func testPinMFSServiceWithError(t *testing.T, cfg *config.Config, expectedErrorPrefix string) {
- goctx, cancel := context.WithCancel(context.Background())
+ goctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
ctx := &testPinMFSContext{
ctx: goctx,
cfg: cfg,
@@ -164,16 +199,36 @@ func testPinMFSServiceWithError(t *testing.T, cfg *config.Config, expectedErrorP
node := &testPinMFSNode{
err: nil,
}
- errCh := make(chan error)
- go pinMFSOnChange(testConfigPollInterval, ctx, node, errCh)
- defer cancel()
- // first pass through the pinning loop
- err := <-errCh
- if !strings.Contains((err).Error(), expectedErrorPrefix) {
- t.Errorf("expecting error containing %q", expectedErrorPrefix)
+ logReader := logging.NewPipeReader()
+ go func() {
+ pinMFSOnChange(ctx, testConfigPollInterval, node)
+ logReader.Close()
+ }()
+ level, msg := readLogLine(t, logReader)
+ if level != "error" {
+ t.Error("expected error to be logged")
}
- // second pass through the pinning loop
- if !strings.Contains((err).Error(), expectedErrorPrefix) {
+ if !strings.Contains(msg, expectedErrorPrefix) {
t.Errorf("expecting error containing %q", expectedErrorPrefix)
}
}
+
+func readLogLine(t *testing.T, logReader io.Reader) (string, string) {
+ t.Helper()
+
+ r := bufio.NewReader(logReader)
+ data, err := r.ReadBytes('\n')
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ logInfo := struct {
+ Level string `json:"level"`
+ Msg string `json:"msg"`
+ }{}
+ err = json.Unmarshal(data, &logInfo)
+ if err != nil {
+ t.Fatal(err)
+ }
+ return logInfo.Level, logInfo.Msg
+}
diff --git a/cmd/ipfs/kubo/start.go b/cmd/ipfs/kubo/start.go
index cae1e2c1b70..19a88f37ce4 100644
--- a/cmd/ipfs/kubo/start.go
+++ b/cmd/ipfs/kubo/start.go
@@ -16,12 +16,11 @@ import (
"time"
"github.com/blang/semver/v4"
- "github.com/google/uuid"
u "github.com/ipfs/boxo/util"
cmds "github.com/ipfs/go-ipfs-cmds"
"github.com/ipfs/go-ipfs-cmds/cli"
cmdhttp "github.com/ipfs/go-ipfs-cmds/http"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
ipfs "github.com/ipfs/kubo"
"github.com/ipfs/kubo/client/rpc/auth"
"github.com/ipfs/kubo/cmd/ipfs/util"
@@ -89,16 +88,6 @@ 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 BuildDefaultEnv(ctx context.Context, req *cmds.Request) (cmds.Environment, error) {
return BuildEnv(nil)(ctx, req)
}
@@ -157,8 +146,7 @@ func BuildEnv(pl PluginPreloader) func(ctx context.Context, req *cmds.Request) (
// - output the response
// - if anything fails, print error, maybe with help.
func Start(buildEnv func(ctx context.Context, req *cmds.Request) (cmds.Environment, error)) (exitCode int) {
- ctx := logging.ContextWithLoggable(context.Background(), newUUID("session"))
-
+ ctx := context.Background()
tp, err := tracing.NewTracerProvider(ctx)
if err != nil {
return printErr(err)
@@ -226,7 +214,10 @@ func insideGUI() bool {
func checkDebug(req *cmds.Request) {
// check if user wants to debug. option OR env var.
debug, _ := req.Options["debug"].(bool)
- if debug || os.Getenv("IPFS_LOGGING") == "debug" {
+ ipfsLogLevel, _ := logging.LevelFromString(os.Getenv("IPFS_LOGGING")) // IPFS_LOGGING is deprecated
+ goLogLevel, _ := logging.LevelFromString(os.Getenv("GOLOG_LOG_LEVEL"))
+
+ if debug || goLogLevel == logging.LevelDebug || ipfsLogLevel == logging.LevelDebug {
u.Debug = true
logging.SetDebugLogging()
}
@@ -303,7 +294,10 @@ func makeExecutor(req *cmds.Request, env interface{}) (cmds.Executor, error) {
}
// Resolve the API addr.
- apiAddr, err = resolveAddr(req.Context, apiAddr)
+ //
+ // Do not replace apiAddr with the resolved addr so that the requested
+ // hostname is kept for use in the request's HTTP header.
+ _, err = resolveAddr(req.Context, apiAddr)
if err != nil {
return nil, err
}
@@ -327,6 +321,11 @@ func makeExecutor(req *cmds.Request, env interface{}) (cmds.Executor, error) {
switch network {
case "tcp", "tcp4", "tcp6":
tpt = http.DefaultTransport
+ // RPC over HTTPS requires explicit schema in the address passed to cmdhttp.NewClient
+ httpAddr := apiAddr.String()
+ if !strings.HasPrefix(host, "http:") && !strings.HasPrefix(host, "https:") && (strings.Contains(httpAddr, "/https") || strings.Contains(httpAddr, "/tls/http")) {
+ host = "https://" + host
+ }
case "unix":
path := host
host = "unix"
diff --git a/cmd/ipfs/util/ulimit.go b/cmd/ipfs/util/ulimit.go
index 188444d6774..9f58007c99f 100644
--- a/cmd/ipfs/util/ulimit.go
+++ b/cmd/ipfs/util/ulimit.go
@@ -6,7 +6,7 @@ import (
"strconv"
"syscall"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
)
var log = logging.Logger("ulimit")
diff --git a/cmd/ipfswatch/main.go b/cmd/ipfswatch/main.go
index 0f0283fb87c..6850f642328 100644
--- a/cmd/ipfswatch/main.go
+++ b/cmd/ipfswatch/main.go
@@ -16,12 +16,12 @@ import (
core "github.com/ipfs/kubo/core"
coreapi "github.com/ipfs/kubo/core/coreapi"
corehttp "github.com/ipfs/kubo/core/corehttp"
+ "github.com/ipfs/kubo/misc/fsutil"
fsrepo "github.com/ipfs/kubo/repo/fsrepo"
fsnotify "github.com/fsnotify/fsnotify"
"github.com/ipfs/boxo/files"
process "github.com/jbenet/goprocess"
- homedir "github.com/mitchellh/go-homedir"
)
var (
@@ -57,7 +57,7 @@ func run(ipfsPath, watchPath string) error {
proc := process.WithParent(process.Background())
log.Printf("running IPFSWatch on '%s' using repo at '%s'...", watchPath, ipfsPath)
- ipfsPath, err := homedir.Expand(ipfsPath)
+ ipfsPath, err := fsutil.ExpandHome(ipfsPath)
if err != nil {
return err
}
diff --git a/commands/context.go b/commands/context.go
index cc95d55f439..ca425acbfb5 100644
--- a/commands/context.go
+++ b/commands/context.go
@@ -11,7 +11,7 @@ import (
loader "github.com/ipfs/kubo/plugin/loader"
cmds "github.com/ipfs/go-ipfs-cmds"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
config "github.com/ipfs/kubo/config"
coreiface "github.com/ipfs/kubo/core/coreiface"
options "github.com/ipfs/kubo/core/coreiface/options"
diff --git a/config/autonat.go b/config/autonat.go
index eb87b48e6f4..e8940d14eeb 100644
--- a/config/autonat.go
+++ b/config/autonat.go
@@ -20,6 +20,9 @@ const (
// AutoNATServiceDisabled indicates that the user has disabled the
// AutoNATService.
AutoNATServiceDisabled
+ // AutoNATServiceEnabledV1Only forces use of V1 and disables V2
+ // (used for testing)
+ AutoNATServiceEnabledV1Only
)
func (m *AutoNATServiceMode) UnmarshalText(text []byte) error {
@@ -30,6 +33,8 @@ func (m *AutoNATServiceMode) UnmarshalText(text []byte) error {
*m = AutoNATServiceEnabled
case "disabled":
*m = AutoNATServiceDisabled
+ case "legacy-v1":
+ *m = AutoNATServiceEnabledV1Only
default:
return fmt.Errorf("unknown autonat mode: %s", string(text))
}
@@ -44,6 +49,8 @@ func (m AutoNATServiceMode) MarshalText() ([]byte, error) {
return []byte("enabled"), nil
case AutoNATServiceDisabled:
return []byte("disabled"), nil
+ case AutoNATServiceEnabledV1Only:
+ return []byte("legacy-v1"), nil
default:
return nil, fmt.Errorf("unknown autonat mode: %d", m)
}
diff --git a/config/autotls.go b/config/autotls.go
new file mode 100644
index 00000000000..805a9ded65f
--- /dev/null
+++ b/config/autotls.go
@@ -0,0 +1,46 @@
+package config
+
+import (
+ "time"
+
+ p2pforge "github.com/ipshipyard/p2p-forge/client"
+)
+
+// AutoTLS includes optional configuration of p2p-forge client of service
+// for obtaining a domain and TLS certificate to improve connectivity for web
+// browser clients. More: https://github.com/ipshipyard/p2p-forge#readme
+type AutoTLS struct {
+ // Enables the p2p-forge feature and all related features.
+ Enabled Flag `json:",omitempty"`
+
+ // Optional, controls if Kubo should add /tls/sni/.../ws listener to every /tcp port if no explicit /ws is defined in Addresses.Swarm
+ AutoWSS Flag `json:",omitempty"`
+
+ // Optional override of the parent domain that will be used
+ DomainSuffix *OptionalString `json:",omitempty"`
+
+ // Optional override of HTTP API that acts as ACME DNS-01 Challenge broker
+ RegistrationEndpoint *OptionalString `json:",omitempty"`
+
+ // Optional Authorization token, used with private/test instances of p2p-forge
+ RegistrationToken *OptionalString `json:",omitempty"`
+
+ // Optional registration delay used when AutoTLS.Enabled is not explicitly set to true in config
+ RegistrationDelay *OptionalDuration `json:",omitempty"`
+
+ // Optional override of CA ACME API used by p2p-forge system
+ CAEndpoint *OptionalString `json:",omitempty"`
+
+ // Optional, controls if features like AutoWSS should generate shorter /dnsX instead of /ipX/../sni/..
+ ShortAddrs Flag `json:",omitempty"`
+}
+
+const (
+ DefaultAutoTLSEnabled = true // with DefaultAutoTLSRegistrationDelay, unless explicitly enabled in config
+ DefaultDomainSuffix = p2pforge.DefaultForgeDomain
+ DefaultRegistrationEndpoint = p2pforge.DefaultForgeEndpoint
+ DefaultCAEndpoint = p2pforge.DefaultCAEndpoint
+ DefaultAutoWSS = true // requires AutoTLS.Enabled
+ DefaultAutoTLSShortAddrs = true // requires AutoTLS.Enabled
+ DefaultAutoTLSRegistrationDelay = 1 * time.Hour
+)
diff --git a/config/bitswap.go b/config/bitswap.go
new file mode 100644
index 00000000000..5adcdef9c84
--- /dev/null
+++ b/config/bitswap.go
@@ -0,0 +1,15 @@
+package config
+
+// Bitswap holds Bitswap configuration options
+type Bitswap struct {
+ // Libp2pEnabled controls if the node initializes bitswap over libp2p (enabled by default)
+ // (This can be disabled if HTTPRetrieval.Enabled is set to true)
+ Libp2pEnabled Flag `json:",omitempty"`
+ // ServerEnabled controls if the node responds to WANTs (depends on Libp2pEnabled, enabled by default)
+ ServerEnabled Flag `json:",omitempty"`
+}
+
+const (
+ DefaultBitswapLibp2pEnabled = true
+ DefaultBitswapServerEnabled = true
+)
diff --git a/config/bootstrap_peers.go b/config/bootstrap_peers.go
index 1671d9f8156..55fe66a986f 100644
--- a/config/bootstrap_peers.go
+++ b/config/bootstrap_peers.go
@@ -16,11 +16,12 @@ import (
// import dependency issue. TODO: move this into a config/default/ package.
var DefaultBootstrapAddresses = []string{
"/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
- "/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
+ "/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa", // rust-libp2p-server
"/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
"/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
- "/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io
- "/ip4/104.131.131.82/udp/4001/quic-v1/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io
+ "/dnsaddr/va1.bootstrap.libp2p.io/p2p/12D3KooWKnDdG3iXw9eTFijk3EWSunZcFi54Zka4wmtqtt6rPxc8", // js-libp2p-amino-dht-bootstrapper
+ "/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io
+ "/ip4/104.131.131.82/udp/4001/quic-v1/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io
}
// ErrInvalidPeerAddr signals an address is not a valid peer address.
@@ -46,7 +47,7 @@ func (c *Config) SetBootstrapPeers(bps []peer.AddrInfo) {
c.Bootstrap = BootstrapPeerStrings(bps)
}
-// ParseBootstrapPeer parses a bootstrap list into a list of AddrInfos.
+// ParseBootstrapPeers parses a bootstrap list into a list of AddrInfos.
func ParseBootstrapPeers(addrs []string) ([]peer.AddrInfo, error) {
maddrs := make([]ma.Multiaddr, len(addrs))
for i, addr := range addrs {
diff --git a/config/config.go b/config/config.go
index 1951784dd1d..eee7e768b6b 100644
--- a/config/config.go
+++ b/config/config.go
@@ -7,9 +7,10 @@ import (
"fmt"
"os"
"path/filepath"
+ "reflect"
"strings"
- "github.com/mitchellh/go-homedir"
+ "github.com/ipfs/kubo/misc/fsutil"
)
// Config is used to load ipfs config files.
@@ -26,18 +27,24 @@ type Config struct {
API API // local node's API settings
Swarm SwarmConfig
AutoNAT AutoNATConfig
+ AutoTLS AutoTLS
Pubsub PubsubConfig
Peering Peering
DNS DNS
Migration Migration
- Provider Provider
- Reprovider Reprovider
- Experimental Experiments
- Plugins Plugins
- Pinning Pinning
+ Provider Provider
+ Reprovider Reprovider
+ HTTPRetrieval HTTPRetrieval
+ Experimental Experiments
+ Plugins Plugins
+ Pinning Pinning
+ Import Import
+ Version Version
Internal Internal // experimental/unstable options
+
+ Bitswap Bitswap `json:",omitempty"`
}
const (
@@ -56,7 +63,7 @@ func PathRoot() (string, error) {
dir := os.Getenv(EnvDir)
var err error
if len(dir) == 0 {
- dir, err = homedir.Expand(DefaultPathRoot)
+ dir, err = fsutil.ExpandHome(DefaultPathRoot)
}
return dir, err
}
@@ -134,6 +141,71 @@ func ToMap(conf *Config) (map[string]interface{}, error) {
return m, nil
}
+// Convert config to a map, without using encoding/json, since
+// zero/empty/'omitempty' fields are excluded by encoding/json during
+// marshaling.
+func ReflectToMap(conf interface{}) interface{} {
+ v := reflect.ValueOf(conf)
+ if !v.IsValid() {
+ return nil
+ }
+
+ // Handle pointer type
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ // Create a zero value of the pointer's element type
+ elemType := v.Type().Elem()
+ zero := reflect.Zero(elemType)
+ return ReflectToMap(zero.Interface())
+ }
+ v = v.Elem()
+ }
+
+ switch v.Kind() {
+ case reflect.Struct:
+ result := make(map[string]interface{})
+ t := v.Type()
+ for i := 0; i < v.NumField(); i++ {
+ field := v.Field(i)
+ // Only include exported fields
+ if field.CanInterface() {
+ result[t.Field(i).Name] = ReflectToMap(field.Interface())
+ }
+ }
+ return result
+
+ case reflect.Map:
+ result := make(map[string]interface{})
+ iter := v.MapRange()
+ for iter.Next() {
+ key := iter.Key()
+ // Convert map keys to strings for consistency
+ keyStr := fmt.Sprint(ReflectToMap(key.Interface()))
+ result[keyStr] = ReflectToMap(iter.Value().Interface())
+ }
+ // Add a sample to differentiate between a map and a struct on validation.
+ sample := reflect.Zero(v.Type().Elem())
+ if sample.CanInterface() {
+ result["*"] = ReflectToMap(sample.Interface())
+ }
+ return result
+
+ case reflect.Slice, reflect.Array:
+ result := make([]interface{}, v.Len())
+ for i := 0; i < v.Len(); i++ {
+ result[i] = ReflectToMap(v.Index(i).Interface())
+ }
+ return result
+
+ default:
+ // For basic types (int, string, etc.), just return the value
+ if v.CanInterface() {
+ return v.Interface()
+ }
+ return nil
+ }
+}
+
// Clone copies the config. Use when updating.
func (c *Config) Clone() (*Config, error) {
var newConfig Config
@@ -149,3 +221,38 @@ func (c *Config) Clone() (*Config, error) {
return &newConfig, nil
}
+
+// Check if the provided key is present in the structure.
+func CheckKey(key string) error {
+ conf := Config{}
+
+ // Convert an empty config to a map without JSON.
+ cursor := ReflectToMap(&conf)
+
+ // Parse the key and verify it's presence in the map.
+ var ok bool
+ var mapCursor map[string]interface{}
+
+ parts := strings.Split(key, ".")
+ for i, part := range parts {
+ mapCursor, ok = cursor.(map[string]interface{})
+ if !ok {
+ if cursor == nil {
+ return nil
+ }
+ path := strings.Join(parts[:i], ".")
+ return fmt.Errorf("%s key is not a map", path)
+ }
+
+ cursor, ok = mapCursor[part]
+ if !ok {
+ // If the config sections is a map, validate against the default entry.
+ if cursor, ok = mapCursor["*"]; ok {
+ continue
+ }
+ path := strings.Join(parts[:i+1], ".")
+ return fmt.Errorf("%s not found", path)
+ }
+ }
+ return nil
+}
diff --git a/config/config_test.go b/config/config_test.go
index dead06f8a23..16573504370 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -27,3 +27,135 @@ func TestClone(t *testing.T) {
t.Fatal("HTTP headers not preserved")
}
}
+
+func TestReflectToMap(t *testing.T) {
+ // Helper function to create a test config with various field types
+ reflectedConfig := ReflectToMap(new(Config))
+
+ mapConfig, ok := reflectedConfig.(map[string]interface{})
+ if !ok {
+ t.Fatal("Config didn't convert to map")
+ }
+
+ reflectedIdentity, ok := mapConfig["Identity"]
+ if !ok {
+ t.Fatal("Identity field not found")
+ }
+
+ mapIdentity, ok := reflectedIdentity.(map[string]interface{})
+ if !ok {
+ t.Fatal("Identity field didn't convert to map")
+ }
+
+ // Test string field reflection
+ reflectedPeerID, ok := mapIdentity["PeerID"]
+ if !ok {
+ t.Fatal("PeerID field not found in Identity")
+ }
+ if _, ok := reflectedPeerID.(string); !ok {
+ t.Fatal("PeerID field didn't convert to string")
+ }
+
+ // Test omitempty json string field
+ reflectedPrivKey, ok := mapIdentity["PrivKey"]
+ if !ok {
+ t.Fatal("PrivKey omitempty field not found in Identity")
+ }
+ if _, ok := reflectedPrivKey.(string); !ok {
+ t.Fatal("PrivKey omitempty field didn't convert to string")
+ }
+
+ // Test slices field
+ reflectedBootstrap, ok := mapConfig["Bootstrap"]
+ if !ok {
+ t.Fatal("Bootstrap field not found in config")
+ }
+ bootstrap, ok := reflectedBootstrap.([]interface{})
+ if !ok {
+ t.Fatal("Bootstrap field didn't convert to []string")
+ }
+ if len(bootstrap) != 0 {
+ t.Fatal("Bootstrap len is incorrect")
+ }
+
+ reflectedDatastore, ok := mapConfig["Datastore"]
+ if !ok {
+ t.Fatal("Datastore field not found in config")
+ }
+ datastore, ok := reflectedDatastore.(map[string]interface{})
+ if !ok {
+ t.Fatal("Datastore field didn't convert to map")
+ }
+ storageGCWatermark, ok := datastore["StorageGCWatermark"]
+ if !ok {
+ t.Fatal("StorageGCWatermark field not found in Datastore")
+ }
+ // Test int field
+ if _, ok := storageGCWatermark.(int64); !ok {
+ t.Fatal("StorageGCWatermark field didn't convert to int64")
+ }
+ noSync, ok := datastore["NoSync"]
+ if !ok {
+ t.Fatal("NoSync field not found in Datastore")
+ }
+ // Test bool field
+ if _, ok := noSync.(bool); !ok {
+ t.Fatal("NoSync field didn't convert to bool")
+ }
+
+ reflectedDNS, ok := mapConfig["DNS"]
+ if !ok {
+ t.Fatal("DNS field not found in config")
+ }
+ DNS, ok := reflectedDNS.(map[string]interface{})
+ if !ok {
+ t.Fatal("DNS field didn't convert to map")
+ }
+ reflectedResolvers, ok := DNS["Resolvers"]
+ if !ok {
+ t.Fatal("Resolvers field not found in DNS")
+ }
+ // Test map field
+ if _, ok := reflectedResolvers.(map[string]interface{}); !ok {
+ t.Fatal("Resolvers field didn't convert to map")
+ }
+
+ // Test pointer field
+ if _, ok := DNS["MaxCacheTTL"].(map[string]interface{}); !ok {
+ // Since OptionalDuration only field is private, we cannot test it
+ t.Fatal("MaxCacheTTL field didn't convert to map")
+ }
+}
+
+// Test validation of options set through "ipfs config"
+func TestCheckKey(t *testing.T) {
+ err := CheckKey("Foo.Bar")
+ if err == nil {
+ t.Fatal("Foo.Bar isn't a valid key in the config")
+ }
+
+ err = CheckKey("Reprovider.Strategy")
+ if err != nil {
+ t.Fatalf("%s: %s", err, "Reprovider.Strategy is a valid key in the config")
+ }
+
+ err = CheckKey("Provider.Foo")
+ if err == nil {
+ t.Fatal("Provider.Foo isn't a valid key in the config")
+ }
+
+ err = CheckKey("Gateway.PublicGateways.Foo.Paths")
+ if err != nil {
+ t.Fatalf("%s: %s", err, "Gateway.PublicGateways.Foo.Paths is a valid key in the config")
+ }
+
+ err = CheckKey("Gateway.PublicGateways.Foo.Bar")
+ if err == nil {
+ t.Fatal("Gateway.PublicGateways.Foo.Bar isn't a valid key in the config")
+ }
+
+ err = CheckKey("Plugins.Plugins.peerlog.Config.Enabled")
+ if err != nil {
+ t.Fatalf("%s: %s", err, "Plugins.Plugins.peerlog.Config.Enabled is a valid key in the config")
+ }
+}
diff --git a/config/datastore.go b/config/datastore.go
index 1a5994a1750..665e0364798 100644
--- a/config/datastore.go
+++ b/config/datastore.go
@@ -4,8 +4,21 @@ import (
"encoding/json"
)
-// DefaultDataStoreDirectory is the directory to store all the local IPFS data.
-const DefaultDataStoreDirectory = "datastore"
+const (
+ // DefaultDataStoreDirectory is the directory to store all the local IPFS data.
+ DefaultDataStoreDirectory = "datastore"
+
+ // DefaultBlockKeyCacheSize is the size for the blockstore two-queue
+ // cache which caches block keys and sizes.
+ DefaultBlockKeyCacheSize = 64 << 10
+
+ // DefaultWriteThrough specifies whether to use a "write-through"
+ // Blockstore and Blockservice. This means that they will write
+ // without performing any reads to check if the incoming blocks are
+ // already present in the datastore. Enable for datastores with fast
+ // writes and slower reads.
+ DefaultWriteThrough bool = true
+)
// Datastore tracks the configuration of the datastore.
type Datastore struct {
@@ -21,8 +34,10 @@ type Datastore struct {
Spec map[string]interface{}
- HashOnRead bool
- BloomFilterSize int
+ HashOnRead bool
+ BloomFilterSize int
+ BlockKeyCacheSize OptionalInteger `json:",omitempty"`
+ WriteThrough Flag `json:",omitempty"`
}
// DataStorePath returns the default data store path given a configuration root
diff --git a/config/experiments.go b/config/experiments.go
index fab1f953c2e..6c43ac04f07 100644
--- a/config/experiments.go
+++ b/config/experiments.go
@@ -6,7 +6,7 @@ type Experiments struct {
ShardingEnabled bool `json:",omitempty"` // deprecated by autosharding: https://github.com/ipfs/kubo/pull/8527
Libp2pStreamMounting bool
P2pHttpProxy bool //nolint
- StrategicProviding bool
+ StrategicProviding bool `json:",omitempty"` // removed, use Provider.Enabled instead
OptimisticProvide bool
OptimisticProvideJobsPoolSize int
GatewayOverLibp2p bool `json:",omitempty"`
diff --git a/config/gateway.go b/config/gateway.go
index fa093245d9a..35af598b435 100644
--- a/config/gateway.go
+++ b/config/gateway.go
@@ -9,7 +9,7 @@ const (
type GatewaySpec struct {
// Paths is explicit list of path prefixes that should be handled by
- // this gateway. Example: `["/ipfs", "/ipns", "/api"]`
+ // this gateway. Example: `["/ipfs", "/ipns"]`
Paths []string
// UseSubdomains indicates whether or not this gateway uses subdomains
diff --git a/config/http_retrieval.go b/config/http_retrieval.go
new file mode 100644
index 00000000000..a058e26c41c
--- /dev/null
+++ b/config/http_retrieval.go
@@ -0,0 +1,19 @@
+package config
+
+// HTTPRetrieval is the configuration object for HTTP Retrieval settings.
+// Implicit defaults can be found in core/node/bitswap.go
+type HTTPRetrieval struct {
+ Enabled Flag `json:",omitempty"`
+ Allowlist []string `json:",omitempty"`
+ Denylist []string `json:",omitempty"`
+ NumWorkers *OptionalInteger `json:",omitempty"`
+ MaxBlockSize *OptionalString `json:",omitempty"`
+ TLSInsecureSkipVerify Flag `json:",omitempty"`
+}
+
+const (
+ DefaultHTTPRetrievalEnabled = false // opt-in for now, until we figure out https://github.com/ipfs/specs/issues/496
+ DefaultHTTPRetrievalNumWorkers = 16
+ DefaultHTTPRetrievalTLSInsecureSkipVerify = false // only for testing with self-signed HTTPS certs
+ DefaultHTTPRetrievalMaxBlockSize = "2MiB" // matching bitswap: https://specs.ipfs.tech/bitswap-protocol/#block-sizes
+)
diff --git a/config/import.go b/config/import.go
new file mode 100644
index 00000000000..21bf232c1c0
--- /dev/null
+++ b/config/import.go
@@ -0,0 +1,46 @@
+package config
+
+import (
+ "github.com/ipfs/boxo/ipld/unixfs/importer/helpers"
+ "github.com/ipfs/boxo/ipld/unixfs/io"
+)
+
+const (
+ DefaultCidVersion = 0
+ DefaultUnixFSRawLeaves = false
+ DefaultUnixFSChunker = "size-262144"
+ DefaultHashFunction = "sha2-256"
+
+ DefaultUnixFSHAMTDirectorySizeThreshold = "256KiB" // https://github.com/ipfs/boxo/blob/6c5a07602aed248acc86598f30ab61923a54a83e/ipld/unixfs/io/directory.go#L26
+
+ // DefaultBatchMaxNodes controls the maximum number of nodes in a
+ // write-batch. The total size of the batch is limited by
+ // BatchMaxnodes and BatchMaxSize.
+ DefaultBatchMaxNodes = 128
+ // DefaultBatchMaxSize controls the maximum size of a single
+ // write-batch. The total size of the batch is limited by
+ // BatchMaxnodes and BatchMaxSize.
+ DefaultBatchMaxSize = 100 << 20 // 20MiB
+
+)
+
+var (
+ DefaultUnixFSFileMaxLinks = int64(helpers.DefaultLinksPerBlock)
+ DefaultUnixFSDirectoryMaxLinks = int64(0)
+ DefaultUnixFSHAMTDirectoryMaxFanout = int64(io.DefaultShardWidth)
+)
+
+// Import configures the default options for ingesting data. This affects commands
+// that ingest data, such as 'ipfs add', 'ipfs dag put, 'ipfs block put', 'ipfs files write'.
+type Import struct {
+ CidVersion OptionalInteger
+ UnixFSRawLeaves Flag
+ UnixFSChunker OptionalString
+ HashFunction OptionalString
+ UnixFSFileMaxLinks OptionalInteger
+ UnixFSDirectoryMaxLinks OptionalInteger
+ UnixFSHAMTDirectoryMaxFanout OptionalInteger
+ UnixFSHAMTDirectorySizeThreshold OptionalString
+ BatchMaxNodes OptionalInteger
+ BatchMaxSize OptionalInteger
+}
diff --git a/config/init.go b/config/init.go
index e3d0af30d9e..40c24bd25d9 100644
--- a/config/init.go
+++ b/config/init.go
@@ -7,6 +7,7 @@ import (
"io"
"time"
+ "github.com/cockroachdb/pebble/v2"
"github.com/ipfs/kubo/core/coreiface/options"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
@@ -47,16 +48,11 @@ func InitWithIdentity(identity Identity) (*Config, error) {
},
},
- Routing: Routing{
- Type: nil,
- Methods: nil,
- Routers: nil,
- },
-
// setup the node mount points.
Mounts: Mounts{
IPFS: "/ipfs",
IPNS: "/ipns",
+ MFS: "/mfs",
},
Ipns: Ipns{
@@ -112,8 +108,10 @@ func addressesConfig() Addresses {
Swarm: []string{
"/ip4/0.0.0.0/tcp/4001",
"/ip6/::/tcp/4001",
+ "/ip4/0.0.0.0/udp/4001/webrtc-direct",
"/ip4/0.0.0.0/udp/4001/quic-v1",
"/ip4/0.0.0.0/udp/4001/quic-v1/webtransport",
+ "/ip6/::/udp/4001/webrtc-direct",
"/ip6/::/udp/4001/quic-v1",
"/ip6/::/udp/4001/quic-v1/webtransport",
},
@@ -136,7 +134,38 @@ func DefaultDatastoreConfig() Datastore {
}
}
+func pebbleSpec() map[string]interface{} {
+ return map[string]interface{}{
+ "type": "pebbleds",
+ "prefix": "pebble.datastore",
+ "path": "pebbleds",
+ "formatMajorVersion": int(pebble.FormatNewest),
+ }
+}
+
+func pebbleSpecMeasure() map[string]interface{} {
+ return map[string]interface{}{
+ "type": "measure",
+ "prefix": "pebble.datastore",
+ "child": map[string]interface{}{
+ "formatMajorVersion": int(pebble.FormatNewest),
+ "type": "pebbleds",
+ "path": "pebbleds",
+ },
+ }
+}
+
func badgerSpec() map[string]interface{} {
+ return map[string]interface{}{
+ "type": "badgerds",
+ "prefix": "badger.datastore",
+ "path": "badgerds",
+ "syncWrites": false,
+ "truncate": true,
+ }
+}
+
+func badgerSpecMeasure() map[string]interface{} {
return map[string]interface{}{
"type": "measure",
"prefix": "badger.datastore",
@@ -150,6 +179,29 @@ func badgerSpec() map[string]interface{} {
}
func flatfsSpec() map[string]interface{} {
+ return map[string]interface{}{
+ "type": "mount",
+ "mounts": []interface{}{
+ map[string]interface{}{
+ "mountpoint": "/blocks",
+ "type": "flatfs",
+ "prefix": "flatfs.datastore",
+ "path": "blocks",
+ "sync": false,
+ "shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",
+ },
+ map[string]interface{}{
+ "mountpoint": "/",
+ "type": "levelds",
+ "prefix": "leveldb.datastore",
+ "path": "datastore",
+ "compression": "none",
+ },
+ },
+ }
+}
+
+func flatfsSpecMeasure() map[string]interface{} {
return map[string]interface{}{
"type": "mount",
"mounts": []interface{}{
@@ -160,7 +212,7 @@ func flatfsSpec() map[string]interface{} {
"child": map[string]interface{}{
"type": "flatfs",
"path": "blocks",
- "sync": true,
+ "sync": false,
"shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",
},
},
diff --git a/config/internal.go b/config/internal.go
index 40070b11b52..f8300f540b9 100644
--- a/config/internal.go
+++ b/config/internal.go
@@ -3,7 +3,7 @@ package config
type Internal struct {
// All marked as omitempty since we are expecting to make changes to all subcomponents of Internal
Bitswap *InternalBitswap `json:",omitempty"`
- UnixFSShardingSizeThreshold *OptionalString `json:",omitempty"`
+ UnixFSShardingSizeThreshold *OptionalString `json:",omitempty"` // moved to Import.UnixFSHAMTDirectorySizeThreshold
Libp2pForceReachability *OptionalString `json:",omitempty"`
BackupBootstrapInterval *OptionalDuration `json:",omitempty"`
}
@@ -14,4 +14,6 @@ type InternalBitswap struct {
EngineTaskWorkerCount OptionalInteger
MaxOutstandingBytesPerPeer OptionalInteger
ProviderSearchDelay OptionalDuration
+ ProviderSearchMaxResults OptionalInteger
+ WantHaveReplaceSize OptionalInteger
}
diff --git a/config/mounts.go b/config/mounts.go
index dfdd1e5bf6c..571316cf386 100644
--- a/config/mounts.go
+++ b/config/mounts.go
@@ -4,5 +4,6 @@ package config
type Mounts struct {
IPFS string
IPNS string
+ MFS string
FuseAllowOther bool
}
diff --git a/config/profile.go b/config/profile.go
index 83d53359dae..ec2e5a0b7ae 100644
--- a/config/profile.go
+++ b/config/profile.go
@@ -82,9 +82,11 @@ is useful when using the daemon in test environments.`,
}
c.Swarm.DisableNatPortMap = true
+ c.Routing.LoopbackAddressesOnLanDHT = True
c.Bootstrap = []string{}
c.Discovery.MDNS.Enabled = false
+ c.AutoTLS.Enabled = False
return nil
},
},
@@ -103,6 +105,7 @@ Inverse profile of the test profile.`,
c.Swarm.DisableNatPortMap = false
c.Discovery.MDNS.Enabled = true
+ c.AutoTLS.Enabled = Default
return nil
},
},
@@ -123,7 +126,7 @@ This profile may only be applied when first initializing the node.
"flatfs": {
Description: `Configures the node to use the flatfs datastore.
-This is the most battle-tested and reliable datastore.
+This is the most battle-tested and reliable datastore.
You should use this datastore if:
* You need a very simple and very reliable datastore, and you trust your
@@ -134,7 +137,11 @@ You should use this datastore if:
* You want to minimize memory usage.
* You are ok with the default speed of data import, or prefer to use --nocopy.
-This profile may only be applied when first initializing the node.
+See configuration documentation at:
+https://github.com/ipfs/kubo/blob/master/docs/datastores.md#flatfs
+
+NOTE: This profile may only be applied when first initializing node at IPFS_PATH
+ via 'ipfs init --profile flatfs'
`,
InitOnly: true,
@@ -143,24 +150,82 @@ This profile may only be applied when first initializing the node.
return nil
},
},
+ "flatfs-measure": {
+ Description: `Configures the node to use the flatfs datastore with metrics tracking wrapper.
+Additional '*_datastore_*' metrics will be exposed on /debug/metrics/prometheus
+
+NOTE: This profile may only be applied when first initializing node at IPFS_PATH
+ via 'ipfs init --profile flatfs-measure'
+`,
+
+ InitOnly: true,
+ Transform: func(c *Config) error {
+ c.Datastore.Spec = flatfsSpecMeasure()
+ return nil
+ },
+ },
+ "pebbleds": {
+ Description: `Configures the node to use the pebble high-performance datastore.
+
+Pebble is a LevelDB/RocksDB inspired key-value store focused on performance
+and internal usage by CockroachDB.
+You should use this datastore if:
+
+- You need a datastore that is focused on performance.
+- You need reliability by default, but may choose to disable WAL for maximum performance when reliability is not critical.
+- This datastore is good for multi-terabyte data sets.
+- May benefit from tuning depending on read/write patterns and throughput.
+- Performance is helped significantly by running on a system with plenty of memory.
+
+See configuration documentation at:
+https://github.com/ipfs/kubo/blob/master/docs/datastores.md#pebbleds
+
+NOTE: This profile may only be applied when first initializing node at IPFS_PATH
+ via 'ipfs init --profile pebbleds'
+`,
+
+ InitOnly: true,
+ Transform: func(c *Config) error {
+ c.Datastore.Spec = pebbleSpec()
+ return nil
+ },
+ },
+ "pebbleds-measure": {
+ Description: `Configures the node to use the pebble datastore with metrics tracking wrapper.
+Additional '*_datastore_*' metrics will be exposed on /debug/metrics/prometheus
+
+NOTE: This profile may only be applied when first initializing node at IPFS_PATH
+ via 'ipfs init --profile pebbleds-measure'
+`,
+
+ InitOnly: true,
+ Transform: func(c *Config) error {
+ c.Datastore.Spec = pebbleSpecMeasure()
+ return nil
+ },
+ },
"badgerds": {
- Description: `Configures the node to use the experimental badger datastore.
+ Description: `Configures the node to use the legacy badgerv1 datastore.
+
+NOTE: this is badger 1.x, which has known bugs and is no longer supported by the upstream team.
+It is provided here only for pre-existing users, allowing them to migrate away to more modern datastore.
-Use this datastore if some aspects of performance,
-especially the speed of adding many gigabytes of files, are critical.
-However, be aware that:
+Other caveats:
* This datastore will not properly reclaim space when your datastore is
smaller than several gigabytes. If you run IPFS with --enable-gc, you plan
on storing very little data in your IPFS node, and disk usage is more
critical than performance, consider using flatfs.
-* This datastore uses up to several gigabytes of memory.
+* This datastore uses up to several gigabytes of memory.
* Good for medium-size datastores, but may run into performance issues
if your dataset is bigger than a terabyte.
-* The current implementation is based on old badger 1.x
- which is no longer supported by the upstream team.
-This profile may only be applied when first initializing the node.`,
+See configuration documentation at:
+https://github.com/ipfs/kubo/blob/master/docs/datastores.md#badgerds
+
+NOTE: This profile may only be applied when first initializing node at IPFS_PATH
+ via 'ipfs init --profile badgerds'
+`,
InitOnly: true,
Transform: func(c *Config) error {
@@ -168,16 +233,32 @@ This profile may only be applied when first initializing the node.`,
return nil
},
},
+ "badgerds-measure": {
+ Description: `Configures the node to use the legacy badgerv1 datastore with metrics wrapper.
+Additional '*_datastore_*' metrics will be exposed on /debug/metrics/prometheus
+
+NOTE: This profile may only be applied when first initializing node at IPFS_PATH
+ via 'ipfs init --profile badgerds-measure'
+`,
+
+ InitOnly: true,
+ Transform: func(c *Config) error {
+ c.Datastore.Spec = badgerSpecMeasure()
+ return nil
+ },
+ },
"lowpower": {
Description: `Reduces daemon overhead on the system. May affect node
functionality - performance of content discovery and data
fetching may be degraded.
`,
Transform: func(c *Config) error {
- c.Routing.Type = NewOptionalString("dhtclient") // TODO: https://github.com/ipfs/kubo/issues/9480
+ // Disable "server" services (dht, autonat, limited relay)
+ c.Routing.Type = NewOptionalString("autoclient")
c.AutoNAT.ServiceMode = AutoNATServiceDisabled
- c.Reprovider.Interval = NewOptionalDuration(0)
+ c.Swarm.RelayService.Enabled = False
+ // Keep bare minimum connections around
lowWater := int64(20)
highWater := int64(40)
gracePeriod := time.Minute
@@ -188,6 +269,29 @@ fetching may be degraded.
return nil
},
},
+ "announce-off": {
+ Description: `Disables Provide and Reprovide systems (announcing to Amino DHT).
+
+ USE WITH CAUTION:
+ The main use case for this is setups with manual Peering.Peers config.
+ Data from this node will not be announced on the DHT. This will make
+ DHT-based routing and data retrieval impossible if this node is the only
+ one hosting it, and other peers are not already connected to it.
+`,
+ Transform: func(c *Config) error {
+ c.Provider.Enabled = False
+ c.Reprovider.Interval = NewOptionalDuration(0) // 0 disables periodic reprovide
+ return nil
+ },
+ },
+ "announce-on": {
+ Description: `Re-enables Provide and Reprovide systems (reverts announce-off profile).`,
+ Transform: func(c *Config) error {
+ c.Provider.Enabled = True
+ c.Reprovider.Interval = NewOptionalDuration(DefaultReproviderInterval) // have to apply explicit default because nil would be ignored
+ return nil
+ },
+ },
"randomports": {
Description: `Use a random port number for swarm.`,
@@ -203,6 +307,48 @@ fetching may be degraded.
return nil
},
},
+ "legacy-cid-v0": {
+ Description: `Makes UnixFS import produce legacy CIDv0 with no raw leaves, sha2-256 and 256 KiB chunks. This is likely the least optimal preset, use only if legacy behavior is required.`,
+ Transform: func(c *Config) error {
+ c.Import.CidVersion = *NewOptionalInteger(0)
+ c.Import.UnixFSRawLeaves = False
+ c.Import.UnixFSChunker = *NewOptionalString("size-262144")
+ c.Import.HashFunction = *NewOptionalString("sha2-256")
+ c.Import.UnixFSFileMaxLinks = *NewOptionalInteger(174)
+ c.Import.UnixFSDirectoryMaxLinks = *NewOptionalInteger(0)
+ c.Import.UnixFSHAMTDirectoryMaxFanout = *NewOptionalInteger(256)
+ c.Import.UnixFSHAMTDirectorySizeThreshold = *NewOptionalString("256KiB")
+ return nil
+ },
+ },
+ "test-cid-v1": {
+ Description: `Makes UnixFS import produce CIDv1 with raw leaves, sha2-256 and 1 MiB chunks (max 174 links per file, 256 per HAMT node, switch dir to HAMT above 256KiB).`,
+ Transform: func(c *Config) error {
+ c.Import.CidVersion = *NewOptionalInteger(1)
+ c.Import.UnixFSRawLeaves = True
+ c.Import.UnixFSChunker = *NewOptionalString("size-1048576")
+ c.Import.HashFunction = *NewOptionalString("sha2-256")
+ c.Import.UnixFSFileMaxLinks = *NewOptionalInteger(174)
+ c.Import.UnixFSDirectoryMaxLinks = *NewOptionalInteger(0)
+ c.Import.UnixFSHAMTDirectoryMaxFanout = *NewOptionalInteger(256)
+ c.Import.UnixFSHAMTDirectorySizeThreshold = *NewOptionalString("256KiB")
+ return nil
+ },
+ },
+ "test-cid-v1-wide": {
+ Description: `Makes UnixFS import produce CIDv1 with raw leaves, sha2-256 and 1MiB chunks and wider file DAGs (max 1024 links per every node type, switch dir to HAMT above 1MiB).`,
+ Transform: func(c *Config) error {
+ c.Import.CidVersion = *NewOptionalInteger(1)
+ c.Import.UnixFSRawLeaves = True
+ c.Import.UnixFSChunker = *NewOptionalString("size-1048576") // 1MiB
+ c.Import.HashFunction = *NewOptionalString("sha2-256")
+ c.Import.UnixFSFileMaxLinks = *NewOptionalInteger(1024)
+ c.Import.UnixFSDirectoryMaxLinks = *NewOptionalInteger(0) // no limit here, use size-based Import.UnixFSHAMTDirectorySizeThreshold instead
+ c.Import.UnixFSHAMTDirectoryMaxFanout = *NewOptionalInteger(1024)
+ c.Import.UnixFSHAMTDirectorySizeThreshold = *NewOptionalString("1MiB") // 1MiB
+ return nil
+ },
+ },
}
func getAvailablePort() (port int, err error) {
diff --git a/config/provider.go b/config/provider.go
index f2b5afe05b4..4a2243acb07 100644
--- a/config/provider.go
+++ b/config/provider.go
@@ -1,5 +1,14 @@
package config
+const (
+ DefaultProviderEnabled = true
+ DefaultProviderWorkerCount = 16
+)
+
+// Provider configuration describes how NEW CIDs are announced the moment they are created.
+// For periodical reprovide configuration, see Reprovider.*
type Provider struct {
- Strategy string // Which keys to announce
+ Enabled Flag `json:",omitempty"`
+ Strategy *OptionalString `json:",omitempty"` // Unused, you are likely looking for Reprovider.Strategy instead
+ WorkerCount *OptionalInteger `json:",omitempty"` // Number of concurrent provides allowed, 0 means unlimited
}
diff --git a/config/reprovider.go b/config/reprovider.go
index dae9ae6dee9..3e8a5b476ca 100644
--- a/config/reprovider.go
+++ b/config/reprovider.go
@@ -7,6 +7,8 @@ const (
DefaultReproviderStrategy = "all"
)
+// Reprovider configuration describes how CID from local datastore are periodically re-announced to routing systems.
+// For provide behavior of ad-hoc or newly created CIDs and their first-time announcement, see Provider.*
type Reprovider struct {
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 60faa605cce..aea60c3bd24 100644
--- a/config/routing.go
+++ b/config/routing.go
@@ -3,7 +3,34 @@ package config
import (
"encoding/json"
"fmt"
+ "os"
"runtime"
+ "strings"
+)
+
+const (
+ DefaultAcceleratedDHTClient = false
+ DefaultLoopbackAddressesOnLanDHT = false
+ CidContactRoutingURL = "https://cid.contact"
+ PublicGoodDelegatedRoutingURL = "https://delegated-ipfs.dev" // cid.contact + amino dht (incl. IPNS PUTs)
+ EnvHTTPRouters = "IPFS_HTTP_ROUTERS"
+ EnvHTTPRoutersFilterProtocols = "IPFS_HTTP_ROUTERS_FILTER_PROTOCOLS"
+)
+
+var (
+ // Default HTTP routers used in parallel to DHT when Routing.Type = "auto"
+ DefaultHTTPRouters = getEnvOrDefault(EnvHTTPRouters, []string{
+ CidContactRoutingURL, // https://github.com/ipfs/kubo/issues/9422#issuecomment-1338142084
+ })
+
+ // Default filter-protocols to pass along with delegated routing requests (as defined in IPIP-484)
+ // and also filter out locally
+ DefaultHTTPRoutersFilterProtocols = getEnvOrDefault(EnvHTTPRoutersFilterProtocols, []string{
+ "unknown", // allow results without protocol list, we can do libp2p identify to test them
+ "transport-bitswap",
+ // http is added dynamically in routing/delegated.go.
+ // 'transport-ipfs-gateway-http'
+ })
)
// Routing defines configuration options for libp2p routing.
@@ -15,11 +42,18 @@ type Routing struct {
// When "custom" is set, user-provided Routing.Routers is used.
Type *OptionalString `json:",omitempty"`
- AcceleratedDHTClient bool
+ AcceleratedDHTClient Flag `json:",omitempty"`
- Routers Routers
+ LoopbackAddressesOnLanDHT Flag `json:",omitempty"`
- Methods Methods
+ IgnoreProviders []string `json:",omitempty"`
+
+ // Simplified configuration used by default when Routing.Type=auto|autoclient
+ DelegatedRouters []string `json:",omitempty"`
+
+ // Advanced configuration used when Routing.Type=custom
+ Routers Routers `json:",omitempty"`
+ Methods Methods `json:",omitempty"`
}
type Router struct {
@@ -173,3 +207,13 @@ type ConfigRouter struct {
type Method struct {
RouterName string
}
+
+// getEnvOrDefault reads space or comma separated strings from env if present,
+// and uses provided defaultValue as a fallback
+func getEnvOrDefault(key string, defaultValue []string) []string {
+ if value, exists := os.LookupEnv(key); exists {
+ splitFunc := func(r rune) bool { return r == ',' || r == ' ' }
+ return strings.FieldsFunc(value, splitFunc)
+ }
+ return defaultValue
+}
diff --git a/config/swarm.go b/config/swarm.go
index f15634b578a..4a04a0054eb 100644
--- a/config/swarm.go
+++ b/config/swarm.go
@@ -65,8 +65,6 @@ type RelayService struct {
// BufferSize is the size of the relayed connection buffers.
BufferSize *OptionalInteger `json:",omitempty"`
- // MaxReservationsPerPeer is the maximum number of reservations originating from the same peer.
- MaxReservationsPerPeer *OptionalInteger `json:",omitempty"`
// MaxReservationsPerIP is the maximum number of reservations originating from the same IP address.
MaxReservationsPerIP *OptionalInteger `json:",omitempty"`
// MaxReservationsPerASN is the maximum number of reservations origination from the same ASN.
diff --git a/config/version.go b/config/version.go
new file mode 100644
index 00000000000..8d6d4b6a6b4
--- /dev/null
+++ b/config/version.go
@@ -0,0 +1,14 @@
+package config
+
+const DefaultSwarmCheckPercentThreshold = 5
+
+// Version allows controlling things like custom user agent and update checks.
+type Version struct {
+ // Optional suffix to the AgentVersion presented by `ipfs id` and exposed
+ // via libp2p identify protocol.
+ AgentSuffix *OptionalString `json:",omitempty"`
+
+ // Detect when to warn about new version when observed via libp2p identify
+ SwarmCheckEnabled Flag `json:",omitempty"`
+ SwarmCheckPercentThreshold *OptionalInteger `json:",omitempty"`
+}
diff --git a/core/commands/add.go b/core/commands/add.go
index 33d79a2eb1f..f800e4f42d0 100644
--- a/core/commands/add.go
+++ b/core/commands/add.go
@@ -6,8 +6,10 @@ import (
"io"
"os"
gopath "path"
+ "strconv"
"strings"
+ "github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/cheggaaa/pb"
@@ -22,33 +24,45 @@ import (
)
// ErrDepthLimitExceeded indicates that the max depth has been exceeded.
-var ErrDepthLimitExceeded = fmt.Errorf("depth limit exceeded")
+var ErrDepthLimitExceeded = errors.New("depth limit exceeded")
type AddEvent struct {
- Name string
- Hash string `json:",omitempty"`
- Bytes int64 `json:",omitempty"`
- Size string `json:",omitempty"`
+ Name string
+ Hash string `json:",omitempty"`
+ Bytes int64 `json:",omitempty"`
+ Size string `json:",omitempty"`
+ Mode string `json:",omitempty"`
+ Mtime int64 `json:",omitempty"`
+ MtimeNsecs int `json:",omitempty"`
}
const (
- quietOptionName = "quiet"
- quieterOptionName = "quieter"
- silentOptionName = "silent"
- progressOptionName = "progress"
- trickleOptionName = "trickle"
- wrapOptionName = "wrap-with-directory"
- onlyHashOptionName = "only-hash"
- chunkerOptionName = "chunker"
- pinOptionName = "pin"
- rawLeavesOptionName = "raw-leaves"
- noCopyOptionName = "nocopy"
- fstoreCacheOptionName = "fscache"
- cidVersionOptionName = "cid-version"
- hashOptionName = "hash"
- inlineOptionName = "inline"
- inlineLimitOptionName = "inline-limit"
- toFilesOptionName = "to-files"
+ quietOptionName = "quiet"
+ quieterOptionName = "quieter"
+ silentOptionName = "silent"
+ progressOptionName = "progress"
+ trickleOptionName = "trickle"
+ wrapOptionName = "wrap-with-directory"
+ onlyHashOptionName = "only-hash"
+ chunkerOptionName = "chunker"
+ pinOptionName = "pin"
+ rawLeavesOptionName = "raw-leaves"
+ maxFileLinksOptionName = "max-file-links"
+ maxDirectoryLinksOptionName = "max-directory-links"
+ maxHAMTFanoutOptionName = "max-hamt-fanout"
+ noCopyOptionName = "nocopy"
+ fstoreCacheOptionName = "fscache"
+ cidVersionOptionName = "cid-version"
+ hashOptionName = "hash"
+ inlineOptionName = "inline"
+ inlineLimitOptionName = "inline-limit"
+ toFilesOptionName = "to-files"
+
+ preserveModeOptionName = "preserve-mode"
+ preserveMtimeOptionName = "preserve-mtime"
+ modeOptionName = "mode"
+ mtimeOptionName = "mtime"
+ mtimeNsecsOptionName = "mtime-nsecs"
)
const adderOutChanSize = 8
@@ -132,6 +146,9 @@ new flags may be added in the future. It is not guaranteed for the implicit
defaults of 'ipfs add' to remain the same in future Kubo releases, or for other
IPFS software to use the same import parameters as Kubo.
+Use Import.* configuration options to override global implicit defaults:
+https://github.com/ipfs/kubo/blob/master/docs/config.md#import
+
If you need to back up or transport content-addressed data using a non-IPFS
medium, CID can be preserved with CAR files.
See 'dag export' and 'dag import' for more information.
@@ -155,32 +172,37 @@ See 'dag export' and 'dag import' for more information.
cmds.BoolOption(trickleOptionName, "t", "Use trickle-dag format for dag generation."),
cmds.BoolOption(onlyHashOptionName, "n", "Only chunk and hash - do not write to disk."),
cmds.BoolOption(wrapOptionName, "w", "Wrap files with a directory object."),
- cmds.StringOption(chunkerOptionName, "s", "Chunking algorithm, size-[bytes], rabin-[min]-[avg]-[max] or buzhash").WithDefault("size-262144"),
- cmds.BoolOption(rawLeavesOptionName, "Use raw blocks for leaf nodes."),
+ cmds.StringOption(chunkerOptionName, "s", "Chunking algorithm, size-[bytes], rabin-[min]-[avg]-[max] or buzhash. Default: Import.UnixFSChunker"),
+ cmds.BoolOption(rawLeavesOptionName, "Use raw blocks for leaf nodes. Default: Import.UnixFSRawLeaves"),
+ cmds.IntOption(maxFileLinksOptionName, "Limit the maximum number of links in UnixFS file nodes to this value. (experimental) Default: Import.UnixFSFileMaxLinks"),
+ cmds.IntOption(maxDirectoryLinksOptionName, "Limit the maximum number of links in UnixFS basic directory nodes to this value. Default: Import.UnixFSDirectoryMaxLinks. WARNING: experimental, Import.UnixFSHAMTThreshold is a safer alternative."),
+ cmds.IntOption(maxHAMTFanoutOptionName, "Limit the maximum number of links of a UnixFS HAMT directory node to this (power of 2, multiple of 8). Default: Import.UnixFSHAMTDirectoryMaxFanout WARNING: experimental, see Import.UnixFSHAMTDirectorySizeThreshold as well."),
cmds.BoolOption(noCopyOptionName, "Add the file using filestore. Implies raw-leaves. (experimental)"),
cmds.BoolOption(fstoreCacheOptionName, "Check the filestore for pre-existing blocks. (experimental)"),
- cmds.IntOption(cidVersionOptionName, "CID version. Defaults to 0 unless an option that depends on CIDv1 is passed. Passing version 1 will cause the raw-leaves option to default to true."),
- cmds.StringOption(hashOptionName, "Hash function to use. Implies CIDv1 if not sha2-256. (experimental)").WithDefault("sha2-256"),
+ cmds.IntOption(cidVersionOptionName, "CID version. Defaults to 0 unless an option that depends on CIDv1 is passed. Passing version 1 will cause the raw-leaves option to default to true. Default: Import.CidVersion"),
+ cmds.StringOption(hashOptionName, "Hash function to use. Implies CIDv1 if not sha2-256. Default: Import.HashFunction"),
cmds.BoolOption(inlineOptionName, "Inline small blocks into CIDs. (experimental)"),
cmds.IntOption(inlineLimitOptionName, "Maximum block size to inline. (experimental)").WithDefault(32),
cmds.BoolOption(pinOptionName, "Pin locally to protect added files from garbage collection.").WithDefault(true),
cmds.StringOption(toFilesOptionName, "Add reference to Files API (MFS) at the provided path."),
+ cmds.BoolOption(preserveModeOptionName, "Apply existing POSIX permissions to created UnixFS entries. Disables raw-leaves. (experimental)"),
+ cmds.BoolOption(preserveMtimeOptionName, "Apply existing POSIX modification time to created UnixFS entries. Disables raw-leaves. (experimental)"),
+ cmds.UintOption(modeOptionName, "Custom POSIX file mode to store in created UnixFS entries. Disables raw-leaves. (experimental)"),
+ cmds.Int64Option(mtimeOptionName, "Custom POSIX modification time to store in created UnixFS entries (seconds before or after the Unix Epoch). Disables raw-leaves. (experimental)"),
+ cmds.UintOption(mtimeNsecsOptionName, "Custom POSIX modification time (optional time fraction in nanoseconds)"),
},
PreRun: func(req *cmds.Request, env cmds.Environment) error {
quiet, _ := req.Options[quietOptionName].(bool)
quieter, _ := req.Options[quieterOptionName].(bool)
quiet = quiet || quieter
-
silent, _ := req.Options[silentOptionName].(bool)
- if quiet || silent {
- return nil
- }
-
- // ipfs cli progress bar defaults to true unless quiet or silent is used
- _, found := req.Options[progressOptionName].(bool)
- if !found {
- req.Options[progressOptionName] = true
+ if !quiet && !silent {
+ // ipfs cli progress bar defaults to true unless quiet or silent is used
+ _, found := req.Options[progressOptionName].(bool)
+ if !found {
+ req.Options[progressOptionName] = true
+ }
}
return nil
@@ -191,14 +213,27 @@ See 'dag export' and 'dag import' for more information.
return err
}
+ nd, err := cmdenv.GetNode(env)
+ if err != nil {
+ return err
+ }
+
+ cfg, err := nd.Repo.Config()
+ if err != nil {
+ return err
+ }
+
progress, _ := req.Options[progressOptionName].(bool)
trickle, _ := req.Options[trickleOptionName].(bool)
wrap, _ := req.Options[wrapOptionName].(bool)
- hash, _ := req.Options[onlyHashOptionName].(bool)
+ onlyHash, _ := req.Options[onlyHashOptionName].(bool)
silent, _ := req.Options[silentOptionName].(bool)
chunker, _ := req.Options[chunkerOptionName].(string)
dopin, _ := req.Options[pinOptionName].(bool)
rawblks, rbset := req.Options[rawLeavesOptionName].(bool)
+ maxFileLinks, maxFileLinksSet := req.Options[maxFileLinksOptionName].(int)
+ maxDirectoryLinks, maxDirectoryLinksSet := req.Options[maxDirectoryLinksOptionName].(int)
+ maxHAMTFanout, maxHAMTFanoutSet := req.Options[maxHAMTFanoutOptionName].(int)
nocopy, _ := req.Options[noCopyOptionName].(bool)
fscache, _ := req.Options[fstoreCacheOptionName].(bool)
cidVer, cidVerSet := req.Options[cidVersionOptionName].(int)
@@ -206,6 +241,65 @@ See 'dag export' and 'dag import' for more information.
inline, _ := req.Options[inlineOptionName].(bool)
inlineLimit, _ := req.Options[inlineLimitOptionName].(int)
toFilesStr, toFilesSet := req.Options[toFilesOptionName].(string)
+ preserveMode, _ := req.Options[preserveModeOptionName].(bool)
+ preserveMtime, _ := req.Options[preserveMtimeOptionName].(bool)
+ mode, _ := req.Options[modeOptionName].(uint)
+ mtime, _ := req.Options[mtimeOptionName].(int64)
+ mtimeNsecs, _ := req.Options[mtimeNsecsOptionName].(uint)
+
+ if chunker == "" {
+ chunker = cfg.Import.UnixFSChunker.WithDefault(config.DefaultUnixFSChunker)
+ }
+
+ if hashFunStr == "" {
+ hashFunStr = cfg.Import.HashFunction.WithDefault(config.DefaultHashFunction)
+ }
+
+ if !cidVerSet && !cfg.Import.CidVersion.IsDefault() {
+ cidVerSet = true
+ cidVer = int(cfg.Import.CidVersion.WithDefault(config.DefaultCidVersion))
+ }
+
+ if !rbset && cfg.Import.UnixFSRawLeaves != config.Default {
+ rbset = true
+ rawblks = cfg.Import.UnixFSRawLeaves.WithDefault(config.DefaultUnixFSRawLeaves)
+ }
+
+ if !maxFileLinksSet && !cfg.Import.UnixFSFileMaxLinks.IsDefault() {
+ maxFileLinksSet = true
+ maxFileLinks = int(cfg.Import.UnixFSFileMaxLinks.WithDefault(config.DefaultUnixFSFileMaxLinks))
+ }
+
+ if !maxDirectoryLinksSet && !cfg.Import.UnixFSDirectoryMaxLinks.IsDefault() {
+ maxDirectoryLinksSet = true
+ maxDirectoryLinks = int(cfg.Import.UnixFSDirectoryMaxLinks.WithDefault(config.DefaultUnixFSDirectoryMaxLinks))
+ }
+
+ if !maxHAMTFanoutSet && !cfg.Import.UnixFSHAMTDirectoryMaxFanout.IsDefault() {
+ maxHAMTFanoutSet = true
+ maxHAMTFanout = int(cfg.Import.UnixFSHAMTDirectoryMaxFanout.WithDefault(config.DefaultUnixFSHAMTDirectoryMaxFanout))
+ }
+
+ // Storing optional mode or mtime (UnixFS 1.5) requires root block
+ // to always be 'dag-pb' and not 'raw'. Below adjusts raw-leaves setting, if possible.
+ if preserveMode || preserveMtime || mode != 0 || mtime != 0 {
+ // Error if --raw-leaves flag was explicitly passed by the user.
+ // (let user make a decision to manually disable it and retry)
+ if rbset && rawblks {
+ return fmt.Errorf("%s can't be used with UnixFS metadata like mode or modification time", rawLeavesOptionName)
+ }
+ // No explicit preference from user, disable raw-leaves and continue
+ rbset = true
+ rawblks = false
+ }
+
+ if onlyHash && toFilesSet {
+ return fmt.Errorf("%s and %s options are not compatible", onlyHashOptionName, toFilesOptionName)
+ }
+
+ if wrap && toFilesSet {
+ return fmt.Errorf("%s and %s options are not compatible", wrapOptionName, toFilesOptionName)
+ }
hashFunCode, ok := mh.Names[strings.ToLower(hashFunStr)]
if !ok {
@@ -233,12 +327,25 @@ See 'dag export' and 'dag import' for more information.
options.Unixfs.Chunker(chunker),
options.Unixfs.Pin(dopin),
- options.Unixfs.HashOnly(hash),
+ options.Unixfs.HashOnly(onlyHash),
options.Unixfs.FsCache(fscache),
options.Unixfs.Nocopy(nocopy),
options.Unixfs.Progress(progress),
options.Unixfs.Silent(silent),
+
+ options.Unixfs.PreserveMode(preserveMode),
+ options.Unixfs.PreserveMtime(preserveMtime),
+ }
+
+ if mode != 0 {
+ opts = append(opts, options.Unixfs.Mode(os.FileMode(mode)))
+ }
+
+ if mtime != 0 {
+ opts = append(opts, options.Unixfs.Mtime(mtime, uint32(mtimeNsecs)))
+ } else if mtimeNsecs != 0 {
+ return fmt.Errorf("option %q requires %q to be provided as well", mtimeNsecsOptionName, mtimeOptionName)
}
if cidVerSet {
@@ -249,6 +356,18 @@ See 'dag export' and 'dag import' for more information.
opts = append(opts, options.Unixfs.RawLeaves(rawblks))
}
+ if maxFileLinksSet {
+ opts = append(opts, options.Unixfs.MaxFileLinks(maxFileLinks))
+ }
+
+ if maxDirectoryLinksSet {
+ opts = append(opts, options.Unixfs.MaxDirectoryLinks(maxDirectoryLinks))
+ }
+
+ if maxHAMTFanoutSet {
+ opts = append(opts, options.Unixfs.MaxHAMTFanout(maxHAMTFanout))
+ }
+
if trickle {
opts = append(opts, options.Unixfs.Layout(options.TrickleLayout))
}
@@ -279,6 +398,11 @@ See 'dag export' and 'dag import' for more information.
// creating MFS pointers when optional --to-files is set
if toFilesSet {
+ if addit.Name() == "" {
+ errCh <- fmt.Errorf("%s: cannot add unnamed files to MFS", toFilesOptionName)
+ return
+ }
+
if toFilesStr == "" {
toFilesStr = "/"
}
@@ -350,12 +474,33 @@ See 'dag export' and 'dag import' for more information.
output.Name = gopath.Join(addit.Name(), output.Name)
}
- if err := res.Emit(&AddEvent{
- Name: output.Name,
- Hash: h,
- Bytes: output.Bytes,
- Size: output.Size,
- }); err != nil {
+ output.Mode = addit.Node().Mode()
+ if ts := addit.Node().ModTime(); !ts.IsZero() {
+ output.Mtime = addit.Node().ModTime().Unix()
+ output.MtimeNsecs = addit.Node().ModTime().Nanosecond()
+ }
+
+ addEvent := AddEvent{
+ Name: output.Name,
+ Hash: h,
+ Bytes: output.Bytes,
+ Size: output.Size,
+ Mtime: output.Mtime,
+ MtimeNsecs: output.MtimeNsecs,
+ }
+
+ if output.Mode != 0 {
+ addEvent.Mode = "0" + strconv.FormatUint(uint64(output.Mode), 8)
+ }
+
+ if output.Mtime > 0 {
+ addEvent.Mtime = output.Mtime
+ if output.MtimeNsecs > 0 {
+ addEvent.MtimeNsecs = output.MtimeNsecs
+ }
+ }
+
+ if err := res.Emit(&addEvent); err != nil {
return err
}
}
diff --git a/core/commands/bitswap.go b/core/commands/bitswap.go
index 6502876d197..7bddaac60ac 100644
--- a/core/commands/bitswap.go
+++ b/core/commands/bitswap.go
@@ -5,7 +5,6 @@ import (
"io"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
- e "github.com/ipfs/kubo/core/commands/e"
humanize "github.com/dustin/go-humanize"
bitswap "github.com/ipfs/boxo/bitswap"
@@ -25,7 +24,7 @@ var BitswapCmd = &cmds.Command{
"stat": bitswapStatCmd,
"wantlist": showWantlistCmd,
"ledger": ledgerCmd,
- "reprovide": reprovideCmd,
+ "reprovide": deprecatedBitswapReprovideCmd,
},
}
@@ -33,6 +32,17 @@ const (
peerOptionName = "peer"
)
+var deprecatedBitswapReprovideCmd = &cmds.Command{
+ Status: cmds.Deprecated,
+ Helptext: cmds.HelpText{
+ Tagline: "Deprecated command to announce to bitswap. Use 'ipfs routing reprovide' instead.",
+ ShortDescription: `
+'ipfs bitswap reprovide' is a legacy plumbing command used to announce to DHT.
+Deprecated, use modern 'ipfs routing reprovide' instead.`,
+ },
+ Run: reprovideRoutingCmd.Run, // alias to routing reprovide to not break existing users
+}
+
var showWantlistCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Show blocks currently on the wantlist.",
@@ -53,10 +63,7 @@ Print out all blocks currently on the bitswap wantlist for the local peer.`,
return ErrNotOnline
}
- bs, ok := nd.Exchange.(*bitswap.Bitswap)
- if !ok {
- return e.TypeErr(bs, nd.Exchange)
- }
+ bs := nd.Bitswap
pstr, found := req.Options[peerOptionName].(string)
if found {
@@ -109,15 +116,10 @@ var bitswapStatCmd = &cmds.Command{
}
if !nd.IsOnline {
- return cmds.Errorf(cmds.ErrClient, ErrNotOnline.Error())
- }
-
- bs, ok := nd.Exchange.(*bitswap.Bitswap)
- if !ok {
- return e.TypeErr(bs, nd.Exchange)
+ return cmds.Errorf(cmds.ErrClient, "unable to run offline: %s", ErrNotOnline)
}
- st, err := bs.Stat()
+ st, err := nd.Bitswap.Stat()
if err != nil {
return err
}
@@ -134,7 +136,6 @@ var bitswapStatCmd = &cmds.Command{
human, _ := req.Options[bitswapHumanOptionName].(bool)
fmt.Fprintln(w, "bitswap status")
- fmt.Fprintf(w, "\tprovides buffer: %d / %d\n", s.ProvideBufLen, bitswap.HasBlockBufferSize)
fmt.Fprintf(w, "\tblocks received: %d\n", s.BlocksReceived)
fmt.Fprintf(w, "\tblocks sent: %d\n", s.BlocksSent)
if human {
@@ -190,17 +191,12 @@ prints the ledger associated with a given peer.
return ErrNotOnline
}
- bs, ok := nd.Exchange.(*bitswap.Bitswap)
- if !ok {
- return e.TypeErr(bs, nd.Exchange)
- }
-
partner, err := peer.Decode(req.Arguments[0])
if err != nil {
return err
}
- return cmds.EmitOnce(res, bs.LedgerForPeer(partner))
+ return cmds.EmitOnce(res, nd.Bitswap.LedgerForPeer(partner))
},
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *server.Receipt) error {
@@ -215,29 +211,3 @@ prints the ledger associated with a given peer.
}),
},
}
-
-var reprovideCmd = &cmds.Command{
- Helptext: cmds.HelpText{
- Tagline: "Trigger reprovider.",
- ShortDescription: `
-Trigger reprovider to announce our data to network.
-`,
- },
- 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
- }
-
- err = nd.Provider.Reprovide(req.Context)
- if err != nil {
- return err
- }
-
- return nil
- },
-}
diff --git a/core/commands/block.go b/core/commands/block.go
index 6ceb258f62c..b4b0fd20457 100644
--- a/core/commands/block.go
+++ b/core/commands/block.go
@@ -8,6 +8,7 @@ import (
"github.com/ipfs/boxo/files"
+ "github.com/ipfs/kubo/config"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
@@ -153,7 +154,7 @@ only for backward compatibility when a legacy CIDv0 is required (--format=v0).
},
Options: []cmds.Option{
cmds.StringOption(blockCidCodecOptionName, "Multicodec to use in returned CID").WithDefault("raw"),
- cmds.StringOption(mhtypeOptionName, "Multihash hash function").WithDefault("sha2-256"),
+ cmds.StringOption(mhtypeOptionName, "Multihash hash function"),
cmds.IntOption(mhlenOptionName, "Multihash hash length").WithDefault(-1),
cmds.BoolOption(pinOptionName, "Pin added blocks recursively").WithDefault(false),
cmdutils.AllowBigBlockOption,
@@ -165,7 +166,21 @@ only for backward compatibility when a legacy CIDv0 is required (--format=v0).
return err
}
+ nd, err := cmdenv.GetNode(env)
+ if err != nil {
+ return err
+ }
+
+ cfg, err := nd.Repo.Config()
+ if err != nil {
+ return err
+ }
+
mhtype, _ := req.Options[mhtypeOptionName].(string)
+ if mhtype == "" {
+ mhtype = cfg.Import.HashFunction.WithDefault(config.DefaultHashFunction)
+ }
+
mhtval, ok := mh.Names[mhtype]
if !ok {
return fmt.Errorf("unrecognized multihash function: %s", mhtype)
diff --git a/core/commands/cat.go b/core/commands/cat.go
index 6fa1f71b79d..38a3e8dfaf6 100644
--- a/core/commands/cat.go
+++ b/core/commands/cat.go
@@ -2,7 +2,7 @@ package commands
import (
"context"
- "fmt"
+ "errors"
"io"
"os"
@@ -43,13 +43,13 @@ var CatCmd = &cmds.Command{
offset, _ := req.Options[offsetOptionName].(int64)
if offset < 0 {
- return fmt.Errorf("cannot specify negative offset")
+ return errors.New("cannot specify negative offset")
}
max, found := req.Options[lengthOptionName].(int64)
if max < 0 {
- return fmt.Errorf("cannot specify negative length")
+ return errors.New("cannot specify negative length")
}
if !found {
max = -1
diff --git a/core/commands/cid.go b/core/commands/cid.go
index b2e8f131d53..26596f01155 100644
--- a/core/commands/cid.go
+++ b/core/commands/cid.go
@@ -1,6 +1,7 @@
package commands
import (
+ "errors"
"fmt"
"io"
"sort"
@@ -33,7 +34,7 @@ var CidCmd = &cmds.Command{
const (
cidFormatOptionName = "f"
- cidVerisonOptionName = "v"
+ cidToVersionOptionName = "v"
cidCodecOptionName = "mc"
cidMultibaseOptionName = "b"
)
@@ -52,13 +53,13 @@ The optional format string is a printf style format string:
},
Options: []cmds.Option{
cmds.StringOption(cidFormatOptionName, "Printf style format string.").WithDefault("%s"),
- cmds.StringOption(cidVerisonOptionName, "CID version to convert to."),
+ cmds.StringOption(cidToVersionOptionName, "CID version to convert to."),
cmds.StringOption(cidCodecOptionName, "CID multicodec to convert to."),
cmds.StringOption(cidMultibaseOptionName, "Multibase to display CID in."),
},
Run: func(req *cmds.Request, resp cmds.ResponseEmitter, env cmds.Environment) error {
fmtStr, _ := req.Options[cidFormatOptionName].(string)
- verStr, _ := req.Options[cidVerisonOptionName].(string)
+ verStr, _ := req.Options[cidToVersionOptionName].(string)
codecStr, _ := req.Options[cidCodecOptionName].(string)
baseStr, _ := req.Options[cidMultibaseOptionName].(string)
@@ -85,10 +86,10 @@ The optional format string is a printf style format string:
}
case "0":
if opts.newCodec != 0 && opts.newCodec != cid.DagProtobuf {
- return fmt.Errorf("cannot convert to CIDv0 with any codec other than dag-pb")
+ return errors.New("cannot convert to CIDv0 with any codec other than dag-pb")
}
if baseStr != "" && baseStr != "base58btc" {
- return fmt.Errorf("cannot convert to CIDv0 with any multibase other than the implicit base58btc")
+ return errors.New("cannot convert to CIDv0 with any multibase other than the implicit base58btc")
}
opts.verConv = toCidV0
case "1":
diff --git a/core/commands/cid_test.go b/core/commands/cid_test.go
index 10629628264..d159521d256 100644
--- a/core/commands/cid_test.go
+++ b/core/commands/cid_test.go
@@ -40,7 +40,7 @@ func TestCidFmtCmd(t *testing.T) {
// Mock request
req := &cmds.Request{
Options: map[string]interface{}{
- cidVerisonOptionName: "0",
+ cidToVersionOptionName: "0",
cidMultibaseOptionName: e.MultibaseName,
cidFormatOptionName: "%s",
},
@@ -91,7 +91,7 @@ func TestCidFmtCmd(t *testing.T) {
// Mock request
req := &cmds.Request{
Options: map[string]interface{}{
- cidVerisonOptionName: e.Ver,
+ cidToVersionOptionName: e.Ver,
cidMultibaseOptionName: e.MultibaseName,
cidFormatOptionName: "%s",
},
diff --git a/core/commands/cmdenv/cidbase.go b/core/commands/cmdenv/cidbase.go
index 55815f52427..926cd24a105 100644
--- a/core/commands/cmdenv/cidbase.go
+++ b/core/commands/cmdenv/cidbase.go
@@ -16,14 +16,14 @@ var (
)
// GetCidEncoder processes the `cid-base` and `output-cidv1` options and
-// returns a encoder to use based on those parameters.
+// returns an encoder to use based on those parameters.
func GetCidEncoder(req *cmds.Request) (cidenc.Encoder, error) {
return getCidBase(req, true)
}
-// GetLowLevelCidEncoder is like GetCidEncoder but meant to be used by
-// lower level commands. It differs from GetCidEncoder in that CIDv0
-// are not, by default, auto-upgraded to CIDv1.
+// GetLowLevelCidEncoder is like GetCidEncoder but meant to be used by lower
+// level commands. It differs from GetCidEncoder in that CIDv0 are not, by
+// default, auto-upgraded to CIDv1.
func GetLowLevelCidEncoder(req *cmds.Request) (cidenc.Encoder, error) {
return getCidBase(req, false)
}
@@ -52,19 +52,19 @@ func getCidBase(req *cmds.Request, autoUpgrade bool) (cidenc.Encoder, error) {
return e, nil
}
-// CidBaseDefined returns true if the `cid-base` option is specified
-// on the command line
+// CidBaseDefined returns true if the `cid-base` option is specified on the
+// command line
func CidBaseDefined(req *cmds.Request) bool {
base, _ := req.Options["cid-base"].(string)
return base != ""
}
-// CidEncoderFromPath creates a new encoder that is influenced from
-// the encoded Cid in a Path. For CidV0 the multibase from the base
-// encoder is used and automatic upgrades are disabled. For CidV1 the
-// multibase from the CID is used and upgrades are enabled.
+// CidEncoderFromPath creates a new encoder that is influenced from the encoded
+// Cid in a Path. For CIDv0 the multibase from the base encoder is used and
+// automatic upgrades are disabled. For CIDv1 the multibase from the CID is
+// used and upgrades are enabled.
//
-// This logic is intentionally fuzzy and will match anything of the form
+// This logic is intentionally fuzzy and matches anything of the form
// `CidLike`, `CidLike/...`, or `/namespace/CidLike/...`.
//
// For example:
diff --git a/core/commands/cmdenv/env.go b/core/commands/cmdenv/env.go
index fb538dc1200..06bccb0ef67 100644
--- a/core/commands/cmdenv/env.go
+++ b/core/commands/cmdenv/env.go
@@ -9,7 +9,7 @@ import (
"github.com/ipfs/kubo/core"
cmds "github.com/ipfs/go-ipfs-cmds"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
coreiface "github.com/ipfs/kubo/core/coreiface"
options "github.com/ipfs/kubo/core/coreiface/options"
)
diff --git a/core/commands/commands_test.go b/core/commands/commands_test.go
index 00c09d77a7b..d8b4c408380 100644
--- a/core/commands/commands_test.go
+++ b/core/commands/commands_test.go
@@ -15,63 +15,6 @@ func collectPaths(prefix string, cmd *cmds.Command, out map[string]struct{}) {
}
}
-func TestROCommands(t *testing.T) {
- list := []string{
- "/block",
- "/block/get",
- "/block/stat",
- "/cat",
- "/commands",
- "/commands/completion",
- "/commands/completion/bash",
- "/commands/completion/fish",
- "/commands/completion/zsh",
- "/dag",
- "/dag/get",
- "/dag/resolve",
- "/dag/stat",
- "/dag/export",
- "/get",
- "/ls",
- "/name",
- "/name/resolve",
- "/object",
- "/object/data",
- "/object/get",
- "/object/links",
- "/object/stat",
- "/refs",
- "/resolve",
- "/version",
- }
-
- cmdSet := make(map[string]struct{})
- collectPaths("", RootRO, cmdSet)
-
- for _, path := range list {
- if _, ok := cmdSet[path]; !ok {
- t.Errorf("%q not in result", path)
- } else {
- delete(cmdSet, path)
- }
- }
-
- for path := range cmdSet {
- t.Errorf("%q in result but shouldn't be", path)
- }
-
- for _, path := range list {
- path = path[1:] // remove leading slash
- split := strings.Split(path, "/")
- sub, err := RootRO.Get(split)
- if err != nil {
- t.Errorf("error getting subcommand %q: %v", path, err)
- } else if sub == nil {
- t.Errorf("subcommand %q is nil even though there was no error", path)
- }
- }
-}
-
func TestCommands(t *testing.T) {
list := []string{
"/add",
@@ -117,18 +60,19 @@ func TestCommands(t *testing.T) {
"/dag/resolve",
"/dag/stat",
"/dht",
- "/dht/findpeer",
+ "/dht/query",
"/dht/findprovs",
+ "/dht/findpeer",
"/dht/get",
"/dht/provide",
"/dht/put",
- "/dht/query",
"/routing",
"/routing/put",
"/routing/get",
"/routing/findpeer",
"/routing/findprovs",
"/routing/provide",
+ "/routing/reprovide",
"/diag",
"/diag/cmds",
"/diag/cmds/clear",
@@ -146,6 +90,8 @@ func TestCommands(t *testing.T) {
"/files/rm",
"/files/stat",
"/files/write",
+ "/files/chmod",
+ "/files/touch",
"/filestore",
"/filestore/dups",
"/filestore/ls",
@@ -238,6 +184,7 @@ func TestCommands(t *testing.T) {
"/stats/bw",
"/stats/dht",
"/stats/provide",
+ "/stats/reprovide",
"/stats/repo",
"/swarm",
"/swarm/addrs",
@@ -256,6 +203,7 @@ func TestCommands(t *testing.T) {
"/swarm/resources",
"/update",
"/version",
+ "/version/check",
"/version/deps",
}
diff --git a/core/commands/config.go b/core/commands/config.go
index b52c05af232..9d37111c333 100644
--- a/core/commands/config.go
+++ b/core/commands/config.go
@@ -48,13 +48,18 @@ file inside your IPFS repository (IPFS_PATH).
Examples:
-Get the value of the 'Datastore.Path' key:
+Get the value of the 'Routing.Type' key:
- $ ipfs config Datastore.Path
+ $ ipfs config Routing.Type
-Set the value of the 'Datastore.Path' key:
+Set the value of the 'Routing.Type' key:
- $ ipfs config Datastore.Path ~/.ipfs/datastore
+ $ ipfs config Routing.Type auto
+
+Set multiple values in the 'Addresses.AppendAnnounce' array:
+
+ $ ipfs config Addresses.AppendAnnounce --json \
+ '["/dns4/a.example.com/tcp/4001", "/dns4/b.example.com/tcp/4002"]'
`,
},
Subcommands: map[string]*cmds.Command{
diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go
index 56aae4105da..ce5edb64167 100644
--- a/core/commands/dag/dag.go
+++ b/core/commands/dag/dag.go
@@ -87,7 +87,7 @@ into an object of the specified format.
cmds.StringOption("store-codec", "Codec that the stored object will be encoded with").WithDefault("dag-cbor"),
cmds.StringOption("input-codec", "Codec that the input object is encoded in").WithDefault("dag-json"),
cmds.BoolOption("pin", "Pin this object when adding."),
- cmds.StringOption("hash", "Hash function to use").WithDefault("sha2-256"),
+ cmds.StringOption("hash", "Hash function to use"),
cmdutils.AllowBigBlockOption,
},
Run: dagPut,
diff --git a/core/commands/dag/import.go b/core/commands/dag/import.go
index 5e39393c1ce..e298a2d52a0 100644
--- a/core/commands/dag/import.go
+++ b/core/commands/dag/import.go
@@ -11,6 +11,7 @@ import (
cmds "github.com/ipfs/go-ipfs-cmds"
ipld "github.com/ipfs/go-ipld-format"
ipldlegacy "github.com/ipfs/go-ipld-legacy"
+ "github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core/coreiface/options"
gocarv2 "github.com/ipld/go-car/v2"
@@ -24,6 +25,11 @@ func dagImport(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment
return err
}
+ cfg, err := node.Repo.Config()
+ if err != nil {
+ return err
+ }
+
api, err := cmdenv.GetApi(env, req)
if err != nil {
return err
@@ -55,7 +61,14 @@ func dagImport(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment
// this is *not* a transaction
// it is simply a way to relieve pressure on the blockstore
// similar to pinner.Pin/pinner.Flush
- batch := ipld.NewBatch(req.Context, api.Dag())
+ batch := ipld.NewBatch(req.Context, api.Dag(),
+ // Default: 128. Means 128 file descriptors needed in flatfs
+ ipld.MaxNodesBatchOption(int(cfg.Import.BatchMaxNodes.WithDefault(config.DefaultBatchMaxNodes))),
+ // Default 100MiB. When setting block size to 1MiB, we can add
+ // ~100 nodes maximum. With default 256KiB block-size, we will
+ // hit the max nodes limit at 32MiB.p
+ ipld.MaxSizeBatchOption(int(cfg.Import.BatchMaxSize.WithDefault(config.DefaultBatchMaxSize))),
+ )
roots := cid.NewSet()
var blockCount, blockBytesCount uint64
diff --git a/core/commands/dag/put.go b/core/commands/dag/put.go
index c9c0b455b07..fb719916cdf 100644
--- a/core/commands/dag/put.go
+++ b/core/commands/dag/put.go
@@ -7,6 +7,7 @@ import (
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
ipldlegacy "github.com/ipfs/go-ipld-legacy"
+ "github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
"github.com/ipld/go-ipld-prime/multicodec"
@@ -32,11 +33,25 @@ func dagPut(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) e
return err
}
+ nd, err := cmdenv.GetNode(env)
+ if err != nil {
+ return err
+ }
+
+ cfg, err := nd.Repo.Config()
+ if err != nil {
+ return err
+ }
+
inputCodec, _ := req.Options["input-codec"].(string)
storeCodec, _ := req.Options["store-codec"].(string)
hash, _ := req.Options["hash"].(string)
dopin, _ := req.Options["pin"].(bool)
+ if hash == "" {
+ hash = cfg.Import.HashFunction.WithDefault(config.DefaultHashFunction)
+ }
+
var icodec mc.Code
if err := icodec.Set(inputCodec); err != nil {
return err
diff --git a/core/commands/dht.go b/core/commands/dht.go
index 95ac187f590..eaa8188e650 100644
--- a/core/commands/dht.go
+++ b/core/commands/dht.go
@@ -15,6 +15,7 @@ import (
var ErrNotDHT = errors.New("routing service is not a DHT")
var DhtCmd = &cmds.Command{
+ Status: cmds.Deprecated,
Helptext: cmds.HelpText{
Tagline: "Issue commands directly through the DHT.",
ShortDescription: ``,
@@ -22,64 +23,14 @@ var DhtCmd = &cmds.Command{
Subcommands: map[string]*cmds.Command{
"query": queryDhtCmd,
- "findprovs": findProvidersDhtCmd,
- "findpeer": findPeerDhtCmd,
- "get": getValueDhtCmd,
- "put": putValueDhtCmd,
- "provide": provideRefDhtCmd,
+ "findprovs": RemovedDHTCmd,
+ "findpeer": RemovedDHTCmd,
+ "get": RemovedDHTCmd,
+ "put": RemovedDHTCmd,
+ "provide": RemovedDHTCmd,
},
}
-var findProvidersDhtCmd = &cmds.Command{
- Helptext: findProvidersRoutingCmd.Helptext,
- Arguments: findProvidersRoutingCmd.Arguments,
- Options: findProvidersRoutingCmd.Options,
- Run: findProvidersRoutingCmd.Run,
- Encoders: findProvidersRoutingCmd.Encoders,
- Type: findProvidersRoutingCmd.Type,
- Status: cmds.Deprecated,
-}
-
-var findPeerDhtCmd = &cmds.Command{
- Helptext: findPeerRoutingCmd.Helptext,
- Arguments: findPeerRoutingCmd.Arguments,
- Options: findPeerRoutingCmd.Options,
- Run: findPeerRoutingCmd.Run,
- Encoders: findPeerRoutingCmd.Encoders,
- Type: findPeerRoutingCmd.Type,
- Status: cmds.Deprecated,
-}
-
-var getValueDhtCmd = &cmds.Command{
- Helptext: getValueRoutingCmd.Helptext,
- Arguments: getValueRoutingCmd.Arguments,
- Options: getValueRoutingCmd.Options,
- Run: getValueRoutingCmd.Run,
- Encoders: getValueRoutingCmd.Encoders,
- Type: getValueRoutingCmd.Type,
- Status: cmds.Deprecated,
-}
-
-var putValueDhtCmd = &cmds.Command{
- Helptext: putValueRoutingCmd.Helptext,
- Arguments: putValueRoutingCmd.Arguments,
- Options: putValueRoutingCmd.Options,
- Run: putValueRoutingCmd.Run,
- Encoders: putValueRoutingCmd.Encoders,
- Type: putValueRoutingCmd.Type,
- Status: cmds.Deprecated,
-}
-
-var provideRefDhtCmd = &cmds.Command{
- Helptext: provideRefRoutingCmd.Helptext,
- Arguments: provideRefRoutingCmd.Arguments,
- Options: provideRefRoutingCmd.Options,
- Run: provideRefRoutingCmd.Run,
- Encoders: provideRefRoutingCmd.Encoders,
- Type: provideRefRoutingCmd.Type,
- Status: cmds.Deprecated,
-}
-
// kademlia extends the routing interface with a command to get the peers closest to the target
type kademlia interface {
routing.Routing
@@ -87,6 +38,7 @@ type kademlia interface {
}
var queryDhtCmd = &cmds.Command{
+ Status: cmds.Deprecated,
Helptext: cmds.HelpText{
Tagline: "Find the closest Peer IDs to a given Peer ID by querying the DHT.",
ShortDescription: "Outputs a list of newline-delimited Peer IDs.",
@@ -126,7 +78,7 @@ var queryDhtCmd = &cmds.Command{
}
if d, ok := client.(kademlia); !ok {
- return fmt.Errorf("dht client does not support GetClosestPeers")
+ return errors.New("dht client does not support GetClosestPeers")
} else {
errCh := make(chan error, 1)
go func() {
@@ -169,3 +121,12 @@ var queryDhtCmd = &cmds.Command{
},
Type: routing.QueryEvent{},
}
+var RemovedDHTCmd = &cmds.Command{
+ Status: cmds.Removed,
+ Helptext: cmds.HelpText{
+ Tagline: "Removed, use 'ipfs routing' instead.",
+ },
+ Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
+ return errors.New("removed, use 'ipfs routing' instead")
+ },
+}
diff --git a/core/commands/files.go b/core/commands/files.go
index 9a7ee639a2c..eb10a9bc761 100644
--- a/core/commands/files.go
+++ b/core/commands/files.go
@@ -2,15 +2,19 @@ package commands
import (
"context"
+ "encoding/json"
"errors"
"fmt"
"io"
"os"
gopath "path"
"sort"
+ "strconv"
"strings"
+ "time"
humanize "github.com/dustin/go-humanize"
+ "github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/core/commands/cmdenv"
@@ -24,7 +28,7 @@ import (
cidenc "github.com/ipfs/go-cidutil/cidenc"
cmds "github.com/ipfs/go-ipfs-cmds"
ipld "github.com/ipfs/go-ipld-format"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
iface "github.com/ipfs/kubo/core/coreiface"
mh "github.com/multiformats/go-multihash"
)
@@ -55,16 +59,18 @@ Content added with "ipfs add" (which by default also becomes pinned), is not
added to MFS. Any content can be lazily referenced from MFS with the command
"ipfs files cp /ipfs/ /some/path/" (see ipfs files cp --help).
-
-NOTE:
-Most of the subcommands of 'ipfs files' accept the '--flush' flag. It defaults
-to true. Use caution when setting this flag to false. It will improve
+NOTE: Most of the subcommands of 'ipfs files' accept the '--flush' flag. It
+defaults to true and ensures two things: 1) that the changes are reflected in
+the full MFS structure (updated CIDs) 2) that the parent-folder's cache is
+cleared. Use caution when setting this flag to false. It will improve
performance for large numbers of file operations, but it does so at the cost
-of consistency guarantees. If the daemon is unexpectedly killed before running
-'ipfs files flush' on the files in question, then data may be lost. This also
-applies to run 'ipfs repo gc' concurrently with '--flush=false'
-operations.
-`,
+of consistency guarantees and unbound growth of the directories' in-memory
+caches. If the daemon is unexpectedly killed before running 'ipfs files
+flush' on the files in question, then data may be lost. This also applies to
+run 'ipfs repo gc' concurrently with '--flush=false' operations. We recommend
+flushing paths regularly with 'ipfs files flush', specially the folders on
+which many write operations are happening, as a way to clear the directory
+cache, free memory and speed up read operations.`,
},
Options: []cmds.Option{
cmds.BoolOption(filesFlushOptionName, "f", "Flush target and ancestors after write.").WithDefault(true),
@@ -80,6 +86,8 @@ operations.
"rm": filesRmCmd,
"flush": filesFlushCmd,
"chcid": filesChcidCmd,
+ "chmod": filesChmodCmd,
+ "touch": filesTouchCmd,
},
}
@@ -104,6 +112,43 @@ type statOutput struct {
WithLocality bool `json:",omitempty"`
Local bool `json:",omitempty"`
SizeLocal uint64 `json:",omitempty"`
+ Mode uint32 `json:",omitempty"`
+ Mtime int64 `json:",omitempty"`
+ MtimeNsecs int `json:",omitempty"`
+}
+
+func (s *statOutput) MarshalJSON() ([]byte, error) {
+ type so statOutput
+ out := &struct {
+ *so
+ Mode string `json:",omitempty"`
+ }{so: (*so)(s)}
+
+ if s.Mode != 0 {
+ out.Mode = fmt.Sprintf("%04o", s.Mode)
+ }
+ return json.Marshal(out)
+}
+
+func (s *statOutput) UnmarshalJSON(data []byte) error {
+ var err error
+ type so statOutput
+ tmp := &struct {
+ *so
+ Mode string `json:",omitempty"`
+ }{so: (*so)(s)}
+
+ if err := json.Unmarshal(data, &tmp); err != nil {
+ return err
+ }
+
+ if tmp.Mode != "" {
+ mode, err := strconv.ParseUint(tmp.Mode, 8, 32)
+ if err == nil {
+ s.Mode = uint32(mode)
+ }
+ }
+ return err
}
const (
@@ -111,10 +156,13 @@ const (
Size:
CumulativeSize:
ChildBlocks:
-Type: `
+Type:
+Mode: ()
+Mtime: `
filesFormatOptionName = "format"
filesSizeOptionName = "size"
filesWithLocalOptionName = "with-local"
+ filesStatUnspecified = "not set"
)
var filesStatCmd = &cmds.Command{
@@ -127,7 +175,8 @@ var filesStatCmd = &cmds.Command{
},
Options: []cmds.Option{
cmds.StringOption(filesFormatOptionName, "Print statistics in given format. Allowed tokens: "+
- " . Conflicts with other format options.").WithDefault(defaultStatFormat),
+ " and optional ."+
+ "Conflicts with other format options.").WithDefault(defaultStatFormat),
cmds.BoolOption(filesHashOptionName, "Print only hash. Implies '--format='. Conflicts with other format options."),
cmds.BoolOption(filesSizeOptionName, "Print only size. Implies '--format='. Conflicts with other format options."),
cmds.BoolOption(filesWithLocalOptionName, "Compute the amount of the dag that is local, and if possible the total size"),
@@ -135,7 +184,7 @@ var filesStatCmd = &cmds.Command{
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
_, err := statGetFormatOptions(req)
if err != nil {
- return cmds.Errorf(cmds.ErrClient, err.Error())
+ return cmds.Errorf(cmds.ErrClient, "invalid parameters: %s", err)
}
node, err := cmdenv.GetNode(env)
@@ -198,12 +247,29 @@ var filesStatCmd = &cmds.Command{
},
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *statOutput) error {
+ mode, modeo := filesStatUnspecified, filesStatUnspecified
+ if out.Mode != 0 {
+ mode = strings.ToLower(os.FileMode(out.Mode).String())
+ modeo = "0" + strconv.FormatInt(int64(out.Mode&0x1FF), 8)
+ }
+ mtime, mtimes, mtimens := filesStatUnspecified, filesStatUnspecified, filesStatUnspecified
+ if out.Mtime > 0 {
+ mtime = time.Unix(out.Mtime, int64(out.MtimeNsecs)).UTC().Format("2 Jan 2006, 15:04:05 MST")
+ mtimes = strconv.FormatInt(out.Mtime, 10)
+ mtimens = strconv.Itoa(out.MtimeNsecs)
+ }
+
s, _ := statGetFormatOptions(req)
s = strings.Replace(s, "", out.Hash, -1)
s = strings.Replace(s, "", fmt.Sprintf("%d", out.Size), -1)
s = strings.Replace(s, "", fmt.Sprintf("%d", out.CumulativeSize), -1)
s = strings.Replace(s, "", fmt.Sprintf("%d", out.Blocks), -1)
s = strings.Replace(s, "", out.Type, -1)
+ s = strings.Replace(s, "", mode, -1)
+ s = strings.Replace(s, "", modeo, -1)
+ s = strings.Replace(s, "", mtime, -1)
+ s = strings.Replace(s, "", mtimes, -1)
+ s = strings.Replace(s, "", mtimens, -1)
fmt.Fprintln(w, s)
@@ -253,28 +319,7 @@ func statNode(nd ipld.Node, enc cidenc.Encoder) (*statOutput, error) {
switch n := nd.(type) {
case *dag.ProtoNode:
- d, err := ft.FSNodeFromBytes(n.Data())
- if err != nil {
- return nil, err
- }
-
- var ndtype string
- switch d.Type() {
- case ft.TDirectory, ft.THAMTShard:
- ndtype = "directory"
- case ft.TFile, ft.TMetadata, ft.TRaw:
- ndtype = "file"
- default:
- return nil, fmt.Errorf("unrecognized node type: %s", d.Type())
- }
-
- return &statOutput{
- Hash: enc.Encode(c),
- Blocks: len(nd.Links()),
- Size: d.FileSize(),
- CumulativeSize: cumulsize,
- Type: ndtype,
- }, nil
+ return statProtoNode(n, enc, c, cumulsize)
case *dag.RawNode:
return &statOutput{
Hash: enc.Encode(c),
@@ -284,10 +329,48 @@ func statNode(nd ipld.Node, enc cidenc.Encoder) (*statOutput, error) {
Type: "file",
}, nil
default:
- return nil, fmt.Errorf("not unixfs node (proto or raw)")
+ return nil, errors.New("not unixfs node (proto or raw)")
}
}
+func statProtoNode(n *dag.ProtoNode, enc cidenc.Encoder, cid cid.Cid, cumulsize uint64) (*statOutput, error) {
+ d, err := ft.FSNodeFromBytes(n.Data())
+ if err != nil {
+ return nil, err
+ }
+
+ stat := statOutput{
+ Hash: enc.Encode(cid),
+ Blocks: len(n.Links()),
+ Size: d.FileSize(),
+ CumulativeSize: cumulsize,
+ }
+
+ switch d.Type() {
+ case ft.TDirectory, ft.THAMTShard:
+ stat.Type = "directory"
+ case ft.TFile, ft.TSymlink, ft.TMetadata, ft.TRaw:
+ stat.Type = "file"
+ default:
+ return nil, fmt.Errorf("unrecognized node type: %s", d.Type())
+ }
+
+ if mode := d.Mode(); mode != 0 {
+ stat.Mode = uint32(mode)
+ } else if d.Type() == ft.TSymlink {
+ stat.Mode = uint32(os.ModeSymlink | 0x1FF)
+ }
+
+ if mt := d.ModTime(); !mt.IsZero() {
+ stat.Mtime = mt.Unix()
+ if ns := mt.Nanosecond(); ns > 0 {
+ stat.MtimeNsecs = ns
+ }
+ }
+
+ return &stat, nil
+}
+
func walkBlock(ctx context.Context, dagserv ipld.DAGService, nd ipld.Node) (bool, uint64, error) {
// Start with the block data size
sizeLocal := uint64(len(nd.RawData()))
@@ -319,6 +402,7 @@ func walkBlock(ctx context.Context, dagserv ipld.DAGService, nd ipld.Node) (bool
return local, sizeLocal, nil
}
+var errFilesCpInvalidUnixFS = errors.New("cp: source must be a valid UnixFS (dag-pb or raw codec)")
var filesCpCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Add references to IPFS files and directories in MFS (or copy within MFS).",
@@ -340,7 +424,7 @@ $ ipfs add --quieter --pin=false
$ ipfs files cp /ipfs/ /your/desired/mfs/path
If you wish to fully copy content from a different IPFS peer into MFS, do not
-forget to force IPFS to fetch to full DAG after doing the "cp" operation. i.e:
+forget to force IPFS to fetch the full DAG after doing a "cp" operation. i.e:
$ ipfs files cp /ipfs/ /your/desired/mfs/path
$ ipfs pin add
@@ -397,6 +481,25 @@ being GC'ed.
return fmt.Errorf("cp: cannot get node from path %s: %s", src, err)
}
+ // Sanity-check: ensure root CID is a valid UnixFS (dag-pb or raw block)
+ // Context: https://github.com/ipfs/kubo/issues/10331
+ srcCidType := node.Cid().Type()
+ switch srcCidType {
+ case cid.Raw:
+ if _, ok := node.(*dag.RawNode); !ok {
+ return errFilesCpInvalidUnixFS
+ }
+ case cid.DagProtobuf:
+ if _, ok := node.(*dag.ProtoNode); !ok {
+ return errFilesCpInvalidUnixFS
+ }
+ if _, err = ft.FSNodeFromBytes(node.(*dag.ProtoNode).Data()); err != nil {
+ return fmt.Errorf("%w: %v", errFilesCpInvalidUnixFS, err)
+ }
+ default:
+ return errFilesCpInvalidUnixFS
+ }
+
if mkParents {
err := ensureContainingDirectoryExists(nd.FilesRoot, dst, prefix)
if err != nil {
@@ -410,10 +513,14 @@ being GC'ed.
}
if flush {
- _, err := mfs.FlushPath(req.Context, nd.FilesRoot, dst)
- if err != nil {
+ if _, err := mfs.FlushPath(req.Context, nd.FilesRoot, dst); err != nil {
return fmt.Errorf("cp: cannot flush the created file %s: %s", dst, err)
}
+ // Flush parent to clear directory cache and free memory.
+ parent := gopath.Dir(dst)
+ if _, err = mfs.FlushPath(req.Context, nd.FilesRoot, parent); err != nil {
+ return fmt.Errorf("cp: cannot flush the created file's parent folder %s: %s", dst, err)
+ }
}
return nil
@@ -711,10 +818,30 @@ Example:
}
err = mfs.Mv(nd.FilesRoot, src, dst)
- if err == nil && flush {
- _, err = mfs.FlushPath(req.Context, nd.FilesRoot, "/")
+ if err != nil {
+ return err
}
- return err
+ if flush {
+ parentSrc := gopath.Dir(src)
+ parentDst := gopath.Dir(dst)
+ // Flush parent to clear directory cache and free memory.
+ if _, err = mfs.FlushPath(req.Context, nd.FilesRoot, parentDst); err != nil {
+ return fmt.Errorf("cp: cannot flush the destination file's parent folder %s: %s", dst, err)
+ }
+
+ // Avoid re-flushing when moving within the same folder.
+ if parentSrc != parentDst {
+ if _, err = mfs.FlushPath(req.Context, nd.FilesRoot, parentSrc); err != nil {
+ return fmt.Errorf("cp: cannot flush the source's file's parent folder %s: %s", dst, err)
+ }
+ }
+
+ if _, err = mfs.FlushPath(req.Context, nd.FilesRoot, "/"); err != nil {
+ return err
+ }
+ }
+
+ return nil
},
}
@@ -802,18 +929,28 @@ See '--to-files' in 'ipfs add --help' for more information.
return err
}
+ nd, err := cmdenv.GetNode(env)
+ if err != nil {
+ return err
+ }
+
+ cfg, err := nd.Repo.Config()
+ if err != nil {
+ return err
+ }
+
create, _ := req.Options[filesCreateOptionName].(bool)
mkParents, _ := req.Options[filesParentsOptionName].(bool)
trunc, _ := req.Options[filesTruncateOptionName].(bool)
flush, _ := req.Options[filesFlushOptionName].(bool)
rawLeaves, rawLeavesDef := req.Options[filesRawLeavesOptionName].(bool)
- prefix, err := getPrefixNew(req)
- if err != nil {
- return err
+ if !rawLeavesDef && cfg.Import.UnixFSRawLeaves != config.Default {
+ rawLeavesDef = true
+ rawLeaves = cfg.Import.UnixFSRawLeaves.WithDefault(config.DefaultUnixFSRawLeaves)
}
- nd, err := cmdenv.GetNode(env)
+ prefix, err := getPrefixNew(req)
if err != nil {
return err
}
@@ -852,6 +989,17 @@ See '--to-files' in 'ipfs add --help' for more information.
flog.Error("files: error closing file mfs file descriptor", err)
}
}
+ if flush {
+ // Flush parent to clear directory cache and free memory.
+ parent := gopath.Dir(path)
+ if _, err := mfs.FlushPath(req.Context, nd.FilesRoot, parent); err != nil {
+ if retErr == nil {
+ retErr = err
+ } else {
+ flog.Error("files: flushing the parent folder", err)
+ }
+ }
+ }
}()
if trunc {
@@ -1014,11 +1162,20 @@ Change the CID version or hash function of the root node of a given path.
return err
}
- err = updatePath(nd.FilesRoot, path, prefix)
- if err == nil && flush {
- _, err = mfs.FlushPath(req.Context, nd.FilesRoot, path)
+ if err := updatePath(nd.FilesRoot, path, prefix); err != nil {
+ return err
}
- return err
+ if flush {
+ if _, err = mfs.FlushPath(req.Context, nd.FilesRoot, path); err != nil {
+ return err
+ }
+ // Flush parent to clear directory cache and free memory.
+ parent := gopath.Dir(path)
+ if _, err = mfs.FlushPath(req.Context, nd.FilesRoot, parent); err != nil {
+ return err
+ }
+ }
+ return nil
},
}
@@ -1302,3 +1459,86 @@ func getParentDir(root *mfs.Root, dir string) (*mfs.Directory, error) {
}
return pdir, nil
}
+
+var filesChmodCmd = &cmds.Command{
+ Status: cmds.Experimental,
+ Helptext: cmds.HelpText{
+ Tagline: "Change optional POSIX mode permissions",
+ ShortDescription: `
+The mode argument must be specified in Unix numeric notation.
+
+ $ ipfs files chmod 0644 /foo
+ $ ipfs files stat /foo
+ ...
+ Type: file
+ Mode: -rw-r--r-- (0644)
+ ...
+`,
+ },
+ Arguments: []cmds.Argument{
+ cmds.StringArg("mode", true, false, "Mode to apply to node (numeric notation)"),
+ cmds.StringArg("path", true, false, "Path to apply mode"),
+ },
+ Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
+ nd, err := cmdenv.GetNode(env)
+ if err != nil {
+ return err
+ }
+
+ path, err := checkPath(req.Arguments[1])
+ if err != nil {
+ return err
+ }
+
+ mode, err := strconv.ParseInt(req.Arguments[0], 8, 32)
+ if err != nil {
+ return err
+ }
+
+ return mfs.Chmod(nd.FilesRoot, path, os.FileMode(mode))
+ },
+}
+
+var filesTouchCmd = &cmds.Command{
+ Status: cmds.Experimental,
+ Helptext: cmds.HelpText{
+ Tagline: "Set or change optional POSIX modification times.",
+ ShortDescription: `
+Examples:
+ # set modification time to now.
+ $ ipfs files touch /foo
+ # set a custom modification time.
+ $ ipfs files touch --mtime=1630937926 /foo
+`,
+ },
+ Arguments: []cmds.Argument{
+ cmds.StringArg("path", true, false, "Path of target to update."),
+ },
+ Options: []cmds.Option{
+ cmds.Int64Option(mtimeOptionName, "Modification time in seconds before or since the Unix Epoch to apply to created UnixFS entries."),
+ cmds.UintOption(mtimeNsecsOptionName, "Modification time fraction in nanoseconds"),
+ },
+ Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
+ nd, err := cmdenv.GetNode(env)
+ if err != nil {
+ return err
+ }
+
+ path, err := checkPath(req.Arguments[0])
+ if err != nil {
+ return err
+ }
+
+ mtime, _ := req.Options[mtimeOptionName].(int64)
+ nsecs, _ := req.Options[mtimeNsecsOptionName].(uint)
+
+ var ts time.Time
+ if mtime != 0 {
+ ts = time.Unix(mtime, int64(nsecs)).UTC()
+ } else {
+ ts = time.Now().UTC()
+ }
+
+ return mfs.Touch(nd.FilesRoot, path, ts)
+ },
+}
diff --git a/core/commands/files_test.go b/core/commands/files_test.go
new file mode 100644
index 00000000000..bcd73bd3b17
--- /dev/null
+++ b/core/commands/files_test.go
@@ -0,0 +1,47 @@
+package commands
+
+import (
+ "context"
+ "io"
+ "testing"
+
+ dag "github.com/ipfs/boxo/ipld/merkledag"
+ cmds "github.com/ipfs/go-ipfs-cmds"
+ coremock "github.com/ipfs/kubo/core/mock"
+ "github.com/stretchr/testify/require"
+)
+
+func TestFilesCp_DagCborNodeFails(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ cmdCtx, err := coremock.MockCmdsCtx()
+ require.NoError(t, err)
+
+ node, err := cmdCtx.ConstructNode()
+ require.NoError(t, err)
+
+ invalidData := []byte{0x00}
+ protoNode := dag.NodeWithData(invalidData)
+ err = node.DAG.Add(ctx, protoNode)
+ require.NoError(t, err)
+
+ req := &cmds.Request{
+ Context: ctx,
+ Arguments: []string{
+ "/ipfs/" + protoNode.Cid().String(),
+ "/test-destination",
+ },
+ Options: map[string]interface{}{
+ "force": false,
+ },
+ }
+
+ _, pw := io.Pipe()
+ res, err := cmds.NewWriterResponseEmitter(pw, req)
+ require.NoError(t, err)
+
+ err = filesCpCmd.Run(req, res, &cmdCtx)
+ require.Error(t, err)
+ require.ErrorContains(t, err, "cp: source must be a valid UnixFS (dag-pb or raw codec)")
+}
diff --git a/core/commands/get.go b/core/commands/get.go
index 5b64c281bbd..12a3ea8ca26 100644
--- a/core/commands/get.go
+++ b/core/commands/get.go
@@ -1,6 +1,7 @@
package commands
import (
+ gotar "archive/tar"
"bufio"
"compress/gzip"
"errors"
@@ -331,7 +332,8 @@ func fileArchive(f files.Node, name string, archive bool, compression int) (io.R
closeGzwAndPipe() // everything seems to be ok
}()
} else {
- // the case for 1. archive, and 2. not archived and not compressed, in which tar is used anyway as a transport format
+ // the case for 1. archive, and 2. not archived and not compressed, in
+ // which tar is used anyway as a transport format
// construct the tar writer
w, err := files.NewTarWriter(maybeGzw)
@@ -339,6 +341,11 @@ func fileArchive(f files.Node, name string, archive bool, compression int) (io.R
return nil, err
}
+ // if not creating an archive set the format to PAX in order to preserve nanoseconds
+ if !archive {
+ w.SetFormat(gotar.FormatPAX)
+ }
+
go func() {
// write all the nodes recursively
if err := w.WriteFile(f, filename); checkErrAndClosePipe(err) {
diff --git a/core/commands/id.go b/core/commands/id.go
index 3446fc267cd..33ad0328698 100644
--- a/core/commands/id.go
+++ b/core/commands/id.go
@@ -81,7 +81,7 @@ EXAMPLE:
var err error
id, err = peer.Decode(req.Arguments[0])
if err != nil {
- return fmt.Errorf("invalid peer id")
+ return errors.New("invalid peer id")
}
} else {
id = n.Identity
diff --git a/core/commands/keystore.go b/core/commands/keystore.go
index a86fb281af3..0ffd141891e 100644
--- a/core/commands/keystore.go
+++ b/core/commands/keystore.go
@@ -5,6 +5,7 @@ import (
"crypto/ed25519"
"crypto/x509"
"encoding/pem"
+ "errors"
"fmt"
"io"
"os"
@@ -101,12 +102,12 @@ var keyGenCmd = &cmds.Command{
typ, f := req.Options[keyStoreTypeOptionName].(string)
if !f {
- return fmt.Errorf("please specify a key type with --type")
+ return errors.New("please specify a key type with --type")
}
name := req.Arguments[0]
if name == "self" {
- return fmt.Errorf("cannot create key with name 'self'")
+ return errors.New("cannot create key with name 'self'")
}
opts := []options.KeyGenerateOption{options.Key.Type(typ)}
diff --git a/core/commands/log.go b/core/commands/log.go
index d2cb4a1a168..81427aa131b 100644
--- a/core/commands/log.go
+++ b/core/commands/log.go
@@ -5,8 +5,7 @@ import (
"io"
cmds "github.com/ipfs/go-ipfs-cmds"
- logging "github.com/ipfs/go-log"
- lwriter "github.com/ipfs/go-log/writer"
+ logging "github.com/ipfs/go-log/v2"
)
// Golang os.Args overrides * and replaces the character argument with
@@ -22,12 +21,12 @@ var LogCmd = &cmds.Command{
'ipfs log' contains utility commands to affect or read the logging
output of a running daemon.
-There are also two environmental variables that direct the logging
+There are also two environmental variables that direct the logging
system (not just for the daemon logs, but all commands):
- IPFS_LOGGING - sets the level of verbosity of the logging.
+ GOLOG_LOG_LEVEL - sets the level of verbosity of the logging.
One of: debug, info, warn, error, dpanic, panic, fatal
- IPFS_LOGGING_FMT - sets formatting of the log output.
- One of: color, nocolor
+ GOLOG_LOG_FMT - sets formatting of the log output.
+ One of: color, nocolor, json
`,
},
@@ -104,25 +103,46 @@ subsystems of a running daemon.
Type: stringList{},
}
+const logLevelOption = "log-level"
+
var logTailCmd = &cmds.Command{
Status: cmds.Experimental,
Helptext: cmds.HelpText{
- Tagline: "Read the event log.",
+ Tagline: "Read and outpt log messages.",
ShortDescription: `
-Outputs event log messages (not other log messages) as they are generated.
+Outputs log messages as they are generated.
+
+NOTE: --log-level requires the server to be logging at least at this level
+
+Example:
+
+ GOLOG_LOG_LEVEL="error,bitswap=debug" ipfs daemon
+ ipfs log tail --log-level info
-Currently broken. Follow https://github.com/ipfs/kubo/issues/9245 for updates.
+This will only return 'info' logs from bitswap and skip 'debug'.
`,
},
+ Options: []cmds.Option{
+ cmds.StringOption(logLevelOption, "Log level to listen to.").WithDefault(""),
+ },
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
- ctx := req.Context
- r, w := io.Pipe()
+ var pipeReader *logging.PipeReader
+ logLevelString, _ := req.Options[logLevelOption].(string)
+ if logLevelString != "" {
+ logLevel, err := logging.LevelFromString(logLevelString)
+ if err != nil {
+ return fmt.Errorf("setting log level %s: %w", logLevelString, err)
+ }
+ pipeReader = logging.NewPipeReader(logging.PipeLevel(logLevel))
+ } else {
+ pipeReader = logging.NewPipeReader()
+ }
+
go func() {
- defer w.Close()
- <-ctx.Done()
+ <-req.Context.Done()
+ pipeReader.Close()
}()
- lwriter.WriterGroup.AddWriter(w)
- return res.Emit(r)
+ return res.Emit(pipeReader)
},
}
diff --git a/core/commands/ls.go b/core/commands/ls.go
index 6fd53528271..bdd475d96cb 100644
--- a/core/commands/ls.go
+++ b/core/commands/ls.go
@@ -1,11 +1,13 @@
package commands
import (
+ "context"
"fmt"
"io"
"os"
"sort"
"text/tabwriter"
+ "time"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
@@ -23,6 +25,8 @@ type LsLink struct {
Size uint64
Type unixfs_pb.Data_DataType
Target string
+ Mode os.FileMode
+ ModTime time.Time
}
// LsObject is an element of LsOutput
@@ -130,23 +134,24 @@ The JSON output contains type information.
}
}
+ lsCtx, cancel := context.WithCancel(req.Context)
+ defer cancel()
+
for i, fpath := range paths {
pth, err := cmdutils.PathOrCidPath(fpath)
if err != nil {
return err
}
- results, err := api.Unixfs().Ls(req.Context, pth,
- options.Unixfs.ResolveChildren(resolveSize || resolveType))
- if err != nil {
- return err
- }
+ results := make(chan iface.DirEntry)
+ lsErr := make(chan error, 1)
+ go func() {
+ lsErr <- api.Unixfs().Ls(lsCtx, pth, results,
+ options.Unixfs.ResolveChildren(resolveSize || resolveType))
+ }()
processLink, dirDone = processDir()
for link := range results {
- if link.Err != nil {
- return link.Err
- }
var ftype unixfs_pb.Data_DataType
switch link.Type {
case iface.TFile:
@@ -163,11 +168,17 @@ The JSON output contains type information.
Size: link.Size,
Type: ftype,
Target: link.Target,
+
+ Mode: link.Mode,
+ ModTime: link.ModTime,
}
- if err := processLink(paths[i], lsLink); err != nil {
+ if err = processLink(paths[i], lsLink); err != nil {
return err
}
}
+ if err = <-lsErr; err != nil {
+ return err
+ }
dirDone(i)
}
return done()
@@ -256,6 +267,7 @@ func tabularOutput(req *cmds.Request, w io.Writer, out *LsOutput, lastObjectHash
}
}
+ // TODO: Print link.Mode and link.ModTime?
fmt.Fprintf(tw, s, link.Hash, link.Size, cmdenv.EscNonPrint(link.Name))
}
}
diff --git a/core/commands/mount_nofuse.go b/core/commands/mount_nofuse.go
index c425aff0fcf..103678e77ca 100644
--- a/core/commands/mount_nofuse.go
+++ b/core/commands/mount_nofuse.go
@@ -14,10 +14,11 @@ var MountCmd = &cmds.Command{
ShortDescription: `
This version of ipfs is compiled without fuse support, which is required
for mounting. If you'd like to be able to mount, please use a version of
-ipfs compiled with fuse.
+Kubo compiled with fuse.
For the latest instructions, please check the project's repository:
- http://github.com/ipfs/go-ipfs
+ http://github.com/ipfs/kubo
+ https://github.com/ipfs/kubo/blob/master/docs/fuse.md
`,
},
}
diff --git a/core/commands/mount_unix.go b/core/commands/mount_unix.go
index 52a1b843b80..6051f86aa6f 100644
--- a/core/commands/mount_unix.go
+++ b/core/commands/mount_unix.go
@@ -18,6 +18,7 @@ import (
const (
mountIPFSPathOptionName = "ipfs-path"
mountIPNSPathOptionName = "ipns-path"
+ mountMFSPathOptionName = "mfs-path"
)
var MountCmd = &cmds.Command{
@@ -25,14 +26,14 @@ var MountCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Mounts IPFS to the filesystem (read-only).",
ShortDescription: `
-Mount IPFS at a read-only mountpoint on the OS (default: /ipfs and /ipns).
+Mount IPFS at a read-only mountpoint on the OS (default: /ipfs, /ipns, /mfs).
All IPFS objects will be accessible under that directory. Note that the
root will not be listable, as it is virtual. Access known paths directly.
You may have to create /ipfs and /ipns before using 'ipfs mount':
-> sudo mkdir /ipfs /ipns
-> sudo chown $(whoami) /ipfs /ipns
+> sudo mkdir /ipfs /ipns /mfs
+> sudo chown $(whoami) /ipfs /ipns /mfs
> ipfs daemon &
> ipfs mount
`,
@@ -44,8 +45,8 @@ root will not be listable, as it is virtual. Access known paths directly.
You may have to create /ipfs and /ipns before using 'ipfs mount':
-> sudo mkdir /ipfs /ipns
-> sudo chown $(whoami) /ipfs /ipns
+> sudo mkdir /ipfs /ipns /mfs
+> sudo chown $(whoami) /ipfs /ipns /mfs
> ipfs daemon &
> ipfs mount
@@ -67,6 +68,7 @@ baz
> ipfs mount
IPFS mounted at: /ipfs
IPNS mounted at: /ipns
+MFS mounted at: /mfs
> cd /ipfs/QmSh5e7S6fdcu75LAbXNZAFY2nGyZUJXyLCJDvn2zRkWyC
> ls
bar
@@ -81,6 +83,7 @@ baz
Options: []cmds.Option{
cmds.StringOption(mountIPFSPathOptionName, "f", "The path where IPFS should be mounted."),
cmds.StringOption(mountIPNSPathOptionName, "n", "The path where IPNS should be mounted."),
+ cmds.StringOption(mountMFSPathOptionName, "m", "The path where MFS should be mounted."),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
cfg, err := env.(*oldcmds.Context).GetConfig()
@@ -109,7 +112,12 @@ baz
nsdir = cfg.Mounts.IPNS // NB: be sure to not redeclare!
}
- err = nodeMount.Mount(nd, fsdir, nsdir)
+ mfsdir, found := req.Options[mountMFSPathOptionName].(string)
+ if !found {
+ mfsdir = cfg.Mounts.MFS
+ }
+
+ err = nodeMount.Mount(nd, fsdir, nsdir, mfsdir)
if err != nil {
return err
}
@@ -117,6 +125,7 @@ baz
var output config.Mounts
output.IPFS = fsdir
output.IPNS = nsdir
+ output.MFS = mfsdir
return cmds.EmitOnce(res, &output)
},
Type: config.Mounts{},
@@ -124,6 +133,7 @@ baz
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, mounts *config.Mounts) error {
fmt.Fprintf(w, "IPFS mounted at: %s\n", cmdenv.EscNonPrint(mounts.IPFS))
fmt.Fprintf(w, "IPNS mounted at: %s\n", cmdenv.EscNonPrint(mounts.IPNS))
+ fmt.Fprintf(w, "MFS mounted at: %s\n", cmdenv.EscNonPrint(mounts.MFS))
return nil
}),
diff --git a/core/commands/name/ipns.go b/core/commands/name/ipns.go
index 92cbb59a30c..e9d5c4426c3 100644
--- a/core/commands/name/ipns.go
+++ b/core/commands/name/ipns.go
@@ -10,7 +10,7 @@ import (
"github.com/ipfs/boxo/namesys"
"github.com/ipfs/boxo/path"
cmds "github.com/ipfs/go-ipfs-cmds"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
options "github.com/ipfs/kubo/core/coreiface/options"
)
diff --git a/core/commands/name/ipnsps.go b/core/commands/name/ipnsps.go
index f57173eeaca..e465549e07c 100644
--- a/core/commands/name/ipnsps.go
+++ b/core/commands/name/ipnsps.go
@@ -135,7 +135,7 @@ var ipnspsCancelCmd = &cmds.Command{
name = strings.TrimPrefix(name, "/ipns/")
pid, err := peer.Decode(name)
if err != nil {
- return cmds.Errorf(cmds.ErrClient, err.Error())
+ return cmds.Errorf(cmds.ErrClient, "not a valid IPNS name: %s", err)
}
ok, err := n.PSRouter.Cancel("/ipns/" + string(pid))
diff --git a/core/commands/name/name.go b/core/commands/name/name.go
index 9445fc362f0..912629d6883 100644
--- a/core/commands/name/name.go
+++ b/core/commands/name/name.go
@@ -260,8 +260,7 @@ Passing --verify will verify signature against provided public key.
if out.HexDump != "" {
tw.Flush()
- fmt.Fprintf(w, "\nHex Dump:\n")
- fmt.Fprintf(w, out.HexDump)
+ fmt.Fprintf(w, "\nHex Dump:\n%s", out.HexDump)
}
return nil
diff --git a/core/commands/name/publish.go b/core/commands/name/publish.go
index 9c8d837cb83..168d7fb445f 100644
--- a/core/commands/name/publish.go
+++ b/core/commands/name/publish.go
@@ -79,7 +79,7 @@ Alternatively, publish an using a valid PeerID (as listed by
cmds.StringOption(ttlOptionName, "Time duration hint, akin to --lifetime, indicating how long to cache this record before checking for updates.").WithDefault(ipns.DefaultRecordTTL.String()),
cmds.BoolOption(quieterOptionName, "Q", "Write only final IPNS Name encoded as CIDv1 (for use in /ipns content paths)."),
cmds.BoolOption(v1compatOptionName, "Produce a backward-compatible IPNS Record by including fields for both V1 and V2 signatures.").WithDefault(true),
- cmds.BoolOption(allowOfflineOptionName, "When --offline, save the IPNS record to the the local datastore without broadcasting to the network (instead of failing)."),
+ cmds.BoolOption(allowOfflineOptionName, "When --offline, save the IPNS record to the local datastore without broadcasting to the network (instead of failing)."),
ke.OptionIPNSBase,
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
diff --git a/core/commands/object/object.go b/core/commands/object/object.go
index 5a8577cf295..380ca253389 100644
--- a/core/commands/object/object.go
+++ b/core/commands/object/object.go
@@ -1,28 +1,11 @@
package objectcmd
import (
- "encoding/base64"
"errors"
- "fmt"
- "io"
- "text/tabwriter"
cmds "github.com/ipfs/go-ipfs-cmds"
- "github.com/ipfs/kubo/core/commands/cmdenv"
- "github.com/ipfs/kubo/core/commands/cmdutils"
-
- humanize "github.com/dustin/go-humanize"
- dag "github.com/ipfs/boxo/ipld/merkledag"
- "github.com/ipfs/go-cid"
- ipld "github.com/ipfs/go-ipld-format"
- "github.com/ipfs/kubo/core/coreiface/options"
)
-type Node struct {
- Links []Link
- Data string
-}
-
type Link struct {
Name, Hash string
Size uint64
@@ -35,16 +18,6 @@ type Object struct {
var ErrDataEncoding = errors.New("unknown data field encoding")
-const (
- headersOptionName = "headers"
- encodingOptionName = "data-encoding"
- inputencOptionName = "inputenc"
- datafieldencOptionName = "datafieldenc"
- pinOptionName = "pin"
- quietOptionName = "quiet"
- humanOptionName = "human"
-)
-
var ObjectCmd = &cmds.Command{
Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
Helptext: cmds.HelpText{
@@ -55,516 +28,23 @@ directly. Deprecated, use more modern 'ipfs dag' and 'ipfs files' instead.`,
},
Subcommands: map[string]*cmds.Command{
- "data": ObjectDataCmd,
+ "data": RemovedObjectCmd,
"diff": ObjectDiffCmd,
- "get": ObjectGetCmd,
- "links": ObjectLinksCmd,
- "new": ObjectNewCmd,
+ "get": RemovedObjectCmd,
+ "links": RemovedObjectCmd,
+ "new": RemovedObjectCmd,
"patch": ObjectPatchCmd,
- "put": ObjectPutCmd,
- "stat": ObjectStatCmd,
- },
-}
-
-// ObjectDataCmd object data command
-var ObjectDataCmd = &cmds.Command{
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
- Helptext: cmds.HelpText{
- Tagline: "Deprecated way to read the raw bytes of a dag-pb object: use 'dag get' instead.",
- ShortDescription: `
-'ipfs object data' is a deprecated plumbing command for retrieving the raw
-bytes stored in a dag-pb node. It outputs to stdout, and is a base58
-encoded multihash. Provided for legacy reasons. Use 'ipfs dag get' instead.
-`,
- LongDescription: `
-'ipfs object data' is a deprecated plumbing command for retrieving the raw
-bytes stored in a dag-pb node. It outputs to stdout, and is a base58
-encoded multihash. Provided for legacy reasons. Use 'ipfs dag get' instead.
-
-Note that the "--encoding" option does not affect the output, since the output
-is the raw data of the object.
-`,
- },
-
- Arguments: []cmds.Argument{
- cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format.").EnableStdin(),
- },
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
- api, err := cmdenv.GetApi(env, req)
- if err != nil {
- return err
- }
-
- path, err := cmdutils.PathOrCidPath(req.Arguments[0])
- if err != nil {
- return err
- }
-
- data, err := api.Object().Data(req.Context, path)
- if err != nil {
- return err
- }
-
- return res.Emit(data)
- },
-}
-
-// ObjectLinksCmd object links command
-var ObjectLinksCmd = &cmds.Command{
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
- Helptext: cmds.HelpText{
- Tagline: "Deprecated way to output links in the specified dag-pb object: use 'dag get' instead.",
- ShortDescription: `
-'ipfs object links' is a plumbing command for retrieving the links from
-a dag-pb node. It outputs to stdout, and is a base58 encoded
-multihash. Provided for legacy reasons. Use 'ipfs dag get' instead.
-`,
- },
-
- Arguments: []cmds.Argument{
- cmds.StringArg("key", true, false, "Key of the dag-pb object to retrieve, in base58-encoded multihash format.").EnableStdin(),
- },
- Options: []cmds.Option{
- cmds.BoolOption(headersOptionName, "v", "Print table headers (Hash, Size, Name)."),
- },
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
- api, err := cmdenv.GetApi(env, req)
- if err != nil {
- return err
- }
-
- enc, err := cmdenv.GetLowLevelCidEncoder(req)
- if err != nil {
- return err
- }
-
- path, err := cmdutils.PathOrCidPath(req.Arguments[0])
- if err != nil {
- return err
- }
-
- rp, _, err := api.ResolvePath(req.Context, path)
- if err != nil {
- return err
- }
-
- links, err := api.Object().Links(req.Context, rp)
- if err != nil {
- return err
- }
-
- outLinks := make([]Link, len(links))
- for i, link := range links {
- outLinks[i] = Link{
- Hash: enc.Encode(link.Cid),
- Name: link.Name,
- Size: link.Size,
- }
- }
-
- out := &Object{
- Hash: enc.Encode(rp.RootCid()),
- Links: outLinks,
- }
-
- return cmds.EmitOnce(res, out)
- },
- Encoders: cmds.EncoderMap{
- cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *Object) error {
- tw := tabwriter.NewWriter(w, 1, 2, 1, ' ', 0)
- headers, _ := req.Options[headersOptionName].(bool)
- if headers {
- fmt.Fprintln(tw, "Hash\tSize\tName")
- }
- for _, link := range out.Links {
- fmt.Fprintf(tw, "%s\t%v\t%s\n", link.Hash, link.Size, cmdenv.EscNonPrint(link.Name))
- }
- tw.Flush()
-
- return nil
- }),
- },
- Type: &Object{},
-}
-
-// ObjectGetCmd object get command
-var ObjectGetCmd = &cmds.Command{
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
- Helptext: cmds.HelpText{
- Tagline: "Deprecated way to get and serialize the dag-pb node. Use 'dag get' instead",
- ShortDescription: `
-'ipfs object get' is a plumbing command for retrieving dag-pb nodes.
-It serializes the DAG node to the format specified by the "--encoding"
-flag. It outputs to stdout, and is a base58 encoded multihash.
-
-DEPRECATED and provided for legacy reasons. Use 'ipfs dag get' instead.
-`,
- },
-
- Arguments: []cmds.Argument{
- cmds.StringArg("key", true, false, "Key of the dag-pb object to retrieve, in base58-encoded multihash format.").EnableStdin(),
- },
- Options: []cmds.Option{
- cmds.StringOption(encodingOptionName, "Encoding type of the data field, either \"text\" or \"base64\".").WithDefault("text"),
- },
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
- api, err := cmdenv.GetApi(env, req)
- if err != nil {
- return err
- }
-
- enc, err := cmdenv.GetLowLevelCidEncoder(req)
- if err != nil {
- return err
- }
-
- path, err := cmdutils.PathOrCidPath(req.Arguments[0])
- if err != nil {
- return err
- }
-
- datafieldenc, _ := req.Options[encodingOptionName].(string)
- if err != nil {
- return err
- }
-
- nd, err := api.Object().Get(req.Context, path)
- if err != nil {
- return err
- }
-
- r, err := api.Object().Data(req.Context, path)
- if err != nil {
- return err
- }
-
- data, err := io.ReadAll(r)
- if err != nil {
- return err
- }
-
- out, err := encodeData(data, datafieldenc)
- if err != nil {
- return err
- }
-
- node := &Node{
- Links: make([]Link, len(nd.Links())),
- Data: out,
- }
-
- for i, link := range nd.Links() {
- node.Links[i] = Link{
- Hash: enc.Encode(link.Cid),
- Name: link.Name,
- Size: link.Size,
- }
- }
-
- return cmds.EmitOnce(res, node)
- },
- Type: Node{},
- Encoders: cmds.EncoderMap{
- cmds.Protobuf: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *Node) error {
- // deserialize the Data field as text as this was the standard behaviour
- object, err := deserializeNode(out, "text")
- if err != nil {
- return nil
- }
-
- marshaled, err := object.Marshal()
- if err != nil {
- return err
- }
- _, err = w.Write(marshaled)
- return err
- }),
- },
-}
-
-// ObjectStatCmd object stat command
-var ObjectStatCmd = &cmds.Command{
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
- Helptext: cmds.HelpText{
- Tagline: "Deprecated way to read stats for the dag-pb node. Use 'files stat' instead.",
- ShortDescription: `
-'ipfs object stat' is a plumbing command to print dag-pb node statistics.
- is a base58 encoded multihash.
-
-DEPRECATED: modern replacements are 'files stat' and 'dag stat'
-`,
- LongDescription: `
-'ipfs object stat' is a plumbing command to print dag-pb node statistics.
- is a base58 encoded multihash. It outputs to stdout:
-
- NumLinks int number of links in link table
- BlockSize int size of the raw, encoded data
- LinksSize int size of the links segment
- DataSize int size of the data segment
- CumulativeSize int cumulative size of object and its references
-
-DEPRECATED: Provided for legacy reasons. Modern replacements:
-
- For unixfs, 'ipfs files stat' can be used:
-
- $ ipfs files stat --with-local /ipfs/QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX
- QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX
- Size: 5
- CumulativeSize: 13
- ChildBlocks: 0
- Type: file
- Local: 13 B of 13 B (100.00%)
-
- Reported sizes are based on metadata present in root block, and should not be
- trusted. A slower, but more secure alternative is 'ipfs dag stat', which
- will work for every DAG type. It comes with a benefit of calculating the
- size by walking the DAG:
-
- $ ipfs dag stat /ipfs/QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX
- Size: 13, NumBlocks: 1
-`,
- },
-
- Arguments: []cmds.Argument{
- cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format.").EnableStdin(),
- },
- Options: []cmds.Option{
- cmds.BoolOption(humanOptionName, "Print sizes in human readable format (e.g., 1K 234M 2G)"),
- },
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
- api, err := cmdenv.GetApi(env, req)
- if err != nil {
- return err
- }
-
- enc, err := cmdenv.GetLowLevelCidEncoder(req)
- if err != nil {
- return err
- }
-
- p, err := cmdutils.PathOrCidPath(req.Arguments[0])
- if err != nil {
- return err
- }
-
- ns, err := api.Object().Stat(req.Context, p)
- if err != nil {
- return err
- }
-
- oldStat := &ipld.NodeStat{
- Hash: enc.Encode(ns.Cid),
- NumLinks: ns.NumLinks,
- BlockSize: ns.BlockSize,
- LinksSize: ns.LinksSize,
- DataSize: ns.DataSize,
- CumulativeSize: ns.CumulativeSize,
- }
-
- return cmds.EmitOnce(res, oldStat)
- },
- Type: ipld.NodeStat{},
- Encoders: cmds.EncoderMap{
- cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *ipld.NodeStat) error {
- wtr := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0)
- defer wtr.Flush()
- fw := func(s string, n int) {
- fmt.Fprintf(wtr, "%s:\t%d\n", s, n)
- }
- human, _ := req.Options[humanOptionName].(bool)
- fw("NumLinks", out.NumLinks)
- fw("BlockSize", out.BlockSize)
- fw("LinksSize", out.LinksSize)
- fw("DataSize", out.DataSize)
- if human {
- fmt.Fprintf(wtr, "%s:\t%s\n", "CumulativeSize", humanize.Bytes(uint64(out.CumulativeSize)))
- } else {
- fw("CumulativeSize", out.CumulativeSize)
- }
-
- return nil
- }),
- },
-}
-
-// ObjectPutCmd object put command
-var ObjectPutCmd = &cmds.Command{
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
- Helptext: cmds.HelpText{
- Tagline: "Deprecated way to store input as a DAG object. Use 'dag put' instead.",
- ShortDescription: `
-'ipfs object put' is a plumbing command for storing dag-pb nodes.
-It reads from stdin, and the output is a base58 encoded multihash.
-
-DEPRECATED and provided for legacy reasons. Use 'ipfs dag put' instead.
-`,
- },
-
- Arguments: []cmds.Argument{
- cmds.FileArg("data", true, false, "Data to be stored as a dag-pb object.").EnableStdin(),
- },
- Options: []cmds.Option{
- cmds.StringOption(inputencOptionName, "Encoding type of input data. One of: {\"protobuf\", \"json\"}.").WithDefault("json"),
- cmds.StringOption(datafieldencOptionName, "Encoding type of the data field, either \"text\" or \"base64\".").WithDefault("text"),
- cmds.BoolOption(pinOptionName, "Pin this object when adding."),
- cmds.BoolOption(quietOptionName, "q", "Write minimal output."),
- },
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
- api, err := cmdenv.GetApi(env, req)
- if err != nil {
- return err
- }
-
- enc, err := cmdenv.GetLowLevelCidEncoder(req)
- if err != nil {
- return err
- }
-
- file, err := cmdenv.GetFileArg(req.Files.Entries())
- if err != nil {
- return err
- }
-
- inputenc, _ := req.Options[inputencOptionName].(string)
- if err != nil {
- return err
- }
-
- datafieldenc, _ := req.Options[datafieldencOptionName].(string)
- if err != nil {
- return err
- }
-
- dopin, _ := req.Options[pinOptionName].(bool)
- if err != nil {
- return err
- }
-
- p, err := api.Object().Put(req.Context, file,
- options.Object.DataType(datafieldenc),
- options.Object.InputEnc(inputenc),
- options.Object.Pin(dopin))
- if err != nil {
- return err
- }
-
- return cmds.EmitOnce(res, &Object{Hash: enc.Encode(p.RootCid())})
- },
- Encoders: cmds.EncoderMap{
- cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *Object) error {
- quiet, _ := req.Options[quietOptionName].(bool)
-
- o := out.Hash
- if !quiet {
- o = "added " + o
- }
-
- fmt.Fprintln(w, o)
-
- return nil
- }),
+ "put": RemovedObjectCmd,
+ "stat": RemovedObjectCmd,
},
- Type: Object{},
}
-// ObjectNewCmd object new command
-var ObjectNewCmd = &cmds.Command{
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
+var RemovedObjectCmd = &cmds.Command{
+ Status: cmds.Removed,
Helptext: cmds.HelpText{
- Tagline: "Deprecated way to create a new dag-pb object from a template.",
- ShortDescription: `
-'ipfs object new' is a plumbing command for creating new dag-pb nodes.
-DEPRECATED and provided for legacy reasons. Use 'dag put' and 'files' instead.
-`,
- LongDescription: `
-'ipfs object new' is a plumbing command for creating new dag-pb nodes.
-By default it creates and returns a new empty merkledag node, but
-you may pass an optional template argument to create a preformatted
-node.
-
-Available templates:
- * unixfs-dir
-
-DEPRECATED and provided for legacy reasons. Use 'dag put' and 'files' instead.
-`,
- },
- Arguments: []cmds.Argument{
- cmds.StringArg("template", false, false, "Template to use. Optional."),
+ Tagline: "Removed, use 'ipfs dag' or 'ipfs files' instead.",
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
- api, err := cmdenv.GetApi(env, req)
- if err != nil {
- return err
- }
-
- enc, err := cmdenv.GetLowLevelCidEncoder(req)
- if err != nil {
- return err
- }
-
- template := "empty"
- if len(req.Arguments) == 1 {
- template = req.Arguments[0]
- }
-
- nd, err := api.Object().New(req.Context, options.Object.Type(template))
- if err != nil && err != io.EOF {
- return err
- }
-
- return cmds.EmitOnce(res, &Object{Hash: enc.Encode(nd.Cid())})
+ return errors.New("removed, use 'ipfs dag' or 'ipfs files' instead")
},
- Encoders: cmds.EncoderMap{
- cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *Object) error {
- fmt.Fprintln(w, out.Hash)
- return nil
- }),
- },
- Type: Object{},
-}
-
-// converts the Node object into a real dag.ProtoNode
-func deserializeNode(nd *Node, dataFieldEncoding string) (*dag.ProtoNode, error) {
- dagnode := new(dag.ProtoNode)
- switch dataFieldEncoding {
- case "text":
- dagnode.SetData([]byte(nd.Data))
- case "base64":
- data, err := base64.StdEncoding.DecodeString(nd.Data)
- if err != nil {
- return nil, err
- }
- dagnode.SetData(data)
- default:
- return nil, ErrDataEncoding
- }
-
- links := make([]*ipld.Link, len(nd.Links))
- for i, link := range nd.Links {
- c, err := cid.Decode(link.Hash)
- if err != nil {
- return nil, err
- }
- links[i] = &ipld.Link{
- Name: link.Name,
- Size: link.Size,
- Cid: c,
- }
- }
- if err := dagnode.SetLinks(links); err != nil {
- return nil, err
- }
-
- return dagnode, nil
-}
-
-func encodeData(data []byte, encoding string) (string, error) {
- switch encoding {
- case "text":
- return string(data), nil
- case "base64":
- return base64.StdEncoding.EncodeToString(data), nil
- }
-
- return "", ErrDataEncoding
}
diff --git a/core/commands/object/patch.go b/core/commands/object/patch.go
index 7c35151fbe2..5a82dfe0b69 100644
--- a/core/commands/object/patch.go
+++ b/core/commands/object/patch.go
@@ -37,128 +37,16 @@ For modern use cases, use MFS with 'files' commands: 'ipfs files --help'.
},
Arguments: []cmds.Argument{},
Subcommands: map[string]*cmds.Command{
- "append-data": patchAppendDataCmd,
+ "append-data": RemovedObjectCmd,
"add-link": patchAddLinkCmd,
"rm-link": patchRmLinkCmd,
- "set-data": patchSetDataCmd,
+ "set-data": RemovedObjectCmd,
},
Options: []cmds.Option{
cmdutils.AllowBigBlockOption,
},
}
-var patchAppendDataCmd = &cmds.Command{
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
- Helptext: cmds.HelpText{
- Tagline: "Deprecated way to append data to the data segment of a DAG node.",
- ShortDescription: `
-Append data to what already exists in the data segment in the given object.
-
-Example:
-
- $ echo "hello" | ipfs object patch $HASH append-data
-
-NOTE: This does not append data to a file - it modifies the actual raw
-data within a dag-pb object. Blocks have a max size of 1MiB and objects larger than
-the limit will not be respected by the network.
-
-DEPRECATED and provided for legacy reasons. Use 'ipfs add' or 'ipfs files' instead.
-`,
- },
- Arguments: []cmds.Argument{
- cmds.StringArg("root", true, false, "The hash of the node to modify."),
- cmds.FileArg("data", true, false, "Data to append.").EnableStdin(),
- },
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
- api, err := cmdenv.GetApi(env, req)
- if err != nil {
- return err
- }
-
- root, err := cmdutils.PathOrCidPath(req.Arguments[0])
- if err != nil {
- return err
- }
-
- file, err := cmdenv.GetFileArg(req.Files.Entries())
- if err != nil {
- return err
- }
-
- p, err := api.Object().AppendData(req.Context, root, file)
- if err != nil {
- return err
- }
-
- if err := cmdutils.CheckCIDSize(req, p.RootCid(), api.Dag()); err != nil {
- return err
- }
-
- return cmds.EmitOnce(res, &Object{Hash: p.RootCid().String()})
- },
- Type: &Object{},
- Encoders: cmds.EncoderMap{
- cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, obj *Object) error {
- _, err := fmt.Fprintln(w, obj.Hash)
- return err
- }),
- },
-}
-
-var patchSetDataCmd = &cmds.Command{
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
- Helptext: cmds.HelpText{
- Tagline: "Deprecated way to set the data field of dag-pb object.",
- ShortDescription: `
-Set the data of an IPFS object from stdin or with the contents of a file.
-
-Example:
-
- $ echo "my data" | ipfs object patch $MYHASH set-data
-
-DEPRECATED and provided for legacy reasons. Use 'files cp' and 'dag put' instead.
-`,
- },
- Arguments: []cmds.Argument{
- cmds.StringArg("root", true, false, "The hash of the node to modify."),
- cmds.FileArg("data", true, false, "The data to set the object to.").EnableStdin(),
- },
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
- api, err := cmdenv.GetApi(env, req)
- if err != nil {
- return err
- }
-
- root, err := cmdutils.PathOrCidPath(req.Arguments[0])
- if err != nil {
- return err
- }
-
- file, err := cmdenv.GetFileArg(req.Files.Entries())
- if err != nil {
- return err
- }
-
- p, err := api.Object().SetData(req.Context, root, file)
- if err != nil {
- return err
- }
-
- if err := cmdutils.CheckCIDSize(req, p.RootCid(), api.Dag()); err != nil {
- return err
- }
-
- return cmds.EmitOnce(res, &Object{Hash: p.RootCid().String()})
- },
- Type: Object{},
- Encoders: cmds.EncoderMap{
- cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *Object) error {
- fmt.Fprintln(w, out.Hash)
- return nil
- }),
- },
-}
-
var patchRmLinkCmd = &cmds.Command{
Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
Helptext: cmds.HelpText{
diff --git a/core/commands/p2p.go b/core/commands/p2p.go
index 7b8b416e59c..1fbdc8a2861 100644
--- a/core/commands/p2p.go
+++ b/core/commands/p2p.go
@@ -250,7 +250,7 @@ func checkPort(target ma.Multiaddr) error {
if sport != "" {
return sport, nil
}
- return "", fmt.Errorf("address does not contain tcp or udp protocol")
+ return "", errors.New("address does not contain tcp or udp protocol")
}
sport, err := getPort()
@@ -264,7 +264,7 @@ func checkPort(target ma.Multiaddr) error {
}
if port == 0 {
- return fmt.Errorf("port can not be 0")
+ return errors.New("port can not be 0")
}
return nil
diff --git a/core/commands/pin/pin.go b/core/commands/pin/pin.go
index ca3c932bff0..428a75b695d 100644
--- a/core/commands/pin/pin.go
+++ b/core/commands/pin/pin.go
@@ -359,9 +359,10 @@ Example:
},
Options: []cmds.Option{
cmds.StringOption(pinTypeOptionName, "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\".").WithDefault("all"),
- cmds.BoolOption(pinQuietOptionName, "q", "Write just hashes of objects."),
+ cmds.BoolOption(pinQuietOptionName, "q", "Output only the CIDs of pins."),
+ cmds.StringOption(pinNameOptionName, "n", "Limit returned pins to ones with names that contain the value provided (case-sensitive, partial match). Implies --names=true."),
cmds.BoolOption(pinStreamOptionName, "s", "Enable streaming of pins as they are discovered."),
- cmds.BoolOption(pinNamesOptionName, "n", "Enable displaying pin names (slower)."),
+ cmds.BoolOption(pinNamesOptionName, "Include pin names in the output (slower, disabled by default)."),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
api, err := cmdenv.GetApi(env, req)
@@ -372,6 +373,7 @@ Example:
typeStr, _ := req.Options[pinTypeOptionName].(string)
stream, _ := req.Options[pinStreamOptionName].(bool)
displayNames, _ := req.Options[pinNamesOptionName].(bool)
+ name, _ := req.Options[pinNameOptionName].(string)
switch typeStr {
case "all", "direct", "indirect", "recursive":
@@ -397,7 +399,7 @@ Example:
if len(req.Arguments) > 0 {
err = pinLsKeys(req, typeStr, api, emit)
} else {
- err = pinLsAll(req, typeStr, displayNames, api, emit)
+ err = pinLsAll(req, typeStr, displayNames || name != "", name, api, emit)
}
if err != nil {
return err
@@ -537,7 +539,7 @@ func pinLsKeys(req *cmds.Request, typeStr string, api coreiface.CoreAPI, emit fu
return nil
}
-func pinLsAll(req *cmds.Request, typeStr string, detailed bool, api coreiface.CoreAPI, emit func(value PinLsOutputWrapper) error) error {
+func pinLsAll(req *cmds.Request, typeStr string, detailed bool, name string, api coreiface.CoreAPI, emit func(value PinLsOutputWrapper) error) error {
enc, err := cmdenv.GetCidEncoder(req)
if err != nil {
return err
@@ -555,15 +557,16 @@ func pinLsAll(req *cmds.Request, typeStr string, detailed bool, api coreiface.Co
panic("unhandled pin type")
}
- pins, err := api.Pin().Ls(req.Context, opt, options.Pin.Ls.Detailed(detailed))
- if err != nil {
- return err
- }
+ pins := make(chan coreiface.Pin)
+ lsErr := make(chan error, 1)
+ lsCtx, cancel := context.WithCancel(req.Context)
+ defer cancel()
+
+ go func() {
+ lsErr <- api.Pin().Ls(lsCtx, pins, opt, options.Pin.Ls.Detailed(detailed), options.Pin.Ls.Name(name))
+ }()
for p := range pins {
- if err := p.Err(); err != nil {
- return err
- }
err = emit(PinLsOutputWrapper{
PinLsObject: PinLsObject{
Type: p.Type(),
@@ -575,8 +578,7 @@ func pinLsAll(req *cmds.Request, typeStr string, detailed bool, api coreiface.Co
return err
}
}
-
- return nil
+ return <-lsErr
}
const (
diff --git a/core/commands/pin/remotepin.go b/core/commands/pin/remotepin.go
index 132532554cc..068d15d0bd8 100644
--- a/core/commands/pin/remotepin.go
+++ b/core/commands/pin/remotepin.go
@@ -18,7 +18,7 @@ import (
pinclient "github.com/ipfs/boxo/pinning/remote/client"
cid "github.com/ipfs/go-cid"
cmds "github.com/ipfs/go-ipfs-cmds"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
config "github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
@@ -221,6 +221,8 @@ NOTE: a comma-separated notation is supported in CLI for convenience:
// Block unless --background=true is passed
if !req.Options[pinBackgroundOptionName].(bool) {
+ const pinWaitTime = 500 * time.Millisecond
+ var timer *time.Timer
requestID := ps.GetRequestId()
for {
ps, err = c.GetStatusByID(ctx, requestID)
@@ -237,10 +239,15 @@ NOTE: a comma-separated notation is supported in CLI for convenience:
if s == pinclient.StatusFailed {
return fmt.Errorf("remote service failed to pin requestid=%q", requestID)
}
- tmr := time.NewTimer(time.Second / 2)
+ if timer == nil {
+ timer = time.NewTimer(pinWaitTime)
+ } else {
+ timer.Reset(pinWaitTime)
+ }
select {
- case <-tmr.C:
+ case <-timer.C:
case <-ctx.Done():
+ timer.Stop()
return fmt.Errorf("waiting for pin interrupted, requestid=%q remains on remote service", requestID)
}
}
@@ -278,26 +285,26 @@ Pass '--status=queued,pinning,pinned,failed' to list pins in all states.
cmds.DelimitedStringsOption(",", pinStatusOptionName, "Return pins with the specified statuses (queued,pinning,pinned,failed).").WithDefault([]string{"pinned"}),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
- ctx, cancel := context.WithCancel(req.Context)
- defer cancel()
-
c, err := getRemotePinServiceFromRequest(req, env)
if err != nil {
return err
}
- psCh, errCh, err := lsRemote(ctx, req, c)
- if err != nil {
- return err
- }
+ ctx, cancel := context.WithCancel(req.Context)
+ defer cancel()
+ psCh := make(chan pinclient.PinStatusGetter)
+ lsErr := make(chan error, 1)
+ go func() {
+ lsErr <- lsRemote(ctx, req, c, psCh)
+ }()
for ps := range psCh {
if err := res.Emit(toRemotePinOutput(ps)); err != nil {
return err
}
}
- return <-errCh
+ return <-lsErr
},
Type: RemotePinOutput{},
Encoders: cmds.EncoderMap{
@@ -310,7 +317,7 @@ Pass '--status=queued,pinning,pinned,failed' to list pins in all states.
}
// Executes GET /pins/?query-with-filters
-func lsRemote(ctx context.Context, req *cmds.Request, c *pinclient.Client) (chan pinclient.PinStatusGetter, chan error, error) {
+func lsRemote(ctx context.Context, req *cmds.Request, c *pinclient.Client, out chan<- pinclient.PinStatusGetter) error {
opts := []pinclient.LsOption{}
if name, nameFound := req.Options[pinNameOptionName]; nameFound {
nameStr := name.(string)
@@ -323,7 +330,8 @@ func lsRemote(ctx context.Context, req *cmds.Request, c *pinclient.Client) (chan
for _, rawCID := range cidsRawArr {
parsedCID, err := cid.Decode(rawCID)
if err != nil {
- return nil, nil, fmt.Errorf("CID %q cannot be parsed: %v", rawCID, err)
+ close(out)
+ return fmt.Errorf("CID %q cannot be parsed: %v", rawCID, err)
}
parsedCIDs = append(parsedCIDs, parsedCID)
}
@@ -335,16 +343,15 @@ func lsRemote(ctx context.Context, req *cmds.Request, c *pinclient.Client) (chan
for _, rawStatus := range statusRawArr {
s := pinclient.Status(rawStatus)
if s.String() == string(pinclient.StatusUnknown) {
- return nil, nil, fmt.Errorf("status %q is not valid", rawStatus)
+ close(out)
+ return fmt.Errorf("status %q is not valid", rawStatus)
}
parsedStatuses = append(parsedStatuses, s)
}
opts = append(opts, pinclient.PinOpts.FilterStatus(parsedStatuses...))
}
- psCh, errCh := c.Ls(ctx, opts...)
-
- return psCh, errCh, nil
+ return c.Ls(ctx, out, opts...)
}
var rmRemotePinCmd = &cmds.Command{
@@ -386,36 +393,37 @@ To list and then remove all pending pin requests, pass an explicit status list:
cmds.BoolOption(pinForceOptionName, "Allow removal of multiple pins matching the query without additional confirmation.").WithDefault(false),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
- ctx, cancel := context.WithCancel(req.Context)
- defer cancel()
-
c, err := getRemotePinServiceFromRequest(req, env)
if err != nil {
return err
}
rmIDs := []string{}
- if len(req.Arguments) == 0 {
- psCh, errCh, err := lsRemote(ctx, req, c)
- if err != nil {
- return err
- }
- for ps := range psCh {
- rmIDs = append(rmIDs, ps.GetRequestId())
- }
- if err = <-errCh; err != nil {
- return fmt.Errorf("error while listing remote pins: %v", err)
- }
-
- if len(rmIDs) > 1 && !req.Options[pinForceOptionName].(bool) {
- return fmt.Errorf("multiple remote pins are matching this query, add --force to confirm the bulk removal")
- }
- } else {
+ if len(req.Arguments) != 0 {
return fmt.Errorf("unexpected argument %q", req.Arguments[0])
}
+ psCh := make(chan pinclient.PinStatusGetter)
+ errCh := make(chan error, 1)
+ ctx, cancel := context.WithCancel(req.Context)
+ defer cancel()
+
+ go func() {
+ errCh <- lsRemote(ctx, req, c, psCh)
+ }()
+ for ps := range psCh {
+ rmIDs = append(rmIDs, ps.GetRequestId())
+ }
+ if err = <-errCh; err != nil {
+ return fmt.Errorf("error while listing remote pins: %v", err)
+ }
+
+ if len(rmIDs) > 1 && !req.Options[pinForceOptionName].(bool) {
+ return fmt.Errorf("multiple remote pins are matching this query, add --force to confirm the bulk removal")
+ }
+
for _, rmID := range rmIDs {
- if err := c.DeleteByID(ctx, rmID); err != nil {
+ if err = c.DeleteByID(ctx, rmID); err != nil {
return fmt.Errorf("removing pin identified by requestid=%q failed: %v", rmID, err)
}
}
diff --git a/core/commands/pubsub.go b/core/commands/pubsub.go
index 8f52881a36e..d50e651b2c7 100644
--- a/core/commands/pubsub.go
+++ b/core/commands/pubsub.go
@@ -2,6 +2,7 @@ package commands
import (
"context"
+ "errors"
"fmt"
"io"
"net/http"
@@ -9,7 +10,6 @@ import (
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
mbase "github.com/multiformats/go-multibase"
- "github.com/pkg/errors"
cmds "github.com/ipfs/go-ipfs-cmds"
options "github.com/ipfs/kubo/core/coreiface/options"
@@ -351,7 +351,7 @@ func urlArgsDecoder(req *cmds.Request, env cmds.Environment) error {
for n, arg := range req.Arguments {
encoding, data, err := mbase.Decode(arg)
if err != nil {
- return errors.Wrap(err, "URL arg must be multibase encoded")
+ return fmt.Errorf("URL arg must be multibase encoded: %w", err)
}
// Enforce URL-safe encoding is used for data passed via URL arguments
diff --git a/core/commands/refs.go b/core/commands/refs.go
index cefd8af9071..53c92c3df04 100644
--- a/core/commands/refs.go
+++ b/core/commands/refs.go
@@ -21,7 +21,7 @@ import (
var refsEncoderMap = cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *RefWrapper) error {
if out.Err != "" {
- return fmt.Errorf(out.Err)
+ return errors.New(out.Err)
}
fmt.Fprintln(w, out.Ref)
diff --git a/core/commands/root.go b/core/commands/root.go
index b4e563cdb3a..80c2309df04 100644
--- a/core/commands/root.go
+++ b/core/commands/root.go
@@ -10,7 +10,7 @@ import (
"github.com/ipfs/kubo/core/commands/pin"
cmds "github.com/ipfs/go-ipfs-cmds"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
)
var log = logging.Logger("core/commands")
@@ -162,72 +162,9 @@ var rootSubcommands = map[string]*cmds.Command{
"multibase": MbaseCmd,
}
-// RootRO is the readonly version of Root
-var RootRO = &cmds.Command{}
-
-var CommandsDaemonROCmd = CommandsCmd(RootRO)
-
-// RefsROCmd is `ipfs refs` command
-var RefsROCmd = &cmds.Command{}
-
-// VersionROCmd is `ipfs version` command (without deps).
-var VersionROCmd = &cmds.Command{}
-
-var rootROSubcommands = map[string]*cmds.Command{
- "commands": CommandsDaemonROCmd,
- "cat": CatCmd,
- "block": {
- Subcommands: map[string]*cmds.Command{
- "stat": blockStatCmd,
- "get": blockGetCmd,
- },
- },
- "get": GetCmd,
- "ls": LsCmd,
- "name": {
- Subcommands: map[string]*cmds.Command{
- "resolve": name.IpnsCmd,
- },
- },
- "object": {
- Subcommands: map[string]*cmds.Command{
- "data": ocmd.ObjectDataCmd,
- "links": ocmd.ObjectLinksCmd,
- "get": ocmd.ObjectGetCmd,
- "stat": ocmd.ObjectStatCmd,
- },
- },
- "dag": {
- Subcommands: map[string]*cmds.Command{
- "get": dag.DagGetCmd,
- "resolve": dag.DagResolveCmd,
- "stat": dag.DagStatCmd,
- "export": dag.DagExportCmd,
- },
- },
- "resolve": ResolveCmd,
-}
-
func init() {
Root.ProcessHelp()
- *RootRO = *Root
-
- // this was in the big map definition above before,
- // but if we leave it there lgc.NewCommand will be executed
- // before the value is updated (:/sanitize readonly refs command/)
-
- // sanitize readonly refs command
- *RefsROCmd = *RefsCmd
- RefsROCmd.Subcommands = map[string]*cmds.Command{}
- rootROSubcommands["refs"] = RefsROCmd
-
- // sanitize readonly version command (no need to expose precise deps)
- *VersionROCmd = *VersionCmd
- VersionROCmd.Subcommands = map[string]*cmds.Command{}
- rootROSubcommands["version"] = VersionROCmd
-
Root.Subcommands = rootSubcommands
- RootRO.Subcommands = rootROSubcommands
}
type MessageOutput struct {
diff --git a/core/commands/root_test.go b/core/commands/root_test.go
index f5e5c248bda..d1bf2e610ef 100644
--- a/core/commands/root_test.go
+++ b/core/commands/root_test.go
@@ -18,5 +18,4 @@ func TestCommandTree(t *testing.T) {
}
}
printErrors(Root.DebugValidate())
- printErrors(RootRO.DebugValidate())
}
diff --git a/core/commands/routing.go b/core/commands/routing.go
index 2442570acb5..0804b1f44c3 100644
--- a/core/commands/routing.go
+++ b/core/commands/routing.go
@@ -9,6 +9,7 @@ import (
"strings"
"time"
+ "github.com/ipfs/kubo/config"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
dag "github.com/ipfs/boxo/ipld/merkledag"
@@ -42,6 +43,7 @@ var RoutingCmd = &cmds.Command{
"get": getValueRoutingCmd,
"put": putValueRoutingCmd,
"provide": provideRefRoutingCmd,
+ "reprovide": reprovideRoutingCmd,
},
}
@@ -70,7 +72,7 @@ var findProvidersRoutingCmd = &cmds.Command{
numProviders, _ := req.Options[numProvidersOptionName].(int)
if numProviders < 1 {
- return fmt.Errorf("number of providers must be greater than 0")
+ return errors.New("number of providers must be greater than 0")
}
c, err := cid.Parse(req.Arguments[0])
@@ -157,6 +159,14 @@ var provideRefRoutingCmd = &cmds.Command{
if !nd.IsOnline {
return ErrNotOnline
}
+ // respect global config
+ cfg, err := nd.Repo.Config()
+ if err != nil {
+ return err
+ }
+ if !cfg.Provider.Enabled.WithDefault(config.DefaultProviderEnabled) {
+ return errors.New("invalid configuration: Provider.Enabled is set to 'false'")
+ }
if len(nd.PeerHost.Network().Conns()) == 0 {
return errors.New("cannot provide, no connected peers")
@@ -235,6 +245,45 @@ var provideRefRoutingCmd = &cmds.Command{
Type: routing.QueryEvent{},
}
+var reprovideRoutingCmd = &cmds.Command{
+ Status: cmds.Experimental,
+ Helptext: cmds.HelpText{
+ Tagline: "Trigger reprovider.",
+ ShortDescription: `
+Trigger reprovider to announce our data to network.
+`,
+ },
+ 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
+ }
+
+ // respect global config
+ cfg, err := nd.Repo.Config()
+ if err != nil {
+ return err
+ }
+ if !cfg.Provider.Enabled.WithDefault(config.DefaultProviderEnabled) {
+ return errors.New("invalid configuration: Provider.Enabled is set to 'false'")
+ }
+ if cfg.Reprovider.Interval.WithDefault(config.DefaultReproviderInterval) == 0 {
+ return errors.New("invalid configuration: Reprovider.Interval is set to '0'")
+ }
+
+ err = nd.Provider.Reprovide(req.Context)
+ if err != nil {
+ return err
+ }
+
+ return nil
+ },
+}
+
func provideKeys(ctx context.Context, r routing.Routing, cids []cid.Cid) error {
for _, c := range cids {
err := r.Provide(ctx, c, true)
@@ -426,7 +475,7 @@ identified by QmFoo.
cmds.FileArg("value-file", true, false, "A path to a file containing the value to store.").EnableStdin(),
},
Options: []cmds.Option{
- cmds.BoolOption(allowOfflineOptionName, "When offline, save the IPNS record to the the local datastore without broadcasting to the network instead of simply failing."),
+ cmds.BoolOption(allowOfflineOptionName, "When offline, save the IPNS record to the local datastore without broadcasting to the network instead of simply failing."),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
api, err := cmdenv.GetApi(env, req)
diff --git a/core/commands/stat.go b/core/commands/stat.go
index a09c70ea1c1..2b4485a9513 100644
--- a/core/commands/stat.go
+++ b/core/commands/stat.go
@@ -1,6 +1,7 @@
package commands
import (
+ "errors"
"fmt"
"io"
"os"
@@ -26,11 +27,12 @@ for your IPFS node.`,
},
Subcommands: map[string]*cmds.Command{
- "bw": statBwCmd,
- "repo": repoStatCmd,
- "bitswap": bitswapStatCmd,
- "dht": statDhtCmd,
- "provide": statProvideCmd,
+ "bw": statBwCmd,
+ "repo": repoStatCmd,
+ "bitswap": bitswapStatCmd,
+ "dht": statDhtCmd,
+ "provide": statProvideCmd,
+ "reprovide": statReprovideCmd,
},
}
@@ -55,7 +57,7 @@ to a particular peer, use the 'peer' option along with that peer's multihash
id. To specify a specific protocol, use the 'proto' option. The 'peer' and
'proto' options cannot be specified simultaneously. The protocols that are
queried using this method are outlined in the specification:
-https://github.com/libp2p/specs/blob/master/7-properties.md#757-protocol-multicodecs
+https://github.com/libp2p/specs/blob/master/_archive/7-properties.md#757-protocol-multicodecs
Example protocol options:
- /ipfs/id/1.0.0
@@ -96,11 +98,11 @@ Example:
// Must be online!
if !nd.IsOnline {
- return cmds.Errorf(cmds.ErrClient, ErrNotOnline.Error())
+ return cmds.Errorf(cmds.ErrClient, "unable to run offline: %s", ErrNotOnline)
}
if nd.Reporter == nil {
- return fmt.Errorf("bandwidth reporter disabled in config")
+ return errors.New("bandwidth reporter disabled in config")
}
pstr, pfound := req.Options[statPeerOptionName].(string)
diff --git a/core/commands/stat_provide.go b/core/commands/stat_provide.go
index 6ee51e516fa..ef06d8e2828 100644
--- a/core/commands/stat_provide.go
+++ b/core/commands/stat_provide.go
@@ -4,22 +4,20 @@ import (
"fmt"
"io"
"text/tabwriter"
- "time"
- humanize "github.com/dustin/go-humanize"
- "github.com/ipfs/boxo/provider"
cmds "github.com/ipfs/go-ipfs-cmds"
"github.com/ipfs/kubo/core/commands/cmdenv"
- "golang.org/x/exp/constraints"
+ "github.com/libp2p/go-libp2p-kad-dht/fullrt"
)
var statProvideCmd = &cmds.Command{
+ Status: cmds.Deprecated,
Helptext: cmds.HelpText{
- Tagline: "Returns statistics about the node's (re)provider system.",
+ Tagline: "Deprecated command, use 'ipfs stats reprovide' instead.",
ShortDescription: `
-Returns statistics about the content the node is advertising.
-
-This interface is not stable and may change from release to release.
+'ipfs stats provide' is deprecated because provide and reprovide operations
+are now distinct. This command may be replaced by provide only stats in the
+future.
`,
},
Arguments: []cmds.Argument{},
@@ -38,47 +36,30 @@ This interface is not stable and may change from release to release.
if err != nil {
return err
}
+ _, fullRT := nd.DHTClient.(*fullrt.FullRT)
- if err := res.Emit(stats); err != nil {
+ if err := res.Emit(reprovideStats{stats, fullRT}); err != nil {
return err
}
return nil
},
Encoders: cmds.EncoderMap{
- cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, s *provider.ReproviderStats) error {
+ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, s reprovideStats) error {
wtr := tabwriter.NewWriter(w, 1, 2, 1, ' ', 0)
defer wtr.Flush()
- fmt.Fprintf(wtr, "TotalProvides:\t%s\n", humanNumber(s.TotalProvides))
- fmt.Fprintf(wtr, "AvgProvideDuration:\t%s\n", humanDuration(s.AvgProvideDuration))
+ fmt.Fprintf(wtr, "TotalProvides:\t%s\n", humanNumber(s.TotalReprovides))
+ fmt.Fprintf(wtr, "AvgProvideDuration:\t%s\n", humanDuration(s.AvgReprovideDuration))
fmt.Fprintf(wtr, "LastReprovideDuration:\t%s\n", humanDuration(s.LastReprovideDuration))
- fmt.Fprintf(wtr, "LastReprovideBatchSize:\t%s\n", humanNumber(s.LastReprovideBatchSize))
+ if !s.LastRun.IsZero() {
+ fmt.Fprintf(wtr, "LastRun:\t%s\n", humanTime(s.LastRun))
+ if s.fullRT {
+ fmt.Fprintf(wtr, "NextRun:\t%s\n", humanTime(s.LastRun.Add(s.ReprovideInterval)))
+ }
+ }
return nil
}),
},
- Type: provider.ReproviderStats{},
-}
-
-func humanDuration(val time.Duration) string {
- return val.Truncate(time.Microsecond).String()
-}
-
-func humanNumber[T constraints.Float | constraints.Integer](n T) string {
- nf := float64(n)
- str := humanSI(nf, 0)
- fullStr := humanFull(nf, 0)
- if str != fullStr {
- return fmt.Sprintf("%s\t(%s)", str, fullStr)
- }
- return str
-}
-
-func humanSI(val float64, decimals int) string {
- v, unit := humanize.ComputeSI(val)
- return fmt.Sprintf("%s%s", humanFull(v, decimals), unit)
-}
-
-func humanFull(val float64, decimals int) string {
- return humanize.CommafWithDigits(val, decimals)
+ Type: reprovideStats{},
}
diff --git a/core/commands/stat_reprovide.go b/core/commands/stat_reprovide.go
new file mode 100644
index 00000000000..10dbc727d38
--- /dev/null
+++ b/core/commands/stat_reprovide.go
@@ -0,0 +1,104 @@
+package commands
+
+import (
+ "fmt"
+ "io"
+ "text/tabwriter"
+ "time"
+
+ humanize "github.com/dustin/go-humanize"
+ "github.com/ipfs/boxo/provider"
+ cmds "github.com/ipfs/go-ipfs-cmds"
+ "github.com/ipfs/kubo/core/commands/cmdenv"
+ "github.com/libp2p/go-libp2p-kad-dht/fullrt"
+ "golang.org/x/exp/constraints"
+)
+
+type reprovideStats struct {
+ provider.ReproviderStats
+ fullRT bool
+}
+
+var statReprovideCmd = &cmds.Command{
+ Status: cmds.Experimental,
+ Helptext: cmds.HelpText{
+ Tagline: "Returns statistics about the node's reprovider system.",
+ ShortDescription: `
+Returns statistics about the content the node is reproviding every
+Reprovider.Interval according to Reprovider.Strategy:
+https://github.com/ipfs/kubo/blob/master/docs/config.md#reprovider
+
+This interface is not stable and may change from release to release.
+
+`,
+ },
+ Arguments: []cmds.Argument{},
+ Options: []cmds.Option{},
+ 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
+ }
+
+ stats, err := nd.Provider.Stat()
+ if err != nil {
+ return err
+ }
+ _, fullRT := nd.DHTClient.(*fullrt.FullRT)
+
+ if err := res.Emit(reprovideStats{stats, fullRT}); err != nil {
+ return err
+ }
+
+ return nil
+ },
+ Encoders: cmds.EncoderMap{
+ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, s reprovideStats) error {
+ wtr := tabwriter.NewWriter(w, 1, 2, 1, ' ', 0)
+ defer wtr.Flush()
+
+ fmt.Fprintf(wtr, "TotalReprovides:\t%s\n", humanNumber(s.TotalReprovides))
+ fmt.Fprintf(wtr, "AvgReprovideDuration:\t%s\n", humanDuration(s.AvgReprovideDuration))
+ fmt.Fprintf(wtr, "LastReprovideDuration:\t%s\n", humanDuration(s.LastReprovideDuration))
+ if !s.LastRun.IsZero() {
+ fmt.Fprintf(wtr, "LastReprovide:\t%s\n", humanTime(s.LastRun))
+ if s.fullRT {
+ fmt.Fprintf(wtr, "NextReprovide:\t%s\n", humanTime(s.LastRun.Add(s.ReprovideInterval)))
+ }
+ }
+ return nil
+ }),
+ },
+ Type: reprovideStats{},
+}
+
+func humanDuration(val time.Duration) string {
+ return val.Truncate(time.Microsecond).String()
+}
+
+func humanTime(val time.Time) string {
+ return val.Format("2006-01-02 15:04:05")
+}
+
+func humanNumber[T constraints.Float | constraints.Integer](n T) string {
+ nf := float64(n)
+ str := humanSI(nf, 0)
+ fullStr := humanFull(nf, 0)
+ if str != fullStr {
+ return fmt.Sprintf("%s\t(%s)", str, fullStr)
+ }
+ return str
+}
+
+func humanSI(val float64, decimals int) string {
+ v, unit := humanize.ComputeSI(val)
+ return fmt.Sprintf("%s%s", humanFull(v, decimals), unit)
+}
+
+func humanFull(val float64, decimals int) string {
+ return humanize.CommafWithDigits(val, decimals)
+}
diff --git a/core/commands/swarm.go b/core/commands/swarm.go
index 4fe535ffc21..252c48d334e 100644
--- a/core/commands/swarm.go
+++ b/core/commands/swarm.go
@@ -557,7 +557,7 @@ var swarmAddrsCmd = &cmds.Command{
paddrs := am.Addrs[p]
fmt.Fprintf(w, "%s (%d)\n", p, len(paddrs))
for _, addr := range paddrs {
- fmt.Fprintf(w, "\t"+addr+"\n")
+ fmt.Fprintf(w, "\t%s\n", addr)
}
}
diff --git a/core/commands/version.go b/core/commands/version.go
index e404074fe75..d15a9b1f9a4 100644
--- a/core/commands/version.go
+++ b/core/commands/version.go
@@ -5,17 +5,25 @@ import (
"fmt"
"io"
"runtime/debug"
+ "strings"
- version "github.com/ipfs/kubo"
-
+ versioncmp "github.com/hashicorp/go-version"
cmds "github.com/ipfs/go-ipfs-cmds"
+ version "github.com/ipfs/kubo"
+ "github.com/ipfs/kubo/config"
+ "github.com/ipfs/kubo/core"
+ "github.com/ipfs/kubo/core/commands/cmdenv"
+ "github.com/libp2p/go-libp2p-kad-dht/fullrt"
+ peer "github.com/libp2p/go-libp2p/core/peer"
+ pstore "github.com/libp2p/go-libp2p/core/peerstore"
)
const (
- versionNumberOptionName = "number"
- versionCommitOptionName = "commit"
- versionRepoOptionName = "repo"
- versionAllOptionName = "all"
+ versionNumberOptionName = "number"
+ versionCommitOptionName = "commit"
+ versionRepoOptionName = "repo"
+ versionAllOptionName = "all"
+ versionCheckThresholdOptionName = "min-percent"
)
var VersionCmd = &cmds.Command{
@@ -24,7 +32,8 @@ var VersionCmd = &cmds.Command{
ShortDescription: "Returns the current version of IPFS and exits.",
},
Subcommands: map[string]*cmds.Command{
- "deps": depsVersionCommand,
+ "deps": depsVersionCommand,
+ "check": checkVersionCommand,
},
Options: []cmds.Option{
@@ -130,3 +139,161 @@ Print out all dependencies and their versions.`,
}),
},
}
+
+const DefaultMinimalVersionFraction = 0.05 // 5%
+
+type VersionCheckOutput struct {
+ UpdateAvailable bool
+ RunningVersion string
+ GreatestVersion string
+ PeersSampled int
+ WithGreaterVersion int
+}
+
+var checkVersionCommand = &cmds.Command{
+ Helptext: cmds.HelpText{
+ Tagline: "Checks Kubo version against connected peers.",
+ ShortDescription: `
+This command uses the libp2p identify protocol to check the 'AgentVersion'
+of connected peers and see if the Kubo version we're running is outdated.
+
+Peers with an AgentVersion that doesn't start with 'kubo/' are ignored.
+'UpdateAvailable' is set to true only if the 'min-fraction' criteria are met.
+
+The 'ipfs daemon' does the same check regularly and logs when a new version
+is available. You can stop these regular checks by setting
+Version.SwarmCheckEnabled:false in the config.
+`,
+ },
+ Options: []cmds.Option{
+ cmds.IntOption(versionCheckThresholdOptionName, "t", "Percentage (1-100) of sampled peers with the new Kubo version needed to trigger an update warning.").WithDefault(config.DefaultSwarmCheckPercentThreshold),
+ },
+ Type: VersionCheckOutput{},
+
+ 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
+ }
+
+ minPercent, _ := req.Options[versionCheckThresholdOptionName].(int64)
+ output, err := DetectNewKuboVersion(nd, minPercent)
+ if err != nil {
+ return err
+ }
+
+ if err := cmds.EmitOnce(res, output); err != nil {
+ return err
+ }
+ return nil
+ },
+}
+
+// DetectNewKuboVersion observers kubo version reported by other peers via
+// libp2p identify protocol and notifies when threshold fraction of seen swarm
+// is running updated Kubo. It is used by RPC and CLI at 'ipfs version check'
+// and also periodically when 'ipfs daemon' is running.
+func DetectNewKuboVersion(nd *core.IpfsNode, minPercent int64) (VersionCheckOutput, error) {
+ ourVersion, err := versioncmp.NewVersion(version.CurrentVersionNumber)
+ if err != nil {
+ return VersionCheckOutput{}, fmt.Errorf("could not parse our own version %q: %w",
+ version.CurrentVersionNumber, err)
+ }
+ // MAJOR.MINOR.PATCH without any suffix
+ ourVersion = ourVersion.Core()
+
+ greatestVersionSeen := ourVersion
+ totalPeersSampled := 1 // Us (and to avoid division-by-zero edge case)
+ withGreaterVersion := 0
+
+ recordPeerVersion := func(agentVersion string) {
+ // We process the version as is it assembled in GetUserAgentVersion
+ segments := strings.Split(agentVersion, "/")
+ if len(segments) < 2 {
+ return
+ }
+ if segments[0] != "kubo" {
+ return
+ }
+ versionNumber := segments[1] // As in our CurrentVersionNumber
+
+ peerVersion, err := versioncmp.NewVersion(versionNumber)
+ if err != nil {
+ // Do not error on invalid remote versions, just ignore
+ return
+ }
+
+ // Ignore prereleases and development releases (-dev, -rcX)
+ if peerVersion.Metadata() != "" || peerVersion.Prerelease() != "" {
+ return
+ }
+
+ // MAJOR.MINOR.PATCH without any suffix
+ peerVersion = peerVersion.Core()
+
+ // Valid peer version number
+ totalPeersSampled += 1
+ if ourVersion.LessThan(peerVersion) {
+ withGreaterVersion += 1
+ }
+ if peerVersion.GreaterThan(greatestVersionSeen) {
+ greatestVersionSeen = peerVersion
+ }
+ }
+
+ processPeerstoreEntry := func(id peer.ID) {
+ if v, err := nd.Peerstore.Get(id, "AgentVersion"); err == nil {
+ recordPeerVersion(v.(string))
+ } else if errors.Is(err, pstore.ErrNotFound) { // ignore noop
+ } else { // a bug, usually.
+ log.Errorw("failed to get agent version from peerstore", "error", err)
+ }
+ }
+
+ // Amino DHT client keeps information about previously seen peers
+ if nd.DHTClient != nd.DHT && nd.DHTClient != nil {
+ client, ok := nd.DHTClient.(*fullrt.FullRT)
+ if !ok {
+ return VersionCheckOutput{}, errors.New("could not perform version check due to missing or incompatible DHT configuration")
+ }
+ for _, p := range client.Stat() {
+ processPeerstoreEntry(p)
+ }
+ } else if nd.DHT != nil && nd.DHT.WAN != nil {
+ for _, pi := range nd.DHT.WAN.RoutingTable().GetPeerInfos() {
+ processPeerstoreEntry(pi.Id)
+ }
+ } else if nd.DHT != nil && nd.DHT.LAN != nil {
+ for _, pi := range nd.DHT.LAN.RoutingTable().GetPeerInfos() {
+ processPeerstoreEntry(pi.Id)
+ }
+ } else {
+ return VersionCheckOutput{}, errors.New("could not perform version check due to missing or incompatible DHT configuration")
+ }
+
+ if minPercent < 1 || minPercent > 100 {
+ if minPercent == 0 {
+ minPercent = config.DefaultSwarmCheckPercentThreshold
+ } else {
+ return VersionCheckOutput{}, errors.New("Version.SwarmCheckPercentThreshold must be between 1 and 100")
+ }
+ }
+
+ minFraction := float64(minPercent) / 100.0
+
+ // UpdateAvailable flag is set only if minFraction was reached
+ greaterFraction := float64(withGreaterVersion) / float64(totalPeersSampled)
+
+ // Gathered metric are returned every time
+ return VersionCheckOutput{
+ UpdateAvailable: (greaterFraction >= minFraction),
+ RunningVersion: ourVersion.String(),
+ GreatestVersion: greatestVersionSeen.String(),
+ PeersSampled: totalPeersSampled,
+ WithGreaterVersion: withGreaterVersion,
+ }, nil
+}
diff --git a/core/core.go b/core/core.go
index 0c9333e0683..186da1f09f1 100644
--- a/core/core.go
+++ b/core/core.go
@@ -19,6 +19,7 @@ import (
pin "github.com/ipfs/boxo/pinning/pinner"
"github.com/ipfs/go-datastore"
+ bitswap "github.com/ipfs/boxo/bitswap"
bserv "github.com/ipfs/boxo/blockservice"
bstore "github.com/ipfs/boxo/blockstore"
exchange "github.com/ipfs/boxo/exchange"
@@ -27,7 +28,7 @@ import (
pathresolver "github.com/ipfs/boxo/path/resolver"
provider "github.com/ipfs/boxo/provider"
ipld "github.com/ipfs/go-ipld-format"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
goprocess "github.com/jbenet/goprocess"
ddht "github.com/libp2p/go-libp2p-kad-dht/dual"
pubsub "github.com/libp2p/go-libp2p-pubsub"
@@ -102,7 +103,8 @@ type IpfsNode struct {
UnixFSPathResolver pathresolver.Resolver `name:"unixFSPathResolver"` // The UnixFS path resolver
OfflineIPLDPathResolver pathresolver.Resolver `name:"offlineIpldPathResolver"` // The IPLD path resolver that uses only locally available blocks
OfflineUnixFSPathResolver pathresolver.Resolver `name:"offlineUnixFSPathResolver"` // The UnixFS path resolver that uses only locally available blocks
- Exchange exchange.Interface // the block exchange + strategy (bitswap)
+ Exchange exchange.Interface // the block exchange + strategy
+ Bitswap *bitswap.Bitswap `optional:"true"` // The Bitswap instance
Namesys namesys.NameSystem // the name system, resolves paths to hashes
Provider provider.System // the value provider system
IpnsRepub *ipnsrp.Republisher `optional:"true"`
@@ -132,6 +134,7 @@ type IpfsNode struct {
type Mounts struct {
Ipfs mount.Mount
Ipns mount.Mount
+ Mfs mount.Mount
}
// Close calls Close() on the App object
diff --git a/core/coreapi/coreapi.go b/core/coreapi/coreapi.go
index 0723ab65984..6e099e5fdaa 100644
--- a/core/coreapi/coreapi.go
+++ b/core/coreapi/coreapi.go
@@ -130,11 +130,6 @@ func (api *CoreAPI) Pin() coreiface.PinAPI {
return (*PinAPI)(api)
}
-// Dht returns the DhtAPI interface implementation backed by the go-ipfs node
-func (api *CoreAPI) Dht() coreiface.DhtAPI {
- return (*DhtAPI)(api)
-}
-
// Swarm returns the SwarmAPI interface implementation backed by the go-ipfs node
func (api *CoreAPI) Swarm() coreiface.SwarmAPI {
return (*SwarmAPI)(api)
@@ -212,18 +207,18 @@ func (api *CoreAPI) WithOptions(opts ...options.ApiOption) (coreiface.CoreAPI, e
return nil
}
- if settings.Offline {
- cfg, err := n.Repo.Config()
- if err != nil {
- return nil, err
- }
+ cfg, err := n.Repo.Config()
+ if err != nil {
+ return nil, err
+ }
+ if settings.Offline {
cs := cfg.Ipns.ResolveCacheSize
if cs == 0 {
cs = node.DefaultIpnsCacheSize
}
if cs < 0 {
- return nil, fmt.Errorf("cannot specify negative resolve cache size")
+ return nil, errors.New("cannot specify negative resolve cache size")
}
nsOptions := []namesys.Option{
@@ -249,7 +244,9 @@ func (api *CoreAPI) WithOptions(opts ...options.ApiOption) (coreiface.CoreAPI, e
if settings.Offline || !settings.FetchBlocks {
subAPI.exchange = offlinexch.Exchange(subAPI.blockstore)
- subAPI.blocks = bserv.New(subAPI.blockstore, subAPI.exchange)
+ subAPI.blocks = bserv.New(subAPI.blockstore, subAPI.exchange,
+ bserv.WriteThrough(cfg.Datastore.WriteThrough.WithDefault(config.DefaultWriteThrough)),
+ )
subAPI.dag = dag.NewDAGService(subAPI.blocks)
}
diff --git a/core/coreapi/dht.go b/core/coreapi/dht.go
deleted file mode 100644
index 7b5d4eb8461..00000000000
--- a/core/coreapi/dht.go
+++ /dev/null
@@ -1,154 +0,0 @@
-package coreapi
-
-import (
- "context"
- "fmt"
-
- blockservice "github.com/ipfs/boxo/blockservice"
- blockstore "github.com/ipfs/boxo/blockstore"
- offline "github.com/ipfs/boxo/exchange/offline"
- dag "github.com/ipfs/boxo/ipld/merkledag"
- "github.com/ipfs/boxo/path"
- cid "github.com/ipfs/go-cid"
- cidutil "github.com/ipfs/go-cidutil"
- coreiface "github.com/ipfs/kubo/core/coreiface"
- caopts "github.com/ipfs/kubo/core/coreiface/options"
- "github.com/ipfs/kubo/tracing"
- peer "github.com/libp2p/go-libp2p/core/peer"
- routing "github.com/libp2p/go-libp2p/core/routing"
- "go.opentelemetry.io/otel/attribute"
- "go.opentelemetry.io/otel/trace"
-)
-
-type DhtAPI CoreAPI
-
-func (api *DhtAPI) FindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) {
- ctx, span := tracing.Span(ctx, "CoreAPI.DhtAPI", "FindPeer", trace.WithAttributes(attribute.String("peer", p.String())))
- defer span.End()
- err := api.checkOnline(false)
- if err != nil {
- return peer.AddrInfo{}, err
- }
-
- pi, err := api.routing.FindPeer(ctx, peer.ID(p))
- if err != nil {
- return peer.AddrInfo{}, err
- }
-
- return pi, nil
-}
-
-func (api *DhtAPI) FindProviders(ctx context.Context, p path.Path, opts ...caopts.DhtFindProvidersOption) (<-chan peer.AddrInfo, error) {
- ctx, span := tracing.Span(ctx, "CoreAPI.DhtAPI", "FindProviders", trace.WithAttributes(attribute.String("path", p.String())))
- defer span.End()
-
- settings, err := caopts.DhtFindProvidersOptions(opts...)
- if err != nil {
- return nil, err
- }
- span.SetAttributes(attribute.Int("numproviders", settings.NumProviders))
-
- err = api.checkOnline(false)
- if err != nil {
- return nil, err
- }
-
- rp, _, err := api.core().ResolvePath(ctx, p)
- if err != nil {
- return nil, err
- }
-
- numProviders := settings.NumProviders
- if numProviders < 1 {
- return nil, fmt.Errorf("number of providers must be greater than 0")
- }
-
- pchan := api.routing.FindProvidersAsync(ctx, rp.RootCid(), numProviders)
- return pchan, nil
-}
-
-func (api *DhtAPI) Provide(ctx context.Context, path path.Path, opts ...caopts.DhtProvideOption) error {
- ctx, span := tracing.Span(ctx, "CoreAPI.DhtAPI", "Provide", trace.WithAttributes(attribute.String("path", path.String())))
- defer span.End()
-
- settings, err := caopts.DhtProvideOptions(opts...)
- if err != nil {
- return err
- }
- span.SetAttributes(attribute.Bool("recursive", settings.Recursive))
-
- err = api.checkOnline(false)
- if err != nil {
- return err
- }
-
- rp, _, err := api.core().ResolvePath(ctx, path)
- if err != nil {
- return err
- }
-
- c := rp.RootCid()
-
- has, err := api.blockstore.Has(ctx, c)
- if err != nil {
- return err
- }
-
- if !has {
- return fmt.Errorf("block %s not found locally, cannot provide", c)
- }
-
- if settings.Recursive {
- err = provideKeysRec(ctx, api.routing, api.blockstore, []cid.Cid{c})
- } else {
- err = provideKeys(ctx, api.routing, []cid.Cid{c})
- }
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func provideKeys(ctx context.Context, r routing.Routing, cids []cid.Cid) error {
- for _, c := range cids {
- err := r.Provide(ctx, c, true)
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-func provideKeysRec(ctx context.Context, r routing.Routing, bs blockstore.Blockstore, cids []cid.Cid) error {
- provided := cidutil.NewStreamingSet()
-
- errCh := make(chan error)
- go func() {
- dserv := dag.NewDAGService(blockservice.New(bs, offline.Exchange(bs)))
- for _, c := range cids {
- err := dag.Walk(ctx, dag.GetLinksDirect(dserv), c, provided.Visitor(ctx))
- if err != nil {
- errCh <- err
- }
- }
- }()
-
- for {
- select {
- case k := <-provided.New:
- err := r.Provide(ctx, k, true)
- if err != nil {
- return err
- }
- case err := <-errCh:
- return err
- case <-ctx.Done():
- return ctx.Err()
- }
- }
-}
-
-func (api *DhtAPI) core() coreiface.CoreAPI {
- return (*CoreAPI)(api)
-}
diff --git a/core/coreapi/key.go b/core/coreapi/key.go
index a6101dae826..784045d26e3 100644
--- a/core/coreapi/key.go
+++ b/core/coreapi/key.go
@@ -65,7 +65,7 @@ func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.Key
}
if name == "self" {
- return nil, fmt.Errorf("cannot create key with name 'self'")
+ return nil, errors.New("cannot create key with name 'self'")
}
_, err = api.repo.Keystore().Get(name)
@@ -168,11 +168,11 @@ func (api *KeyAPI) Rename(ctx context.Context, oldName string, newName string, o
ks := api.repo.Keystore()
if oldName == "self" {
- return nil, false, fmt.Errorf("cannot rename key with name 'self'")
+ return nil, false, errors.New("cannot rename key with name 'self'")
}
if newName == "self" {
- return nil, false, fmt.Errorf("cannot overwrite key with name 'self'")
+ return nil, false, errors.New("cannot overwrite key with name 'self'")
}
oldKey, err := ks.Get(oldName)
@@ -232,7 +232,7 @@ func (api *KeyAPI) Remove(ctx context.Context, name string) (coreiface.Key, erro
ks := api.repo.Keystore()
if name == "self" {
- return nil, fmt.Errorf("cannot remove key with name 'self'")
+ return nil, errors.New("cannot remove key with name 'self'")
}
removed, err := ks.Get(name)
diff --git a/core/coreapi/name.go b/core/coreapi/name.go
index 3c4145ed501..305c19e43c6 100644
--- a/core/coreapi/name.go
+++ b/core/coreapi/name.go
@@ -2,6 +2,7 @@ package coreapi
import (
"context"
+ "errors"
"fmt"
"strings"
"time"
@@ -214,5 +215,5 @@ func keylookup(self ci.PrivKey, kstore keystore.Keystore, k string) (ci.PrivKey,
}
}
- return nil, fmt.Errorf("no key by the given name or PeerID was found")
+ return nil, errors.New("no key by the given name or PeerID was found")
}
diff --git a/core/coreapi/object.go b/core/coreapi/object.go
index fca98bc5fa4..0f6c2747a57 100644
--- a/core/coreapi/object.go
+++ b/core/coreapi/object.go
@@ -1,22 +1,12 @@
package coreapi
import (
- "bytes"
"context"
- "encoding/base64"
- "encoding/json"
- "encoding/xml"
- "errors"
- "fmt"
- "io"
dag "github.com/ipfs/boxo/ipld/merkledag"
"github.com/ipfs/boxo/ipld/merkledag/dagutils"
ft "github.com/ipfs/boxo/ipld/unixfs"
"github.com/ipfs/boxo/path"
- pin "github.com/ipfs/boxo/pinning/pinner"
- cid "github.com/ipfs/go-cid"
- ipld "github.com/ipfs/go-ipld-format"
coreiface "github.com/ipfs/kubo/core/coreiface"
caopts "github.com/ipfs/kubo/core/coreiface/options"
"go.opentelemetry.io/otel/attribute"
@@ -25,8 +15,6 @@ import (
"github.com/ipfs/kubo/tracing"
)
-const inputLimit = 2 << 20
-
type ObjectAPI CoreAPI
type Link struct {
@@ -39,180 +27,6 @@ type Node struct {
Data string
}
-func (api *ObjectAPI) New(ctx context.Context, opts ...caopts.ObjectNewOption) (ipld.Node, error) {
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "New")
- defer span.End()
-
- options, err := caopts.ObjectNewOptions(opts...)
- if err != nil {
- return nil, err
- }
-
- var n ipld.Node
- switch options.Type {
- case "empty":
- n = new(dag.ProtoNode)
- case "unixfs-dir":
- n = ft.EmptyDirNode()
- default:
- return nil, fmt.Errorf("unknown node type: %s", options.Type)
- }
-
- err = api.dag.Add(ctx, n)
- if err != nil {
- return nil, err
- }
- return n, nil
-}
-
-func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.ObjectPutOption) (path.ImmutablePath, error) {
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Put")
- defer span.End()
-
- options, err := caopts.ObjectPutOptions(opts...)
- if err != nil {
- return path.ImmutablePath{}, err
- }
- span.SetAttributes(
- attribute.Bool("pin", options.Pin),
- attribute.String("datatype", options.DataType),
- attribute.String("inputenc", options.InputEnc),
- )
-
- data, err := io.ReadAll(io.LimitReader(src, inputLimit+10))
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- var dagnode *dag.ProtoNode
- switch options.InputEnc {
- case "json":
- node := new(Node)
- decoder := json.NewDecoder(bytes.NewReader(data))
- decoder.DisallowUnknownFields()
- err = decoder.Decode(node)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- dagnode, err = deserializeNode(node, options.DataType)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- case "protobuf":
- dagnode, err = dag.DecodeProtobuf(data)
-
- case "xml":
- node := new(Node)
- err = xml.Unmarshal(data, node)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- dagnode, err = deserializeNode(node, options.DataType)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- default:
- return path.ImmutablePath{}, errors.New("unknown object encoding")
- }
-
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- if options.Pin {
- defer api.blockstore.PinLock(ctx).Unlock(ctx)
- }
-
- err = api.dag.Add(ctx, dagnode)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- if options.Pin {
- if err := api.pinning.PinWithMode(ctx, dagnode.Cid(), pin.Recursive, ""); err != nil {
- return path.ImmutablePath{}, err
- }
-
- err = api.pinning.Flush(ctx)
- if err != nil {
- return path.ImmutablePath{}, err
- }
- }
-
- return path.FromCid(dagnode.Cid()), nil
-}
-
-func (api *ObjectAPI) Get(ctx context.Context, path path.Path) (ipld.Node, error) {
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Get", trace.WithAttributes(attribute.String("path", path.String())))
- defer span.End()
- return api.core().ResolveNode(ctx, path)
-}
-
-func (api *ObjectAPI) Data(ctx context.Context, path path.Path) (io.Reader, error) {
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Data", trace.WithAttributes(attribute.String("path", path.String())))
- defer span.End()
-
- nd, err := api.core().ResolveNode(ctx, path)
- if err != nil {
- return nil, err
- }
-
- pbnd, ok := nd.(*dag.ProtoNode)
- if !ok {
- return nil, dag.ErrNotProtobuf
- }
-
- return bytes.NewReader(pbnd.Data()), nil
-}
-
-func (api *ObjectAPI) Links(ctx context.Context, path path.Path) ([]*ipld.Link, error) {
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Links", trace.WithAttributes(attribute.String("path", path.String())))
- defer span.End()
-
- nd, err := api.core().ResolveNode(ctx, path)
- if err != nil {
- return nil, err
- }
-
- links := nd.Links()
- out := make([]*ipld.Link, len(links))
- for n, l := range links {
- out[n] = (*ipld.Link)(l)
- }
-
- return out, nil
-}
-
-func (api *ObjectAPI) Stat(ctx context.Context, path path.Path) (*coreiface.ObjectStat, error) {
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Stat", trace.WithAttributes(attribute.String("path", path.String())))
- defer span.End()
-
- nd, err := api.core().ResolveNode(ctx, path)
- if err != nil {
- return nil, err
- }
-
- stat, err := nd.Stat()
- if err != nil {
- return nil, err
- }
-
- out := &coreiface.ObjectStat{
- Cid: nd.Cid(),
- NumLinks: stat.NumLinks,
- BlockSize: stat.BlockSize,
- LinksSize: stat.LinksSize,
- DataSize: stat.DataSize,
- CumulativeSize: stat.CumulativeSize,
- }
-
- return out, nil
-}
-
func (api *ObjectAPI) AddLink(ctx context.Context, base path.Path, name string, child path.Path, opts ...caopts.ObjectAddLinkOption) (path.ImmutablePath, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "AddLink", trace.WithAttributes(
attribute.String("base", base.String()),
@@ -294,49 +108,6 @@ func (api *ObjectAPI) RmLink(ctx context.Context, base path.Path, link string) (
return path.FromCid(nnode.Cid()), nil
}
-func (api *ObjectAPI) AppendData(ctx context.Context, path path.Path, r io.Reader) (path.ImmutablePath, error) {
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "AppendData", trace.WithAttributes(attribute.String("path", path.String())))
- defer span.End()
-
- return api.patchData(ctx, path, r, true)
-}
-
-func (api *ObjectAPI) SetData(ctx context.Context, path path.Path, r io.Reader) (path.ImmutablePath, error) {
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "SetData", trace.WithAttributes(attribute.String("path", path.String())))
- defer span.End()
-
- return api.patchData(ctx, path, r, false)
-}
-
-func (api *ObjectAPI) patchData(ctx context.Context, p path.Path, r io.Reader, appendData bool) (path.ImmutablePath, error) {
- nd, err := api.core().ResolveNode(ctx, p)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- pbnd, ok := nd.(*dag.ProtoNode)
- if !ok {
- return path.ImmutablePath{}, dag.ErrNotProtobuf
- }
-
- data, err := io.ReadAll(r)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- if appendData {
- data = append(pbnd.Data(), data...)
- }
- pbnd.SetData(data)
-
- err = api.dag.Add(ctx, pbnd)
- if err != nil {
- return path.ImmutablePath{}, err
- }
-
- return path.FromCid(pbnd.Cid()), nil
-}
-
func (api *ObjectAPI) Diff(ctx context.Context, before path.Path, after path.Path) ([]coreiface.ObjectChange, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Diff", trace.WithAttributes(
attribute.String("before", before.String()),
@@ -381,37 +152,3 @@ func (api *ObjectAPI) Diff(ctx context.Context, before path.Path, after path.Pat
func (api *ObjectAPI) core() coreiface.CoreAPI {
return (*CoreAPI)(api)
}
-
-func deserializeNode(nd *Node, dataFieldEncoding string) (*dag.ProtoNode, error) {
- dagnode := new(dag.ProtoNode)
- switch dataFieldEncoding {
- case "text":
- dagnode.SetData([]byte(nd.Data))
- case "base64":
- data, err := base64.StdEncoding.DecodeString(nd.Data)
- if err != nil {
- return nil, err
- }
- dagnode.SetData(data)
- default:
- return nil, fmt.Errorf("unknown data field encoding")
- }
-
- links := make([]*ipld.Link, len(nd.Links))
- for i, link := range nd.Links {
- c, err := cid.Decode(link.Hash)
- if err != nil {
- return nil, err
- }
- links[i] = &ipld.Link{
- Name: link.Name,
- Size: link.Size,
- Cid: c,
- }
- }
- if err := dagnode.SetLinks(links); err != nil {
- return nil, err
- }
-
- return dagnode, nil
-}
diff --git a/core/coreapi/pin.go b/core/coreapi/pin.go
index 8db582a4ffa..878b4c28d0a 100644
--- a/core/coreapi/pin.go
+++ b/core/coreapi/pin.go
@@ -3,6 +3,7 @@ package coreapi
import (
"context"
"fmt"
+ "strings"
bserv "github.com/ipfs/boxo/blockservice"
offline "github.com/ipfs/boxo/exchange/offline"
@@ -43,20 +44,21 @@ func (api *PinAPI) Add(ctx context.Context, p path.Path, opts ...caopts.PinAddOp
return fmt.Errorf("pin: %s", err)
}
- if err := api.provider.Provide(dagNode.Cid()); err != nil {
+ if err := api.provider.Provide(ctx, dagNode.Cid(), true); err != nil {
return err
}
return api.pinning.Flush(ctx)
}
-func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) (<-chan coreiface.Pin, error) {
+func (api *PinAPI) Ls(ctx context.Context, pins chan<- coreiface.Pin, opts ...caopts.PinLsOption) error {
ctx, span := tracing.Span(ctx, "CoreAPI.PinAPI", "Ls")
defer span.End()
settings, err := caopts.PinLsOptions(opts...)
if err != nil {
- return nil, err
+ close(pins)
+ return err
}
span.SetAttributes(attribute.String("type", settings.Type))
@@ -64,10 +66,11 @@ func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) (<-chan c
switch settings.Type {
case "all", "direct", "indirect", "recursive":
default:
- return nil, fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", settings.Type)
+ close(pins)
+ return fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", settings.Type)
}
- return api.pinLsAll(ctx, settings.Type, settings.Detailed), nil
+ return api.pinLsAll(ctx, settings.Type, settings.Detailed, settings.Name, pins)
}
func (api *PinAPI) IsPinned(ctx context.Context, p path.Path, opts ...caopts.PinIsPinnedOption) (string, bool, error) {
@@ -229,6 +232,7 @@ func (api *PinAPI) Verify(ctx context.Context) (<-chan coreiface.PinStatus, erro
}
out := make(chan coreiface.PinStatus)
+
go func() {
defer close(out)
for p := range api.pinning.RecursiveKeys(ctx, false) {
@@ -253,7 +257,6 @@ type pinInfo struct {
pinType string
path path.ImmutablePath
name string
- err error
}
func (p *pinInfo) Path() path.ImmutablePath {
@@ -268,25 +271,20 @@ func (p *pinInfo) Name() string {
return p.name
}
-func (p *pinInfo) Err() error {
- return p.err
-}
-
// pinLsAll is an internal function for returning a list of pins
//
// The caller must keep reading results until the channel is closed to prevent
// leaking the goroutine that is fetching pins.
-func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string, detailed bool) <-chan coreiface.Pin {
- out := make(chan coreiface.Pin, 1)
-
+func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string, detailed bool, name string, out chan<- coreiface.Pin) error {
+ defer close(out)
emittedSet := cid.NewSet()
- AddToResultKeys := func(c cid.Cid, name, typeStr string) error {
- if emittedSet.Visit(c) {
+ AddToResultKeys := func(c cid.Cid, pinName, typeStr string) error {
+ if emittedSet.Visit(c) && (name == "" || strings.Contains(pinName, name)) {
select {
case out <- &pinInfo{
pinType: typeStr,
- name: name,
+ name: pinName,
path: path.FromCid(c),
}:
case <-ctx.Done():
@@ -296,87 +294,79 @@ func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string, detailed bool)
return nil
}
- go func() {
- defer close(out)
-
- var rkeys []cid.Cid
- var err error
- if typeStr == "recursive" || typeStr == "all" {
- for streamedCid := range api.pinning.RecursiveKeys(ctx, detailed) {
- if streamedCid.Err != nil {
- out <- &pinInfo{err: streamedCid.Err}
- return
- }
- if err = AddToResultKeys(streamedCid.Pin.Key, streamedCid.Pin.Name, "recursive"); err != nil {
- out <- &pinInfo{err: err}
- return
- }
- rkeys = append(rkeys, streamedCid.Pin.Key)
+ var rkeys []cid.Cid
+ var err error
+ if typeStr == "recursive" || typeStr == "all" {
+ for streamedCid := range api.pinning.RecursiveKeys(ctx, detailed) {
+ if streamedCid.Err != nil {
+ return streamedCid.Err
}
+ if err = AddToResultKeys(streamedCid.Pin.Key, streamedCid.Pin.Name, "recursive"); err != nil {
+ return err
+ }
+ rkeys = append(rkeys, streamedCid.Pin.Key)
}
- if typeStr == "direct" || typeStr == "all" {
- for streamedCid := range api.pinning.DirectKeys(ctx, detailed) {
- if streamedCid.Err != nil {
- out <- &pinInfo{err: streamedCid.Err}
- return
- }
- if err = AddToResultKeys(streamedCid.Pin.Key, streamedCid.Pin.Name, "direct"); err != nil {
- out <- &pinInfo{err: err}
- return
- }
+ }
+ if typeStr == "direct" || typeStr == "all" {
+ for streamedCid := range api.pinning.DirectKeys(ctx, detailed) {
+ if streamedCid.Err != nil {
+ return streamedCid.Err
+ }
+ if err = AddToResultKeys(streamedCid.Pin.Key, streamedCid.Pin.Name, "direct"); err != nil {
+ return err
}
}
- if typeStr == "indirect" {
- // We need to first visit the direct pins that have priority
- // without emitting them
-
- for streamedCid := range api.pinning.DirectKeys(ctx, detailed) {
- if streamedCid.Err != nil {
- out <- &pinInfo{err: streamedCid.Err}
- return
- }
- emittedSet.Add(streamedCid.Pin.Key)
+ }
+ if typeStr == "indirect" {
+ // We need to first visit the direct pins that have priority
+ // without emitting them
+
+ for streamedCid := range api.pinning.DirectKeys(ctx, detailed) {
+ if streamedCid.Err != nil {
+ return streamedCid.Err
}
+ emittedSet.Add(streamedCid.Pin.Key)
+ }
- for streamedCid := range api.pinning.RecursiveKeys(ctx, detailed) {
- if streamedCid.Err != nil {
- out <- &pinInfo{err: streamedCid.Err}
- return
- }
- emittedSet.Add(streamedCid.Pin.Key)
- rkeys = append(rkeys, streamedCid.Pin.Key)
+ for streamedCid := range api.pinning.RecursiveKeys(ctx, detailed) {
+ if streamedCid.Err != nil {
+ return streamedCid.Err
}
+ emittedSet.Add(streamedCid.Pin.Key)
+ rkeys = append(rkeys, streamedCid.Pin.Key)
}
- if typeStr == "indirect" || typeStr == "all" {
- walkingSet := cid.NewSet()
- for _, k := range rkeys {
- err = merkledag.Walk(
- ctx, merkledag.GetLinksWithDAG(api.dag), k,
- func(c cid.Cid) bool {
- if !walkingSet.Visit(c) {
- return false
- }
- if emittedSet.Has(c) {
- return true // skipped
- }
- err := AddToResultKeys(c, "", "indirect")
- if err != nil {
- out <- &pinInfo{err: err}
- return false
- }
- return true
- },
- merkledag.SkipRoot(), merkledag.Concurrent(),
- )
- if err != nil {
- out <- &pinInfo{err: err}
- return
- }
+ }
+ if typeStr == "indirect" || typeStr == "all" {
+ if len(rkeys) == 0 {
+ return nil
+ }
+ var addErr error
+ walkingSet := cid.NewSet()
+ for _, k := range rkeys {
+ err = merkledag.Walk(
+ ctx, merkledag.GetLinksWithDAG(api.dag), k,
+ func(c cid.Cid) bool {
+ if !walkingSet.Visit(c) {
+ return false
+ }
+ if emittedSet.Has(c) {
+ return true // skipped
+ }
+ addErr = AddToResultKeys(c, "", "indirect")
+ return addErr == nil
+ },
+ merkledag.SkipRoot(), merkledag.Concurrent(),
+ )
+ if err != nil {
+ return err
+ }
+ if addErr != nil {
+ return addErr
}
}
- }()
+ }
- return out
+ return nil
}
func (api *PinAPI) core() coreiface.CoreAPI {
diff --git a/core/coreapi/routing.go b/core/coreapi/routing.go
index d784a738d2a..6d432d744dd 100644
--- a/core/coreapi/routing.go
+++ b/core/coreapi/routing.go
@@ -3,17 +3,29 @@ package coreapi
import (
"context"
"errors"
+ "fmt"
"strings"
+ blockservice "github.com/ipfs/boxo/blockservice"
+ blockstore "github.com/ipfs/boxo/blockstore"
+ offline "github.com/ipfs/boxo/exchange/offline"
+ dag "github.com/ipfs/boxo/ipld/merkledag"
+ "github.com/ipfs/boxo/path"
+ cid "github.com/ipfs/go-cid"
+ cidutil "github.com/ipfs/go-cidutil"
coreiface "github.com/ipfs/kubo/core/coreiface"
caopts "github.com/ipfs/kubo/core/coreiface/options"
+ "github.com/ipfs/kubo/tracing"
peer "github.com/libp2p/go-libp2p/core/peer"
+ routing "github.com/libp2p/go-libp2p/core/routing"
+ "go.opentelemetry.io/otel/attribute"
+ "go.opentelemetry.io/otel/trace"
)
type RoutingAPI CoreAPI
-func (r *RoutingAPI) Get(ctx context.Context, key string) ([]byte, error) {
- if !r.nd.IsOnline {
+func (api *RoutingAPI) Get(ctx context.Context, key string) ([]byte, error) {
+ if !api.nd.IsOnline {
return nil, coreiface.ErrOffline
}
@@ -22,16 +34,16 @@ func (r *RoutingAPI) Get(ctx context.Context, key string) ([]byte, error) {
return nil, err
}
- return r.routing.GetValue(ctx, dhtKey)
+ return api.routing.GetValue(ctx, dhtKey)
}
-func (r *RoutingAPI) Put(ctx context.Context, key string, value []byte, opts ...caopts.RoutingPutOption) error {
+func (api *RoutingAPI) Put(ctx context.Context, key string, value []byte, opts ...caopts.RoutingPutOption) error {
options, err := caopts.RoutingPutOptions(opts...)
if err != nil {
return err
}
- err = r.checkOnline(options.AllowOffline)
+ err = api.checkOnline(options.AllowOffline)
if err != nil {
return err
}
@@ -41,7 +53,7 @@ func (r *RoutingAPI) Put(ctx context.Context, key string, value []byte, opts ...
return err
}
- return r.routing.PutValue(ctx, dhtKey, value)
+ return api.routing.PutValue(ctx, dhtKey, value)
}
func normalizeKey(s string) (string, error) {
@@ -58,3 +70,134 @@ func normalizeKey(s string) (string, error) {
}
return strings.Join(append(parts[:2], string(k)), "/"), nil
}
+
+func (api *RoutingAPI) FindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) {
+ ctx, span := tracing.Span(ctx, "CoreAPI.DhtAPI", "FindPeer", trace.WithAttributes(attribute.String("peer", p.String())))
+ defer span.End()
+ err := api.checkOnline(false)
+ if err != nil {
+ return peer.AddrInfo{}, err
+ }
+
+ pi, err := api.routing.FindPeer(ctx, peer.ID(p))
+ if err != nil {
+ return peer.AddrInfo{}, err
+ }
+
+ return pi, nil
+}
+
+func (api *RoutingAPI) FindProviders(ctx context.Context, p path.Path, opts ...caopts.RoutingFindProvidersOption) (<-chan peer.AddrInfo, error) {
+ ctx, span := tracing.Span(ctx, "CoreAPI.DhtAPI", "FindProviders", trace.WithAttributes(attribute.String("path", p.String())))
+ defer span.End()
+
+ settings, err := caopts.RoutingFindProvidersOptions(opts...)
+ if err != nil {
+ return nil, err
+ }
+ span.SetAttributes(attribute.Int("numproviders", settings.NumProviders))
+
+ err = api.checkOnline(false)
+ if err != nil {
+ return nil, err
+ }
+
+ rp, _, err := api.core().ResolvePath(ctx, p)
+ if err != nil {
+ return nil, err
+ }
+
+ numProviders := settings.NumProviders
+ if numProviders < 1 {
+ return nil, errors.New("number of providers must be greater than 0")
+ }
+
+ pchan := api.routing.FindProvidersAsync(ctx, rp.RootCid(), numProviders)
+ return pchan, nil
+}
+
+func (api *RoutingAPI) Provide(ctx context.Context, path path.Path, opts ...caopts.RoutingProvideOption) error {
+ ctx, span := tracing.Span(ctx, "CoreAPI.DhtAPI", "Provide", trace.WithAttributes(attribute.String("path", path.String())))
+ defer span.End()
+
+ settings, err := caopts.RoutingProvideOptions(opts...)
+ if err != nil {
+ return err
+ }
+ span.SetAttributes(attribute.Bool("recursive", settings.Recursive))
+
+ err = api.checkOnline(false)
+ if err != nil {
+ return err
+ }
+
+ rp, _, err := api.core().ResolvePath(ctx, path)
+ if err != nil {
+ return err
+ }
+
+ c := rp.RootCid()
+
+ has, err := api.blockstore.Has(ctx, c)
+ if err != nil {
+ return err
+ }
+
+ if !has {
+ return fmt.Errorf("block %s not found locally, cannot provide", c)
+ }
+
+ if settings.Recursive {
+ err = provideKeysRec(ctx, api.routing, api.blockstore, []cid.Cid{c})
+ } else {
+ err = provideKeys(ctx, api.routing, []cid.Cid{c})
+ }
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func provideKeys(ctx context.Context, r routing.Routing, cids []cid.Cid) error {
+ for _, c := range cids {
+ err := r.Provide(ctx, c, true)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func provideKeysRec(ctx context.Context, r routing.Routing, bs blockstore.Blockstore, cids []cid.Cid) error {
+ provided := cidutil.NewStreamingSet()
+
+ errCh := make(chan error)
+ go func() {
+ dserv := dag.NewDAGService(blockservice.New(bs, offline.Exchange(bs)))
+ for _, c := range cids {
+ err := dag.Walk(ctx, dag.GetLinksDirect(dserv), c, provided.Visitor(ctx))
+ if err != nil {
+ errCh <- err
+ }
+ }
+ }()
+
+ for {
+ select {
+ case k := <-provided.New:
+ err := r.Provide(ctx, k, true)
+ if err != nil {
+ return err
+ }
+ case err := <-errCh:
+ return err
+ case <-ctx.Done():
+ return ctx.Err()
+ }
+ }
+}
+
+func (api *RoutingAPI) core() coreiface.CoreAPI {
+ return (*CoreAPI)(api)
+}
diff --git a/core/coreapi/test/api_test.go b/core/coreapi/test/api_test.go
index d647a32c87c..dfd8cf6854b 100644
--- a/core/coreapi/test/api_test.go
+++ b/core/coreapi/test/api_test.go
@@ -69,6 +69,7 @@ func (NodeProvider) MakeAPISwarm(t *testing.T, ctx context.Context, fullIdentity
c.Addresses.Swarm = []string{fmt.Sprintf("/ip4/18.0.%d.1/tcp/4001", i)}
c.Identity = ident
c.Experimental.FilestoreEnabled = true
+ c.AutoTLS.Enabled = config.False // disable so no /ws listener is added
ds := syncds.MutexWrap(datastore.NewMapDatastore())
r := &repo.Mock{
diff --git a/core/coreapi/unixfs.go b/core/coreapi/unixfs.go
index 452e6017bc1..eece797a5fa 100644
--- a/core/coreapi/unixfs.go
+++ b/core/coreapi/unixfs.go
@@ -2,15 +2,8 @@ package coreapi
import (
"context"
+ "errors"
"fmt"
- "sync"
-
- "github.com/ipfs/kubo/core"
- "github.com/ipfs/kubo/tracing"
- "go.opentelemetry.io/otel/attribute"
- "go.opentelemetry.io/otel/trace"
-
- "github.com/ipfs/kubo/core/coreunix"
blockservice "github.com/ipfs/boxo/blockservice"
bstore "github.com/ipfs/boxo/blockstore"
@@ -21,41 +14,24 @@ import (
ft "github.com/ipfs/boxo/ipld/unixfs"
unixfile "github.com/ipfs/boxo/ipld/unixfs/file"
uio "github.com/ipfs/boxo/ipld/unixfs/io"
- mfs "github.com/ipfs/boxo/mfs"
+ "github.com/ipfs/boxo/mfs"
"github.com/ipfs/boxo/path"
cid "github.com/ipfs/go-cid"
cidutil "github.com/ipfs/go-cidutil"
+ ds "github.com/ipfs/go-datastore"
+ dssync "github.com/ipfs/go-datastore/sync"
ipld "github.com/ipfs/go-ipld-format"
+ "github.com/ipfs/kubo/config"
coreiface "github.com/ipfs/kubo/core/coreiface"
options "github.com/ipfs/kubo/core/coreiface/options"
+ "github.com/ipfs/kubo/core/coreunix"
+ "github.com/ipfs/kubo/tracing"
+ "go.opentelemetry.io/otel/attribute"
+ "go.opentelemetry.io/otel/trace"
)
type UnixfsAPI CoreAPI
-var (
- nilNode *core.IpfsNode
- once sync.Once
-)
-
-func getOrCreateNilNode() (*core.IpfsNode, error) {
- once.Do(func() {
- if nilNode != nil {
- return
- }
- node, err := core.NewNode(context.Background(), &core.BuildCfg{
- // TODO: need this to be true or all files
- // hashed will be stored in memory!
- NilRepo: true,
- })
- if err != nil {
- panic(err)
- }
- nilNode = node
- })
-
- return nilNode, nil
-}
-
// Add builds a merkledag node from a reader, adds it to the blockstore,
// and returns the key representing that node.
func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options.UnixfsAddOption) (path.ImmutablePath, error) {
@@ -74,6 +50,12 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
attribute.Int("inlinelimit", settings.InlineLimit),
attribute.Bool("rawleaves", settings.RawLeaves),
attribute.Bool("rawleavesset", settings.RawLeavesSet),
+ attribute.Int("maxfilelinks", settings.MaxFileLinks),
+ attribute.Bool("maxfilelinksset", settings.MaxFileLinksSet),
+ attribute.Int("maxdirectorylinks", settings.MaxDirectoryLinks),
+ attribute.Bool("maxdirectorylinksset", settings.MaxDirectoryLinksSet),
+ attribute.Int("maxhamtfanout", settings.MaxHAMTFanout),
+ attribute.Bool("maxhamtfanoutset", settings.MaxHAMTFanoutSet),
attribute.Int("layout", int(settings.Layout)),
attribute.Bool("pin", settings.Pin),
attribute.Bool("onlyhash", settings.OnlyHash),
@@ -97,7 +79,7 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
//}
if settings.NoCopy && !(cfg.Experimental.FilestoreEnabled || cfg.Experimental.UrlstoreEnabled) {
- return path.ImmutablePath{}, fmt.Errorf("either the filestore or the urlstore must be enabled to use nocopy, see: https://github.com/ipfs/kubo/blob/master/docs/experimental-features.md#ipfs-filestore")
+ return path.ImmutablePath{}, errors.New("either the filestore or the urlstore must be enabled to use nocopy, see: https://github.com/ipfs/kubo/blob/master/docs/experimental-features.md#ipfs-filestore")
}
addblockstore := api.blockstore
@@ -108,16 +90,17 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
pinning := api.pinning
if settings.OnlyHash {
- node, err := getOrCreateNilNode()
- if err != nil {
- return path.ImmutablePath{}, err
- }
- addblockstore = node.Blockstore
- exch = node.Exchange
- pinning = node.Pinning
+ // setup a /dev/null pipeline to simulate adding the data
+ dstore := dssync.MutexWrap(ds.NewNullDatastore())
+ bs := bstore.NewBlockstore(dstore, bstore.WriteThrough(true)) // we use NewNullDatastore, so ok to always WriteThrough when OnlyHash
+ addblockstore = bstore.NewGCBlockstore(bs, nil) // gclocker will never be used
+ exch = nil // exchange will never be used
+ pinning = nil // pinner will never be used
}
- bserv := blockservice.New(addblockstore, exch) // hash security 001
+ bserv := blockservice.New(addblockstore, exch,
+ blockservice.WriteThrough(cfg.Datastore.WriteThrough.WithDefault(config.DefaultWriteThrough)),
+ ) // hash security 001
dserv := merkledag.NewDAGService(bserv)
// add a sync call to the DagService
@@ -133,11 +116,11 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
syncDserv = &syncDagService{
DAGService: dserv,
syncFn: func() error {
- ds := api.repo.Datastore()
- if err := ds.Sync(ctx, bstore.BlockPrefix); err != nil {
+ rds := api.repo.Datastore()
+ if err := rds.Sync(ctx, bstore.BlockPrefix); err != nil {
return err
}
- return ds.Sync(ctx, filestore.FilestorePrefix)
+ return rds.Sync(ctx, filestore.FilestorePrefix)
},
}
}
@@ -155,8 +138,22 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
fileAdder.Pin = settings.Pin && !settings.OnlyHash
fileAdder.Silent = settings.Silent
fileAdder.RawLeaves = settings.RawLeaves
+ if settings.MaxFileLinksSet {
+ fileAdder.MaxLinks = settings.MaxFileLinks
+ }
+ if settings.MaxDirectoryLinksSet {
+ fileAdder.MaxDirectoryLinks = settings.MaxDirectoryLinks
+ }
+
+ if settings.MaxHAMTFanoutSet {
+ fileAdder.MaxHAMTFanout = settings.MaxHAMTFanout
+ }
fileAdder.NoCopy = settings.NoCopy
fileAdder.CidBuilder = prefix
+ fileAdder.PreserveMode = settings.PreserveMode
+ fileAdder.PreserveMtime = settings.PreserveMtime
+ fileAdder.FileMode = settings.Mode
+ fileAdder.FileMtime = settings.Mtime
switch settings.Layout {
case options.BalancedLayout:
@@ -196,7 +193,7 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
}
if !settings.OnlyHash {
- if err := api.provider.Provide(nd.Cid()); err != nil {
+ if err := api.provider.Provide(ctx, nd.Cid(), true); err != nil {
return path.ImmutablePath{}, err
}
}
@@ -220,13 +217,15 @@ func (api *UnixfsAPI) Get(ctx context.Context, p path.Path) (files.Node, error)
// Ls returns the contents of an IPFS or IPNS object(s) at path p, with the format:
// ` `
-func (api *UnixfsAPI) Ls(ctx context.Context, p path.Path, opts ...options.UnixfsLsOption) (<-chan coreiface.DirEntry, error) {
+func (api *UnixfsAPI) Ls(ctx context.Context, p path.Path, out chan<- coreiface.DirEntry, opts ...options.UnixfsLsOption) error {
ctx, span := tracing.Span(ctx, "CoreAPI.UnixfsAPI", "Ls", trace.WithAttributes(attribute.String("path", p.String())))
defer span.End()
+ defer close(out)
+
settings, err := options.UnixfsLsOptions(opts...)
if err != nil {
- return nil, err
+ return err
}
span.SetAttributes(attribute.Bool("resolvechildren", settings.ResolveChildren))
@@ -236,21 +235,21 @@ func (api *UnixfsAPI) Ls(ctx context.Context, p path.Path, opts ...options.Unixf
dagnode, err := ses.ResolveNode(ctx, p)
if err != nil {
- return nil, err
+ return err
}
dir, err := uio.NewDirectoryFromNode(ses.dag, dagnode)
- if err == uio.ErrNotADir {
- return uses.lsFromLinks(ctx, dagnode.Links(), settings)
- }
if err != nil {
- return nil, err
+ if errors.Is(err, uio.ErrNotADir) {
+ return uses.lsFromLinks(ctx, dagnode.Links(), settings, out)
+ }
+ return err
}
- return uses.lsFromLinksAsync(ctx, dir, settings)
+ return uses.lsFromDirLinks(ctx, dir, settings, out)
}
-func (api *UnixfsAPI) processLink(ctx context.Context, linkres ft.LinkResult, settings *options.UnixfsLsSettings) coreiface.DirEntry {
+func (api *UnixfsAPI) processLink(ctx context.Context, linkres ft.LinkResult, settings *options.UnixfsLsSettings) (coreiface.DirEntry, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.UnixfsAPI", "ProcessLink")
defer span.End()
if linkres.Link != nil {
@@ -258,7 +257,7 @@ func (api *UnixfsAPI) processLink(ctx context.Context, linkres ft.LinkResult, se
}
if linkres.Err != nil {
- return coreiface.DirEntry{Err: linkres.Err}
+ return coreiface.DirEntry{}, linkres.Err
}
lnk := coreiface.DirEntry{
@@ -275,15 +274,13 @@ func (api *UnixfsAPI) processLink(ctx context.Context, linkres ft.LinkResult, se
if settings.ResolveChildren {
linkNode, err := linkres.Link.GetNode(ctx, api.dag)
if err != nil {
- lnk.Err = err
- break
+ return coreiface.DirEntry{}, err
}
if pn, ok := linkNode.(*merkledag.ProtoNode); ok {
d, err := ft.FSNodeFromBytes(pn.Data())
if err != nil {
- lnk.Err = err
- break
+ return coreiface.DirEntry{}, err
}
switch d.Type() {
case ft.TFile, ft.TRaw:
@@ -297,6 +294,8 @@ func (api *UnixfsAPI) processLink(ctx context.Context, linkres ft.LinkResult, se
if !settings.UseCumulativeSize {
lnk.Size = d.FileSize()
}
+ lnk.Mode = d.Mode()
+ lnk.ModTime = d.ModTime()
}
}
@@ -305,35 +304,50 @@ func (api *UnixfsAPI) processLink(ctx context.Context, linkres ft.LinkResult, se
}
}
- return lnk
+ return lnk, nil
}
-func (api *UnixfsAPI) lsFromLinksAsync(ctx context.Context, dir uio.Directory, settings *options.UnixfsLsSettings) (<-chan coreiface.DirEntry, error) {
- out := make(chan coreiface.DirEntry, uio.DefaultShardWidth)
+func (api *UnixfsAPI) lsFromDirLinks(ctx context.Context, dir uio.Directory, settings *options.UnixfsLsSettings, out chan<- coreiface.DirEntry) error {
+ for l := range dir.EnumLinksAsync(ctx) {
+ dirEnt, err := api.processLink(ctx, l, settings) // TODO: perf: processing can be done in background and in parallel
+ if err != nil {
+ return err
+ }
+ select {
+ case out <- dirEnt:
+ case <-ctx.Done():
+ return nil
+ }
+ }
+ return nil
+}
+func (api *UnixfsAPI) lsFromLinks(ctx context.Context, ndlinks []*ipld.Link, settings *options.UnixfsLsSettings, out chan<- coreiface.DirEntry) error {
+ // Create links channel large enough to not block when writing to out is slower.
+ links := make(chan coreiface.DirEntry, len(ndlinks))
+ errs := make(chan error, 1)
go func() {
- defer close(out)
- for l := range dir.EnumLinksAsync(ctx) {
+ defer close(links)
+ defer close(errs)
+ for _, l := range ndlinks {
+ lr := ft.LinkResult{Link: &ipld.Link{Name: l.Name, Size: l.Size, Cid: l.Cid}}
+ lnk, err := api.processLink(ctx, lr, settings) // TODO: can be parallel if settings.Async
+ if err != nil {
+ errs <- err
+ return
+ }
select {
- case out <- api.processLink(ctx, l, settings): // TODO: perf: processing can be done in background and in parallel
+ case links <- lnk:
case <-ctx.Done():
return
}
}
}()
- return out, nil
-}
-
-func (api *UnixfsAPI) lsFromLinks(ctx context.Context, ndlinks []*ipld.Link, settings *options.UnixfsLsSettings) (<-chan coreiface.DirEntry, error) {
- links := make(chan coreiface.DirEntry, len(ndlinks))
- for _, l := range ndlinks {
- lr := ft.LinkResult{Link: &ipld.Link{Name: l.Name, Size: l.Size, Cid: l.Cid}}
-
- links <- api.processLink(ctx, lr, settings) // TODO: can be parallel if settings.Async
+ for lnk := range links {
+ out <- lnk
}
- close(links)
- return links, nil
+ return <-errs
}
func (api *UnixfsAPI) core() *CoreAPI {
diff --git a/core/corehttp/commands.go b/core/corehttp/commands.go
index 4feef3359a2..14de87d08a1 100644
--- a/core/corehttp/commands.go
+++ b/core/corehttp/commands.go
@@ -9,7 +9,6 @@ import (
"strconv"
"strings"
- "github.com/ipfs/boxo/gateway"
cmds "github.com/ipfs/go-ipfs-cmds"
cmdsHttp "github.com/ipfs/go-ipfs-cmds/http"
version "github.com/ipfs/kubo"
@@ -122,16 +121,13 @@ func patchCORSVars(c *cmdsHttp.ServerConfig, addr net.Addr) {
c.SetAllowedOrigins(newOrigins...)
}
-func commandsOption(cctx oldcmds.Context, command *cmds.Command, allowGet bool) ServeOption {
+func commandsOption(cctx oldcmds.Context, command *cmds.Command) ServeOption {
return func(n *core.IpfsNode, l net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
cfg := cmdsHttp.NewServerConfig()
- cfg.AllowGet = allowGet
- corsAllowedMethods := []string{http.MethodPost}
- if allowGet {
- corsAllowedMethods = append(corsAllowedMethods, http.MethodGet)
- }
- cfg.SetAllowedMethods(corsAllowedMethods...)
+ cfg.AddAllowedHeaders("Origin", "Accept", "Content-Type", "X-Requested-With")
+ cfg.SetAllowedMethods(http.MethodPost)
+
cfg.APIPath = APIPath
rcfg, err := n.Repo.Config()
if err != nil {
@@ -150,13 +146,6 @@ func commandsOption(cctx oldcmds.Context, command *cmds.Command, allowGet bool)
cmdHandler = withAuthSecrets(authorizations, cmdHandler)
}
- // TODO[api-on-gw]: remove for Kubo 0.28
- if command == corecommands.RootRO && allowGet {
- cmdHandler = gateway.NewHeaders(map[string][]string{
- "Link": {`; rel="deprecation"; type="text/html"`},
- }).Wrap(cmdHandler)
- }
-
cmdHandler = otelhttp.NewHandler(cmdHandler, "corehttp.cmdsHandler")
mux.Handle(APIPath+"/", cmdHandler)
return mux, nil
@@ -211,13 +200,7 @@ func withAuthSecrets(authorizations map[string]rpcAuthScopeWithUser, next http.H
// CommandsOption constructs a ServerOption for hooking the commands into the
// HTTP server. It will NOT allow GET requests.
func CommandsOption(cctx oldcmds.Context) ServeOption {
- return commandsOption(cctx, corecommands.Root, false)
-}
-
-// CommandsROOption constructs a ServerOption for hooking the read-only commands
-// into the HTTP server. It will allow GET requests.
-func CommandsROOption(cctx oldcmds.Context) ServeOption {
- return commandsOption(cctx, corecommands.RootRO, true)
+ return commandsOption(cctx, corecommands.Root)
}
// CheckVersionOption returns a ServeOption that checks whether the client ipfs version matches. Does nothing when the user agent string does not contain `/kubo/` or `/go-ipfs/`
diff --git a/core/corehttp/corehttp.go b/core/corehttp/corehttp.go
index 6a9f43b5193..595a0aa5f9f 100644
--- a/core/corehttp/corehttp.go
+++ b/core/corehttp/corehttp.go
@@ -11,7 +11,7 @@ import (
"net/http"
"time"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
core "github.com/ipfs/kubo/core"
"github.com/jbenet/goprocess"
periodicproc "github.com/jbenet/goprocess/periodic"
diff --git a/core/corehttp/gateway.go b/core/corehttp/gateway.go
index 67e3c242d7b..6ac3818856d 100644
--- a/core/corehttp/gateway.go
+++ b/core/corehttp/gateway.go
@@ -235,7 +235,7 @@ func (o *offlineGatewayErrWrapper) GetDNSLinkRecord(ctx context.Context, s strin
var _ gateway.IPFSBackend = (*offlineGatewayErrWrapper)(nil)
-var defaultPaths = []string{"/ipfs/", "/ipns/", "/api/", "/p2p/"}
+var defaultPaths = []string{"/ipfs/", "/ipns/", "/p2p/"}
var subdomainGatewaySpec = &gateway.PublicGateway{
Paths: defaultPaths,
diff --git a/core/corehttp/logs.go b/core/corehttp/logs.go
index 944e62c5b64..fbdc94f6f82 100644
--- a/core/corehttp/logs.go
+++ b/core/corehttp/logs.go
@@ -1,57 +1,68 @@
package corehttp
import (
- "io"
+ "bufio"
+ "fmt"
"net"
"net/http"
- lwriter "github.com/ipfs/go-log/writer"
+ logging "github.com/ipfs/go-log/v2"
core "github.com/ipfs/kubo/core"
)
-type writeErrNotifier struct {
- w io.Writer
- errs chan error
-}
+func LogOption() ServeOption {
+ return func(n *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
+ mux.HandleFunc("/logs", func(w http.ResponseWriter, r *http.Request) {
+ // The log data comes from an io.Reader, and we need to constantly
+ // read from it and then write to the HTTP response.
+ pipeReader := logging.NewPipeReader()
+ done := make(chan struct{})
-func newWriteErrNotifier(w io.Writer) (io.WriteCloser, <-chan error) {
- ch := make(chan error, 1)
- return &writeErrNotifier{
- w: w,
- errs: ch,
- }, ch
-}
+ // Close the pipe reader if the request context is canceled. This
+ // is necessary to avoiding blocking on reading from the pipe
+ // reader when the client terminates the request.
+ go func() {
+ select {
+ case <-r.Context().Done(): // Client canceled request
+ case <-n.Context().Done(): // Node shutdown
+ case <-done: // log reader goroutine exitex
+ }
+ pipeReader.Close()
+ }()
-func (w *writeErrNotifier) Write(b []byte) (int, error) {
- n, err := w.w.Write(b)
- if err != nil {
- select {
- case w.errs <- err:
- default:
- }
- }
- if f, ok := w.w.(http.Flusher); ok {
- f.Flush()
- }
- return n, err
-}
+ errs := make(chan error, 1)
-func (w *writeErrNotifier) Close() error {
- select {
- case w.errs <- io.EOF:
- default:
- }
- return nil
-}
+ go func() {
+ defer close(errs)
+ defer close(done)
-func LogOption() ServeOption {
- return func(n *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
- mux.HandleFunc("/logs", func(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(200)
- wnf, errs := newWriteErrNotifier(w)
- lwriter.WriterGroup.AddWriter(wnf)
- log.Event(n.Context(), "log API client connected") //nolint deprecated
- <-errs
+ rdr := bufio.NewReader(pipeReader)
+ for {
+ // Read a line of log data and send it to the client.
+ line, err := rdr.ReadString('\n')
+ if err != nil {
+ errs <- fmt.Errorf("error reading log message: %s", err)
+ return
+ }
+ _, err = w.Write([]byte(line))
+ if err != nil {
+ // Failed to write to client, probably disconnected.
+ return
+ }
+ if f, ok := w.(http.Flusher); ok {
+ f.Flush()
+ }
+ if r.Context().Err() != nil {
+ return
+ }
+ }
+ }()
+ log.Info("log API client connected")
+ err := <-errs
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
})
return mux, nil
}
diff --git a/core/corehttp/webui.go b/core/corehttp/webui.go
index 5ec6edf1580..387a5b9ca72 100644
--- a/core/corehttp/webui.go
+++ b/core/corehttp/webui.go
@@ -1,11 +1,21 @@
package corehttp
-// TODO: move to IPNS
-const WebUIPath = "/ipfs/bafybeidf7cpkwsjkq6xs3r6fbbxghbugilx3jtezbza7gua3k5wjixpmba" // v4.2.0
+// WebUI version confirmed to work with this Kubo version
+const WebUIPath = "/ipfs/bafybeibfd5kbebqqruouji6ct5qku3tay273g7mt24mmrfzrsfeewaal5y" // v4.7.0
// WebUIPaths is a list of all past webUI paths.
var WebUIPaths = []string{
WebUIPath,
+ "/ipfs/bafybeibpaa5kqrj4gkemiswbwndjqiryl65cks64ypwtyerxixu56gnvvm", // v4.6.0
+ "/ipfs/bafybeiata4qg7xjtwgor6r5dw63jjxyouenyromrrb4lrewxrlvav7gzgi", // v4.5.0
+ "/ipfs/bafybeigp3zm7cqoiciqk5anlheenqjsgovp7j7zq6hah4nu6iugdgb4nby", // v4.4.2
+ "/ipfs/bafybeiatztgdllxnp5p6zu7bdwhjmozsmd7jprff4bdjqjljxtylitvss4", // v4.4.1
+ "/ipfs/bafybeibgic2ex3fvzkinhy6k6aqyv3zy2o7bkbsmrzvzka24xetv7eeadm",
+ "/ipfs/bafybeid4uxz7klxcu3ffsnmn64r7ihvysamlj4ohl5h2orjsffuegcpaeq",
+ "/ipfs/bafybeif6abowqcavbkz243biyh7pde7ick5kkwwytrh7pd2hkbtuqysjxy",
+ "/ipfs/bafybeihatzsgposbr3hrngo42yckdyqcc56yean2rynnwpzxstvdlphxf4",
+ "/ipfs/bafybeigggyffcf6yfhx5irtwzx3cgnk6n3dwylkvcpckzhqqrigsxowjwe",
+ "/ipfs/bafybeidf7cpkwsjkq6xs3r6fbbxghbugilx3jtezbza7gua3k5wjixpmba",
"/ipfs/bafybeiamycmd52xvg6k3nzr6z3n33de6a2teyhquhj4kspdtnvetnkrfim",
"/ipfs/bafybeieqdeoqkf7xf4aozd524qncgiloh33qgr25lyzrkusbcre4c3fxay",
"/ipfs/bafybeicyp7ssbnj3hdzehcibmapmpuc3atrsc4ch3q6acldfh4ojjdbcxe",
diff --git a/core/coreiface/coreapi.go b/core/coreiface/coreapi.go
index 4fd6851af33..dbb08dd7e9c 100644
--- a/core/coreiface/coreapi.go
+++ b/core/coreiface/coreapi.go
@@ -34,9 +34,6 @@ type CoreAPI interface {
// Object returns an implementation of Object API
Object() ObjectAPI
- // Dht returns an implementation of Dht API
- Dht() DhtAPI
-
// Swarm returns an implementation of Swarm API
Swarm() SwarmAPI
diff --git a/core/coreiface/dht.go b/core/coreiface/dht.go
deleted file mode 100644
index a916dbf3d37..00000000000
--- a/core/coreiface/dht.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package iface
-
-import (
- "context"
-
- "github.com/ipfs/boxo/path"
-
- "github.com/ipfs/kubo/core/coreiface/options"
-
- "github.com/libp2p/go-libp2p/core/peer"
-)
-
-// DhtAPI specifies the interface to the DHT
-// Note: This API will likely get deprecated in near future, see
-// https://github.com/ipfs/interface-ipfs-core/issues/249 for more context.
-type DhtAPI interface {
- // FindPeer queries the DHT for all of the multiaddresses associated with a
- // Peer ID
- FindPeer(context.Context, peer.ID) (peer.AddrInfo, error)
-
- // FindProviders finds peers in the DHT who can provide a specific value
- // given a key.
- FindProviders(context.Context, path.Path, ...options.DhtFindProvidersOption) (<-chan peer.AddrInfo, error)
-
- // Provide announces to the network that you are providing given values
- Provide(context.Context, path.Path, ...options.DhtProvideOption) error
-}
diff --git a/core/coreiface/object.go b/core/coreiface/object.go
index fa378ac6c46..27bb8893583 100644
--- a/core/coreiface/object.go
+++ b/core/coreiface/object.go
@@ -2,36 +2,11 @@ package iface
import (
"context"
- "io"
"github.com/ipfs/boxo/path"
"github.com/ipfs/kubo/core/coreiface/options"
-
- "github.com/ipfs/go-cid"
- ipld "github.com/ipfs/go-ipld-format"
)
-// ObjectStat provides information about dag nodes
-type ObjectStat struct {
- // Cid is the CID of the node
- Cid cid.Cid
-
- // NumLinks is number of links the node contains
- NumLinks int
-
- // BlockSize is size of the raw serialized node
- BlockSize int
-
- // LinksSize is size of the links block section
- LinksSize int
-
- // DataSize is the size of data block section
- DataSize int
-
- // CumulativeSize is size of the tree (BlockSize + link sizes)
- CumulativeSize int
-}
-
// ChangeType denotes type of change in ObjectChange
type ChangeType int
@@ -69,24 +44,6 @@ type ObjectChange struct {
// ObjectAPI specifies the interface to MerkleDAG and contains useful utilities
// for manipulating MerkleDAG data structures.
type ObjectAPI interface {
- // New creates new, empty (by default) dag-node.
- New(context.Context, ...options.ObjectNewOption) (ipld.Node, error)
-
- // Put imports the data into merkledag
- Put(context.Context, io.Reader, ...options.ObjectPutOption) (path.ImmutablePath, error)
-
- // Get returns the node for the path
- Get(context.Context, path.Path) (ipld.Node, error)
-
- // Data returns reader for data of the node
- Data(context.Context, path.Path) (io.Reader, error)
-
- // Links returns lint or links the node contains
- Links(context.Context, path.Path) ([]*ipld.Link, error)
-
- // Stat returns information about the node
- Stat(context.Context, path.Path) (*ObjectStat, error)
-
// AddLink adds a link under the specified path. child path can point to a
// subdirectory within the patent which must be present (can be overridden
// with WithCreate option).
@@ -95,12 +52,6 @@ type ObjectAPI interface {
// RmLink removes a link from the node
RmLink(ctx context.Context, base path.Path, link string) (path.ImmutablePath, error)
- // AppendData appends data to the node
- AppendData(context.Context, path.Path, io.Reader) (path.ImmutablePath, error)
-
- // SetData sets the data contained in the node
- SetData(context.Context, path.Path, io.Reader) (path.ImmutablePath, error)
-
// Diff returns a set of changes needed to transform the first object into the
// second.
Diff(context.Context, path.Path, path.Path) ([]ObjectChange, error)
diff --git a/core/coreiface/options/dht.go b/core/coreiface/options/dht.go
index b43bf3e7a75..4a6f7f86e76 100644
--- a/core/coreiface/options/dht.go
+++ b/core/coreiface/options/dht.go
@@ -1,64 +1,29 @@
package options
-type DhtProvideSettings struct {
- Recursive bool
-}
+// nolint deprecated
+// Deprecated: use [RoutingProvideSettings] instead.
+type DhtProvideSettings = RoutingProvideSettings
-type DhtFindProvidersSettings struct {
- NumProviders int
-}
+// nolint deprecated
+// Deprecated: use [RoutingFindProvidersSettings] instead.
+type DhtFindProvidersSettings = RoutingFindProvidersSettings
-type (
- DhtProvideOption func(*DhtProvideSettings) error
- DhtFindProvidersOption func(*DhtFindProvidersSettings) error
-)
+// nolint deprecated
+// Deprecated: use [RoutingProvideOption] instead.
+type DhtProvideOption = RoutingProvideOption
-func DhtProvideOptions(opts ...DhtProvideOption) (*DhtProvideSettings, error) {
- options := &DhtProvideSettings{
- Recursive: false,
- }
+// nolint deprecated
+// Deprecated: use [RoutingFindProvidersOption] instead.
+type DhtFindProvidersOption = RoutingFindProvidersOption
- for _, opt := range opts {
- err := opt(options)
- if err != nil {
- return nil, err
- }
- }
- return options, nil
-}
+// nolint deprecated
+// Deprecated: use [RoutingProvideOptions] instead.
+var DhtProvideOptions = RoutingProvideOptions
-func DhtFindProvidersOptions(opts ...DhtFindProvidersOption) (*DhtFindProvidersSettings, error) {
- options := &DhtFindProvidersSettings{
- NumProviders: 20,
- }
+// nolint deprecated
+// Deprecated: use [RoutingFindProvidersOptions] instead.
+var DhtFindProvidersOptions = RoutingFindProvidersOptions
- for _, opt := range opts {
- err := opt(options)
- if err != nil {
- return nil, err
- }
- }
- return options, nil
-}
-
-type dhtOpts struct{}
-
-var Dht dhtOpts
-
-// Recursive is an option for Dht.Provide which specifies whether to provide
-// the given path recursively
-func (dhtOpts) Recursive(recursive bool) DhtProvideOption {
- return func(settings *DhtProvideSettings) error {
- settings.Recursive = recursive
- return nil
- }
-}
-
-// NumProviders is an option for Dht.FindProviders which specifies the
-// number of peers to look for. Default is 20
-func (dhtOpts) NumProviders(numProviders int) DhtFindProvidersOption {
- return func(settings *DhtFindProvidersSettings) error {
- settings.NumProviders = numProviders
- return nil
- }
-}
+// nolint deprecated
+// Deprecated: use [Routing] instead.
+var Dht = Routing
diff --git a/core/coreiface/options/object.go b/core/coreiface/options/object.go
index b5625a1d61c..ab780ebd988 100644
--- a/core/coreiface/options/object.go
+++ b/core/coreiface/options/object.go
@@ -1,55 +1,13 @@
package options
-type ObjectNewSettings struct {
- Type string
-}
-
-type ObjectPutSettings struct {
- InputEnc string
- DataType string
- Pin bool
-}
-
type ObjectAddLinkSettings struct {
Create bool
}
type (
- ObjectNewOption func(*ObjectNewSettings) error
- ObjectPutOption func(*ObjectPutSettings) error
ObjectAddLinkOption func(*ObjectAddLinkSettings) error
)
-func ObjectNewOptions(opts ...ObjectNewOption) (*ObjectNewSettings, error) {
- options := &ObjectNewSettings{
- Type: "empty",
- }
-
- for _, opt := range opts {
- err := opt(options)
- if err != nil {
- return nil, err
- }
- }
- return options, nil
-}
-
-func ObjectPutOptions(opts ...ObjectPutOption) (*ObjectPutSettings, error) {
- options := &ObjectPutSettings{
- InputEnc: "json",
- DataType: "text",
- Pin: false,
- }
-
- for _, opt := range opts {
- err := opt(options)
- if err != nil {
- return nil, err
- }
- }
- return options, nil
-}
-
func ObjectAddLinkOptions(opts ...ObjectAddLinkOption) (*ObjectAddLinkSettings, error) {
options := &ObjectAddLinkSettings{
Create: false,
@@ -68,54 +26,6 @@ type objectOpts struct{}
var Object objectOpts
-// Type is an option for Object.New which allows to change the type of created
-// dag node.
-//
-// Supported types:
-// * 'empty' - Empty node
-// * 'unixfs-dir' - Empty UnixFS directory
-func (objectOpts) Type(t string) ObjectNewOption {
- return func(settings *ObjectNewSettings) error {
- settings.Type = t
- return nil
- }
-}
-
-// InputEnc is an option for Object.Put which specifies the input encoding of the
-// data. Default is "json".
-//
-// Supported encodings:
-// * "protobuf"
-// * "json"
-func (objectOpts) InputEnc(e string) ObjectPutOption {
- return func(settings *ObjectPutSettings) error {
- settings.InputEnc = e
- return nil
- }
-}
-
-// DataType is an option for Object.Put which specifies the encoding of data
-// field when using Json or XML input encoding.
-//
-// Supported types:
-// * "text" (default)
-// * "base64"
-func (objectOpts) DataType(t string) ObjectPutOption {
- return func(settings *ObjectPutSettings) error {
- settings.DataType = t
- return nil
- }
-}
-
-// Pin is an option for Object.Put which specifies whether to pin the added
-// objects, default is false
-func (objectOpts) Pin(pin bool) ObjectPutOption {
- return func(settings *ObjectPutSettings) error {
- settings.Pin = pin
- return nil
- }
-}
-
// Create is an option for Object.AddLink which specifies whether create required
// directories for the child
func (objectOpts) Create(create bool) ObjectAddLinkOption {
diff --git a/core/coreiface/options/pin.go b/core/coreiface/options/pin.go
index 0efd853ef22..5b4cc9de7ec 100644
--- a/core/coreiface/options/pin.go
+++ b/core/coreiface/options/pin.go
@@ -12,6 +12,7 @@ type PinAddSettings struct {
type PinLsSettings struct {
Type string
Detailed bool
+ Name string
}
// PinIsPinnedSettings represent the settings for PinAPI.IsPinned
@@ -205,6 +206,13 @@ func (pinLsOpts) Detailed(detailed bool) PinLsOption {
}
}
+func (pinLsOpts) Name(name string) PinLsOption {
+ return func(settings *PinLsSettings) error {
+ settings.Name = name
+ return nil
+ }
+}
+
type pinIsPinnedOpts struct{}
// All is an option for Pin.IsPinned which will make it search in all type of pins.
diff --git a/core/coreiface/options/routing.go b/core/coreiface/options/routing.go
index d66d44a0dbd..8da7e7a1db2 100644
--- a/core/coreiface/options/routing.go
+++ b/core/coreiface/options/routing.go
@@ -21,13 +21,76 @@ func RoutingPutOptions(opts ...RoutingPutOption) (*RoutingPutSettings, error) {
return options, nil
}
-type putOpts struct{}
+// nolint deprecated
+// Deprecated: use [Routing] instead.
+var Put = Routing
-var Put putOpts
+type RoutingProvideSettings struct {
+ Recursive bool
+}
+
+type RoutingFindProvidersSettings struct {
+ NumProviders int
+}
+
+type (
+ RoutingProvideOption func(*DhtProvideSettings) error
+ RoutingFindProvidersOption func(*DhtFindProvidersSettings) error
+)
+
+func RoutingProvideOptions(opts ...RoutingProvideOption) (*RoutingProvideSettings, error) {
+ options := &RoutingProvideSettings{
+ Recursive: false,
+ }
+
+ for _, opt := range opts {
+ err := opt(options)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return options, nil
+}
+
+func RoutingFindProvidersOptions(opts ...RoutingFindProvidersOption) (*RoutingFindProvidersSettings, error) {
+ options := &RoutingFindProvidersSettings{
+ NumProviders: 20,
+ }
+
+ for _, opt := range opts {
+ err := opt(options)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return options, nil
+}
+
+type routingOpts struct{}
+
+var Routing routingOpts
+
+// Recursive is an option for [Routing.Provide] which specifies whether to provide
+// the given path recursively.
+func (routingOpts) Recursive(recursive bool) RoutingProvideOption {
+ return func(settings *DhtProvideSettings) error {
+ settings.Recursive = recursive
+ return nil
+ }
+}
+
+// NumProviders is an option for [Routing.FindProviders] which specifies the
+// number of peers to look for. Default is 20.
+func (routingOpts) NumProviders(numProviders int) RoutingFindProvidersOption {
+ return func(settings *DhtFindProvidersSettings) error {
+ settings.NumProviders = numProviders
+ return nil
+ }
+}
-// AllowOffline is an option for Routing.Put which specifies whether to allow
+// AllowOffline is an option for [Routing.Put] which specifies whether to allow
// publishing when the node is offline. Default value is false
-func (putOpts) AllowOffline(allow bool) RoutingPutOption {
+func (routingOpts) AllowOffline(allow bool) RoutingPutOption {
return func(settings *RoutingPutSettings) error {
settings.AllowOffline = allow
return nil
diff --git a/core/coreiface/options/unixfs.go b/core/coreiface/options/unixfs.go
index f00fffb87b0..20f18d1e04c 100644
--- a/core/coreiface/options/unixfs.go
+++ b/core/coreiface/options/unixfs.go
@@ -3,8 +3,12 @@ package options
import (
"errors"
"fmt"
+ "os"
+ "time"
dag "github.com/ipfs/boxo/ipld/merkledag"
+ "github.com/ipfs/boxo/ipld/unixfs/importer/helpers"
+ "github.com/ipfs/boxo/ipld/unixfs/io"
cid "github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"
)
@@ -20,10 +24,16 @@ type UnixfsAddSettings struct {
CidVersion int
MhType uint64
- Inline bool
- InlineLimit int
- RawLeaves bool
- RawLeavesSet bool
+ Inline bool
+ InlineLimit int
+ RawLeaves bool
+ RawLeavesSet bool
+ MaxFileLinks int
+ MaxFileLinksSet bool
+ MaxDirectoryLinks int
+ MaxDirectoryLinksSet bool
+ MaxHAMTFanout int
+ MaxHAMTFanoutSet bool
Chunker string
Layout Layout
@@ -36,6 +46,11 @@ type UnixfsAddSettings struct {
Events chan<- interface{}
Silent bool
Progress bool
+
+ PreserveMode bool
+ PreserveMtime bool
+ Mode os.FileMode
+ Mtime time.Time
}
type UnixfsLsSettings struct {
@@ -53,10 +68,16 @@ func UnixfsAddOptions(opts ...UnixfsAddOption) (*UnixfsAddSettings, cid.Prefix,
CidVersion: -1,
MhType: mh.SHA2_256,
- Inline: false,
- InlineLimit: 32,
- RawLeaves: false,
- RawLeavesSet: false,
+ Inline: false,
+ InlineLimit: 32,
+ RawLeaves: false,
+ RawLeavesSet: false,
+ MaxFileLinks: helpers.DefaultLinksPerBlock,
+ MaxFileLinksSet: false,
+ MaxDirectoryLinks: 0,
+ MaxDirectoryLinksSet: false,
+ MaxHAMTFanout: io.DefaultShardWidth,
+ MaxHAMTFanoutSet: false,
Chunker: "size-262144",
Layout: BalancedLayout,
@@ -69,6 +90,11 @@ func UnixfsAddOptions(opts ...UnixfsAddOption) (*UnixfsAddSettings, cid.Prefix,
Events: nil,
Silent: false,
Progress: false,
+
+ PreserveMode: false,
+ PreserveMtime: false,
+ Mode: 0,
+ Mtime: time.Time{},
}
for _, opt := range opts {
@@ -106,6 +132,14 @@ func UnixfsAddOptions(opts ...UnixfsAddOption) (*UnixfsAddSettings, cid.Prefix,
}
}
+ if !options.Mtime.IsZero() && options.PreserveMtime {
+ options.PreserveMtime = false
+ }
+
+ if options.Mode != 0 && options.PreserveMode {
+ options.PreserveMode = false
+ }
+
// cidV1 -> raw blocks (by default)
if options.CidVersion > 0 && !options.RawLeavesSet {
options.RawLeaves = true
@@ -170,6 +204,35 @@ func (unixfsOpts) RawLeaves(enable bool) UnixfsAddOption {
}
}
+// MaxFileLinks specifies the maximum number of children for UnixFS file
+// nodes.
+func (unixfsOpts) MaxFileLinks(n int) UnixfsAddOption {
+ return func(settings *UnixfsAddSettings) error {
+ settings.MaxFileLinks = n
+ settings.MaxFileLinksSet = true
+ return nil
+ }
+}
+
+// MaxDirectoryLinks specifies the maximum number of children for UnixFS basic
+// directory nodes.
+func (unixfsOpts) MaxDirectoryLinks(n int) UnixfsAddOption {
+ return func(settings *UnixfsAddSettings) error {
+ settings.MaxDirectoryLinks = n
+ settings.MaxDirectoryLinksSet = true
+ return nil
+ }
+}
+
+// MaxHAMTFanout specifies the maximum width of the HAMT directory shards.
+func (unixfsOpts) MaxHAMTFanout(n int) UnixfsAddOption {
+ return func(settings *UnixfsAddSettings) error {
+ settings.MaxHAMTFanout = n
+ settings.MaxHAMTFanoutSet = true
+ return nil
+ }
+}
+
// Inline tells the adder to inline small blocks into CIDs
func (unixfsOpts) Inline(enable bool) UnixfsAddOption {
return func(settings *UnixfsAddSettings) error {
@@ -293,3 +356,38 @@ func (unixfsOpts) UseCumulativeSize(use bool) UnixfsLsOption {
return nil
}
}
+
+// PreserveMode tells the adder to store the file permissions
+func (unixfsOpts) PreserveMode(enable bool) UnixfsAddOption {
+ return func(settings *UnixfsAddSettings) error {
+ settings.PreserveMode = enable
+ return nil
+ }
+}
+
+// PreserveMtime tells the adder to store the file modification time
+func (unixfsOpts) PreserveMtime(enable bool) UnixfsAddOption {
+ return func(settings *UnixfsAddSettings) error {
+ settings.PreserveMtime = enable
+ return nil
+ }
+}
+
+// Mode represents a unix file mode
+func (unixfsOpts) Mode(mode os.FileMode) UnixfsAddOption {
+ return func(settings *UnixfsAddSettings) error {
+ settings.Mode = mode
+ return nil
+ }
+}
+
+// Mtime represents a unix file mtime
+func (unixfsOpts) Mtime(seconds int64, nsecs uint32) UnixfsAddOption {
+ return func(settings *UnixfsAddSettings) error {
+ if nsecs > 999999999 {
+ return errors.New("mtime nanoseconds must be in range [1, 999999999]")
+ }
+ settings.Mtime = time.Unix(seconds, int64(nsecs))
+ return nil
+ }
+}
diff --git a/core/coreiface/pin.go b/core/coreiface/pin.go
index ed837fc9ce2..e0fd2fb90ed 100644
--- a/core/coreiface/pin.go
+++ b/core/coreiface/pin.go
@@ -18,9 +18,6 @@ type Pin interface {
// Type of the pin
Type() string
-
- // if not nil, an error happened. Everything else should be ignored.
- Err() error
}
// PinStatus holds information about pin health
@@ -50,8 +47,9 @@ type PinAPI interface {
// tree
Add(context.Context, path.Path, ...options.PinAddOption) error
- // Ls returns list of pinned objects on this node
- Ls(context.Context, ...options.PinLsOption) (<-chan Pin, error)
+ // Ls returns this node's pinned objects on the provided channel. The
+ // channel is closed when there are no more pins and an error is returned.
+ Ls(context.Context, chan<- Pin, ...options.PinLsOption) error
// IsPinned returns whether or not the given cid is pinned
// and an explanation of why its pinned
diff --git a/core/coreiface/routing.go b/core/coreiface/routing.go
index c64e7baef9c..a17dfcad920 100644
--- a/core/coreiface/routing.go
+++ b/core/coreiface/routing.go
@@ -3,7 +3,9 @@ package iface
import (
"context"
+ "github.com/ipfs/boxo/path"
"github.com/ipfs/kubo/core/coreiface/options"
+ "github.com/libp2p/go-libp2p/core/peer"
)
// RoutingAPI specifies the interface to the routing layer.
@@ -13,4 +15,15 @@ type RoutingAPI interface {
// Put sets a value for a given key
Put(ctx context.Context, key string, value []byte, opts ...options.RoutingPutOption) error
+
+ // FindPeer queries the routing system for all the multiaddresses associated
+ // with the given [peer.ID].
+ FindPeer(context.Context, peer.ID) (peer.AddrInfo, error)
+
+ // FindProviders finds the peers in the routing system who can provide a specific
+ // value given a key.
+ FindProviders(context.Context, path.Path, ...options.RoutingFindProvidersOption) (<-chan peer.AddrInfo, error)
+
+ // Provide announces to the network that you are providing given values
+ Provide(context.Context, path.Path, ...options.RoutingProvideOption) error
}
diff --git a/core/coreiface/tests/api.go b/core/coreiface/tests/api.go
index c1fcb672df1..86ab60ae910 100644
--- a/core/coreiface/tests/api.go
+++ b/core/coreiface/tests/api.go
@@ -75,7 +75,6 @@ func TestApi(p Provider) func(t *testing.T) {
return func(t *testing.T) {
t.Run("Block", tp.TestBlock)
t.Run("Dag", tp.TestDag)
- t.Run("Dht", tp.TestDht)
t.Run("Key", tp.TestKey)
t.Run("Name", tp.TestName)
t.Run("Object", tp.TestObject)
diff --git a/core/coreiface/tests/block.go b/core/coreiface/tests/block.go
index 3b4ca0bc05d..2b5a68a63b8 100644
--- a/core/coreiface/tests/block.go
+++ b/core/coreiface/tests/block.go
@@ -323,9 +323,17 @@ func (tp *TestSuite) TestBlockPin(t *testing.T) {
t.Fatal(err)
}
- if pins, err := api.Pin().Ls(ctx); err != nil || len(pins) != 0 {
+ pinCh := make(chan coreiface.Pin)
+ go func() {
+ err = api.Pin().Ls(ctx, pinCh)
+ }()
+
+ for range pinCh {
t.Fatal("expected 0 pins")
}
+ if err != nil {
+ t.Fatal(err)
+ }
res, err := api.Block().Put(
ctx,
@@ -337,7 +345,7 @@ func (tp *TestSuite) TestBlockPin(t *testing.T) {
t.Fatal(err)
}
- pins, err := accPins(api.Pin().Ls(ctx))
+ pins, err := accPins(ctx, api)
if err != nil {
t.Fatal(err)
}
diff --git a/core/coreiface/tests/dht.go b/core/coreiface/tests/dht.go
deleted file mode 100644
index 6a908c5d331..00000000000
--- a/core/coreiface/tests/dht.go
+++ /dev/null
@@ -1,166 +0,0 @@
-package tests
-
-import (
- "context"
- "io"
- "testing"
- "time"
-
- iface "github.com/ipfs/kubo/core/coreiface"
- "github.com/ipfs/kubo/core/coreiface/options"
-)
-
-func (tp *TestSuite) TestDht(t *testing.T) {
- tp.hasApi(t, func(api iface.CoreAPI) error {
- if api.Dht() == nil {
- return errAPINotImplemented
- }
- return nil
- })
-
- t.Run("TestDhtFindPeer", tp.TestDhtFindPeer)
- t.Run("TestDhtFindProviders", tp.TestDhtFindProviders)
- t.Run("TestDhtProvide", tp.TestDhtProvide)
-}
-
-func (tp *TestSuite) TestDhtFindPeer(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- apis, err := tp.MakeAPISwarm(t, ctx, 5)
- if err != nil {
- t.Fatal(err)
- }
-
- self0, err := apis[0].Key().Self(ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- laddrs0, err := apis[0].Swarm().LocalAddrs(ctx)
- if err != nil {
- t.Fatal(err)
- }
- if len(laddrs0) != 1 {
- t.Fatal("unexpected number of local addrs")
- }
-
- time.Sleep(3 * time.Second)
-
- pi, err := apis[2].Dht().FindPeer(ctx, self0.ID())
- if err != nil {
- t.Fatal(err)
- }
-
- if pi.Addrs[0].String() != laddrs0[0].String() {
- t.Errorf("got unexpected address from FindPeer: %s", pi.Addrs[0].String())
- }
-
- self2, err := apis[2].Key().Self(ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- pi, err = apis[1].Dht().FindPeer(ctx, self2.ID())
- if err != nil {
- t.Fatal(err)
- }
-
- laddrs2, err := apis[2].Swarm().LocalAddrs(ctx)
- if err != nil {
- t.Fatal(err)
- }
- if len(laddrs2) != 1 {
- t.Fatal("unexpected number of local addrs")
- }
-
- if pi.Addrs[0].String() != laddrs2[0].String() {
- t.Errorf("got unexpected address from FindPeer: %s", pi.Addrs[0].String())
- }
-}
-
-func (tp *TestSuite) TestDhtFindProviders(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- apis, err := tp.MakeAPISwarm(t, ctx, 5)
- if err != nil {
- t.Fatal(err)
- }
-
- p, err := addTestObject(ctx, apis[0])
- if err != nil {
- t.Fatal(err)
- }
-
- time.Sleep(3 * time.Second)
-
- out, err := apis[2].Dht().FindProviders(ctx, p, options.Dht.NumProviders(1))
- if err != nil {
- t.Fatal(err)
- }
-
- provider := <-out
-
- self0, err := apis[0].Key().Self(ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- if provider.ID.String() != self0.ID().String() {
- t.Errorf("got wrong provider: %s != %s", provider.ID.String(), self0.ID().String())
- }
-}
-
-func (tp *TestSuite) TestDhtProvide(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- apis, err := tp.MakeAPISwarm(t, ctx, 5)
- if err != nil {
- t.Fatal(err)
- }
-
- off0, err := apis[0].WithOptions(options.Api.Offline(true))
- if err != nil {
- t.Fatal(err)
- }
-
- s, err := off0.Block().Put(ctx, &io.LimitedReader{R: rnd, N: 4092})
- if err != nil {
- t.Fatal(err)
- }
-
- p := s.Path()
-
- time.Sleep(3 * time.Second)
-
- out, err := apis[2].Dht().FindProviders(ctx, p, options.Dht.NumProviders(1))
- if err != nil {
- t.Fatal(err)
- }
-
- _, ok := <-out
-
- if ok {
- t.Fatal("did not expect to find any providers")
- }
-
- self0, err := apis[0].Key().Self(ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- err = apis[0].Dht().Provide(ctx, p)
- if err != nil {
- t.Fatal(err)
- }
-
- out, err = apis[2].Dht().FindProviders(ctx, p, options.Dht.NumProviders(1))
- if err != nil {
- t.Fatal(err)
- }
-
- provider := <-out
-
- if provider.ID.String() != self0.ID().String() {
- t.Errorf("got wrong provider: %s != %s", provider.ID.String(), self0.ID().String())
- }
-}
diff --git a/core/coreiface/tests/object.go b/core/coreiface/tests/object.go
index 9e0463ab690..239b022e14f 100644
--- a/core/coreiface/tests/object.go
+++ b/core/coreiface/tests/object.go
@@ -1,15 +1,15 @@
package tests
import (
- "bytes"
"context"
- "encoding/hex"
- "io"
- "strings"
"testing"
+ dag "github.com/ipfs/boxo/ipld/merkledag"
+ "github.com/ipfs/boxo/path"
+ ipld "github.com/ipfs/go-ipld-format"
iface "github.com/ipfs/kubo/core/coreiface"
opt "github.com/ipfs/kubo/core/coreiface/options"
+ "github.com/stretchr/testify/require"
)
func (tp *TestSuite) TestObject(t *testing.T) {
@@ -20,448 +20,125 @@ func (tp *TestSuite) TestObject(t *testing.T) {
return nil
})
- t.Run("TestNew", tp.TestNew)
- t.Run("TestObjectPut", tp.TestObjectPut)
- t.Run("TestObjectGet", tp.TestObjectGet)
- t.Run("TestObjectData", tp.TestObjectData)
- t.Run("TestObjectLinks", tp.TestObjectLinks)
- t.Run("TestObjectStat", tp.TestObjectStat)
t.Run("TestObjectAddLink", tp.TestObjectAddLink)
t.Run("TestObjectAddLinkCreate", tp.TestObjectAddLinkCreate)
t.Run("TestObjectRmLink", tp.TestObjectRmLink)
- t.Run("TestObjectAddData", tp.TestObjectAddData)
- t.Run("TestObjectSetData", tp.TestObjectSetData)
t.Run("TestDiffTest", tp.TestDiffTest)
}
-func (tp *TestSuite) TestNew(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- api, err := tp.makeAPI(t, ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- emptyNode, err := api.Object().New(ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- dirNode, err := api.Object().New(ctx, opt.Object.Type("unixfs-dir"))
- if err != nil {
- t.Fatal(err)
- }
-
- if emptyNode.String() != "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n" {
- t.Errorf("Unexpected emptyNode path: %s", emptyNode.String())
- }
-
- if dirNode.String() != "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn" {
- t.Errorf("Unexpected dirNode path: %s", dirNode.String())
- }
-}
-
-func (tp *TestSuite) TestObjectPut(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- api, err := tp.makeAPI(t, ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
- if err != nil {
- t.Fatal(err)
- }
-
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"YmFy"}`), opt.Object.DataType("base64")) // bar
- if err != nil {
- t.Fatal(err)
- }
-
- pbBytes, err := hex.DecodeString("0a0362617a")
- if err != nil {
- t.Fatal(err)
- }
-
- p3, err := api.Object().Put(ctx, bytes.NewReader(pbBytes), opt.Object.InputEnc("protobuf"))
- if err != nil {
- t.Fatal(err)
- }
-
- if p1.String() != "/ipfs/QmQeGyS87nyijii7kFt1zbe4n2PsXTFimzsdxyE9qh9TST" {
- t.Errorf("unexpected path: %s", p1.String())
- }
-
- if p2.String() != "/ipfs/QmNeYRbCibmaMMK6Du6ChfServcLqFvLJF76PzzF76SPrZ" {
- t.Errorf("unexpected path: %s", p2.String())
- }
-
- if p3.String() != "/ipfs/QmZreR7M2t7bFXAdb1V5FtQhjk4t36GnrvueLJowJbQM9m" {
- t.Errorf("unexpected path: %s", p3.String())
- }
-}
-
-func (tp *TestSuite) TestObjectGet(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- api, err := tp.makeAPI(t, ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
- if err != nil {
- t.Fatal(err)
- }
-
- nd, err := api.Object().Get(ctx, p1)
- if err != nil {
- t.Fatal(err)
- }
-
- if string(nd.RawData()[len(nd.RawData())-3:]) != "foo" {
- t.Fatal("got non-matching data")
- }
-}
-
-func (tp *TestSuite) TestObjectData(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- api, err := tp.makeAPI(t, ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
- if err != nil {
- t.Fatal(err)
- }
-
- r, err := api.Object().Data(ctx, p1)
- if err != nil {
- t.Fatal(err)
- }
-
- data, err := io.ReadAll(r)
- if err != nil {
- t.Fatal(err)
- }
-
- if string(data) != "foo" {
- t.Fatal("got non-matching data")
- }
-}
-
-func (tp *TestSuite) TestObjectLinks(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- api, err := tp.makeAPI(t, ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
- if err != nil {
- t.Fatal(err)
- }
-
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Links":[{"Name":"bar", "Hash":"`+p1.RootCid().String()+`"}]}`))
- if err != nil {
- t.Fatal(err)
- }
-
- links, err := api.Object().Links(ctx, p2)
- if err != nil {
- t.Fatal(err)
- }
-
- if len(links) != 1 {
- t.Errorf("unexpected number of links: %d", len(links))
- }
-
- if links[0].Cid.String() != p1.RootCid().String() {
- t.Fatal("cids didn't batch")
- }
-
- if links[0].Name != "bar" {
- t.Fatal("unexpected link name")
- }
-}
-
-func (tp *TestSuite) TestObjectStat(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- api, err := tp.makeAPI(t, ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
- if err != nil {
- t.Fatal(err)
- }
-
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bazz", "Links":[{"Name":"bar", "Hash":"`+p1.RootCid().String()+`", "Size":3}]}`))
- if err != nil {
- t.Fatal(err)
- }
-
- stat, err := api.Object().Stat(ctx, p2)
- if err != nil {
- t.Fatal(err)
- }
+func putDagPbNode(t *testing.T, ctx context.Context, api iface.CoreAPI, data string, links []*ipld.Link) path.ImmutablePath {
+ dagnode := new(dag.ProtoNode)
- if stat.Cid.String() != p2.RootCid().String() {
- t.Error("unexpected stat.Cid")
+ if data != "" {
+ dagnode.SetData([]byte(data))
}
- if stat.NumLinks != 1 {
- t.Errorf("unexpected stat.NumLinks")
+ if links != nil {
+ err := dagnode.SetLinks(links)
+ require.NoError(t, err)
}
- if stat.BlockSize != 51 {
- t.Error("unexpected stat.BlockSize")
- }
-
- if stat.LinksSize != 47 {
- t.Errorf("unexpected stat.LinksSize: %d", stat.LinksSize)
- }
+ err := api.Dag().Add(ctx, dagnode)
+ require.NoError(t, err)
- if stat.DataSize != 4 {
- t.Error("unexpected stat.DataSize")
- }
-
- if stat.CumulativeSize != 54 {
- t.Error("unexpected stat.DataSize")
- }
+ return path.FromCid(dagnode.Cid())
}
func (tp *TestSuite) TestObjectAddLink(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
api, err := tp.makeAPI(t, ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
- if err != nil {
- t.Fatal(err)
- }
-
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bazz", "Links":[{"Name":"bar", "Hash":"`+p1.RootCid().String()+`", "Size":3}]}`))
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
+
+ p1 := putDagPbNode(t, ctx, api, "foo", nil)
+ p2 := putDagPbNode(t, ctx, api, "bazz", []*ipld.Link{
+ {
+ Name: "bar",
+ Cid: p1.RootCid(),
+ Size: 3,
+ },
+ })
p3, err := api.Object().AddLink(ctx, p2, "abc", p2)
- if err != nil {
- t.Fatal(err)
- }
-
- links, err := api.Object().Links(ctx, p3)
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
- if len(links) != 2 {
- t.Errorf("unexpected number of links: %d", len(links))
- }
+ nd, err := api.Dag().Get(ctx, p3.RootCid())
+ require.NoError(t, err)
- if links[0].Name != "abc" {
- t.Errorf("unexpected link 0 name: %s", links[0].Name)
- }
-
- if links[1].Name != "bar" {
- t.Errorf("unexpected link 1 name: %s", links[1].Name)
- }
+ links := nd.Links()
+ require.Len(t, links, 2)
+ require.Equal(t, "abc", links[0].Name)
+ require.Equal(t, "bar", links[1].Name)
}
func (tp *TestSuite) TestObjectAddLinkCreate(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
api, err := tp.makeAPI(t, ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
- if err != nil {
- t.Fatal(err)
- }
-
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bazz", "Links":[{"Name":"bar", "Hash":"`+p1.RootCid().String()+`", "Size":3}]}`))
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
+
+ p1 := putDagPbNode(t, ctx, api, "foo", nil)
+ p2 := putDagPbNode(t, ctx, api, "bazz", []*ipld.Link{
+ {
+ Name: "bar",
+ Cid: p1.RootCid(),
+ Size: 3,
+ },
+ })
_, err = api.Object().AddLink(ctx, p2, "abc/d", p2)
- if err == nil {
- t.Fatal("expected an error")
- }
- if !strings.Contains(err.Error(), "no link by that name") {
- t.Fatalf("unexpected error: %s", err.Error())
- }
+ require.ErrorContains(t, err, "no link by that name")
p3, err := api.Object().AddLink(ctx, p2, "abc/d", p2, opt.Object.Create(true))
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
- links, err := api.Object().Links(ctx, p3)
- if err != nil {
- t.Fatal(err)
- }
-
- if len(links) != 2 {
- t.Errorf("unexpected number of links: %d", len(links))
- }
-
- if links[0].Name != "abc" {
- t.Errorf("unexpected link 0 name: %s", links[0].Name)
- }
+ nd, err := api.Dag().Get(ctx, p3.RootCid())
+ require.NoError(t, err)
- if links[1].Name != "bar" {
- t.Errorf("unexpected link 1 name: %s", links[1].Name)
- }
+ links := nd.Links()
+ require.Len(t, links, 2)
+ require.Equal(t, "abc", links[0].Name)
+ require.Equal(t, "bar", links[1].Name)
}
func (tp *TestSuite) TestObjectRmLink(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
api, err := tp.makeAPI(t, ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
- if err != nil {
- t.Fatal(err)
- }
-
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bazz", "Links":[{"Name":"bar", "Hash":"`+p1.RootCid().String()+`", "Size":3}]}`))
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
+
+ p1 := putDagPbNode(t, ctx, api, "foo", nil)
+ p2 := putDagPbNode(t, ctx, api, "bazz", []*ipld.Link{
+ {
+ Name: "bar",
+ Cid: p1.RootCid(),
+ Size: 3,
+ },
+ })
p3, err := api.Object().RmLink(ctx, p2, "bar")
- if err != nil {
- t.Fatal(err)
- }
-
- links, err := api.Object().Links(ctx, p3)
- if err != nil {
- t.Fatal(err)
- }
-
- if len(links) != 0 {
- t.Errorf("unexpected number of links: %d", len(links))
- }
-}
-
-func (tp *TestSuite) TestObjectAddData(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- api, err := tp.makeAPI(t, ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
- if err != nil {
- t.Fatal(err)
- }
-
- p2, err := api.Object().AppendData(ctx, p1, strings.NewReader("bar"))
- if err != nil {
- t.Fatal(err)
- }
-
- r, err := api.Object().Data(ctx, p2)
- if err != nil {
- t.Fatal(err)
- }
-
- data, err := io.ReadAll(r)
- if err != nil {
- t.Fatal(err)
- }
-
- if string(data) != "foobar" {
- t.Error("unexpected data")
- }
-}
-
-func (tp *TestSuite) TestObjectSetData(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- api, err := tp.makeAPI(t, ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
- p2, err := api.Object().SetData(ctx, p1, strings.NewReader("bar"))
- if err != nil {
- t.Fatal(err)
- }
-
- r, err := api.Object().Data(ctx, p2)
- if err != nil {
- t.Fatal(err)
- }
+ nd, err := api.Dag().Get(ctx, p3.RootCid())
+ require.NoError(t, err)
- data, err := io.ReadAll(r)
- if err != nil {
- t.Fatal(err)
- }
-
- if string(data) != "bar" {
- t.Error("unexpected data")
- }
+ links := nd.Links()
+ require.Len(t, links, 0)
}
func (tp *TestSuite) TestDiffTest(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
api, err := tp.makeAPI(t, ctx)
- if err != nil {
- t.Fatal(err)
- }
-
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bar"}`))
- if err != nil {
- t.Fatal(err)
- }
+ p1 := putDagPbNode(t, ctx, api, "foo", nil)
+ p2 := putDagPbNode(t, ctx, api, "bar", nil)
changes, err := api.Object().Diff(ctx, p1, p2)
- if err != nil {
- t.Fatal(err)
- }
-
- if len(changes) != 1 {
- t.Fatal("unexpected changes len")
- }
-
- if changes[0].Type != iface.DiffMod {
- t.Fatal("unexpected change type")
- }
-
- if changes[0].Before.String() != p1.String() {
- t.Fatal("unexpected before path")
- }
-
- if changes[0].After.String() != p2.String() {
- t.Fatal("unexpected before path")
- }
+ require.NoError(t, err)
+ require.Len(t, changes, 1)
+ require.Equal(t, iface.DiffMod, changes[0].Type)
+ require.Equal(t, p1.String(), changes[0].Before.String())
+ require.Equal(t, p2.String(), changes[0].After.String())
}
diff --git a/core/coreiface/tests/pin.go b/core/coreiface/tests/pin.go
index fdd7c15ccbf..4c606323fec 100644
--- a/core/coreiface/tests/pin.go
+++ b/core/coreiface/tests/pin.go
@@ -67,7 +67,7 @@ func (tp *TestSuite) TestPinSimple(t *testing.T) {
t.Fatal(err)
}
- list, err := accPins(api.Pin().Ls(ctx))
+ list, err := accPins(ctx, api)
if err != nil {
t.Fatal(err)
}
@@ -91,7 +91,7 @@ func (tp *TestSuite) TestPinSimple(t *testing.T) {
t.Fatal(err)
}
- list, err = accPins(api.Pin().Ls(ctx))
+ list, err = accPins(ctx, api)
if err != nil {
t.Fatal(err)
}
@@ -143,7 +143,7 @@ func (tp *TestSuite) TestPinRecursive(t *testing.T) {
t.Fatal(err)
}
- list, err := accPins(api.Pin().Ls(ctx))
+ list, err := accPins(ctx, api)
if err != nil {
t.Fatal(err)
}
@@ -152,7 +152,7 @@ func (tp *TestSuite) TestPinRecursive(t *testing.T) {
t.Errorf("unexpected pin list len: %d", len(list))
}
- list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Ls.Direct()))
+ list, err = accPins(ctx, api, opt.Pin.Ls.Direct())
if err != nil {
t.Fatal(err)
}
@@ -165,7 +165,7 @@ func (tp *TestSuite) TestPinRecursive(t *testing.T) {
t.Errorf("unexpected path, %s != %s", list[0].Path().String(), path.FromCid(nd3.Cid()).String())
}
- list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Ls.Recursive()))
+ list, err = accPins(ctx, api, opt.Pin.Ls.Recursive())
if err != nil {
t.Fatal(err)
}
@@ -178,7 +178,7 @@ func (tp *TestSuite) TestPinRecursive(t *testing.T) {
t.Errorf("unexpected path, %s != %s", list[0].Path().String(), path.FromCid(nd2.Cid()).String())
}
- list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Ls.Indirect()))
+ list, err = accPins(ctx, api, opt.Pin.Ls.Indirect())
if err != nil {
t.Fatal(err)
}
@@ -436,21 +436,21 @@ func getThreeChainedNodes(t *testing.T, ctx context.Context, api iface.CoreAPI,
func assertPinTypes(t *testing.T, ctx context.Context, api iface.CoreAPI, recusive, direct, indirect []cidContainer) {
assertPinLsAllConsistency(t, ctx, api)
- list, err := accPins(api.Pin().Ls(ctx, opt.Pin.Ls.Recursive()))
+ list, err := accPins(ctx, api, opt.Pin.Ls.Recursive())
if err != nil {
t.Fatal(err)
}
assertPinCids(t, list, recusive...)
- list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Ls.Direct()))
+ list, err = accPins(ctx, api, opt.Pin.Ls.Direct())
if err != nil {
t.Fatal(err)
}
assertPinCids(t, list, direct...)
- list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Ls.Indirect()))
+ list, err = accPins(ctx, api, opt.Pin.Ls.Indirect())
if err != nil {
t.Fatal(err)
}
@@ -500,7 +500,7 @@ func assertPinCids(t *testing.T, pins []iface.Pin, cids ...cidContainer) {
// assertPinLsAllConsistency verifies that listing all pins gives the same result as listing the pin types individually
func assertPinLsAllConsistency(t *testing.T, ctx context.Context, api iface.CoreAPI) {
t.Helper()
- allPins, err := accPins(api.Pin().Ls(ctx))
+ allPins, err := accPins(ctx, api)
if err != nil {
t.Fatal(err)
}
@@ -531,7 +531,7 @@ func assertPinLsAllConsistency(t *testing.T, ctx context.Context, api iface.Core
}
for typeStr, pinProps := range typeMap {
- pins, err := accPins(api.Pin().Ls(ctx, pinProps.PinLsOption))
+ pins, err := accPins(ctx, api, pinProps.PinLsOption)
if err != nil {
t.Fatal(err)
}
@@ -593,19 +593,19 @@ func assertNotPinned(t *testing.T, ctx context.Context, api iface.CoreAPI, p pat
}
}
-func accPins(pins <-chan iface.Pin, err error) ([]iface.Pin, error) {
- if err != nil {
- return nil, err
- }
-
- var result []iface.Pin
+func accPins(ctx context.Context, api iface.CoreAPI, opts ...opt.PinLsOption) ([]iface.Pin, error) {
+ var err error
+ pins := make(chan iface.Pin)
+ go func() {
+ err = api.Pin().Ls(ctx, pins, opts...)
+ }()
+ var results []iface.Pin
for pin := range pins {
- if pin.Err() != nil {
- return nil, pin.Err()
- }
- result = append(result, pin)
+ results = append(results, pin)
}
-
- return result, nil
+ if err != nil {
+ return nil, err
+ }
+ return results, nil
}
diff --git a/core/coreiface/tests/routing.go b/core/coreiface/tests/routing.go
index 3f1f95d75c7..753d49550e7 100644
--- a/core/coreiface/tests/routing.go
+++ b/core/coreiface/tests/routing.go
@@ -2,6 +2,7 @@ package tests
import (
"context"
+ "io"
"testing"
"time"
@@ -23,6 +24,9 @@ func (tp *TestSuite) TestRouting(t *testing.T) {
t.Run("TestRoutingGet", tp.TestRoutingGet)
t.Run("TestRoutingPut", tp.TestRoutingPut)
t.Run("TestRoutingPutOffline", tp.TestRoutingPutOffline)
+ t.Run("TestRoutingFindPeer", tp.TestRoutingFindPeer)
+ t.Run("TestRoutingFindProviders", tp.TestRoutingFindProviders)
+ t.Run("TestRoutingProvide", tp.TestRoutingProvide)
}
func (tp *TestSuite) testRoutingPublishKey(t *testing.T, ctx context.Context, api iface.CoreAPI, opts ...options.NamePublishOption) (path.Path, ipns.Name) {
@@ -95,6 +99,148 @@ func (tp *TestSuite) TestRoutingPutOffline(t *testing.T) {
err = api.Routing().Put(ctx, ipns.NamespacePrefix+name.String(), data)
require.Error(t, err, "this operation should fail because we are offline")
- err = api.Routing().Put(ctx, ipns.NamespacePrefix+name.String(), data, options.Put.AllowOffline(true))
+ err = api.Routing().Put(ctx, ipns.NamespacePrefix+name.String(), data, options.Routing.AllowOffline(true))
require.NoError(t, err)
}
+
+func (tp *TestSuite) TestRoutingFindPeer(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ apis, err := tp.MakeAPISwarm(t, ctx, 5)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ self0, err := apis[0].Key().Self(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ laddrs0, err := apis[0].Swarm().LocalAddrs(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(laddrs0) != 1 {
+ t.Fatal("unexpected number of local addrs")
+ }
+
+ time.Sleep(3 * time.Second)
+
+ pi, err := apis[2].Routing().FindPeer(ctx, self0.ID())
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if pi.Addrs[0].String() != laddrs0[0].String() {
+ t.Errorf("got unexpected address from FindPeer: %s", pi.Addrs[0].String())
+ }
+
+ self2, err := apis[2].Key().Self(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ pi, err = apis[1].Routing().FindPeer(ctx, self2.ID())
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ laddrs2, err := apis[2].Swarm().LocalAddrs(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(laddrs2) != 1 {
+ t.Fatal("unexpected number of local addrs")
+ }
+
+ if pi.Addrs[0].String() != laddrs2[0].String() {
+ t.Errorf("got unexpected address from FindPeer: %s", pi.Addrs[0].String())
+ }
+}
+
+func (tp *TestSuite) TestRoutingFindProviders(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ apis, err := tp.MakeAPISwarm(t, ctx, 5)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ p, err := addTestObject(ctx, apis[0])
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ time.Sleep(3 * time.Second)
+
+ out, err := apis[2].Routing().FindProviders(ctx, p, options.Routing.NumProviders(1))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ provider := <-out
+
+ self0, err := apis[0].Key().Self(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if provider.ID.String() != self0.ID().String() {
+ t.Errorf("got wrong provider: %s != %s", provider.ID.String(), self0.ID().String())
+ }
+}
+
+func (tp *TestSuite) TestRoutingProvide(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ apis, err := tp.MakeAPISwarm(t, ctx, 5)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ off0, err := apis[0].WithOptions(options.Api.Offline(true))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ s, err := off0.Block().Put(ctx, &io.LimitedReader{R: rnd, N: 4092})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ p := s.Path()
+
+ time.Sleep(3 * time.Second)
+
+ out, err := apis[2].Routing().FindProviders(ctx, p, options.Routing.NumProviders(1))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ _, ok := <-out
+
+ if ok {
+ t.Fatal("did not expect to find any providers")
+ }
+
+ self0, err := apis[0].Key().Self(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = apis[0].Routing().Provide(ctx, p)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ out, err = apis[2].Routing().FindProviders(ctx, p, options.Routing.NumProviders(1))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ provider := <-out
+
+ if provider.ID.String() != self0.ID().String() {
+ t.Errorf("got wrong provider: %s != %s", provider.ID.String(), self0.ID().String())
+ }
+}
diff --git a/core/coreiface/tests/unixfs.go b/core/coreiface/tests/unixfs.go
index 538f4d8ed7c..43447990ec4 100644
--- a/core/coreiface/tests/unixfs.go
+++ b/core/coreiface/tests/unixfs.go
@@ -544,7 +544,7 @@ func (tp *TestSuite) TestAddPinned(t *testing.T) {
t.Fatal(err)
}
- pins, err := accPins(api.Pin().Ls(ctx))
+ pins, err := accPins(ctx, api)
if err != nil {
t.Fatal(err)
}
@@ -571,7 +571,7 @@ func (tp *TestSuite) TestAddHashOnly(t *testing.T) {
}
if p.String() != hello {
- t.Errorf("unxepected path: %s", p.String())
+ t.Errorf("unexpected path: %s", p.String())
}
_, err = api.Block().Get(ctx, p)
@@ -579,7 +579,7 @@ func (tp *TestSuite) TestAddHashOnly(t *testing.T) {
t.Fatal("expected an error")
}
if !ipld.IsNotFound(err) {
- t.Errorf("unxepected error: %s", err.Error())
+ t.Errorf("unexpected error: %s", err.Error())
}
}
@@ -630,16 +630,11 @@ func (tp *TestSuite) TestGetDir(t *testing.T) {
}
p := path.FromCid(edir.Cid())
- emptyDir, err := api.Object().New(ctx, options.Object.Type("unixfs-dir"))
- if err != nil {
- t.Fatal(err)
+ if p.String() != path.FromCid(edir.Cid()).String() {
+ t.Fatalf("expected path %s, got: %s", edir.Cid(), p.String())
}
- if p.String() != path.FromCid(emptyDir.Cid()).String() {
- t.Fatalf("expected path %s, got: %s", emptyDir.Cid(), p.String())
- }
-
- r, err := api.Unixfs().Get(ctx, path.FromCid(emptyDir.Cid()))
+ r, err := api.Unixfs().Get(ctx, path.FromCid(edir.Cid()))
if err != nil {
t.Fatal(err)
}
@@ -664,8 +659,8 @@ func (tp *TestSuite) TestGetNonUnixfs(t *testing.T) {
}
_, err = api.Unixfs().Get(ctx, path.FromCid(nd.Cid()))
- if !strings.Contains(err.Error(), "proto: required field") {
- t.Fatalf("expected protobuf error, got: %s", err)
+ if !strings.Contains(err.Error(), "proto:") || !strings.Contains(err.Error(), "required field") {
+ t.Fatalf("expected \"proto: required field\", got: %q", err)
}
}
@@ -686,14 +681,15 @@ func (tp *TestSuite) TestLs(t *testing.T) {
t.Fatal(err)
}
- entries, err := api.Unixfs().Ls(ctx, p)
- if err != nil {
- t.Fatal(err)
- }
+ errCh := make(chan error, 1)
+ entries := make(chan coreiface.DirEntry)
+ go func() {
+ errCh <- api.Unixfs().Ls(ctx, p, entries)
+ }()
- entry := <-entries
- if entry.Err != nil {
- t.Fatal(entry.Err)
+ entry, ok := <-entries
+ if !ok {
+ t.Fatal("expected another entry")
}
if entry.Size != 15 {
t.Errorf("expected size = 15, got %d", entry.Size)
@@ -707,9 +703,9 @@ func (tp *TestSuite) TestLs(t *testing.T) {
if entry.Cid.String() != "QmX3qQVKxDGz3URVC3861Z3CKtQKGBn6ffXRBBWGMFz9Lr" {
t.Errorf("expected cid = QmX3qQVKxDGz3URVC3861Z3CKtQKGBn6ffXRBBWGMFz9Lr, got %s", entry.Cid)
}
- entry = <-entries
- if entry.Err != nil {
- t.Fatal(entry.Err)
+ entry, ok = <-entries
+ if !ok {
+ t.Fatal("expected another entry")
}
if entry.Type != coreiface.TSymlink {
t.Errorf("wrong type %s", entry.Type)
@@ -721,11 +717,12 @@ func (tp *TestSuite) TestLs(t *testing.T) {
t.Errorf("expected symlink target to be /foo/bar, got %s", entry.Target)
}
- if l, ok := <-entries; ok {
- t.Errorf("didn't expect a second link")
- if l.Err != nil {
- t.Error(l.Err)
- }
+ _, ok = <-entries
+ if ok {
+ t.Errorf("didn't expect a another link")
+ }
+ if err = <-errCh; err != nil {
+ t.Error(err)
}
}
@@ -779,23 +776,27 @@ func (tp *TestSuite) TestLsEmptyDir(t *testing.T) {
t.Fatal(err)
}
- _, err = api.Unixfs().Add(ctx, files.NewSliceDirectory([]files.DirEntry{}))
+ p, err := api.Unixfs().Add(ctx, files.NewSliceDirectory([]files.DirEntry{}))
if err != nil {
t.Fatal(err)
}
- emptyDir, err := api.Object().New(ctx, options.Object.Type("unixfs-dir"))
- if err != nil {
- t.Fatal(err)
- }
+ errCh := make(chan error, 1)
+ links := make(chan coreiface.DirEntry)
+ go func() {
+ errCh <- api.Unixfs().Ls(ctx, p, links)
+ }()
- links, err := api.Unixfs().Ls(ctx, path.FromCid(emptyDir.Cid()))
- if err != nil {
+ var count int
+ for range links {
+ count++
+ }
+ if err = <-errCh; err != nil {
t.Fatal(err)
}
- if len(links) != 0 {
- t.Fatalf("expected 0 links, got %d", len(links))
+ if count != 0 {
+ t.Fatalf("expected 0 links, got %d", count)
}
}
@@ -818,13 +819,22 @@ func (tp *TestSuite) TestLsNonUnixfs(t *testing.T) {
t.Fatal(err)
}
- links, err := api.Unixfs().Ls(ctx, path.FromCid(nd.Cid()))
- if err != nil {
+ errCh := make(chan error, 1)
+ links := make(chan coreiface.DirEntry)
+ go func() {
+ errCh <- api.Unixfs().Ls(ctx, path.FromCid(nd.Cid()), links)
+ }()
+
+ var count int
+ for range links {
+ count++
+ }
+ if err = <-errCh; err != nil {
t.Fatal(err)
}
- if len(links) != 0 {
- t.Fatalf("expected 0 links, got %d", len(links))
+ if count != 0 {
+ t.Fatalf("expected 0 links, got %d", count)
}
}
diff --git a/core/coreiface/unixfs.go b/core/coreiface/unixfs.go
index d0dc4d8ce09..a8740e2b3ba 100644
--- a/core/coreiface/unixfs.go
+++ b/core/coreiface/unixfs.go
@@ -2,6 +2,9 @@ package iface
import (
"context"
+ "iter"
+ "os"
+ "time"
"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/path"
@@ -10,10 +13,13 @@ import (
)
type AddEvent struct {
- Name string
- Path path.ImmutablePath `json:",omitempty"`
- Bytes int64 `json:",omitempty"`
- Size string `json:",omitempty"`
+ Name string
+ Path path.ImmutablePath `json:",omitempty"`
+ Bytes int64 `json:",omitempty"`
+ Size string `json:",omitempty"`
+ Mode os.FileMode `json:",omitempty"`
+ Mtime int64 `json:",omitempty"`
+ MtimeNsecs int `json:",omitempty"`
}
// FileType is an enum of possible UnixFS file types.
@@ -56,7 +62,8 @@ type DirEntry struct {
Type FileType // The type of the file.
Target string // The symlink target (if a symlink).
- Err error
+ Mode os.FileMode
+ ModTime time.Time
}
// UnixfsAPI is the basic interface to immutable files in IPFS
@@ -73,7 +80,56 @@ type UnixfsAPI interface {
// to operations performed on the returned file
Get(context.Context, path.Path) (files.Node, error)
- // Ls returns the list of links in a directory. Links aren't guaranteed to be
- // returned in order
- Ls(context.Context, path.Path, ...options.UnixfsLsOption) (<-chan DirEntry, error)
+ // Ls writes the links in a directory to the DirEntry channel. Links aren't
+ // guaranteed to be returned in order. If an error occurs or the context is
+ // canceled, the DirEntry channel is closed and an error is returned.
+ //
+ // Example:
+ //
+ // dirs := make(chan DirEntry)
+ // lsErr := make(chan error, 1)
+ // go func() {
+ // lsErr <- Ls(ctx, p, dirs)
+ // }()
+ // for dirEnt := range dirs {
+ // fmt.Println("Dir name:", dirEnt.Name)
+ // }
+ // err := <-lsErr
+ // if err != nil {
+ // return fmt.Errorf("error listing directory: %w", err)
+ // }
+ Ls(context.Context, path.Path, chan<- DirEntry, ...options.UnixfsLsOption) error
+}
+
+// LsIter returns a go iterator that allows ranging over DirEntry results.
+// Iteration stops if the context is canceled or if the iterator yields an
+// error.
+//
+// Example:
+//
+// for dirEnt, err := LsIter(ctx, ufsAPI, p) {
+// if err != nil {
+// return fmt.Errorf("error listing directory: %w", err)
+// }
+// fmt.Println("Dir name:", dirEnt.Name)
+// }
+func LsIter(ctx context.Context, api UnixfsAPI, p path.Path, opts ...options.UnixfsLsOption) iter.Seq2[DirEntry, error] {
+ return func(yield func(DirEntry, error) bool) {
+ ctx, cancel := context.WithCancel(ctx)
+ defer cancel() // cancel Ls if done iterating early
+
+ dirs := make(chan DirEntry)
+ lsErr := make(chan error, 1)
+ go func() {
+ lsErr <- api.Ls(ctx, p, dirs, opts...)
+ }()
+ for dirEnt := range dirs {
+ if !yield(dirEnt, nil) {
+ return
+ }
+ }
+ if err := <-lsErr; err != nil {
+ yield(DirEntry{}, err)
+ }
+ }
}
diff --git a/core/corerepo/gc.go b/core/corerepo/gc.go
index cf89587d66f..bf285e3d933 100644
--- a/core/corerepo/gc.go
+++ b/core/corerepo/gc.go
@@ -13,7 +13,7 @@ import (
"github.com/dustin/go-humanize"
"github.com/ipfs/boxo/mfs"
"github.com/ipfs/go-cid"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
)
var log = logging.Logger("corerepo")
diff --git a/core/coreunix/add.go b/core/coreunix/add.go
index a8d7e5982f0..eb6f25e0f68 100644
--- a/core/coreunix/add.go
+++ b/core/coreunix/add.go
@@ -5,8 +5,10 @@ import (
"errors"
"fmt"
"io"
+ "os"
gopath "path"
"strconv"
+ "time"
bstore "github.com/ipfs/boxo/blockstore"
chunker "github.com/ipfs/boxo/chunker"
@@ -17,12 +19,13 @@ import (
"github.com/ipfs/boxo/ipld/unixfs/importer/balanced"
ihelper "github.com/ipfs/boxo/ipld/unixfs/importer/helpers"
"github.com/ipfs/boxo/ipld/unixfs/importer/trickle"
+ uio "github.com/ipfs/boxo/ipld/unixfs/io"
"github.com/ipfs/boxo/mfs"
"github.com/ipfs/boxo/path"
pin "github.com/ipfs/boxo/pinning/pinner"
"github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
coreiface "github.com/ipfs/kubo/core/coreiface"
"github.com/ipfs/kubo/tracing"
@@ -49,50 +52,61 @@ func NewAdder(ctx context.Context, p pin.Pinner, bs bstore.GCLocker, ds ipld.DAG
bufferedDS := ipld.NewBufferedDAG(ctx, ds)
return &Adder{
- ctx: ctx,
- pinning: p,
- gcLocker: bs,
- dagService: ds,
- bufferedDS: bufferedDS,
- Progress: false,
- Pin: true,
- Trickle: false,
- Chunker: "",
+ ctx: ctx,
+ pinning: p,
+ gcLocker: bs,
+ dagService: ds,
+ bufferedDS: bufferedDS,
+ Progress: false,
+ Pin: true,
+ Trickle: false,
+ MaxLinks: ihelper.DefaultLinksPerBlock,
+ MaxHAMTFanout: uio.DefaultShardWidth,
+ Chunker: "",
}, nil
}
// Adder holds the switches passed to the `add` command.
type Adder struct {
- ctx context.Context
- pinning pin.Pinner
- gcLocker bstore.GCLocker
- dagService ipld.DAGService
- bufferedDS *ipld.BufferedDAG
- Out chan<- interface{}
- Progress bool
- Pin bool
- Trickle bool
- RawLeaves bool
- Silent bool
- NoCopy bool
- Chunker string
- mroot *mfs.Root
- unlocker bstore.Unlocker
- tempRoot cid.Cid
- CidBuilder cid.Builder
- liveNodes uint64
+ ctx context.Context
+ pinning pin.Pinner
+ gcLocker bstore.GCLocker
+ dagService ipld.DAGService
+ bufferedDS *ipld.BufferedDAG
+ Out chan<- interface{}
+ Progress bool
+ Pin bool
+ Trickle bool
+ RawLeaves bool
+ MaxLinks int
+ MaxDirectoryLinks int
+ MaxHAMTFanout int
+ Silent bool
+ NoCopy bool
+ Chunker string
+ mroot *mfs.Root
+ unlocker bstore.Unlocker
+ tempRoot cid.Cid
+ CidBuilder cid.Builder
+ liveNodes uint64
+
+ PreserveMode bool
+ PreserveMtime bool
+ FileMode os.FileMode
+ FileMtime time.Time
}
func (adder *Adder) mfsRoot() (*mfs.Root, error) {
if adder.mroot != nil {
return adder.mroot, nil
}
- rnode := unixfs.EmptyDirNode()
- err := rnode.SetCidBuilder(adder.CidBuilder)
- if err != nil {
- return nil, err
- }
- mr, err := mfs.NewRoot(adder.ctx, adder.dagService, rnode, nil)
+
+ // Note, this adds it to DAGService already.
+ mr, err := mfs.NewEmptyRoot(adder.ctx, adder.dagService, nil, mfs.MkdirOpts{
+ CidBuilder: adder.CidBuilder,
+ MaxLinks: adder.MaxDirectoryLinks,
+ MaxHAMTFanout: adder.MaxHAMTFanout,
+ })
if err != nil {
return nil, err
}
@@ -112,12 +126,19 @@ func (adder *Adder) add(reader io.Reader) (ipld.Node, error) {
return nil, err
}
+ maxLinks := ihelper.DefaultLinksPerBlock
+ if adder.MaxLinks > 0 {
+ maxLinks = adder.MaxLinks
+ }
+
params := ihelper.DagBuilderParams{
- Dagserv: adder.bufferedDS,
- RawLeaves: adder.RawLeaves,
- Maxlinks: ihelper.DefaultLinksPerBlock,
- NoCopy: adder.NoCopy,
- CidBuilder: adder.CidBuilder,
+ Dagserv: adder.bufferedDS,
+ RawLeaves: adder.RawLeaves,
+ Maxlinks: maxLinks,
+ NoCopy: adder.NoCopy,
+ CidBuilder: adder.CidBuilder,
+ FileMode: adder.FileMode,
+ FileModTime: adder.FileMtime,
}
db, err := params.New(chnk)
@@ -243,12 +264,15 @@ func (adder *Adder) addNode(node ipld.Node, path string) error {
if err != nil {
return err
}
+
dir := gopath.Dir(path)
if dir != "." {
opts := mfs.MkdirOpts{
- Mkparents: true,
- Flush: false,
- CidBuilder: adder.CidBuilder,
+ Mkparents: true,
+ Flush: false,
+ CidBuilder: adder.CidBuilder,
+ MaxLinks: adder.MaxDirectoryLinks,
+ MaxHAMTFanout: adder.MaxHAMTFanout,
}
if err := mfs.Mkdir(mr, dir, opts); err != nil {
return err
@@ -359,6 +383,14 @@ func (adder *Adder) addFileNode(ctx context.Context, path string, file files.Nod
return err
}
+ if adder.PreserveMtime {
+ adder.FileMtime = file.ModTime()
+ }
+
+ if adder.PreserveMode {
+ adder.FileMode = file.Mode()
+ }
+
if adder.liveNodes >= liveCacheSize {
// TODO: A smarter cache that uses some sort of lru cache with an eviction handler
mr, err := adder.mfsRoot()
@@ -391,6 +423,18 @@ func (adder *Adder) addSymlink(path string, l *files.Symlink) error {
return err
}
+ if !adder.FileMtime.IsZero() {
+ fsn, err := unixfs.FSNodeFromBytes(sdata)
+ if err != nil {
+ return err
+ }
+
+ fsn.SetModTime(adder.FileMtime)
+ if sdata, err = fsn.GetBytes(); err != nil {
+ return err
+ }
+ }
+
dagnode := dag.NodeWithData(sdata)
err = dagnode.SetCidBuilder(adder.CidBuilder)
if err != nil {
@@ -429,15 +473,35 @@ func (adder *Adder) addFile(path string, file files.File) error {
func (adder *Adder) addDir(ctx context.Context, path string, dir files.Directory, toplevel bool) error {
log.Infof("adding directory: %s", path)
+ // if we need to store mode or modification time then create a new root which includes that data
+ if toplevel && (adder.FileMode != 0 || !adder.FileMtime.IsZero()) {
+ mr, err := mfs.NewEmptyRoot(ctx, adder.dagService, nil,
+ mfs.MkdirOpts{
+ CidBuilder: adder.CidBuilder,
+ MaxLinks: adder.MaxDirectoryLinks,
+ MaxHAMTFanout: adder.MaxHAMTFanout,
+ ModTime: adder.FileMtime,
+ Mode: adder.FileMode,
+ })
+ if err != nil {
+ return err
+ }
+ adder.SetMfsRoot(mr)
+ }
+
if !(toplevel && path == "") {
mr, err := adder.mfsRoot()
if err != nil {
return err
}
err = mfs.Mkdir(mr, path, mfs.MkdirOpts{
- Mkparents: true,
- Flush: false,
- CidBuilder: adder.CidBuilder,
+ Mkparents: true,
+ Flush: false,
+ CidBuilder: adder.CidBuilder,
+ Mode: adder.FileMode,
+ ModTime: adder.FileMtime,
+ MaxLinks: adder.MaxDirectoryLinks,
+ MaxHAMTFanout: adder.MaxHAMTFanout,
})
if err != nil {
return err
diff --git a/core/coreunix/metadata_test.go b/core/coreunix/metadata_test.go
index b40f010db48..c7d1b94db38 100644
--- a/core/coreunix/metadata_test.go
+++ b/core/coreunix/metadata_test.go
@@ -16,11 +16,11 @@ import (
bstore "github.com/ipfs/boxo/blockstore"
chunker "github.com/ipfs/boxo/chunker"
offline "github.com/ipfs/boxo/exchange/offline"
- u "github.com/ipfs/boxo/util"
cid "github.com/ipfs/go-cid"
ds "github.com/ipfs/go-datastore"
dssync "github.com/ipfs/go-datastore/sync"
ipld "github.com/ipfs/go-ipld-format"
+ "github.com/ipfs/go-test/random"
)
func getDagserv(t *testing.T) ipld.DAGService {
@@ -35,7 +35,7 @@ func TestMetadata(t *testing.T) {
// Make some random node
ds := getDagserv(t)
data := make([]byte, 1000)
- _, err := io.ReadFull(u.NewTimeSeededRand(), data)
+ _, err := io.ReadFull(random.NewRand(), data)
if err != nil {
t.Fatal(err)
}
diff --git a/core/node/bitswap.go b/core/node/bitswap.go
index 1c4c1df2157..e87464b8a67 100644
--- a/core/node/bitswap.go
+++ b/core/node/bitswap.go
@@ -2,17 +2,31 @@ package node
import (
"context"
+ "errors"
+ "io"
"time"
+ "github.com/dustin/go-humanize"
"github.com/ipfs/boxo/bitswap"
+ "github.com/ipfs/boxo/bitswap/client"
"github.com/ipfs/boxo/bitswap/network"
+ bsnet "github.com/ipfs/boxo/bitswap/network/bsnet"
+ "github.com/ipfs/boxo/bitswap/network/httpnet"
blockstore "github.com/ipfs/boxo/blockstore"
exchange "github.com/ipfs/boxo/exchange"
+ "github.com/ipfs/boxo/exchange/providing"
+ provider "github.com/ipfs/boxo/provider"
+ rpqm "github.com/ipfs/boxo/routing/providerquerymanager"
+ "github.com/ipfs/go-cid"
+ ipld "github.com/ipfs/go-ipld-format"
+ version "github.com/ipfs/kubo"
"github.com/ipfs/kubo/config"
irouting "github.com/ipfs/kubo/routing"
"github.com/libp2p/go-libp2p/core/host"
+ peer "github.com/libp2p/go-libp2p/core/peer"
"go.uber.org/fx"
+ blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/kubo/core/node/helpers"
)
@@ -23,6 +37,8 @@ const (
DefaultEngineTaskWorkerCount = 8
DefaultMaxOutstandingBytesPerPeer = 1 << 20
DefaultProviderSearchDelay = 1000 * time.Millisecond
+ DefaultMaxProviders = 10 // matching BitswapClientDefaultMaxProviders from https://github.com/ipfs/boxo/blob/v0.29.1/bitswap/internal/defaults/defaults.go#L15
+ DefaultWantHaveReplaceSize = 1024
)
type bitswapOptionsOut struct {
@@ -33,7 +49,7 @@ type bitswapOptionsOut struct {
// BitswapOptions creates configuration options for Bitswap from the config file
// and whether to provide data.
-func BitswapOptions(cfg *config.Config, provide bool) interface{} {
+func BitswapOptions(cfg *config.Config) interface{} {
return func() bitswapOptionsOut {
var internalBsCfg config.InternalBitswap
if cfg.Internal.Bitswap != nil {
@@ -41,41 +57,160 @@ func BitswapOptions(cfg *config.Config, provide bool) interface{} {
}
opts := []bitswap.Option{
- bitswap.ProvideEnabled(provide),
bitswap.ProviderSearchDelay(internalBsCfg.ProviderSearchDelay.WithDefault(DefaultProviderSearchDelay)), // See https://github.com/ipfs/go-ipfs/issues/8807 for rationale
bitswap.EngineBlockstoreWorkerCount(int(internalBsCfg.EngineBlockstoreWorkerCount.WithDefault(DefaultEngineBlockstoreWorkerCount))),
bitswap.TaskWorkerCount(int(internalBsCfg.TaskWorkerCount.WithDefault(DefaultTaskWorkerCount))),
bitswap.EngineTaskWorkerCount(int(internalBsCfg.EngineTaskWorkerCount.WithDefault(DefaultEngineTaskWorkerCount))),
bitswap.MaxOutstandingBytesPerPeer(int(internalBsCfg.MaxOutstandingBytesPerPeer.WithDefault(DefaultMaxOutstandingBytesPerPeer))),
+ bitswap.WithWantHaveReplaceSize(int(internalBsCfg.WantHaveReplaceSize.WithDefault(DefaultWantHaveReplaceSize))),
}
return bitswapOptionsOut{BitswapOpts: opts}
}
}
-type onlineExchangeIn struct {
+type bitswapIn struct {
fx.In
Mctx helpers.MetricsCtx
+ Cfg *config.Config
Host host.Host
Rt irouting.ProvideManyRouter
Bs blockstore.GCBlockstore
BitswapOpts []bitswap.Option `group:"bitswap-options"`
}
-// OnlineExchange creates new LibP2P backed block exchange (BitSwap).
-// Additional options to bitswap.New can be provided via the "bitswap-options"
-// group.
-func OnlineExchange() interface{} {
- return func(in onlineExchangeIn, lc fx.Lifecycle) exchange.Interface {
- bitswapNetwork := network.NewFromIpfsHost(in.Host, in.Rt)
+// Bitswap creates the BitSwap server/client instance.
+// If Bitswap.ServerEnabled is false, the node will act only as a client
+// using an empty blockstore to prevent serving blocks to other peers.
+func Bitswap(serverEnabled, libp2pEnabled, httpEnabled bool) interface{} {
+ return func(in bitswapIn, lc fx.Lifecycle) (*bitswap.Bitswap, error) {
+ var bitswapNetworks, bitswapLibp2p network.BitSwapNetwork
+ var bitswapBlockstore blockstore.Blockstore = in.Bs
- exch := bitswap.New(helpers.LifecycleCtx(in.Mctx, lc), bitswapNetwork, in.Bs, in.BitswapOpts...)
+ libp2pEnabled := in.Cfg.Bitswap.Libp2pEnabled.WithDefault(config.DefaultBitswapLibp2pEnabled)
+ if libp2pEnabled {
+ bitswapLibp2p = bsnet.NewFromIpfsHost(in.Host)
+ }
+
+ if httpEnabled {
+ httpCfg := in.Cfg.HTTPRetrieval
+ maxBlockSize, err := humanize.ParseBytes(httpCfg.MaxBlockSize.WithDefault(config.DefaultHTTPRetrievalMaxBlockSize))
+ if err != nil {
+ return nil, err
+ }
+ bitswapHTTP := httpnet.New(in.Host,
+ httpnet.WithHTTPWorkers(int(httpCfg.NumWorkers.WithDefault(config.DefaultHTTPRetrievalNumWorkers))),
+ httpnet.WithAllowlist(httpCfg.Allowlist),
+ httpnet.WithDenylist(httpCfg.Denylist),
+ httpnet.WithInsecureSkipVerify(httpCfg.TLSInsecureSkipVerify.WithDefault(config.DefaultHTTPRetrievalTLSInsecureSkipVerify)),
+ httpnet.WithMaxBlockSize(int64(maxBlockSize)),
+ httpnet.WithUserAgent(version.GetUserAgentVersion()),
+ )
+ bitswapNetworks = network.New(in.Host.Peerstore(), bitswapLibp2p, bitswapHTTP)
+ } else if libp2pEnabled {
+ bitswapNetworks = bitswapLibp2p
+ } else {
+ return nil, errors.New("invalid configuration: Bitswap.Libp2pEnabled and HTTPRetrieval.Enabled are both disabled, unable to initialize Bitswap")
+ }
+
+ // Kubo uses own, customized ProviderQueryManager
+ in.BitswapOpts = append(in.BitswapOpts, bitswap.WithClientOption(client.WithDefaultProviderQueryManager(false)))
+ var maxProviders int = DefaultMaxProviders
+ if in.Cfg.Internal.Bitswap != nil {
+ maxProviders = int(in.Cfg.Internal.Bitswap.ProviderSearchMaxResults.WithDefault(DefaultMaxProviders))
+ }
+ ignoredPeerIDs := make([]peer.ID, 0, len(in.Cfg.Routing.IgnoreProviders))
+ for _, str := range in.Cfg.Routing.IgnoreProviders {
+ pid, err := peer.Decode(str)
+ if err != nil {
+ return nil, err
+ }
+ ignoredPeerIDs = append(ignoredPeerIDs, pid)
+ }
+ providerQueryMgr, err := rpqm.New(bitswapNetworks,
+ in.Rt,
+ rpqm.WithMaxProviders(maxProviders),
+ rpqm.WithIgnoreProviders(ignoredPeerIDs...),
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ // Explicitly enable/disable server
+ in.BitswapOpts = append(in.BitswapOpts, bitswap.WithServerEnabled(serverEnabled))
+
+ bs := bitswap.New(helpers.LifecycleCtx(in.Mctx, lc), bitswapNetworks, providerQueryMgr, bitswapBlockstore, in.BitswapOpts...)
+
+ lc.Append(fx.Hook{
+ OnStop: func(ctx context.Context) error {
+ return bs.Close()
+ },
+ })
+ return bs, nil
+ }
+}
+
+// OnlineExchange creates new LibP2P backed block exchange.
+// Returns a no-op exchange if Bitswap is disabled.
+func OnlineExchange(isBitswapActive bool) interface{} {
+ return func(in *bitswap.Bitswap, lc fx.Lifecycle) exchange.Interface {
+ if !isBitswapActive {
+ return &noopExchange{closer: in}
+ }
lc.Append(fx.Hook{
OnStop: func(ctx context.Context) error {
- return exch.Close()
+ return in.Close()
},
})
+ return in
+ }
+}
+
+type providingExchangeIn struct {
+ fx.In
+
+ BaseExch exchange.Interface
+ Provider provider.System
+}
+
+// ProvidingExchange creates a providing.Exchange with the existing exchange
+// and the provider.System.
+// We cannot do this in OnlineExchange because it causes cycles so this is for
+// a decorator.
+func ProvidingExchange(provide bool) interface{} {
+ return func(in providingExchangeIn, lc fx.Lifecycle) exchange.Interface {
+ exch := in.BaseExch
+ if provide {
+ exch = providing.New(in.BaseExch, in.Provider)
+ lc.Append(fx.Hook{
+ OnStop: func(ctx context.Context) error {
+ return exch.Close()
+ },
+ })
+ }
return exch
}
}
+
+type noopExchange struct {
+ closer io.Closer
+}
+
+func (e *noopExchange) GetBlock(ctx context.Context, c cid.Cid) (blocks.Block, error) {
+ return nil, ipld.ErrNotFound{Cid: c}
+}
+
+func (e *noopExchange) GetBlocks(ctx context.Context, cids []cid.Cid) (<-chan blocks.Block, error) {
+ ch := make(chan blocks.Block)
+ close(ch)
+ return ch, nil
+}
+
+func (e *noopExchange) NotifyNewBlocks(ctx context.Context, blocks ...blocks.Block) error {
+ return nil
+}
+
+func (e *noopExchange) Close() error {
+ return e.closer.Close()
+}
diff --git a/core/node/builder.go b/core/node/builder.go
index 57fa209457a..411e3228c78 100644
--- a/core/node/builder.go
+++ b/core/node/builder.go
@@ -4,7 +4,6 @@ import (
"context"
"crypto/rand"
"encoding/base64"
- "errors"
"go.uber.org/fx"
@@ -34,9 +33,6 @@ type BuildCfg struct {
// DO NOT SET THIS UNLESS YOU'RE TESTING.
DisableEncryptedConnections bool
- // If NilRepo is set, a Repo backed by a nil datastore will be constructed
- NilRepo bool
-
Routing libp2p.RoutingOption
Host libp2p.HostOption
Repo repo.Repo
@@ -51,18 +47,8 @@ func (cfg *BuildCfg) getOpt(key string) bool {
}
func (cfg *BuildCfg) fillDefaults() error {
- if cfg.Repo != nil && cfg.NilRepo {
- return errors.New("cannot set a Repo and specify nilrepo at the same time")
- }
-
if cfg.Repo == nil {
- var d ds.Datastore
- if cfg.NilRepo {
- d = ds.NewNullDatastore()
- } else {
- d = ds.NewMapDatastore()
- }
- r, err := defaultRepo(dsync.MutexWrap(d))
+ r, err := defaultRepo(dsync.MutexWrap(ds.NewMapDatastore()))
if err != nil {
return err
}
diff --git a/core/node/core.go b/core/node/core.go
index 9a2035a4c8c..cb34399394d 100644
--- a/core/node/core.go
+++ b/core/node/core.go
@@ -24,21 +24,26 @@ import (
dagpb "github.com/ipld/go-codec-dagpb"
"go.uber.org/fx"
+ "github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core/node/helpers"
"github.com/ipfs/kubo/repo"
)
// BlockService creates new blockservice which provides an interface to fetch content-addressable blocks
-func BlockService(lc fx.Lifecycle, bs blockstore.Blockstore, rem exchange.Interface) blockservice.BlockService {
- bsvc := blockservice.New(bs, rem)
-
- lc.Append(fx.Hook{
- OnStop: func(ctx context.Context) error {
- return bsvc.Close()
- },
- })
-
- return bsvc
+func BlockService(cfg *config.Config) func(lc fx.Lifecycle, bs blockstore.Blockstore, rem exchange.Interface) blockservice.BlockService {
+ return func(lc fx.Lifecycle, bs blockstore.Blockstore, rem exchange.Interface) blockservice.BlockService {
+ bsvc := blockservice.New(bs, rem,
+ blockservice.WriteThrough(cfg.Datastore.WriteThrough.WithDefault(config.DefaultWriteThrough)),
+ )
+
+ lc.Append(fx.Hook{
+ OnStop: func(ctx context.Context) error {
+ return bsvc.Close()
+ },
+ })
+
+ return bsvc
+ }
}
// Pinning creates new pinner which tells GC which blocks should be kept
@@ -110,6 +115,7 @@ func FetcherConfig(bs blockservice.BlockService) FetchersOut {
// path resolution should not fetch new blocks via exchange.
offlineBs := blockservice.New(bs.Blockstore(), offline.Exchange(bs.Blockstore()))
offlineIpldFetcher := bsfetcher.NewFetcherConfig(offlineBs)
+ offlineIpldFetcher.SkipNotFound = true // carries onto the UnixFSFetcher below
offlineIpldFetcher.PrototypeChooser = dagpb.AddSupportToChooser(bsfetcher.DefaultPrototypeChooser)
offlineUnixFSFetcher := offlineIpldFetcher.WithReifier(unixfsnode.Reify)
@@ -146,7 +152,7 @@ func Dag(bs blockservice.BlockService) format.DAGService {
}
// Files loads persisted MFS root
-func Files(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo, dag format.DAGService) (*mfs.Root, error) {
+func Files(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo, dag format.DAGService, bs blockstore.Blockstore) (*mfs.Root, error) {
dsk := datastore.NewKey("/local/filesroot")
pf := func(ctx context.Context, c cid.Cid) error {
rootDS := repo.Datastore()
@@ -172,7 +178,7 @@ func Files(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo, dag format.
nd = unixfs.EmptyDirNode()
err := dag.Add(ctx, nd)
if err != nil {
- return nil, fmt.Errorf("failure writing to dagstore: %s", err)
+ return nil, fmt.Errorf("failure writing filesroot to dagstore: %s", err)
}
case err == nil:
c, err := cid.Cast(val)
@@ -180,9 +186,10 @@ func Files(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo, dag format.
return nil, err
}
- rnd, err := dag.Get(ctx, c)
+ offineDag := merkledag.NewDAGService(blockservice.New(bs, offline.Exchange(bs)))
+ rnd, err := offineDag.Get(ctx, c)
if err != nil {
- return nil, fmt.Errorf("error loading filesroot from DAG: %s", err)
+ return nil, fmt.Errorf("error loading filesroot from dagservice: %s", err)
}
pbnd, ok := rnd.(*merkledag.ProtoNode)
diff --git a/core/node/groups.go b/core/node/groups.go
index 061087c276b..1794b74c301 100644
--- a/core/node/groups.go
+++ b/core/node/groups.go
@@ -4,6 +4,8 @@ import (
"context"
"errors"
"fmt"
+ "regexp"
+ "strings"
"time"
"github.com/dustin/go-humanize"
@@ -11,7 +13,7 @@ import (
offline "github.com/ipfs/boxo/exchange/offline"
uio "github.com/ipfs/boxo/ipld/unixfs/io"
util "github.com/ipfs/boxo/util"
- "github.com/ipfs/go-log"
+ "github.com/ipfs/go-log/v2"
"github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core/node/libp2p"
"github.com/ipfs/kubo/p2p"
@@ -105,12 +107,19 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part
// to dhtclient.
fallthrough
case config.AutoNATServiceEnabled:
- autonat = fx.Provide(libp2p.AutoNATService(cfg.AutoNAT.Throttle))
+ autonat = fx.Provide(libp2p.AutoNATService(cfg.AutoNAT.Throttle, false))
+ case config.AutoNATServiceEnabledV1Only:
+ autonat = fx.Provide(libp2p.AutoNATService(cfg.AutoNAT.Throttle, true))
}
+ enableTCPTransport := cfg.Swarm.Transports.Network.TCP.WithDefault(true)
+ enableWebsocketTransport := cfg.Swarm.Transports.Network.Websocket.WithDefault(true)
enableRelayTransport := cfg.Swarm.Transports.Network.Relay.WithDefault(true) // nolint
enableRelayService := cfg.Swarm.RelayService.Enabled.WithDefault(enableRelayTransport)
enableRelayClient := cfg.Swarm.RelayClient.Enabled.WithDefault(enableRelayTransport)
+ enableAutoTLS := cfg.AutoTLS.Enabled.WithDefault(config.DefaultAutoTLSEnabled)
+ enableAutoWSS := cfg.AutoTLS.AutoWSS.WithDefault(config.DefaultAutoWSS)
+ atlsLog := log.Logger("autotls")
// Log error when relay subsystem could not be initialized due to missing dependency
if !enableRelayTransport {
@@ -122,6 +131,63 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part
}
}
+ switch {
+ case enableAutoTLS && enableTCPTransport && enableWebsocketTransport:
+ // AutoTLS for Secure WebSockets: ensure WSS listeners are in place (manual or automatic)
+ wssWildcard := fmt.Sprintf("/tls/sni/*.%s/ws", cfg.AutoTLS.DomainSuffix.WithDefault(config.DefaultDomainSuffix))
+ wssWildcardPresent := false
+ customWsPresent := false
+ customWsRegex := regexp.MustCompile(`/wss?$`)
+ tcpRegex := regexp.MustCompile(`/tcp/\d+$`)
+
+ // inspect listeners defined in config at Addresses.Swarm
+ var tcpListeners []string
+ for _, listener := range cfg.Addresses.Swarm {
+ // detect if user manually added /tls/sni/.../ws listener matching AutoTLS.DomainSuffix
+ if strings.Contains(listener, wssWildcard) {
+ atlsLog.Infof("found compatible wildcard listener in Addresses.Swarm. AutoTLS will be used on %s", listener)
+ wssWildcardPresent = true
+ break
+ }
+ // detect if user manually added own /ws or /wss listener that is
+ // not related to AutoTLS feature
+ if customWsRegex.MatchString(listener) {
+ atlsLog.Infof("found custom /ws listener set by user in Addresses.Swarm. AutoTLS will not be used on %s.", listener)
+ customWsPresent = true
+ break
+ }
+ // else, remember /tcp listeners that can be reused for /tls/sni/../ws
+ if tcpRegex.MatchString(listener) {
+ tcpListeners = append(tcpListeners, listener)
+ }
+ }
+
+ // Append AutoTLS's wildcard listener
+ // if no manual /ws listener was set by the user
+ if enableAutoWSS && !wssWildcardPresent && !customWsPresent {
+ if len(tcpListeners) == 0 {
+ logger.Error("Invalid configuration, AutoTLS will be disabled: AutoTLS.AutoWSS=true requires at least one /tcp listener present in Addresses.Swarm, see https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls")
+ enableAutoTLS = false
+ }
+ for _, tcpListener := range tcpListeners {
+ wssListener := tcpListener + wssWildcard
+ cfg.Addresses.Swarm = append(cfg.Addresses.Swarm, wssListener)
+ atlsLog.Infof("appended AutoWSS listener: %s", wssListener)
+ }
+ }
+
+ if !wssWildcardPresent && !enableAutoWSS {
+ logger.Error(fmt.Sprintf("Invalid configuration, AutoTLS will be disabled: AutoTLS.Enabled=true requires a /tcp listener ending with %q to be present in Addresses.Swarm or AutoTLS.AutoWSS=true, see https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls", wssWildcard))
+ enableAutoTLS = false
+ }
+ case enableAutoTLS && !enableTCPTransport:
+ logger.Error("Invalid configuration: AutoTLS.Enabled=true requires Swarm.Transports.Network.TCP to be true as well. AutoTLS will be disabled.")
+ enableAutoTLS = false
+ case enableAutoTLS && !enableWebsocketTransport:
+ logger.Error("Invalid configuration: AutoTLS.Enabled=true requires Swarm.Transports.Network.Websocket to be true as well. AutoTLS will be disabled.")
+ enableAutoTLS = false
+ }
+
// Gather all the options
opts := fx.Options(
BaseLibP2P,
@@ -130,7 +196,9 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part
fx.Provide(libp2p.UserAgent()),
// Services (resource management)
- fx.Provide(libp2p.ResourceManager(cfg.Swarm, userResourceOverrides)),
+ fx.Provide(libp2p.ResourceManager(bcfg.Repo.Path(), cfg.Swarm, userResourceOverrides)),
+ maybeProvide(libp2p.P2PForgeCertMgr(bcfg.Repo.Path(), cfg.AutoTLS, atlsLog), enableAutoTLS),
+ maybeInvoke(libp2p.StartP2PAutoTLS, enableAutoTLS),
fx.Provide(libp2p.AddrFilters(cfg.Swarm.AddrFilters)),
fx.Provide(libp2p.AddrsFactory(cfg.Addresses.Announce, cfg.Addresses.AppendAnnounce, cfg.Addresses.NoAnnounce)),
fx.Provide(libp2p.SmuxTransport(cfg.Swarm.Transports)),
@@ -166,6 +234,7 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part
func Storage(bcfg *BuildCfg, cfg *config.Config) fx.Option {
cacheOpts := blockstore.DefaultCacheOpts()
cacheOpts.HasBloomFilterSize = cfg.Datastore.BloomFilterSize
+ cacheOpts.HasTwoQueueCacheSize = int(cfg.Datastore.BlockKeyCacheSize.WithDefault(config.DefaultBlockKeyCacheSize))
if !bcfg.Permanent {
cacheOpts.HasBloomFilterSize = 0
}
@@ -178,7 +247,7 @@ func Storage(bcfg *BuildCfg, cfg *config.Config) fx.Option {
return fx.Options(
fx.Provide(RepoConfig),
fx.Provide(Datastore),
- fx.Provide(BaseBlockstoreCtor(cacheOpts, bcfg.NilRepo, cfg.Datastore.HashOnRead)),
+ fx.Provide(BaseBlockstoreCtor(cacheOpts, cfg.Datastore.HashOnRead, cfg.Datastore.WriteThrough.WithDefault(config.DefaultWriteThrough))),
finalBstore,
)
}
@@ -237,7 +306,7 @@ func Online(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part
ipnsCacheSize = DefaultIpnsCacheSize
}
if ipnsCacheSize < 0 {
- return fx.Error(fmt.Errorf("cannot specify negative resolve cache size"))
+ return fx.Error(errors.New("cannot specify negative resolve cache size"))
}
// Republisher params
@@ -266,12 +335,20 @@ func Online(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part
recordLifetime = d
}
- /* don't provide from bitswap when the strategic provider service is active */
- shouldBitswapProvide := !cfg.Experimental.StrategicProviding
+ isBitswapLibp2pEnabled := cfg.Bitswap.Libp2pEnabled.WithDefault(config.DefaultBitswapLibp2pEnabled)
+ isBitswapServerEnabled := cfg.Bitswap.ServerEnabled.WithDefault(config.DefaultBitswapServerEnabled)
+ isHTTPRetrievalEnabled := cfg.HTTPRetrieval.Enabled.WithDefault(config.DefaultHTTPRetrievalEnabled)
+
+ // Right now Provider and Reprovider systems are tied together - disabling Reprovider by setting interval to 0 disables Provider
+ // and vice versa: Provider.Enabled=false will disable both Provider of new CIDs and the Reprovider of old ones.
+ isProviderEnabled := cfg.Provider.Enabled.WithDefault(config.DefaultProviderEnabled) && cfg.Reprovider.Interval.WithDefault(config.DefaultReproviderInterval) != 0
return fx.Options(
- fx.Provide(BitswapOptions(cfg, shouldBitswapProvide)),
- fx.Provide(OnlineExchange()),
+ fx.Provide(BitswapOptions(cfg)),
+ fx.Provide(Bitswap(isBitswapServerEnabled, isBitswapLibp2pEnabled, isHTTPRetrievalEnabled)),
+ fx.Provide(OnlineExchange(isBitswapLibp2pEnabled)),
+ // Replace our Exchange with a Providing exchange!
+ fx.Decorate(ProvidingExchange(isProviderEnabled && isBitswapServerEnabled)),
fx.Provide(DNSResolver),
fx.Provide(Namesys(ipnsCacheSize, cfg.Ipns.MaxCacheTTL.WithDefault(config.DefaultIpnsMaxCacheTTL))),
fx.Provide(Peering),
@@ -283,10 +360,11 @@ func Online(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part
LibP2P(bcfg, cfg, userResourceOverrides),
OnlineProviders(
- cfg.Experimental.StrategicProviding,
+ isProviderEnabled,
cfg.Reprovider.Strategy.WithDefault(config.DefaultReproviderStrategy),
cfg.Reprovider.Interval.WithDefault(config.DefaultReproviderInterval),
- cfg.Routing.AcceleratedDHTClient,
+ cfg.Routing.AcceleratedDHTClient.WithDefault(config.DefaultAcceleratedDHTClient),
+ int(cfg.Provider.WorkerCount.WithDefault(config.DefaultProviderWorkerCount)),
),
)
}
@@ -306,7 +384,6 @@ func Offline(cfg *config.Config) fx.Option {
// Core groups basic IPFS services
var Core = fx.Options(
- fx.Provide(BlockService),
fx.Provide(Dag),
fx.Provide(FetcherConfig),
fx.Provide(PathResolverConfig),
@@ -337,20 +414,29 @@ func IPFS(ctx context.Context, bcfg *BuildCfg) fx.Option {
return fx.Error(err)
}
+ // Migrate users of deprecated Experimental.ShardingEnabled flag
+ if cfg.Experimental.ShardingEnabled {
+ logger.Fatal("The `Experimental.ShardingEnabled` field is no longer used, please remove it from the config. Use Import.UnixFSHAMTDirectorySizeThreshold instead.")
+ }
+ if !cfg.Internal.UnixFSShardingSizeThreshold.IsDefault() {
+ msg := "The `Internal.UnixFSShardingSizeThreshold` field was renamed to `Import.UnixFSHAMTDirectorySizeThreshold`. Please update your config.\n"
+ if !cfg.Import.UnixFSHAMTDirectorySizeThreshold.IsDefault() {
+ logger.Fatal(msg) // conflicting values, hard fail
+ }
+ logger.Error(msg)
+ cfg.Import.UnixFSHAMTDirectorySizeThreshold = *cfg.Internal.UnixFSShardingSizeThreshold
+ }
+
// Auto-sharding settings
- shardSizeString := cfg.Internal.UnixFSShardingSizeThreshold.WithDefault("256kiB")
- shardSizeInt, err := humanize.ParseBytes(shardSizeString)
+ shardingThresholdString := cfg.Import.UnixFSHAMTDirectorySizeThreshold.WithDefault(config.DefaultUnixFSHAMTDirectorySizeThreshold)
+ shardSingThresholdInt, err := humanize.ParseBytes(shardingThresholdString)
if err != nil {
return fx.Error(err)
}
- uio.HAMTShardingSize = int(shardSizeInt)
-
- // Migrate users of deprecated Experimental.ShardingEnabled flag
- if cfg.Experimental.ShardingEnabled {
- logger.Fatal("The `Experimental.ShardingEnabled` field is no longer used, please remove it from the config.\n" +
- "go-ipfs now automatically shards when directory block is bigger than `" + shardSizeString + "`.\n" +
- "If you need to restore the old behavior (sharding everything) set `Internal.UnixFSShardingSizeThreshold` to `1B`.\n")
- }
+ shardMaxFanout := cfg.Import.UnixFSHAMTDirectoryMaxFanout.WithDefault(config.DefaultUnixFSHAMTDirectoryMaxFanout)
+ // TODO: avoid overriding this globally, see if we can extend Directory interface like Get/SetMaxLinks from https://github.com/ipfs/boxo/pull/906
+ uio.HAMTShardingSize = int(shardSingThresholdInt)
+ uio.DefaultShardWidth = int(shardMaxFanout)
return fx.Options(
bcfgOpts,
@@ -361,7 +447,7 @@ func IPFS(ctx context.Context, bcfg *BuildCfg) fx.Option {
Identity(cfg),
IPNS,
Networked(bcfg, cfg, userResourceOverrides),
-
+ fx.Provide(BlockService(cfg)),
Core,
)
}
diff --git a/core/node/helpers.go b/core/node/helpers.go
index 6e6cb29207f..491d627bf5d 100644
--- a/core/node/helpers.go
+++ b/core/node/helpers.go
@@ -2,36 +2,41 @@ package node
import (
"context"
+ "errors"
"github.com/jbenet/goprocess"
- "github.com/pkg/errors"
"go.uber.org/fx"
)
-type lcProcess struct {
+type lcStartStop struct {
fx.In
- LC fx.Lifecycle
- Proc goprocess.Process
+ LC fx.Lifecycle
}
-// Append wraps ProcessFunc into a goprocess, and appends it to the lifecycle
-func (lp *lcProcess) Append(f goprocess.ProcessFunc) {
+// Append wraps a function into a fx.Hook and appends it to the fx.Lifecycle.
+func (lcss *lcStartStop) Append(f func() func()) {
// Hooks are guaranteed to run in sequence. If a hook fails to start, its
// OnStop won't be executed.
- var proc goprocess.Process
+ var stopFunc func()
- lp.LC.Append(fx.Hook{
+ lcss.LC.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
- proc = lp.Proc.Go(f)
+ if ctx.Err() != nil {
+ return nil
+ }
+ stopFunc = f()
return nil
},
OnStop: func(ctx context.Context) error {
- if proc == nil { // Theoretically this shouldn't ever happen
- return errors.New("lcProcess: proc was nil")
+ if ctx.Err() != nil {
+ return nil
}
-
- return proc.Close() // todo: respect ctx, somehow
+ if stopFunc == nil { // Theoretically this shouldn't ever happen
+ return errors.New("lcStatStop: stopFunc was nil")
+ }
+ stopFunc()
+ return nil
},
})
}
diff --git a/core/node/helpers/helpers.go b/core/node/helpers/helpers.go
index 4c3a0488116..36ac435e8da 100644
--- a/core/node/helpers/helpers.go
+++ b/core/node/helpers/helpers.go
@@ -8,7 +8,7 @@ import (
type MetricsCtx context.Context
-// LifecycleCtx creates a context which will be cancelled when lifecycle stops
+// LifecycleCtx creates a context which will be canceled when lifecycle stops
//
// This is a hack which we need because most of our services use contexts in a
// wrong way
diff --git a/core/node/ipns.go b/core/node/ipns.go
index 5f516d0354b..df9b087c542 100644
--- a/core/node/ipns.go
+++ b/core/node/ipns.go
@@ -45,8 +45,8 @@ func Namesys(cacheSize int, cacheMaxTTL time.Duration) func(rt irouting.ProvideM
}
// IpnsRepublisher runs new IPNS republisher service
-func IpnsRepublisher(repubPeriod time.Duration, recordLifetime time.Duration) func(lcProcess, namesys.NameSystem, repo.Repo, crypto.PrivKey) error {
- return func(lc lcProcess, namesys namesys.NameSystem, repo repo.Repo, privKey crypto.PrivKey) error {
+func IpnsRepublisher(repubPeriod time.Duration, recordLifetime time.Duration) func(lcStartStop, namesys.NameSystem, repo.Repo, crypto.PrivKey) error {
+ return func(lc lcStartStop, namesys namesys.NameSystem, repo repo.Repo, privKey crypto.PrivKey) error {
repub := republisher.NewRepublisher(namesys, repo.Datastore(), privKey, repo.Keystore())
if repubPeriod != 0 {
diff --git a/core/node/libp2p/addrs.go b/core/node/libp2p/addrs.go
index b287c20ff3b..91fae17c5c6 100644
--- a/core/node/libp2p/addrs.go
+++ b/core/node/libp2p/addrs.go
@@ -1,12 +1,24 @@
package libp2p
import (
+ "context"
"fmt"
+ "os"
+ "path/filepath"
+ "time"
+ logging "github.com/ipfs/go-log/v2"
+ version "github.com/ipfs/kubo"
+ "github.com/ipfs/kubo/config"
+ p2pforge "github.com/ipshipyard/p2p-forge/client"
"github.com/libp2p/go-libp2p"
+ "github.com/libp2p/go-libp2p/core/host"
p2pbhost "github.com/libp2p/go-libp2p/p2p/host/basic"
ma "github.com/multiformats/go-multiaddr"
mamask "github.com/whyrusleeping/multiaddr-filter"
+
+ "github.com/caddyserver/certmagic"
+ "go.uber.org/fx"
)
func AddrFilters(filters []string) func() (*ma.Filters, Libp2pOpts, error) {
@@ -87,12 +99,26 @@ func makeAddrsFactory(announce []string, appendAnnouce []string, noAnnounce []st
}, nil
}
-func AddrsFactory(announce []string, appendAnnouce []string, noAnnounce []string) func() (opts Libp2pOpts, err error) {
- return func() (opts Libp2pOpts, err error) {
- addrsFactory, err := makeAddrsFactory(announce, appendAnnouce, noAnnounce)
+func AddrsFactory(announce []string, appendAnnouce []string, noAnnounce []string) interface{} {
+ return func(params struct {
+ fx.In
+ ForgeMgr *p2pforge.P2PForgeCertMgr `optional:"true"`
+ },
+ ) (opts Libp2pOpts, err error) {
+ var addrsFactory p2pbhost.AddrsFactory
+ announceAddrsFactory, err := makeAddrsFactory(announce, appendAnnouce, noAnnounce)
if err != nil {
return opts, err
}
+ if params.ForgeMgr == nil {
+ addrsFactory = announceAddrsFactory
+ } else {
+ addrsFactory = func(multiaddrs []ma.Multiaddr) []ma.Multiaddr {
+ forgeProcessing := params.ForgeMgr.AddressFactory()(multiaddrs)
+ annouceProcessing := announceAddrsFactory(forgeProcessing)
+ return annouceProcessing
+ }
+ }
opts.Opts = append(opts.Opts, libp2p.AddrsFactory(addrsFactory))
return
}
@@ -107,3 +133,55 @@ func ListenOn(addresses []string) interface{} {
}
}
}
+
+func P2PForgeCertMgr(repoPath string, cfg config.AutoTLS, atlsLog *logging.ZapEventLogger) interface{} {
+ return func() (*p2pforge.P2PForgeCertMgr, error) {
+ storagePath := filepath.Join(repoPath, "p2p-forge-certs")
+ rawLogger := atlsLog.Desugar()
+
+ // TODO: this should not be necessary after
+ // https://github.com/ipshipyard/p2p-forge/pull/42 but keep it here for
+ // now to help tracking down any remaining conditions causing
+ // https://github.com/ipshipyard/p2p-forge/issues/8
+ certmagic.Default.Logger = rawLogger.Named("default_fixme")
+ certmagic.DefaultACME.Logger = rawLogger.Named("default_acme_client_fixme")
+
+ registrationDelay := cfg.RegistrationDelay.WithDefault(config.DefaultAutoTLSRegistrationDelay)
+ if cfg.Enabled == config.True && cfg.RegistrationDelay.IsDefault() {
+ // Skip delay if user explicitly enabled AutoTLS.Enabled in config
+ // and did not set custom AutoTLS.RegistrationDelay
+ registrationDelay = 0 * time.Second
+ }
+
+ certStorage := &certmagic.FileStorage{Path: storagePath}
+ certMgr, err := p2pforge.NewP2PForgeCertMgr(
+ p2pforge.WithLogger(rawLogger.Sugar()),
+ p2pforge.WithForgeDomain(cfg.DomainSuffix.WithDefault(config.DefaultDomainSuffix)),
+ p2pforge.WithForgeRegistrationEndpoint(cfg.RegistrationEndpoint.WithDefault(config.DefaultRegistrationEndpoint)),
+ p2pforge.WithRegistrationDelay(registrationDelay),
+ p2pforge.WithCAEndpoint(cfg.CAEndpoint.WithDefault(config.DefaultCAEndpoint)),
+ p2pforge.WithForgeAuth(cfg.RegistrationToken.WithDefault(os.Getenv(p2pforge.ForgeAuthEnv))),
+ p2pforge.WithUserAgent(version.GetUserAgentVersion()),
+ p2pforge.WithCertificateStorage(certStorage),
+ p2pforge.WithShortForgeAddrs(cfg.ShortAddrs.WithDefault(config.DefaultAutoTLSShortAddrs)),
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ return certMgr, nil
+ }
+}
+
+func StartP2PAutoTLS(lc fx.Lifecycle, certMgr *p2pforge.P2PForgeCertMgr, h host.Host) {
+ lc.Append(fx.Hook{
+ OnStart: func(ctx context.Context) error {
+ certMgr.ProvideHost(h)
+ return certMgr.Start()
+ },
+ OnStop: func(ctx context.Context) error {
+ certMgr.Stop()
+ return nil
+ },
+ })
+}
diff --git a/core/node/libp2p/dns.go b/core/node/libp2p/dns.go
index 1c56a2c0a87..2ee73b4c9f4 100644
--- a/core/node/libp2p/dns.go
+++ b/core/node/libp2p/dns.go
@@ -2,10 +2,11 @@ package libp2p
import (
"github.com/libp2p/go-libp2p"
+ "github.com/libp2p/go-libp2p/p2p/net/swarm"
madns "github.com/multiformats/go-multiaddr-dns"
)
func MultiaddrResolver(rslv *madns.Resolver) (opts Libp2pOpts, err error) {
- opts.Opts = append(opts.Opts, libp2p.MultiaddrResolver(rslv))
+ opts.Opts = append(opts.Opts, libp2p.MultiaddrResolver(swarm.ResolverFromMaDNS{Resolver: rslv}))
return opts, nil
}
diff --git a/core/node/libp2p/host.go b/core/node/libp2p/host.go
index afbd2080c07..7950f3dc6bc 100644
--- a/core/node/libp2p/host.go
+++ b/core/node/libp2p/host.go
@@ -11,6 +11,7 @@ import (
"github.com/libp2p/go-libp2p/core/routing"
routedhost "github.com/libp2p/go-libp2p/p2p/host/routed"
+ "github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core/node/helpers"
"github.com/ipfs/kubo/repo"
@@ -60,6 +61,7 @@ func Host(mctx helpers.MetricsCtx, lc fx.Lifecycle, params P2PHostIn) (out P2PHo
BootstrapPeers: bootstrappers,
OptimisticProvide: cfg.Experimental.OptimisticProvide,
OptimisticProvideJobsPoolSize: cfg.Experimental.OptimisticProvideJobsPoolSize,
+ LoopbackAddressesOnLanDHT: cfg.Routing.LoopbackAddressesOnLanDHT.WithDefault(config.DefaultLoopbackAddressesOnLanDHT),
}
opts = append(opts, libp2p.Routing(func(h host.Host) (routing.PeerRouting, error) {
args := routingOptArgs
diff --git a/core/node/libp2p/libp2p.go b/core/node/libp2p/libp2p.go
index e6977b061e8..1adced34fcd 100644
--- a/core/node/libp2p/libp2p.go
+++ b/core/node/libp2p/libp2p.go
@@ -8,7 +8,7 @@ import (
version "github.com/ipfs/kubo"
config "github.com/ipfs/kubo/config"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
diff --git a/core/node/libp2p/nat.go b/core/node/libp2p/nat.go
index fc72d7fb3c0..6d3cd09c38e 100644
--- a/core/node/libp2p/nat.go
+++ b/core/node/libp2p/nat.go
@@ -9,7 +9,7 @@ import (
var NatPortMap = simpleOpt(libp2p.NATPortMap())
-func AutoNATService(throttle *config.AutoNATThrottleConfig) func() Libp2pOpts {
+func AutoNATService(throttle *config.AutoNATThrottleConfig, v1only bool) func() Libp2pOpts {
return func() (opts Libp2pOpts) {
opts.Opts = append(opts.Opts, libp2p.EnableNATService())
if throttle != nil {
@@ -21,6 +21,13 @@ func AutoNATService(throttle *config.AutoNATThrottleConfig) func() Libp2pOpts {
),
)
}
+
+ // While V1 still exists and V2 rollout is in progress
+ // (https://github.com/ipfs/kubo/issues/10091) we check a flag that
+ // allows users to disable V2 and run V1-only mode
+ if !v1only {
+ opts.Opts = append(opts.Opts, libp2p.EnableAutoNATv2())
+ }
return opts
}
}
diff --git a/core/node/libp2p/rcmgr.go b/core/node/libp2p/rcmgr.go
index 8ec83601b51..91a19bc2eef 100644
--- a/core/node/libp2p/rcmgr.go
+++ b/core/node/libp2p/rcmgr.go
@@ -3,11 +3,16 @@ package libp2p
import (
"context"
"encoding/json"
+ "errors"
"fmt"
"os"
"path/filepath"
- "github.com/benbjohnson/clock"
+ "github.com/ipfs/kubo/config"
+ "github.com/ipfs/kubo/core/node/helpers"
+ "github.com/ipfs/kubo/repo"
+
+ "github.com/filecoin-project/go-clock"
logging "github.com/ipfs/go-log/v2"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/network"
@@ -16,19 +21,15 @@ import (
rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
"github.com/multiformats/go-multiaddr"
"go.uber.org/fx"
-
- "github.com/ipfs/kubo/config"
- "github.com/ipfs/kubo/core/node/helpers"
- "github.com/ipfs/kubo/repo"
)
var rcmgrLogger = logging.Logger("rcmgr")
const NetLimitTraceFilename = "rcmgr.json.gz"
-var ErrNoResourceMgr = fmt.Errorf("missing ResourceMgr: make sure the daemon is running with Swarm.ResourceMgr.Enabled")
+var ErrNoResourceMgr = errors.New("missing ResourceMgr: make sure the daemon is running with Swarm.ResourceMgr.Enabled")
-func ResourceManager(cfg config.SwarmConfig, userResourceOverrides rcmgr.PartialLimitConfig) interface{} {
+func ResourceManager(repoPath string, cfg config.SwarmConfig, userResourceOverrides rcmgr.PartialLimitConfig) interface{} {
return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo) (network.ResourceManager, Libp2pOpts, error) {
var manager network.ResourceManager
var opts Libp2pOpts
@@ -46,11 +47,6 @@ func ResourceManager(cfg config.SwarmConfig, userResourceOverrides rcmgr.Partial
if enabled {
log.Debug("libp2p resource manager is enabled")
- repoPath, err := config.PathRoot()
- if err != nil {
- return nil, opts, fmt.Errorf("opening IPFS_PATH: %w", err)
- }
-
limitConfig, msg, err := LimitConfig(cfg, userResourceOverrides)
if err != nil {
return nil, opts, fmt.Errorf("creating final Resource Manager config: %w", err)
@@ -74,7 +70,21 @@ filled in with autocomputed defaults.`)
return nil, opts, err
}
- ropts := []rcmgr.Option{rcmgr.WithMetrics(createRcmgrMetrics()), rcmgr.WithTraceReporter(str)}
+ ropts := []rcmgr.Option{
+ rcmgr.WithTraceReporter(str),
+ rcmgr.WithLimitPerSubnet(
+ nil,
+ []rcmgr.ConnLimitPerSubnet{
+ {
+ ConnCount: 16,
+ PrefixLength: 56,
+ },
+ {
+ ConnCount: 8 * 16,
+ PrefixLength: 48,
+ },
+ }),
+ }
if len(cfg.ResourceMgr.Allowlist) > 0 {
var mas []multiaddr.Multiaddr
@@ -471,7 +481,7 @@ resource manager System.ConnsInbound (%d) must be bigger than ConnMgr.HighWater
See: https://github.com/ipfs/kubo/blob/master/docs/libp2p-resource-management.md#how-does-the-resource-manager-resourcemgr-relate-to-the-connection-manager-connmgr
`, rcm.System.ConnsInbound, highWater)
}
- if rcm.System.Streams > rcmgr.DefaultLimit || rcm.System.Streams == rcmgr.BlockAllLimit && int64(rcm.System.Streams) <= highWater {
+ if (rcm.System.Streams > rcmgr.DefaultLimit || rcm.System.Streams == rcmgr.BlockAllLimit) && int64(rcm.System.Streams) <= highWater {
// nolint
return fmt.Errorf(`
Unable to initialize libp2p due to conflicting resource manager limit configuration.
diff --git a/core/node/libp2p/rcmgr_logging.go b/core/node/libp2p/rcmgr_logging.go
index 56e017b82ea..4a0b1110211 100644
--- a/core/node/libp2p/rcmgr_logging.go
+++ b/core/node/libp2p/rcmgr_logging.go
@@ -6,7 +6,7 @@ import (
"sync"
"time"
- "github.com/benbjohnson/clock"
+ "github.com/filecoin-project/go-clock"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/protocol"
diff --git a/core/node/libp2p/rcmgr_logging_test.go b/core/node/libp2p/rcmgr_logging_test.go
index 559a3fec33f..a2b4e808580 100644
--- a/core/node/libp2p/rcmgr_logging_test.go
+++ b/core/node/libp2p/rcmgr_logging_test.go
@@ -5,7 +5,7 @@ import (
"testing"
"time"
- "github.com/benbjohnson/clock"
+ "github.com/filecoin-project/go-clock"
"github.com/libp2p/go-libp2p/core/network"
rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
ma "github.com/multiformats/go-multiaddr"
diff --git a/core/node/libp2p/rcmgr_metrics.go b/core/node/libp2p/rcmgr_metrics.go
deleted file mode 100644
index f8b1a7daa3b..00000000000
--- a/core/node/libp2p/rcmgr_metrics.go
+++ /dev/null
@@ -1,251 +0,0 @@
-package libp2p
-
-import (
- "errors"
- "strconv"
-
- "github.com/libp2p/go-libp2p/core/network"
- "github.com/libp2p/go-libp2p/core/peer"
- "github.com/libp2p/go-libp2p/core/protocol"
- rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
-
- "github.com/prometheus/client_golang/prometheus"
-)
-
-func mustRegister(c prometheus.Collector) {
- err := prometheus.Register(c)
- are := prometheus.AlreadyRegisteredError{}
- if errors.As(err, &are) {
- return
- }
- if err != nil {
- panic(err)
- }
-}
-
-func createRcmgrMetrics() rcmgr.MetricsReporter {
- const (
- direction = "direction"
- usesFD = "usesFD"
- protocol = "protocol"
- service = "service"
- )
-
- connAllowed := prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "libp2p_rcmgr_conns_allowed_total",
- Help: "allowed connections",
- },
- []string{direction, usesFD},
- )
- mustRegister(connAllowed)
-
- connBlocked := prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "libp2p_rcmgr_conns_blocked_total",
- Help: "blocked connections",
- },
- []string{direction, usesFD},
- )
- mustRegister(connBlocked)
-
- streamAllowed := prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "libp2p_rcmgr_streams_allowed_total",
- Help: "allowed streams",
- },
- []string{direction},
- )
- mustRegister(streamAllowed)
-
- streamBlocked := prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "libp2p_rcmgr_streams_blocked_total",
- Help: "blocked streams",
- },
- []string{direction},
- )
- mustRegister(streamBlocked)
-
- peerAllowed := prometheus.NewCounter(prometheus.CounterOpts{
- Name: "libp2p_rcmgr_peers_allowed_total",
- Help: "allowed peers",
- })
- mustRegister(peerAllowed)
-
- peerBlocked := prometheus.NewCounter(prometheus.CounterOpts{
- Name: "libp2p_rcmgr_peer_blocked_total",
- Help: "blocked peers",
- })
- mustRegister(peerBlocked)
-
- protocolAllowed := prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "libp2p_rcmgr_protocols_allowed_total",
- Help: "allowed streams attached to a protocol",
- },
- []string{protocol},
- )
- mustRegister(protocolAllowed)
-
- protocolBlocked := prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "libp2p_rcmgr_protocols_blocked_total",
- Help: "blocked streams attached to a protocol",
- },
- []string{protocol},
- )
- mustRegister(protocolBlocked)
-
- protocolPeerBlocked := prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "libp2p_rcmgr_protocols_for_peer_blocked_total",
- Help: "blocked streams attached to a protocol for a specific peer",
- },
- []string{protocol},
- )
- mustRegister(protocolPeerBlocked)
-
- serviceAllowed := prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "libp2p_rcmgr_services_allowed_total",
- Help: "allowed streams attached to a service",
- },
- []string{service},
- )
- mustRegister(serviceAllowed)
-
- serviceBlocked := prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "libp2p_rcmgr_services_blocked_total",
- Help: "blocked streams attached to a service",
- },
- []string{service},
- )
- mustRegister(serviceBlocked)
-
- servicePeerBlocked := prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "libp2p_rcmgr_service_for_peer_blocked_total",
- Help: "blocked streams attached to a service for a specific peer",
- },
- []string{service},
- )
- mustRegister(servicePeerBlocked)
-
- memoryAllowed := prometheus.NewCounter(prometheus.CounterOpts{
- Name: "libp2p_rcmgr_memory_allocations_allowed_total",
- Help: "allowed memory allocations",
- })
- mustRegister(memoryAllowed)
-
- memoryBlocked := prometheus.NewCounter(prometheus.CounterOpts{
- Name: "libp2p_rcmgr_memory_allocations_blocked_total",
- Help: "blocked memory allocations",
- })
- mustRegister(memoryBlocked)
-
- return rcmgrMetrics{
- connAllowed,
- connBlocked,
- streamAllowed,
- streamBlocked,
- peerAllowed,
- peerBlocked,
- protocolAllowed,
- protocolBlocked,
- protocolPeerBlocked,
- serviceAllowed,
- serviceBlocked,
- servicePeerBlocked,
- memoryAllowed,
- memoryBlocked,
- }
-}
-
-// Failsafe to ensure interface from go-libp2p-resource-manager is implemented
-var _ rcmgr.MetricsReporter = rcmgrMetrics{}
-
-type rcmgrMetrics struct {
- connAllowed *prometheus.CounterVec
- connBlocked *prometheus.CounterVec
- streamAllowed *prometheus.CounterVec
- streamBlocked *prometheus.CounterVec
- peerAllowed prometheus.Counter
- peerBlocked prometheus.Counter
- protocolAllowed *prometheus.CounterVec
- protocolBlocked *prometheus.CounterVec
- protocolPeerBlocked *prometheus.CounterVec
- serviceAllowed *prometheus.CounterVec
- serviceBlocked *prometheus.CounterVec
- servicePeerBlocked *prometheus.CounterVec
- memoryAllowed prometheus.Counter
- memoryBlocked prometheus.Counter
-}
-
-func getDirection(d network.Direction) string {
- switch d {
- default:
- return ""
- case network.DirInbound:
- return "inbound"
- case network.DirOutbound:
- return "outbound"
- }
-}
-
-func (r rcmgrMetrics) AllowConn(dir network.Direction, usefd bool) {
- r.connAllowed.WithLabelValues(getDirection(dir), strconv.FormatBool(usefd)).Inc()
-}
-
-func (r rcmgrMetrics) BlockConn(dir network.Direction, usefd bool) {
- r.connBlocked.WithLabelValues(getDirection(dir), strconv.FormatBool(usefd)).Inc()
-}
-
-func (r rcmgrMetrics) AllowStream(_ peer.ID, dir network.Direction) {
- r.streamAllowed.WithLabelValues(getDirection(dir)).Inc()
-}
-
-func (r rcmgrMetrics) BlockStream(_ peer.ID, dir network.Direction) {
- r.streamBlocked.WithLabelValues(getDirection(dir)).Inc()
-}
-
-func (r rcmgrMetrics) AllowPeer(_ peer.ID) {
- r.peerAllowed.Inc()
-}
-
-func (r rcmgrMetrics) BlockPeer(_ peer.ID) {
- r.peerBlocked.Inc()
-}
-
-func (r rcmgrMetrics) AllowProtocol(proto protocol.ID) {
- r.protocolAllowed.WithLabelValues(string(proto)).Inc()
-}
-
-func (r rcmgrMetrics) BlockProtocol(proto protocol.ID) {
- r.protocolBlocked.WithLabelValues(string(proto)).Inc()
-}
-
-func (r rcmgrMetrics) BlockProtocolPeer(proto protocol.ID, _ peer.ID) {
- r.protocolPeerBlocked.WithLabelValues(string(proto)).Inc()
-}
-
-func (r rcmgrMetrics) AllowService(svc string) {
- r.serviceAllowed.WithLabelValues(svc).Inc()
-}
-
-func (r rcmgrMetrics) BlockService(svc string) {
- r.serviceBlocked.WithLabelValues(svc).Inc()
-}
-
-func (r rcmgrMetrics) BlockServicePeer(svc string, _ peer.ID) {
- r.servicePeerBlocked.WithLabelValues(svc).Inc()
-}
-
-func (r rcmgrMetrics) AllowMemory(_ int) {
- r.memoryAllowed.Inc()
-}
-
-func (r rcmgrMetrics) BlockMemory(_ int) {
- r.memoryBlocked.Inc()
-}
diff --git a/core/node/libp2p/relay.go b/core/node/libp2p/relay.go
index 89567e30d82..dd56835fba4 100644
--- a/core/node/libp2p/relay.go
+++ b/core/node/libp2p/relay.go
@@ -33,13 +33,12 @@ func RelayService(enable bool, relayOpts config.RelayService) func() (opts Libp2
Data: relayOpts.ConnectionDataLimit.WithDefault(def.Limit.Data),
Duration: relayOpts.ConnectionDurationLimit.WithDefault(def.Limit.Duration),
},
- MaxCircuits: int(relayOpts.MaxCircuits.WithDefault(int64(def.MaxCircuits))),
- BufferSize: int(relayOpts.BufferSize.WithDefault(int64(def.BufferSize))),
- ReservationTTL: relayOpts.ReservationTTL.WithDefault(def.ReservationTTL),
- MaxReservations: int(relayOpts.MaxReservations.WithDefault(int64(def.MaxReservations))),
- MaxReservationsPerIP: int(relayOpts.MaxReservationsPerIP.WithDefault(int64(def.MaxReservationsPerIP))),
- MaxReservationsPerPeer: int(relayOpts.MaxReservationsPerPeer.WithDefault(int64(def.MaxReservationsPerPeer))),
- MaxReservationsPerASN: int(relayOpts.MaxReservationsPerASN.WithDefault(int64(def.MaxReservationsPerASN))),
+ MaxCircuits: int(relayOpts.MaxCircuits.WithDefault(int64(def.MaxCircuits))),
+ BufferSize: int(relayOpts.BufferSize.WithDefault(int64(def.BufferSize))),
+ ReservationTTL: relayOpts.ReservationTTL.WithDefault(def.ReservationTTL),
+ MaxReservations: int(relayOpts.MaxReservations.WithDefault(int64(def.MaxReservations))),
+ MaxReservationsPerIP: int(relayOpts.MaxReservationsPerIP.WithDefault(int64(def.MaxReservationsPerIP))),
+ MaxReservationsPerASN: int(relayOpts.MaxReservationsPerASN.WithDefault(int64(def.MaxReservationsPerASN))),
})))
}
return
diff --git a/core/node/libp2p/routing.go b/core/node/libp2p/routing.go
index 98234f5ceda..94c99e5dd4e 100644
--- a/core/node/libp2p/routing.go
+++ b/core/node/libp2p/routing.go
@@ -90,7 +90,7 @@ func BaseRouting(cfg *config.Config) interface{} {
}
}
- if dualDHT != nil && cfg.Routing.AcceleratedDHTClient {
+ if dualDHT != nil && cfg.Routing.AcceleratedDHTClient.WithDefault(config.DefaultAcceleratedDHTClient) {
cfg, err := in.Repo.Config()
if err != nil {
return out, err
@@ -184,9 +184,8 @@ type p2pOnlineRoutingIn struct {
Validator record.Validator
}
-// Routing will get all routers obtained from different methods
-// (delegated routers, pub-sub, and so on) and add them all together
-// using a TieredRouter.
+// Routing will get all routers obtained from different methods (delegated
+// routers, pub-sub, and so on) and add them all together using a TieredRouter.
func Routing(in p2pOnlineRoutingIn) irouting.ProvideManyRouter {
routers := in.Routers
@@ -206,7 +205,8 @@ func Routing(in p2pOnlineRoutingIn) irouting.ProvideManyRouter {
return routinghelpers.NewComposableParallel(cRouters)
}
-// OfflineRouting provides a special Router to the routers list when we are creating a offline node.
+// OfflineRouting provides a special Router to the routers list when we are
+// creating an offline node.
func OfflineRouting(dstore ds.Datastore, validator record.Validator) p2pRouterOut {
return p2pRouterOut{
Router: Router{
diff --git a/core/node/libp2p/routingopt.go b/core/node/libp2p/routingopt.go
index a58a8c49885..43565265b37 100644
--- a/core/node/libp2p/routingopt.go
+++ b/core/node/libp2p/routingopt.go
@@ -3,7 +3,6 @@ package libp2p
import (
"context"
"os"
- "strings"
"time"
"github.com/ipfs/go-datastore"
@@ -26,38 +25,49 @@ type RoutingOptionArgs struct {
BootstrapPeers []peer.AddrInfo
OptimisticProvide bool
OptimisticProvideJobsPoolSize int
+ LoopbackAddressesOnLanDHT bool
}
type RoutingOption func(args RoutingOptionArgs) (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, " ")
- }
-}
+var noopRouter = routinghelpers.Null{}
func constructDefaultHTTPRouters(cfg *config.Config) ([]*routinghelpers.ParallelRouter, error) {
var routers []*routinghelpers.ParallelRouter
+ httpRetrievalEnabled := cfg.HTTPRetrieval.Enabled.WithDefault(config.DefaultHTTPRetrievalEnabled)
+
+ // Use config.DefaultHTTPRouters if custom override was sent via config.EnvHTTPRouters
+ // or if user did not set any preference in cfg.Routing.DelegatedRouters
+ var httpRouterEndpoints []string
+ if os.Getenv(config.EnvHTTPRouters) != "" || len(cfg.Routing.DelegatedRouters) == 0 {
+ httpRouterEndpoints = config.DefaultHTTPRouters
+ } else {
+ httpRouterEndpoints = cfg.Routing.DelegatedRouters
+ }
+
// Append HTTP routers for additional speed
- for _, endpoint := range defaultHTTPRouters {
- httpRouter, err := irouting.ConstructHTTPRouter(endpoint, cfg.Identity.PeerID, httpAddrsFromConfig(cfg.Addresses), cfg.Identity.PrivKey)
+ for _, endpoint := range httpRouterEndpoints {
+ httpRouter, err := irouting.ConstructHTTPRouter(endpoint, cfg.Identity.PeerID, httpAddrsFromConfig(cfg.Addresses), cfg.Identity.PrivKey, httpRetrievalEnabled)
if err != nil {
return nil, err
}
-
+ // Mapping router to /routing/v1/* endpoints
+ // https://specs.ipfs.tech/routing/http-routing-v1/
r := &irouting.Composer{
- GetValueRouter: routinghelpers.Null{},
- PutValueRouter: routinghelpers.Null{},
- ProvideRouter: routinghelpers.Null{}, // modify this when indexers supports provide
- FindPeersRouter: routinghelpers.Null{},
- FindProvidersRouter: httpRouter,
+ GetValueRouter: httpRouter, // GET /routing/v1/ipns
+ PutValueRouter: httpRouter, // PUT /routing/v1/ipns
+ ProvideRouter: noopRouter, // we don't have spec for sending provides to /routing/v1 (revisit once https://github.com/ipfs/specs/pull/378 or similar is ratified)
+ FindPeersRouter: httpRouter, // /routing/v1/peers
+ FindProvidersRouter: httpRouter, // /routing/v1/providers
+ }
+
+ if endpoint == config.CidContactRoutingURL {
+ // Special-case: cid.contact only supports /routing/v1/providers/cid
+ // we disable other endpoints to avoid sending requests that always fail
+ r.GetValueRouter = noopRouter
+ r.PutValueRouter = noopRouter
+ r.ProvideRouter = noopRouter
+ r.FindPeersRouter = noopRouter
}
routers = append(routers, &routinghelpers.ParallelRouter{
@@ -116,16 +126,24 @@ func constructDHTRouting(mode dht.ModeOpt) RoutingOption {
if args.OptimisticProvideJobsPoolSize != 0 {
dhtOpts = append(dhtOpts, dht.OptimisticProvideJobsPoolSize(args.OptimisticProvideJobsPoolSize))
}
+ wanOptions := []dht.Option{
+ dht.BootstrapPeers(args.BootstrapPeers...),
+ }
+ lanOptions := []dht.Option{}
+ if args.LoopbackAddressesOnLanDHT {
+ lanOptions = append(lanOptions, dht.AddressFilter(nil))
+ }
return dual.New(
args.Ctx, args.Host,
dual.DHTOption(dhtOpts...),
- dual.WanDHTOption(dht.BootstrapPeers(args.BootstrapPeers...)),
+ dual.WanDHTOption(wanOptions...),
+ dual.LanDHTOption(lanOptions...),
)
}
}
// ConstructDelegatedRouting is used when Routing.Type = "custom"
-func ConstructDelegatedRouting(routers config.Routers, methods config.Methods, peerID string, addrs config.Addresses, privKey string) RoutingOption {
+func ConstructDelegatedRouting(routers config.Routers, methods config.Methods, peerID string, addrs config.Addresses, privKey string, httpRetrieval bool) RoutingOption {
return func(args RoutingOptionArgs) (routing.Routing, error) {
return irouting.Parse(routers, methods,
&irouting.ExtraDHTParams{
@@ -136,9 +154,10 @@ func ConstructDelegatedRouting(routers config.Routers, methods config.Methods, p
Context: args.Ctx,
},
&irouting.ExtraHTTPParams{
- PeerID: peerID,
- Addrs: httpAddrsFromConfig(addrs),
- PrivKeyB64: privKey,
+ PeerID: peerID,
+ Addrs: httpAddrsFromConfig(addrs),
+ PrivKeyB64: privKey,
+ HTTPRetrieval: httpRetrieval,
},
)
}
diff --git a/core/node/libp2p/sec.go b/core/node/libp2p/sec.go
index 0dc6940d8f9..5a3e95e3150 100644
--- a/core/node/libp2p/sec.go
+++ b/core/node/libp2p/sec.go
@@ -22,11 +22,11 @@ func Security(enabled bool, tptConfig config.Transports) interface{} {
return func() (opts Libp2pOpts) {
opts.Opts = append(opts.Opts, prioritizeOptions([]priorityOption{{
priority: tptConfig.Security.TLS,
- defaultPriority: 200,
+ defaultPriority: 100,
opt: libp2p.Security(tls.ID, tls.New),
}, {
priority: tptConfig.Security.Noise,
- defaultPriority: 100,
+ defaultPriority: 200,
opt: libp2p.Security(noise.ID, noise.New),
}}))
return opts
diff --git a/core/node/libp2p/smux.go b/core/node/libp2p/smux.go
index d52b306d85b..5b87f7d0821 100644
--- a/core/node/libp2p/smux.go
+++ b/core/node/libp2p/smux.go
@@ -1,7 +1,7 @@
package libp2p
import (
- "fmt"
+ "errors"
"os"
"github.com/ipfs/kubo/config"
@@ -12,10 +12,10 @@ import (
func makeSmuxTransportOption(tptConfig config.Transports) (libp2p.Option, error) {
if prefs := os.Getenv("LIBP2P_MUX_PREFS"); prefs != "" {
- return nil, fmt.Errorf("configuring muxers with LIBP2P_MUX_PREFS is no longer supported, use Swarm.Transports.Multiplexers")
+ return nil, errors.New("configuring muxers with LIBP2P_MUX_PREFS is no longer supported, use Swarm.Transports.Multiplexers")
}
if tptConfig.Multiplexers.Yamux < 0 {
- return nil, fmt.Errorf("running libp2p with Swarm.Transports.Multiplexers.Yamux disabled is not supported")
+ return nil, errors.New("running libp2p with Swarm.Transports.Multiplexers.Yamux disabled is not supported")
}
return libp2p.Muxer(yamux.ID, yamux.DefaultTransport), nil
diff --git a/core/node/libp2p/transport.go b/core/node/libp2p/transport.go
index 797917b72cb..3e5ab956888 100644
--- a/core/node/libp2p/transport.go
+++ b/core/node/libp2p/transport.go
@@ -2,8 +2,10 @@ package libp2p
import (
"fmt"
+ "os"
"github.com/ipfs/kubo/config"
+ "github.com/ipshipyard/p2p-forge/client"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/metrics"
quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
@@ -16,20 +18,35 @@ import (
)
func Transports(tptConfig config.Transports) interface{} {
- return func(pnet struct {
+ return func(params struct {
fx.In
- Fprint PNetFingerprint `optional:"true"`
+ Fprint PNetFingerprint `optional:"true"`
+ ForgeMgr *client.P2PForgeCertMgr `optional:"true"`
},
) (opts Libp2pOpts, err error) {
- privateNetworkEnabled := pnet.Fprint != nil
+ privateNetworkEnabled := params.Fprint != nil
- if tptConfig.Network.TCP.WithDefault(true) {
+ tcpEnabled := tptConfig.Network.TCP.WithDefault(true)
+ wsEnabled := tptConfig.Network.Websocket.WithDefault(true)
+ if tcpEnabled {
// TODO(9290): Make WithMetrics configurable
opts.Opts = append(opts.Opts, libp2p.Transport(tcp.NewTCPTransport, tcp.WithMetrics()))
}
- if tptConfig.Network.Websocket.WithDefault(true) {
- opts.Opts = append(opts.Opts, libp2p.Transport(websocket.New))
+ if wsEnabled {
+ if params.ForgeMgr == nil {
+ opts.Opts = append(opts.Opts, libp2p.Transport(websocket.New))
+ } else {
+ opts.Opts = append(opts.Opts, libp2p.Transport(websocket.New, websocket.WithTLSConfig(params.ForgeMgr.TLSConfig())))
+ }
+ }
+
+ if tcpEnabled && wsEnabled && os.Getenv("LIBP2P_TCP_MUX") != "false" {
+ if privateNetworkEnabled {
+ log.Error("libp2p.ShareTCPListener() is not supported in private networks, please disable Swarm.Transports.Network.Websocket or run with LIBP2P_TCP_MUX=false to make this message go away")
+ } else {
+ opts.Opts = append(opts.Opts, libp2p.ShareTCPListener())
+ }
}
if tptConfig.Network.QUIC.WithDefault(!privateNetworkEnabled) {
@@ -50,7 +67,7 @@ func Transports(tptConfig config.Transports) interface{} {
opts.Opts = append(opts.Opts, libp2p.Transport(webtransport.New))
}
- if tptConfig.Network.WebRTCDirect.WithDefault(false) {
+ if tptConfig.Network.WebRTCDirect.WithDefault(!privateNetworkEnabled) {
if privateNetworkEnabled {
return opts, fmt.Errorf(
"WebRTC Direct transport does not support private networks, please disable Swarm.Transports.Network.WebRTCDirect",
diff --git a/core/node/provider.go b/core/node/provider.go
index c1c99e6003f..79fed2a4f99 100644
--- a/core/node/provider.go
+++ b/core/node/provider.go
@@ -7,22 +7,29 @@ import (
"github.com/ipfs/boxo/blockstore"
"github.com/ipfs/boxo/fetcher"
+ "github.com/ipfs/boxo/mfs"
pin "github.com/ipfs/boxo/pinning/pinner"
provider "github.com/ipfs/boxo/provider"
+ "github.com/ipfs/go-cid"
"github.com/ipfs/kubo/repo"
irouting "github.com/ipfs/kubo/routing"
"go.uber.org/fx"
)
-func ProviderSys(reprovideInterval time.Duration, acceleratedDHTClient bool) fx.Option {
- const magicThroughputReportCount = 128
+// The size of a batch that will be used for calculating average announcement
+// time per CID, inside of boxo/provider.ThroughputReport
+// and in 'ipfs stats provide' report.
+const sampledBatchSize = 1000
+
+func ProviderSys(reprovideInterval time.Duration, acceleratedDHTClient bool, provideWorkerCount int) fx.Option {
return fx.Provide(func(lc fx.Lifecycle, cr irouting.ProvideManyRouter, keyProvider provider.KeyChanFunc, repo repo.Repo, bs blockstore.Blockstore) (provider.System, error) {
opts := []provider.Option{
provider.Online(cr),
provider.ReproviderInterval(reprovideInterval),
provider.KeyProvider(keyProvider),
+ provider.ProvideWorkerCount(provideWorkerCount),
}
- if !acceleratedDHTClient {
+ if !acceleratedDHTClient && reprovideInterval > 0 {
// The estimation kinda suck if you are running with accelerated DHT client,
// given this message is just trying to push people to use the acceleratedDHTClient
// let's not report on through if it's in use
@@ -64,7 +71,7 @@ func ProviderSys(reprovideInterval time.Duration, acceleratedDHTClient bool) fx.
🔔🔔🔔 YOU MAY BE FALLING BEHIND DHT REPROVIDES! 🔔🔔🔔
⚠️ Your system might be struggling to keep up with DHT reprovides!
-This means your content could partially or completely inaccessible on the network.
+This means your content could be partially or completely inaccessible on the network.
We observed that you recently provided %d keys at an average rate of %v per key.
🕑 An attempt to estimate your blockstore size timed out after 5 minutes,
@@ -83,13 +90,17 @@ https://github.com/ipfs/kubo/blob/master/docs/config.md#routingaccelerateddhtcli
}
// How long per block that lasts us.
- expectedProvideSpeed := reprovideInterval / time.Duration(count)
+ expectedProvideSpeed := reprovideInterval
+ if count > 0 {
+ expectedProvideSpeed = reprovideInterval / time.Duration(count)
+ }
+
if avgProvideSpeed > expectedProvideSpeed {
logger.Errorf(`
🔔🔔🔔 YOU ARE FALLING BEHIND DHT REPROVIDES! 🔔🔔🔔
⚠️ Your system is struggling to keep up with DHT reprovides!
-This means your content could partially or completely inaccessible on the network.
+This means your content could be partially or completely inaccessible on the network.
We observed that you recently provided %d keys at an average rate of %v per key.
💾 Your total CID count is ~%d which would total at %v reprovide process.
@@ -101,7 +112,7 @@ https://github.com/ipfs/kubo/blob/master/docs/config.md#routingaccelerateddhtcli
keysProvided, avgProvideSpeed, count, avgProvideSpeed*time.Duration(count), reprovideInterval)
}
return false
- }, magicThroughputReportCount))
+ }, sampledBatchSize))
}
sys, err := provider.New(repo.Datastore(), opts...)
if err != nil {
@@ -121,26 +132,22 @@ https://github.com/ipfs/kubo/blob/master/docs/config.md#routingaccelerateddhtcli
// ONLINE/OFFLINE
// OnlineProviders groups units managing provider routing records online
-func OnlineProviders(useStrategicProviding bool, reprovideStrategy string, reprovideInterval time.Duration, acceleratedDHTClient bool) fx.Option {
- if useStrategicProviding {
+func OnlineProviders(provide bool, reprovideStrategy string, reprovideInterval time.Duration, acceleratedDHTClient bool, provideWorkerCount int) fx.Option {
+ if !provide {
return OfflineProviders()
}
var keyProvider fx.Option
switch reprovideStrategy {
- case "all", "":
- keyProvider = fx.Provide(provider.NewBlockstoreProvider)
- case "roots":
- keyProvider = fx.Provide(pinnedProviderStrategy(true))
- case "pinned":
- keyProvider = fx.Provide(pinnedProviderStrategy(false))
+ case "all", "", "roots", "pinned", "mfs", "pinned+mfs", "flat":
+ keyProvider = fx.Provide(newProvidingStrategy(reprovideStrategy))
default:
return fx.Error(fmt.Errorf("unknown reprovider strategy %q", reprovideStrategy))
}
return fx.Options(
keyProvider,
- ProviderSys(reprovideInterval, acceleratedDHTClient),
+ ProviderSys(reprovideInterval, acceleratedDHTClient, provideWorkerCount),
)
}
@@ -149,13 +156,67 @@ func OfflineProviders() fx.Option {
return fx.Provide(provider.NewNoopProvider)
}
-func pinnedProviderStrategy(onlyRoots bool) interface{} {
+func mfsProvider(mfsRoot *mfs.Root, fetcher fetcher.Factory) provider.KeyChanFunc {
+ return func(ctx context.Context) (<-chan cid.Cid, error) {
+ err := mfsRoot.FlushMemFree(ctx)
+ if err != nil {
+ return nil, fmt.Errorf("error flushing mfs, cannot provide MFS: %w", err)
+ }
+ rootNode, err := mfsRoot.GetDirectory().GetNode()
+ if err != nil {
+ return nil, fmt.Errorf("error loading mfs root, cannot provide MFS: %w", err)
+ }
+
+ kcf := provider.NewDAGProvider(rootNode.Cid(), fetcher)
+ return kcf(ctx)
+ }
+}
+
+func mfsRootProvider(mfsRoot *mfs.Root) provider.KeyChanFunc {
+ return func(ctx context.Context) (<-chan cid.Cid, error) {
+ rootNode, err := mfsRoot.GetDirectory().GetNode()
+ if err != nil {
+ return nil, fmt.Errorf("error loading mfs root, cannot provide MFS: %w", err)
+ }
+ ch := make(chan cid.Cid, 1)
+ ch <- rootNode.Cid()
+ close(ch)
+ return ch, nil
+ }
+}
+
+func newProvidingStrategy(strategy string) interface{} {
type input struct {
fx.In
- Pinner pin.Pinner
- IPLDFetcher fetcher.Factory `name:"ipldFetcher"`
+ Pinner pin.Pinner
+ Blockstore blockstore.Blockstore
+ OfflineIPLDFetcher fetcher.Factory `name:"offlineIpldFetcher"`
+ OfflineUnixFSFetcher fetcher.Factory `name:"offlineUnixfsFetcher"`
+ MFSRoot *mfs.Root
}
return func(in input) provider.KeyChanFunc {
- return provider.NewPinnedProvider(onlyRoots, in.Pinner, in.IPLDFetcher)
+ switch strategy {
+ case "roots":
+ return provider.NewBufferedProvider(provider.NewPinnedProvider(true, in.Pinner, in.OfflineIPLDFetcher))
+ case "pinned":
+ return provider.NewBufferedProvider(provider.NewPinnedProvider(false, in.Pinner, in.OfflineIPLDFetcher))
+ case "pinned+mfs":
+ return provider.NewPrioritizedProvider(
+ provider.NewBufferedProvider(provider.NewPinnedProvider(false, in.Pinner, in.OfflineIPLDFetcher)),
+ mfsProvider(in.MFSRoot, in.OfflineUnixFSFetcher),
+ )
+ case "mfs":
+ return mfsProvider(in.MFSRoot, in.OfflineUnixFSFetcher)
+ case "flat":
+ return provider.NewBlockstoreProvider(in.Blockstore)
+ default: // "all", ""
+ return provider.NewPrioritizedProvider(
+ provider.NewPrioritizedProvider(
+ provider.NewBufferedProvider(provider.NewPinnedProvider(true, in.Pinner, in.OfflineIPLDFetcher)),
+ mfsRootProvider(in.MFSRoot),
+ ),
+ provider.NewBlockstoreProvider(in.Blockstore),
+ )
+ }
}
}
diff --git a/core/node/storage.go b/core/node/storage.go
index 782ff58f043..fd8dfb82e58 100644
--- a/core/node/storage.go
+++ b/core/node/storage.go
@@ -27,17 +27,16 @@ func Datastore(repo repo.Repo) datastore.Datastore {
type BaseBlocks blockstore.Blockstore
// BaseBlockstoreCtor creates cached blockstore backed by the provided datastore
-func BaseBlockstoreCtor(cacheOpts blockstore.CacheOpts, nilRepo bool, hashOnRead bool) func(mctx helpers.MetricsCtx, repo repo.Repo, lc fx.Lifecycle) (bs BaseBlocks, err error) {
+func BaseBlockstoreCtor(cacheOpts blockstore.CacheOpts, hashOnRead bool, writeThrough bool) func(mctx helpers.MetricsCtx, repo repo.Repo, lc fx.Lifecycle) (bs BaseBlocks, err error) {
return func(mctx helpers.MetricsCtx, repo repo.Repo, lc fx.Lifecycle) (bs BaseBlocks, err error) {
// hash security
- bs = blockstore.NewBlockstore(repo.Datastore())
+ bs = blockstore.NewBlockstore(repo.Datastore(),
+ blockstore.WriteThrough(writeThrough),
+ )
bs = &verifbs.VerifBS{Blockstore: bs}
-
- if !nilRepo {
- bs, err = blockstore.CachedBlockstore(helpers.LifecycleCtx(mctx, lc), bs, cacheOpts)
- if err != nil {
- return nil, err
- }
+ bs, err = blockstore.CachedBlockstore(helpers.LifecycleCtx(mctx, lc), bs, cacheOpts)
+ if err != nil {
+ return nil, err
}
bs = blockstore.NewIdStore(bs)
@@ -59,7 +58,7 @@ func GcBlockstoreCtor(bb BaseBlocks) (gclocker blockstore.GCLocker, gcbs blockst
return
}
-// GcBlockstoreCtor wraps GcBlockstore and adds Filestore support
+// FilestoreBlockstoreCtor wraps GcBlockstore and adds Filestore support
func FilestoreBlockstoreCtor(repo repo.Repo, bb BaseBlocks) (gclocker blockstore.GCLocker, gcbs blockstore.GCBlockstore, bs blockstore.Blockstore, fstore *filestore.Filestore) {
gclocker = blockstore.NewGCLocker()
diff --git a/docs/EARLY_TESTERS.md b/docs/EARLY_TESTERS.md
index 6c5b09b1585..e3280b0eb16 100644
--- a/docs/EARLY_TESTERS.md
+++ b/docs/EARLY_TESTERS.md
@@ -27,7 +27,7 @@ We will ask early testers to participate at two points in the process:
- [ ] Infura (@MichaelMure)
- [ ] OrbitDB (@haydenyoung)
- [ ] Pinata (@obo20)
-- [ ] PL EngRes bifrost (@cewood ns4plabs)
+- [ ] Shipyard (@cewood, @ns4plabs)
- [ ] Siderus (@koalalorenzo)
- [ ] Textile (@sanderpick)
- [ ] @RubenKelevra
diff --git a/docs/RELEASE_CHECKLIST.md b/docs/RELEASE_CHECKLIST.md
index d9fbd9348cf..423e9663271 100644
--- a/docs/RELEASE_CHECKLIST.md
+++ b/docs/RELEASE_CHECKLIST.md
@@ -1,19 +1,16 @@
-
+
# ✅ Release Checklist (vX.Y.Z[-rcN])
## Labels
-If an item should be executed for a specific release type, it should be labeled with one of the following labels:
+If an item should be executed only for a specific release type, it is labeled with:
-  execute **ONLY** when releasing a Release Candidate
--  execute **ONLY** when releasing a Final Release
+-  execute **ONLY** when releasing a Final Release
+-  do **NOT** execute when releasing a Patch Release
-Otherwise, it means it should be executed for **ALL** release types.
-
-Patch releases should follow the same process as `.0` releases. If some item should **NOT** be executed for a Patch Release, it should be labeled with:
-
--  do **NOT** execute when releasing a Patch Release
+Otherwise, it means a step should be executed for **ALL** release types.
## Before the release
@@ -21,160 +18,120 @@ This section covers tasks to be done ahead of the release.
- [ ] Verify you have access to all the services and tools required for the release
- [ ] [GPG signature](https://docs.github.com/en/authentication/managing-commit-signature-verification) configured in local git and in GitHub
- - [ ] [admin access to IPFS Discourse](https://discuss.ipfs.tech/g/admins)
- - ask the previous release owner (or @2color) for an invite
- - [ ]  [access to #shared-pl-marketing-requests](https://filecoinproject.slack.com/archives/C018EJ8LWH1) channel in FIL Slack
- - ask the previous release owner for an invite
- - [ ] [access to IPFS network metrics](https://github.com/protocol/pldw/blob/624f47cf4ec14ad2cec6adf601a9f7b203ef770d/docs/sources/ipfs.md#ipfs-network-metrics) dashboards in Grafana
- - open an access request in the [pldw](https://github.com/protocol/pldw/issues/new/choose)
- - [example](https://github.com/protocol/pldw/issues/158)
- - [ ] [kuboreleaser](https://github.com/ipfs/kuboreleaser) checked out on your system (_only if you're using [kuboreleaser](https://github.com/ipfs/kuboreleaser)_)
- - [ ] [Thunderdome](https://github.com/ipfs-shipyard/thunderdome) checked out on your system and configured (see the [Thunderdome release docs](./releases_thunderdome.md) for setup)
- - [ ] [docker](https://docs.docker.com/get-docker/) installed on your system (_only if you're using [kuboreleaser](https://github.com/ipfs/kuboreleaser)_)
- - [ ] [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) installed on your system (_only if you're **NOT** using [kuboreleaser](https://github.com/ipfs/kuboreleaser)_)
- - [ ] [zsh](https://github.com/ohmyzsh/ohmyzsh/wiki/Installing-ZSH#install-and-set-up-zsh-as-default) installed on your system
+ - [ ] [docker](https://docs.docker.com/get-docker/) installed on your system
+ - [ ] [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) installed on your system
- [ ] [kubo](https://github.com/ipfs/kubo) checked out under `$(go env GOPATH)/src/github.com/ipfs/kubo`
- you can also symlink your clone to the expected location by running `mkdir -p $(go env GOPATH)/src/github.com/ipfs && ln -s $(pwd) $(go env GOPATH)/src/github.com/ipfs/kubo`
- - [ ]  [Reddit](https://www.reddit.com) account
--  Upgrade Go used in CI to the latest patch release available in [CircleCI](https://hub.docker.com/r/cimg/go/tags) in:
- - [ ]  [ipfs/distributions](https://github.com/ipfs/distributions)
- - [example](https://github.com/ipfs/distributions/pull/756)
- - [ ]  [ipfs/ipfs-docs](https://github.com/ipfs/ipfs-docs)
- - [example](https://github.com/ipfs/ipfs-docs/pull/1298)
-- [ ] Verify there is nothing [left for release](-what-s-left-for-release)
-- [ ] Create a release process improvement PR
- - [ ] update the [release issue template](docs/RELEASE_ISSUE_TEMPLATE.md) as you go
- - [ ] link it in the [Meta](#meta) section
+-  Upgrade Go used in CI to the latest patch release available at
## The release
This section covers tasks to be done during each release.
-- [ ] Prepare the release branch and update version numbers accordingly using `./kuboreleaser --skip-check-before release --version vX.Y.Z(-rcN) prepare-branch` or ...
+### 1. Prepare release branch
+
+- [ ] Prepare the release branch and update version numbers accordingly
- [ ] create a new branch `release-vX.Y.Z`
- use `master` as base if `Z == 0`
- use `release` as base if `Z > 0`
- - [ ]  update the `CurrentVersionNumber` in [version.go](version.go) in the `master` branch to `vX.Y+1.0-dev`
- - [example](https://github.com/ipfs/kubo/pull/9305)
- - [ ] update the `CurrentVersionNumber` in [version.go](version.go) in the `release-vX.Y` branch to `vX.Y.Z(-RCN)`
- - [example](https://github.com/ipfs/kubo/pull/9394)
- - [ ] create a draft PR from `release-vX.Y` to `release`
- - [example](https://github.com/ipfs/kubo/pull/9306)
- - [ ] Cherry-pick commits from `master` to the `release-vX.Y.Z` using `git cherry-pick -x `
- - [ ]  Add full changelog and contributors to the [changelog](docs/changelogs/vX.Y.md)
- - [ ]  Replace the `Changelog` and `Contributors` sections of the [changelog](docs/changelogs/vX.Y.md) with the stdout of `./bin/mkreleaselog`
- - do **NOT** copy the stderr
- - [ ] verify all CI checks on the PR from `release-vX.Y` to `release` are passing
- - [ ]  Merge the PR from `release-vX.Y` to `release` using the `Create a merge commit`
+ - [ ]  update the `CurrentVersionNumber` in [version.go](version.go) in the `master` branch to `vX.Y+1.0-dev` ([example](https://github.com/ipfs/kubo/pull/9305))
+ - [ ] update the `CurrentVersionNumber` in [version.go](version.go) in the `release-vX.Y.Z` branch to `vX.Y.Z(-rcN)` ([example](https://github.com/ipfs/kubo/pull/9394))
+ - [ ] create a draft PR from `release-vX.Y.Z` to `release` ([example](https://github.com/ipfs/kubo/pull/9306))
+ - [ ] Cherry-pick commits from `master` to the `release-vX.Y.Z` using `git cherry-pick -x ` ([example](https://github.com/ipfs/kubo/pull/10636/commits/033de22e3bc6191dbb024ad6472f5b96b34e3ccf))
+ - **NOTE:** cherry-picking with `-x` is important
+ - [ ]  Replace the `Changelog` and `Contributors` sections of the [changelog](docs/changelogs/vX.Y.md) with the stdout (do **NOT** copy the stderr) of `./bin/mkreleaselog`.
+ - **NOTE:** `mkreleaselog` expects your `$GOPATH/src/github.com/ipfs/kubo` to include latest commits from `release-vX.Y.Z`
+ - [ ] verify all CI checks on the PR from `release-vX.Y.Z` to `release` are passing
+ - [ ]  Merge the PR from `release-vX.Y.Z` to `release` using the `Create a merge commit`
- do **NOT** use `Squash and merge` nor `Rebase and merge` because we need to be able to sign the merge commit
- - do **NOT** delete the `release-vX.Y` branch
-
-- [ ] Run Thunderdome testing, see the [Thunderdome release docs](./releases_thunderdome.md) for details
- - [ ] create a PR and merge the experiment config into Thunderdome
-- [ ] Create the release tag using `./kuboreleaser release --version vX.Y.Z(-rcN) tag` or ...
- - This is a dangerous operation! Go and Docker publishing are difficult to reverse! Have the release reviewer verify all the commands marked with ⚠️!
- - [ ] ⚠️  tag the HEAD commit using `git tag -s vX.Y.Z(-RCN) -m 'Prerelease X.Y.Z(-RCN)'`
- - [ ] ⚠️  tag the HEAD commit of the `release` branch using `git tag -s vX.Y.Z(-RCN) -m 'Release X.Y.Z(-RCN)'`
- - [ ] ⚠️ verify the tag is signed and tied to the correct commit using `git show vX.Y.Z(-RCN)`
- - [ ] ⚠️ push the tag to GitHub using `git push origin vX.Y.Z(-RCN)`
- - do **NOT** use `git push --tags` because it pushes all your local tags
-
-- [ ] Publish the release to [DockerHub](https://hub.docker.com/r/ipfs/kubo/) using `./kuboreleaser --skip-check-before --skip-run release --version vX.Y.Z(-rcN) publish-to-dockerhub` or ...
+ - do **NOT** delete the `release-vX.Y.Z` branch
+
+### 2. Tag release
+
+- [ ] Create the release tag
+ - ⚠️ **NOTE:** This is a dangerous operation! Go and Docker publishing are difficult to reverse! Have the release reviewer verify all the commands marked with !
+ - [ ]  tag the HEAD commit using `git tag -s vX.Y.Z(-rcN) -m 'Prerelease X.Y.Z(-rcN)'`
+ - [ ]  tag the HEAD commit of the `release` branch using `git tag -s vX.Y.Z -m 'Release X.Y.Z'`
+ - [ ] ⚠️ verify the tag is signed and tied to the correct commit using `git show vX.Y.Z(-rcN)`
+ - [ ] push the tag to GitHub using `git push origin vX.Y.Z(-rcN)`
+ - ⚠️ do **NOT** use `git push --tags` because it pushes all your local tags
+
+### 3. Publish
+
+- [ ] Publish Docker image to [DockerHub](https://hub.docker.com/r/ipfs/kubo/tags)
- [ ] Wait for [Publish docker image](https://github.com/ipfs/kubo/actions/workflows/docker-image.yml) workflow run initiated by the tag push to finish
- - [ ] verify the image is available on [Docker Hub](https://hub.docker.com/r/ipfs/kubo/tags)
-- [ ] Verify [ipfs/distributions](https://github.com/ipfs/distributions)'s `.tool-versions`'s `golang` entry is set to the [latest go release](https://go.dev/doc/devel/release) on the major go branch [Kubo is being tested on](https://github.com/ipfs/kubo/blob/master/.github/workflows/gotest.yml) (see `go-version:`).
-- [ ] Publish the release to [dist.ipfs.tech](https://dist.ipfs.tech) using `./kuboreleaser release --version vX.Y.Z(-rcN) publish-to-distributions` or ...
+ - [ ] verify the image is available on [Docker Hub → tags](https://hub.docker.com/r/ipfs/kubo/tags)
+- [ ] Publish the release to [dist.ipfs.tech](https://dist.ipfs.tech)
- [ ] check out [ipfs/distributions](https://github.com/ipfs/distributions)
- - [ ] run `./dist.sh add-version kubo vX.Y.Z(-RCN)` to add the new version to the `versions` file
- - [usage](https://github.com/ipfs/distributions#usage)
- - [ ] create and merge the PR which updates `dists/kubo/versions` and `dists/go-ipfs/versions` ( and `dists/kubo/current_version` and `dists/go-ipfs/current_version`)
- - [example](https://github.com/ipfs/distributions/pull/760)
+ - [ ] create new branch: run `git checkout -b release-kubo-X.Y.Z(-rcN)`
+ - [ ] run `./dist.sh add-version kubo vX.Y.Z(-rcN)` to add the new version to the `versions` file ([usage](https://github.com/ipfs/distributions#usage))
+ - [ ] Verify [ipfs/distributions](https://github.com/ipfs/distributions)'s `.tool-versions`'s `golang` entry is set to the [latest go release](https://go.dev/doc/devel/release) on the major go branch [Kubo is being tested on](https://github.com/ipfs/kubo/blob/master/.github/workflows/gotest.yml) (see `go-version:`). If not, update `.tool-versions` to match the latest golang.
+ - [ ] create and merge the PR which updates `dists/kubo/versions` and `dists/go-ipfs/versions` (**NOTE:**  will also have `dists/kubo/current` and `dists/go-ipfs/current` – [example](https://github.com/ipfs/distributions/pull/1125))
- [ ] wait for the [CI](https://github.com/ipfs/distributions/actions/workflows/main.yml) workflow run initiated by the merge to master to finish
- - [ ] verify the release is available on [dist.ipfs.io](https://dist.ipfs.io/#kubo)
-
-- [ ] Publish the release to [NPM](https://www.npmjs.com/package/go-ipfs?activeTab=versions) using `./kuboreleaser release --version vX.Y.Z(-rcN) publish-to-npm` (⚠️ you might need to run the command a couple of times because GHA might not be able to see the new distribution straight away due to caching) or ...
- - [ ] run the [Release to npm](https://github.com/ipfs/npm-go-ipfs/actions/workflows/main.yml) workflow
+ - [ ] verify the release is available on [dist.ipfs.tech](https://dist.ipfs.tech/#kubo)
+- [ ] Publish the release to [NPM](https://www.npmjs.com/package/kubo?activeTab=versions)
+ - [ ] manually dispatch the [Release to npm](https://github.com/ipfs/npm-go-ipfs/actions/workflows/main.yml) workflow
- [ ] check [Release to npm](https://github.com/ipfs/npm-go-ipfs/actions/workflows/main.yml) workflow run logs to verify it discovered the new release
- - [ ] verify the release is available on [NPM](https://www.npmjs.com/package/go-ipfs?activeTab=versions)
-
-- [ ] Publish the release to [GitHub](https://github.com/ipfs/kubo/releases) using `./kuboreleaser release --version vX.Y.Z(-rcN) publish-to-github` or ...
- - [ ] create a new release on [GitHub](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release)
+ - [ ] verify the release is available on [NPM](https://www.npmjs.com/package/kubo?activeTab=versions)
+- [ ] Publish the release to [GitHub kubo/releases](https://github.com/ipfs/kubo/releases)
+ - [ ] create a new release on [github.com/ipfs/kubo/releases](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release)
- [RC example](https://github.com/ipfs/kubo/releases/tag/v0.17.0-rc1)
- [FINAL example](https://github.com/ipfs/kubo/releases/tag/v0.17.0)
- - [ ] use the `vX.Y.Z(-RCN)` tag
+ - [ ] use the `vX.Y.Z(-rcN)` tag
- [ ] link to the release issue
- [ ]  link to the changelog in the description
- [ ]  check the `This is a pre-release` checkbox
- - [ ]  copy the changelog (without the header) in the description
- - [ ]  do **NOT** check the `This is a pre-release` checkbox
+ - [ ]  copy the changelog (without the header) in the description
+ - [ ]  do **NOT** check the `This is a pre-release` checkbox
- [ ] run the [sync-release-assets](https://github.com/ipfs/kubo/actions/workflows/sync-release-assets.yml) workflow
- [ ] wait for the [sync-release-assets](https://github.com/ipfs/kubo/actions/workflows/sync-release-assets.yml) workflow run to finish
- - [ ] verify the release assets are present in the [GitHub release](https://github.com/ipfs/kubo/releases/tag/vX.Y.Z(-RCN))
-
-- [ ] Promote the release using `./kuboreleaser release --version vX.Y.Z(-rcN) promote` or ...
- - [ ] create an [IPFS Discourse](https://discuss.ipfs.tech) topic
- - [prerelease example](https://discuss.ipfs.tech/t/kubo-v0-16-0-rc1-release-candidate-is-out/15248)
- - [release example](https://discuss.ipfs.tech/t/kubo-v0-16-0-release-is-out/15249)
- - [ ] use `Kubo vX.Y.Z(-RCN) is out!` as the title
- - [ ] use `kubo` and `go-ipfs` as topics
+ - [ ] verify the release assets are present in the [GitHub release](https://github.com/ipfs/kubo/releases/tag/vX.Y.Z(-rcN))
+
+### 4. After Publishing
+
+- [ ]  Merge the [release](https://github.com/ipfs/kubo/tree/release) branch back into [master](https://github.com/ipfs/kubo/tree/master)
+ - [ ] Create a new branch `merge-release-vX.Y.Z` from `release`
+ - [ ] Create the next [`./docs/changelogs/vA.B.md`](https://github.com/ipfs/kubo/blob/master/docs/changelogs/) and link to the new changelog from the [`./CHANGELOG.md`](https://github.com/ipfs/kubo/blob/master/CHANGELOG.md) file
+ - [ ] Create and merge a PR from `merge-release-vX.Y.Z` to `master`
+ - ⚠️ do **NOT** use `Squash and merge` nor `Rebase and merge` because we need to be able to sign the merge commit
+ - ⚠️ **NOTE:** make sure to ignore the changes to [version.go](version.go) (keep the `-dev` in `master`)
+- [ ] Update Kubo staging environment, see the [Running Kubo tests on staging](https://www.notion.so/Running-Kubo-tests-on-staging-488578bb46154f9bad982e4205621af8) for details.
+ - [ ]  Test last release against the current RC
+ - [ ]  Test last release against the current one
+- [ ] Promote the release
+ - [ ] create an [IPFS Discourse](https://discuss.ipfs.tech) topic ([prerelease example](https://discuss.ipfs.tech/t/kubo-v0-16-0-rc1-release-candidate-is-out/15248), [release example](https://discuss.ipfs.tech/t/kubo-v0-16-0-release-is-out/15249))
+ - [ ] use `Kubo vX.Y.Z(-rcN) is out!` as the title and `kubo` and `go-ipfs` as tags
- [ ] repeat the title as a heading (`##`) in the description
- [ ] link to the GitHub Release, binaries on IPNS, docker pull command and release notes in the description
- - [ ] pin the [IPFS Discourse](https://discuss.ipfs.tech) topic globally
- - you can make the topic a banner if there is no banner already
- - verify the [IPFS Discourse](https://discuss.ipfs.tech) topic was copied to:
+ - [ ] pin the [IPFS Discourse](https://discuss.ipfs.tech) topic globally, you can make the topic a banner if there is no banner already
+ - [ ] verify the [IPFS Discourse](https://discuss.ipfs.tech) topic was copied to:
- [ ] [#ipfs-chatter](https://discord.com/channels/669268347736686612/669268347736686615) in IPFS Discord
- [ ] [#ipfs-chatter](https://filecoinproject.slack.com/archives/C018EJ8LWH1) in FIL Slack
- [ ] [#ipfs-chatter:ipfs.io](https://matrix.to/#/#ipfs-chatter:ipfs.io) in Matrix
- - [ ]  Add the link to the [IPFS Discourse](https://discuss.ipfs.tech) topic to the [GitHub Release](https://github.com/ipfs/kubo/releases/tag/vX.Y.Z(-RCN)) description
- - [example](https://github.com/ipfs/kubo/releases/tag/v0.17.0)
- - [ ]  create an issue comment mentioning early testers on the release issue
- - [example](https://github.com/ipfs/kubo/issues/9319#issuecomment-1311002478)
- - [ ]  create an issue comment linking to the release on the release issue
- - [example](https://github.com/ipfs/kubo/issues/9417#issuecomment-1400740975)
- - [ ]   ask the marketing team to tweet about the release in [#shared-pl-marketing-requests](https://filecoinproject.slack.com/archives/C018EJ8LWH1) in FIL Slack
- - [example](https://filecoinproject.slack.com/archives/C018EJ8LWH1/p1664885305374900)
- - [ ]   post the link to the [GitHub Release](https://github.com/ipfs/kubo/releases/tag/vX.Y.Z(-RCN)) to [Reddit](https://reddit.com/r/ipfs)
- - [example](https://www.reddit.com/r/ipfs/comments/9x0q0k/kubo_v0160_release_is_out/)
-
-- [ ] Test the new version with `ipfs-companion` using `./kuboreleaser release --version vX.Y.Z(-rcN) test-ipfs-companion` or ...
- - [ ] run the [e2e](https://github.com/ipfs/ipfs-companion/actions/workflows/e2e.yml)
- - use `vX.Y.Z(-RCN)` as the Kubo image version
- - [ ] wait for the [e2e](https://github.com/ipfs/ipfs-companion/actions/workflows/e2e.yml) workflow run to finish
-
-- [ ]  Update Kubo in [ipfs-desktop](https://github.com/ipfs/ipfs-desktop) using `./kuboreleaser release --version vX.Y.Z(-rcN) update-ipfs-desktop` or ...
+ - [ ]  Add the link to the [IPFS Discourse](https://discuss.ipfs.tech) topic to the [GitHub Release](https://github.com/ipfs/kubo/releases/tag/vX.Y.Z(-rcN)) description ([example](https://github.com/ipfs/kubo/releases/tag/v0.17.0))
+ - [ ]  create an issue comment mentioning early testers on the release issue ([example](https://github.com/ipfs/kubo/issues/9319#issuecomment-1311002478))
+ - [ ]  create an issue comment linking to the release on the release issue ([example](https://github.com/ipfs/kubo/issues/9417#issuecomment-1400740975))
+ - [ ]   promote on bsky.app ([example](https://bsky.app/profile/ipshipyard.com/post/3lh2brzrwbs2c))
+ - [ ]   promote on x.com ([example](https://x.com/ipshipyard/status/1885346348808929609))
+ - [ ]   post the link to the [GitHub Release](https://github.com/ipfs/kubo/releases/tag/vX.Y.Z(-rcN)) to [Reddit](https://reddit.com/r/ipfs) ([example](https://www.reddit.com/r/ipfs/comments/9x0q0k/kubo_v0160_release_is_out/))
+- [ ] Manually smoke-test the new version with [IPFS Companion Browser Extension](https://docs.ipfs.tech/install/ipfs-companion/)
+- [ ]  Update Kubo in [ipfs-desktop](https://github.com/ipfs/ipfs-desktop)
- [ ] check out [ipfs/ipfs-desktop](https://github.com/ipfs/ipfs-desktop)
- - [ ] run `npm install`
- - [ ] create a PR which updates `package.json` and `package-lock.json`
- - [ ]  add @SgtPooki as reviewer
-
-- [ ]  Update Kubo docs using `./kuboreleaser release --version vX.Y.Z(-rcN) update-ipfs-docs` or ...
- - [ ]  run the [update-on-new-ipfs-tag.yml](https://github.com/ipfs/ipfs-docs/actions/workflows/update-on-new-ipfs-tag.yml) workflow
- - [ ]  merge the PR created by the [update-on-new-ipfs-tag.yml](https://github.com/ipfs/ipfs-docs/actions/workflows/update-on-new-ipfs-tag.yml) workflow run
-
-- [ ]  Ask Brave to update Kubo in Brave Desktop
- - [ ]  use [this link](https://github.com/brave/brave-browser/issues/new?assignees=&labels=OS%2FDesktop&projects=&template=desktop.md&title=) to create an issue for the new Kubo version
- - [basic example](https://github.com/brave/brave-browser/issues/31453), [example with additional notes](https://github.com/brave/brave-browser/issues/27965)
- - [ ]  post link to the issue in `#shared-pl-brave` for visibility
-- [ ]  Create a blog entry on [blog.ipfs.tech](https://blog.ipfs.tech) using `./kuboreleaser release --version vX.Y.Z(-rcN) update-ipfs-blog --date YYYY-MM-DD` or ...
- - [ ]  create a PR which adds a release note for the new Kubo version
- - [example](https://github.com/ipfs/ipfs-blog/pull/529)
- - [ ]  merge the PR
- - [ ]  verify the blog entry was published
-
-- [ ]  Merge the [release](https://github.com/ipfs/kubo/tree/release) branch back into [master](https://github.com/ipfs/kubo/tree/master), ignoring the changes to [version.go](version.go) (keep the `-dev`) version, using `./kuboreleaser release --version vX.Y.Z(-rcN) merge-branch` or ...
- - [ ] create a new branch `merge-release-vX.Y.Z` from `release`
- - [ ] create and merge a PR from `merge-release-vX.Y.Z` to `master`
-
-- [ ]   Prepare for the next release using `./kuboreleaser release --version vX.Y.Z(-rcN) prepare-next` or ...
- - [ ]   Create the next [changelog](https://github.com/ipfs/kubo/blob/master/docs/changelogs/vX.(Y+1).md)
- - [ ]   Link to the new changelog in the [CHANGELOG.md](CHANGELOG.md) file
- - [ ]   Create the next release issue
+ - [ ] run `npm install `
+ - [ ] create a PR which updates `package.json` and `package-lock.json`
+- [ ]  Update Kubo docs at docs.ipfs.tech:
+ - [ ]  run the [update-on-new-ipfs-tag.yml](https://github.com/ipfs/ipfs-docs/actions/workflows/update-on-new-ipfs-tag.yml) workflow
+ - [ ]  merge the PR created by the [update-on-new-ipfs-tag.yml](https://github.com/ipfs/ipfs-docs/actions/workflows/update-on-new-ipfs-tag.yml) workflow run
-- [ ]   Create a dependency update PR
- - [ ]   check out [ipfs/kubo](https://github.com/ipfs/kubo)
- - [ ]   run `go get -u` in root directory
- - [ ]   run `go mod tidy` in root directory
- - [ ]   run `go mod tidy` in `docs/examples/kubo-as-a-library` directory
- - [ ]   create a PR which updates `go.mod` and `go.sum`
- - [ ]   add the PR to the next release milestone
-- [ ]  Close the release issue
+- [ ]  Create a blog entry on [blog.ipfs.tech](https://blog.ipfs.tech)
+ - [ ]  create a PR which adds a release note for the new Kubo version ([example](https://github.com/ipfs/ipfs-blog/pull/529))
+ - [ ]  merge the PR
+ - [ ]  verify the blog entry was published
+- [ ]   Create a dependency update PR
+ - [ ]   check out [ipfs/kubo](https://github.com/ipfs/kubo)
+ - [ ]   go over direct dependencies from `go.mod` in the root directory (NOTE: do not run `go get -u` as it will upgrade indirect dependencies which may cause problems)
+ - [ ]   run `make mod_tidy`
+ - [ ]   create a PR which updates `go.mod` and `go.sum`
+ - [ ]   add the PR to the next release milestone
+- [ ]   Create the next release issue
+- [ ]  Close the release issue
diff --git a/docs/RELEASE_ISSUE_TEMPLATE.md b/docs/RELEASE_ISSUE_TEMPLATE.md
index 52f02fb50d8..321026ea6c0 100644
--- a/docs/RELEASE_ISSUE_TEMPLATE.md
+++ b/docs/RELEASE_ISSUE_TEMPLATE.md
@@ -1,4 +1,4 @@
-
+
# Items to do upon creating the release issue
diff --git a/docs/add-code-flow.md b/docs/add-code-flow.md
index a13c7177d40..264731a3b13 100644
--- a/docs/add-code-flow.md
+++ b/docs/add-code-flow.md
@@ -1,6 +1,6 @@
# IPFS : The `Add` command demystified
-The goal of this document is to capture the code flow for adding a file (see the `coreapi` package) using the IPFS CLI, in the process exploring some datastructures and packages like `ipld.Node` (aka `dagnode`), `FSNode`, `MFS`, etc.
+The goal of this document is to capture the code flow for adding a file (see the `coreapi` package) using the IPFS CLI, in the process exploring some data structures and packages like `ipld.Node` (aka `dagnode`), `FSNode`, `MFS`, etc.
## Concepts
- [Files](https://github.com/ipfs/docs/issues/133)
@@ -99,4 +99,4 @@ Within the function, a new `Adder` is created with the configured `Blockstore` a
- **[`adder.PinRoot()`](https://github.com/ipfs/go-ipfs/blob/v0.4.18/core/coreunix/add.go#L171)** - *Pin all files under the `MFS` **root***
- The whole process ends with `PinRoot` recursively pinning all the files under the `MFS` **root**
\ No newline at end of file
+ The whole process ends with `PinRoot` recursively pinning all the files under the `MFS` **root**
diff --git a/docs/changelogs/v0.10.md b/docs/changelogs/v0.10.md
index ea92201a9ff..8cfc29a7ae5 100644
--- a/docs/changelogs/v0.10.md
+++ b/docs/changelogs/v0.10.md
@@ -320,7 +320,7 @@ See `ipfs swarm peering --help` for more details.
- More changelog grooming.
- Changelog grooming.
- node/tests: put most of the schema test cases here
- - Add more explicit discussion of indicies to ListIterator.
+ - Add more explicit discussion of indices to ListIterator.
- node/bindnode: start of a reflect-based Node implementation
- add DeepEqual and start using it in tests
- Add enumerate methods to the multicodec registries. ([ipld/go-ipld-prime#176](https://github.com/ipld/go-ipld-prime/pull/176))
@@ -390,7 +390,7 @@ See `ipfs swarm peering --help` for more details.
- remove note about go modules in README ([libp2p/go-libp2p-noise#100](https://github.com/libp2p/go-libp2p-noise/pull/100))
- fix: remove deprecated call to pk.Bytes ([libp2p/go-libp2p-noise#99](https://github.com/libp2p/go-libp2p-noise/pull/99))
- github.com/libp2p/go-libp2p-peerstore (v0.2.7 -> v0.2.8):
- - Fix perfomance issue in updating addr book ([libp2p/go-libp2p-peerstore#141](https://github.com/libp2p/go-libp2p-peerstore/pull/141))
+ - Fix performance issue in updating addr book ([libp2p/go-libp2p-peerstore#141](https://github.com/libp2p/go-libp2p-peerstore/pull/141))
- Fix test flakes ([libp2p/go-libp2p-peerstore#164](https://github.com/libp2p/go-libp2p-peerstore/pull/164))
- Only remove records during GC ([libp2p/go-libp2p-peerstore#135](https://github.com/libp2p/go-libp2p-peerstore/pull/135))
- sync: update CI config files ([libp2p/go-libp2p-peerstore#160](https://github.com/libp2p/go-libp2p-peerstore/pull/160))
diff --git a/docs/changelogs/v0.11.md b/docs/changelogs/v0.11.md
index 98133052ab6..a3867c003d1 100644
--- a/docs/changelogs/v0.11.md
+++ b/docs/changelogs/v0.11.md
@@ -301,7 +301,7 @@ This work was [contributed](https://github.com/ipfs/go-ipfs/pull/8569) by [Ceram
- fix(graphsync): make sure linkcontext is passed (#207) ([ipfs/go-graphsync#207](https://github.com/ipfs/go-graphsync/pull/207))
- Merge final v0.6.x commit history, and 0.8.0 changelog (#205) ([ipfs/go-graphsync#205](https://github.com/ipfs/go-graphsync/pull/205))
- Fix broken link to IPLD selector documentation (#189) ([ipfs/go-graphsync#189](https://github.com/ipfs/go-graphsync/pull/189))
- - fix: check errors before defering a close (#200) ([ipfs/go-graphsync#200](https://github.com/ipfs/go-graphsync/pull/200))
+ - fix: check errors before deferring a close (#200) ([ipfs/go-graphsync#200](https://github.com/ipfs/go-graphsync/pull/200))
- chore: fix checks (#197) ([ipfs/go-graphsync#197](https://github.com/ipfs/go-graphsync/pull/197))
- Merge the v0.6.x commit history (#190) ([ipfs/go-graphsync#190](https://github.com/ipfs/go-graphsync/pull/190))
- Ready for universal CI (#187) ([ipfs/go-graphsync#187](https://github.com/ipfs/go-graphsync/pull/187))
diff --git a/docs/changelogs/v0.12.md b/docs/changelogs/v0.12.md
index def891271d3..d87f5fc8205 100644
--- a/docs/changelogs/v0.12.md
+++ b/docs/changelogs/v0.12.md
@@ -58,7 +58,7 @@ As usual, this release includes important fixes, some of which may be critical f
- `ipfs refs local` will now list all blocks as if they were [raw]() CIDv1 instead of with whatever CID version and IPLD codecs they were stored with. All other functionality should remain the same.
-Note: This change also effects [ipfs-update](https://github.com/ipfs/ipfs-update) so if you use that tool to mange your go-ipfs installation then grab ipfs-update v1.8.0 from [dist](https://dist.ipfs.tech/#ipfs-update).
+Note: This change also effects [ipfs-update](https://github.com/ipfs/ipfs-update) so if you use that tool to manage your go-ipfs installation then grab ipfs-update v1.8.0 from [dist](https://dist.ipfs.tech/#ipfs-update).
Keep reading to learn more details.
diff --git a/docs/changelogs/v0.13.md b/docs/changelogs/v0.13.md
index 9bf4ee88acf..a985f179c32 100644
--- a/docs/changelogs/v0.13.md
+++ b/docs/changelogs/v0.13.md
@@ -53,7 +53,7 @@ View the linked [security advisory](https://github.com/ipfs/go-ipfs/security/adv
- bump to newer blockstore err not found (#301) ([ipld/go-car#301](https://github.com/ipld/go-car/pull/301))
- Car command supports for `largebytes` nodes (#296) ([ipld/go-car#296](https://github.com/ipld/go-car/pull/296))
- fix(test): rootless fixture should have no roots, not null roots
- - Allow extracton of a raw unixfs file (#284) ([ipld/go-car#284](https://github.com/ipld/go-car/pull/284))
+ - Allow extraction of a raw unixfs file (#284) ([ipld/go-car#284](https://github.com/ipld/go-car/pull/284))
- cmd/car: use a better install command in the README
- feat: --version selector for `car create` & update deps
- feat: add option to create blockstore that writes a plain CARv1 (#288) ([ipld/go-car#288](https://github.com/ipld/go-car/pull/288))
@@ -537,7 +537,7 @@ The more fully featured yamux stream multiplexer is now prioritized over mplex f
- Fix unixfs fetch (#364) ([ipfs/go-graphsync#364](https://github.com/ipfs/go-graphsync/pull/364))
- [Feature] UUIDs, protocol versioning, v2 protocol w/ dag-cbor messaging (#332) ([ipfs/go-graphsync#332](https://github.com/ipfs/go-graphsync/pull/332))
- feat(CHANGELOG): update for v0.12.0
- - Use do not send blocks for pause/resume & prevent processing of blocks on cancelled requests (#333) ([ipfs/go-graphsync#333](https://github.com/ipfs/go-graphsync/pull/333))
+ - Use do not send blocks for pause/resume & prevent processing of blocks on canceled requests (#333) ([ipfs/go-graphsync#333](https://github.com/ipfs/go-graphsync/pull/333))
- Support unixfs reification in default linksystem (#329) ([ipfs/go-graphsync#329](https://github.com/ipfs/go-graphsync/pull/329))
- Don't run hooks on blocks we didn't have (#331) ([ipfs/go-graphsync#331](https://github.com/ipfs/go-graphsync/pull/331))
- feat(responsemanager): trace full messages via links to responses (#325) ([ipfs/go-graphsync#325](https://github.com/ipfs/go-graphsync/pull/325))
diff --git a/docs/changelogs/v0.14.md b/docs/changelogs/v0.14.md
index d725c137454..247570e9c5b 100644
--- a/docs/changelogs/v0.14.md
+++ b/docs/changelogs/v0.14.md
@@ -173,7 +173,7 @@ $ ipfs cid format -v 1 -b base256emoji bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylq
- swarm: fix flaky TestDialExistingConnection test (#1509) ([libp2p/go-libp2p#1509](https://github.com/libp2p/go-libp2p/pull/1509))
- tcp: limit the number of connections in tcp suite test on non-linux hosts (#1507) ([libp2p/go-libp2p#1507](https://github.com/libp2p/go-libp2p/pull/1507))
- increase overly short require.Eventually intervals (#1501) ([libp2p/go-libp2p#1501](https://github.com/libp2p/go-libp2p/pull/1501))
- - tls: fix flaky handshake cancelation test (#1503) ([libp2p/go-libp2p#1503](https://github.com/libp2p/go-libp2p/pull/1503))
+ - tls: fix flaky handshake cancellation test (#1503) ([libp2p/go-libp2p#1503](https://github.com/libp2p/go-libp2p/pull/1503))
- merge the transport test suite from go-libp2p-testing here ([libp2p/go-libp2p#1496](https://github.com/libp2p/go-libp2p/pull/1496))
- fix racy connection comparison in TestDialWorkerLoopBasic (#1499) ([libp2p/go-libp2p#1499](https://github.com/libp2p/go-libp2p/pull/1499))
- swarm: fix race condition in TestFailFirst (#1490) ([libp2p/go-libp2p#1490](https://github.com/libp2p/go-libp2p/pull/1490))
diff --git a/docs/changelogs/v0.16.md b/docs/changelogs/v0.16.md
index 135ef425293..52fcdb165fd 100644
--- a/docs/changelogs/v0.16.md
+++ b/docs/changelogs/v0.16.md
@@ -106,7 +106,7 @@ The previous alternative is websocket secure, which require installing a reverse
#### How to enable WebTransport
-Thoses steps are temporary and wont be needed once we make it enabled by default.
+Those steps are temporary and won't be needed once we make it enabled by default.
1. Enable the WebTransport transport:
`ipfs config Swarm.Transports.Network.WebTransport --json true`
@@ -191,7 +191,7 @@ For more information, see `ipfs add --help` and `ipfs files --help`.
- docs: add WebTransport docs ([ipfs/kubo#9308](https://github.com/ipfs/kubo/pull/9308))
- chore: bump version to 0.16.0-rc1
- fix: ensure hasher is registered when using a hashing function
- - feat: add webtransport as an optin transport ([ipfs/kubo#9293](https://github.com/ipfs/kubo/pull/9293))
+ - feat: add webtransport as an option transport ([ipfs/kubo#9293](https://github.com/ipfs/kubo/pull/9293))
- feat(gateway): _redirects file support (#8890) ([ipfs/kubo#8890](https://github.com/ipfs/kubo/pull/8890))
- docs: fix typo in changelog-v0.16.0.md
- Readme: Rewrite introduction and featureset (#9211) ([ipfs/kubo#9211](https://github.com/ipfs/kubo/pull/9211))
@@ -265,7 +265,7 @@ For more information, see `ipfs add --help` and `ipfs files --help`.
- sync: update CI config files ([ipfs/go-pinning-service-http-client#21](https://github.com/ipfs/go-pinning-service-http-client/pull/21))
- github.com/ipld/edelweiss (v0.1.4 -> v0.2.0):
- Release v0.2.0 (#60) ([ipld/edelweiss#60](https://github.com/ipld/edelweiss/pull/60))
- - feat: add cachable modifier to methods (#48) ([ipld/edelweiss#48](https://github.com/ipld/edelweiss/pull/48))
+ - feat: add cacheable modifier to methods (#48) ([ipld/edelweiss#48](https://github.com/ipld/edelweiss/pull/48))
- adding licenses (#52) ([ipld/edelweiss#52](https://github.com/ipld/edelweiss/pull/52))
- sync: update CI config files ([ipld/edelweiss#56](https://github.com/ipld/edelweiss/pull/56))
- chore: replace deprecated ioutil with io/os ([ipld/edelweiss#59](https://github.com/ipld/edelweiss/pull/59))
diff --git a/docs/changelogs/v0.18.md b/docs/changelogs/v0.18.md
index f2a22d84eb7..972ecb84e50 100644
--- a/docs/changelogs/v0.18.md
+++ b/docs/changelogs/v0.18.md
@@ -56,7 +56,7 @@ As much as possible, the aim is for a user to only think about how much memory t
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.
+2. ``System.ConnsInbound``, ``Transient.Memory``, ``Transient.ConnsInbound`` have higher default computed values.
### 📝 Changelog
@@ -312,11 +312,11 @@ and various improvements have been made to improve the UX including:
- 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: ensure connmgr is smaller then autoscalled resource 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: refuse to start if connmgr is smaller than resource 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
@@ -338,7 +338,7 @@ and various improvements have been made to improve the UX including:
- 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))
+ - Cleaned 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
@@ -484,7 +484,7 @@ and various improvements have been made to improve the UX including:
- 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))
+ - add helper to approximate test creation pattern 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))
diff --git a/docs/changelogs/v0.19.md b/docs/changelogs/v0.19.md
index f7e190a7e9c..f22270e28a0 100644
--- a/docs/changelogs/v0.19.md
+++ b/docs/changelogs/v0.19.md
@@ -89,7 +89,7 @@ There are further followups up on libp2p resource manager improvements in Kubo [
and [0.18.1](https://github.com/ipfs/kubo/blob/master/docs/changelogs/v0.18.md#improving-libp2p-resource-management-integration):
1. `ipfs swarm limits` and `ipfs swarm stats` have been replaced by `ipfs swarm resources` to provide a single/combined view for limits and their current usage in a more intuitive ordering.
1. Removal of `Swarm.ResourceMgr.Limits` config. Instead [the power user can specify limits in a .json file that are fed directly to go-libp2p](https://github.com/ipfs/kubo/blob/master/docs/libp2p-resource-management.md#user-supplied-override-limits). This allows the power user to take advantage of the [new resource manager types introduced in go-libp2p 0.25](https://github.com/libp2p/go-libp2p/blob/master/CHANGELOG.md#new-resource-manager-types-) including "use default", "unlimited", "block all".
- - Note: we don't expect most users to need these capablities, but they are there if so.
+ - Note: we don't expect most users to need these capabilities, but they are there if so.
1. [Doc updates](https://github.com/ipfs/kubo/blob/master/docs/libp2p-resource-management.md).
#### Gateways
@@ -205,11 +205,11 @@ For more information and rational see [#9717](https://github.com/ipfs/kubo/issue
- Merge Kubo: v0.18 ([ipfs/kubo#9581](https://github.com/ipfs/kubo/pull/9581))
- 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: ensure connmgr is smaller then autoscalled resource 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: refuse to start if connmgr is smaller than resource 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
diff --git a/docs/changelogs/v0.21.md b/docs/changelogs/v0.21.md
index 4dd29c5ed29..569ea8f798b 100644
--- a/docs/changelogs/v0.21.md
+++ b/docs/changelogs/v0.21.md
@@ -75,7 +75,7 @@ The [`go-ipfs-http-client`](https://github.com/ipfs/go-ipfs-http-client) RPC has
been migrated into [`kubo/client/rpc`](../../client/rpc).
With this change the two will be kept in sync, in some previous releases we
-updated the CoreAPI with new Kubo features but forgot to port thoses to the
+updated the CoreAPI with new Kubo features but forgot to port those to the
http-client, making it impossible to use them together with the same coreapi
version.
@@ -142,7 +142,7 @@ Shared Size: 2048
Ratio: 1.615755
```
-`ipfs --enc=json dag stat`'s keys are a non breaking change, new keys have been added but old keys with previous sementics are still here.
+`ipfs --enc=json dag stat`'s keys are a non breaking change, new keys have been added but old keys with previous semantics are still here.
#### Accelerated DHT Client is no longer experimental
diff --git a/docs/changelogs/v0.23.md b/docs/changelogs/v0.23.md
index 70c1d460a85..10061fdf439 100644
--- a/docs/changelogs/v0.23.md
+++ b/docs/changelogs/v0.23.md
@@ -27,7 +27,7 @@
Mplex is being deprecated, this is because it is unreliable and
randomly drop streams when sending data *too fast*.
-New pieces of code rely on backpressure, that means the stream will dynamicaly
+New pieces of code rely on backpressure, that means the stream will dynamically
slow down the sending rate if data is getting backed up.
Backpressure is provided by **Yamux** and **QUIC**.
@@ -111,7 +111,7 @@ the `/quic-v1` addresses only. For more background information, check [issue #94
Thanks to [probelab.io's RFM17.1](https://github.com/plprobelab/network-measurements/blob/master/results/rfm17.1-sharing-prs-with-multiaddresses.md) DHT servers will [now cache the addresses of content hosts for the lifetime of the provider record](https://github.com/libp2p/go-libp2p-kad-dht/commit/777160f164b8c187c534debd293157031e9f3a02).
-This means clients who resolve content from theses servers get a responses which include both peer id and multiaddresses.
+This means clients who resolve content from these servers get a responses which include both peer id and multiaddresses.
In most cases this enables skipping a second query which resolves the peer id to multiaddresses for stable enough peers.
This will improve content fetching lantency in the network overtime as servers updates.
@@ -175,7 +175,7 @@ Thx a lot @bmwiedemann for debugging this issue.
- chore: bump boxo for verifcid breaking changes
- chore: remove outdated comment (#10077) ([ipfs/kubo#10077](https://github.com/ipfs/kubo/pull/10077))
- chore: remove deprecated testground plans
- - feat: allow users to optin again into mplex
+ - feat: allow users to option again into mplex
- feat: remove Mplex
- docs(readme): minimal reqs (#10066) ([ipfs/kubo#10066](https://github.com/ipfs/kubo/pull/10066))
- docs: add v0.23.md
diff --git a/docs/changelogs/v0.24.md b/docs/changelogs/v0.24.md
index 9ca7fa84eb6..7e0a755915b 100644
--- a/docs/changelogs/v0.24.md
+++ b/docs/changelogs/v0.24.md
@@ -62,7 +62,7 @@ record remains cached before checking an upstream routing system, such as Amino
DHT, for updates. The TTL value in the IPNS record now serves as a hint for:
- `boxo/namesys`: the internal cache, determining how long the IPNS resolution
- result is cached before asking upsteam routing systems for updates.
+ result is cached before asking upstream routing systems for updates.
- `boxo/gateway`: the `Cache-Control` HTTP header in responses to requests made
for `/ipns/name` content paths.
diff --git a/docs/changelogs/v0.25.md b/docs/changelogs/v0.25.md
index db610044a75..c1ac973c306 100644
--- a/docs/changelogs/v0.25.md
+++ b/docs/changelogs/v0.25.md
@@ -44,7 +44,7 @@ After deprecating and removing mplex support by default in [v0.23.0](https://git
We now fully removed it. If you still need mplex support to talk with other pieces of software,
please try updating them, and if they don't support yamux or QUIC [talk to us about it](https://github.com/ipfs/kubo/issues/new/choose).
-Mplex is unreliable by design, it will drop data and generete errors when sending data *too fast*,
+Mplex is unreliable by design, it will drop data and generate errors when sending data *too fast*,
yamux and QUIC support backpressure, that means if we send data faster than the remote machine can process it, we slows down to match the remote's speed.
#### Graphsync Experiment Removal
diff --git a/docs/changelogs/v0.27.md b/docs/changelogs/v0.27.md
index 26a607f8abb..aba290cf3cf 100644
--- a/docs/changelogs/v0.27.md
+++ b/docs/changelogs/v0.27.md
@@ -7,6 +7,10 @@
- [Overview](#overview)
- [🔦 Highlights](#-highlights)
- [Gateway: support for `/api/v0` is deprecated](#gateway-support-for-apiv0-is-deprecated)
+ - [IPNS resolver cache's TTL can now be configured](#ipns-resolver-caches-ttl-can-now-be-configured)
+ - [RPC client: deprecated DHT API, added Routing API](#rpc-client-deprecated-dht-api-added-routing-api)
+ - [Deprecated DHT commands removed from `/api/v0/dht`](#deprecated-dht-commands-removed-from-apiv0dht)
+ - [Repository migrations are now trustless](#repository-migrations-are-now-trustless)
- [📝 Changelog](#-changelog)
- [👨👩👧👦 Contributors](#-contributors)
@@ -24,6 +28,117 @@ If you have a legacy software that relies on this behavior, and want to expose p
You can now configure the upper-bound of a cached IPNS entry's Time-To-Live via [`Ipns.MaxCacheTTL`](https://github.com/ipfs/kubo/blob/master/docs/config.md#ipnsmaxcachettl).
+#### RPC client: deprecated DHT API, added Routing API
+
+The RPC client for GO (`kubo/client/rpc`) now includes a Routing API to match the available commands in `/api/v0/routing`. In addition, the DHT API has been marked as deprecated.
+
+In the next version, all DHT deprecated methods will be removed from the Go RPC client.
+
+#### Deprecated DHT commands removed from `/api/v0/dht`
+
+All the DHT commands that were deprecated for over a year were finally removed from `/api/v0/dht`. Users should switch to modern `/api/v0/routing` which works with [both Amino DHT and Delegated Routers](https://github.com/ipfs/kubo/blob/master/docs/config.md#routing).
+
+#### Repository migrations are now trustless
+
+Kubo now only uses [trustless requests](https://specs.ipfs.tech/http-gateways/trustless-gateway/) (e.g., CAR files) when downloading repository migrations via HTTP. This further strengthens Kubo by not delegating trust to public gateways. The migration binaries are locally verified before being executed.
+
### 📝 Changelog
+Full Changelog
+
+- github.com/ipfs/kubo:
+ - chore: update version
+ - chore: update version
+ - test: cleanup content blocking tests (#10360) ([ipfs/kubo#10360](https://github.com/ipfs/kubo/pull/10360))
+ - docs: improve release issue template
+ - chore: update version
+ - repo/fsrepo/migrations: verified HTTP migrations (#10324) ([ipfs/kubo#10324](https://github.com/ipfs/kubo/pull/10324))
+ - chore: fix link
+ - docs: clarify Gateway.ExposeRoutingAPI (#10337) ([ipfs/kubo#10337](https://github.com/ipfs/kubo/pull/10337))
+ - commands/add: return an error when using --only-hash and --to-files
+ - docs(config): mention routing v1 spec
+ - core/commands: remove 'ipfs dht' commands, except 'query' (#10328) ([ipfs/kubo#10328](https://github.com/ipfs/kubo/pull/10328))
+ - core: deprecate CoreAPI.Dht, introduce CoreAPI.Routing
+ - refactor: superfluous namespace test redirects (#10322) ([ipfs/kubo#10322](https://github.com/ipfs/kubo/pull/10322))
+ - feat: add Ipns.MaxCacheTTL
+ - fix(gw): negative entity-bytes beyond file size (#10320) ([ipfs/kubo#10320](https://github.com/ipfs/kubo/pull/10320))
+ - core/corehttp: wrap gateway with headers, deprecate gateway /api/v0
+ - docs: add changelog link to release issue template
+ - docs: remove whizzzkid
+ - chore: create next changelog
+ - Merge Release: v0.26.0 [skip changelog] ([ipfs/kubo#10313](https://github.com/ipfs/kubo/pull/10313))
+ - config: remove all options that are marked as REMOVED
+ - chore: remove Gateway.APICommands
+ - docs(cli): name inspect --verify (#10308) ([ipfs/kubo#10308](https://github.com/ipfs/kubo/pull/10308))
+ - docs: improve release issue template (#10305) ([ipfs/kubo#10305](https://github.com/ipfs/kubo/pull/10305))
+ - core/corehttp: wrap hostname option with otelhttp
+ - fix: profiling tests
+ - profile: add trace
+ - docs(config): clarify ReproviderStrategy roots
+ - chore: update version
+ - docs: in RELEASE_ISSUE_TEMPLATE ask releaser to ensure we are using the latest go release on the major branch
+- github.com/ipfs/boxo (v0.17.0 -> v0.18.0):
+ - Release v0.18.0 ([ipfs/boxo#581](https://github.com/ipfs/boxo/pull/581))
+- github.com/libp2p/go-libp2p (v0.32.2 -> v0.33.0):
+ - release v0.33.0 (#2715) ([libp2p/go-libp2p#2715](https://github.com/libp2p/go-libp2p/pull/2715))
+ - chore: update deps for v0.33 (#2713) ([libp2p/go-libp2p#2713](https://github.com/libp2p/go-libp2p/pull/2713))
+ - webrtc: wait for FIN_ACK before closing data channels (#2615) ([libp2p/go-libp2p#2615](https://github.com/libp2p/go-libp2p/pull/2615))
+ - quic: upgrade quic-go to v0.41.0 (#2710) ([libp2p/go-libp2p#2710](https://github.com/libp2p/go-libp2p/pull/2710))
+ - chore: remove unused GenerateEKeyPair function (#2711) ([libp2p/go-libp2p#2711](https://github.com/libp2p/go-libp2p/pull/2711))
+ - chore: drop support for go1.20 (#2708) ([libp2p/go-libp2p#2708](https://github.com/libp2p/go-libp2p/pull/2708))
+ - chore: testify fix got, expected transpositions (#2666) ([libp2p/go-libp2p#2666](https://github.com/libp2p/go-libp2p/pull/2666))
+ - docs: fix broken link in README
+ - chore: fix typos (#2694) ([libp2p/go-libp2p#2694](https://github.com/libp2p/go-libp2p/pull/2694))
+ - libp2phttp: fix flaky ExampleHost_listenOnHTTPTransportAndStreams (#2697) ([libp2p/go-libp2p#2697](https://github.com/libp2p/go-libp2p/pull/2697))
+ - chore(p2p/host): fix typos (#2683) ([libp2p/go-libp2p#2683](https://github.com/libp2p/go-libp2p/pull/2683))
+ - chore: fix typos (#2689) ([libp2p/go-libp2p#2689](https://github.com/libp2p/go-libp2p/pull/2689))
+ - defaults: do TLS by default for encryption (#2650) ([libp2p/go-libp2p#2650](https://github.com/libp2p/go-libp2p/pull/2650))
+ - webrtc: fix flaky TestMaxInFlightRequests (#2682) ([libp2p/go-libp2p#2682](https://github.com/libp2p/go-libp2p/pull/2682))
+ - chore: remove unnecessary conversions (#2680) ([libp2p/go-libp2p#2680](https://github.com/libp2p/go-libp2p/pull/2680))
+ - chore: update chat-with-mdns example readme (#2678) ([libp2p/go-libp2p#2678](https://github.com/libp2p/go-libp2p/pull/2678))
+ - examples: call NewStream from only one side (#2677) ([libp2p/go-libp2p#2677](https://github.com/libp2p/go-libp2p/pull/2677))
+ - chore: fix typos in comment (#2674) ([libp2p/go-libp2p#2674](https://github.com/libp2p/go-libp2p/pull/2674))
+ - chore: update go-libp2p-asn-util (#2673) ([libp2p/go-libp2p#2673](https://github.com/libp2p/go-libp2p/pull/2673))
+ - chore: update go security policy url (#2665) ([libp2p/go-libp2p#2665](https://github.com/libp2p/go-libp2p/pull/2665))
+ - security: remove separate licenses for Noise and TLS (#2663) ([libp2p/go-libp2p#2663](https://github.com/libp2p/go-libp2p/pull/2663))
+ - webrtc: clarify that there is no reuseport functionality (#2652) ([libp2p/go-libp2p#2652](https://github.com/libp2p/go-libp2p/pull/2652))
+ - rcmgr: fix connmgr connection limit conflict warning (#2648) ([libp2p/go-libp2p#2648](https://github.com/libp2p/go-libp2p/pull/2648))
+ - tcp: fix build on loong64 (#2655) ([libp2p/go-libp2p#2655](https://github.com/libp2p/go-libp2p/pull/2655))
+ - swarm: fix grafana dashboard templating (#2640) ([libp2p/go-libp2p#2640](https://github.com/libp2p/go-libp2p/pull/2640))
+ - chore: fix typos (#2608) ([libp2p/go-libp2p#2608](https://github.com/libp2p/go-libp2p/pull/2608))
+ - chore: add resource manager dashboard to docker-compose (#2641) ([libp2p/go-libp2p#2641](https://github.com/libp2p/go-libp2p/pull/2641))
+ - pstoremanager: fix race condition when removing peers from peer store (#2644) ([libp2p/go-libp2p#2644](https://github.com/libp2p/go-libp2p/pull/2644))
+ - examples: remove unused 'SetStreamHandler' (#2598) ([libp2p/go-libp2p#2598](https://github.com/libp2p/go-libp2p/pull/2598))
+ - Update docs from RSA to Ed25519 (#2606) ([libp2p/go-libp2p#2606](https://github.com/libp2p/go-libp2p/pull/2606))
+- github.com/multiformats/go-multiaddr (v0.12.1 -> v0.12.2):
+ - chore: release v0.12.2
+ - tests: add round trip equality check to fuzz (#232) ([multiformats/go-multiaddr#232](https://github.com/multiformats/go-multiaddr/pull/232))
+ - fix: correctly parse ports as uint16 and explicitly fail on overflows (#228) ([multiformats/go-multiaddr#228](https://github.com/multiformats/go-multiaddr/pull/228))
+ - replace custom random tests with testing.F (#227) ([multiformats/go-multiaddr#227](https://github.com/multiformats/go-multiaddr/pull/227))
+
+
+
### 👨👩👧👦 Contributors
+
+| Contributor | Commits | Lines ± | Files Changed |
+|-------------|---------|---------|---------------|
+| Henrique Dias | 26 | +1668/-1484 | 96 |
+| Sukun | 13 | +983/-618 | 68 |
+| Jorropo | 18 | +501/-222 | 32 |
+| Marten Seemann | 2 | +17/-244 | 5 |
+| dozyio | 1 | +117/-132 | 31 |
+| Marcin Rataj | 7 | +100/-20 | 8 |
+| Alexandr Burdiyan | 2 | +29/-54 | 2 |
+| Tyler | 1 | +17/-19 | 2 |
+| KeienWang | 2 | +14/-14 | 12 |
+| Håvard Anda Estensen | 1 | +14/-14 | 11 |
+| Halimao | 2 | +17/-4 | 2 |
+| hannahhoward | 1 | +14/-6 | 2 |
+| alex | 1 | +8/-8 | 4 |
+| shuoer86 | 1 | +7/-7 | 5 |
+| John Chase | 1 | +0/-12 | 1 |
+| GoodDaisy | 1 | +5/-5 | 4 |
+| Michael Muré | 1 | +6/-2 | 1 |
+| 吴小白 | 1 | +3/-3 | 3 |
+| Vehorny | 1 | +3/-3 | 2 |
+| Eric | 1 | +1/-1 | 1 |
diff --git a/docs/changelogs/v0.28.md b/docs/changelogs/v0.28.md
new file mode 100644
index 00000000000..6dfd33386be
--- /dev/null
+++ b/docs/changelogs/v0.28.md
@@ -0,0 +1,130 @@
+# Kubo changelog v0.28
+
+- [v0.28.0](#v0280)
+
+## v0.28.0
+
+- [Overview](#overview)
+- [🔦 Highlights](#-highlights)
+ - [RPC client: removed deprecated DHT API](#rpc-client-removed-deprecated-dht-api)
+ - [Gateway: `/api/v0` is removed](#gateway-apiv0-is-removed)
+ - [Removed deprecated Object API commands](#removed-deprecated-object-api-commands)
+ - [No longer publishes loopback and private addresses on DHT](#no-longer-publishes-loopback-and-private-addresses-on-dht)
+ - [Pin roots are now prioritized when announcing](#pin-roots-are-now-prioritized-when-announcing)
+- [📝 Changelog](#-changelog)
+- [👨👩👧👦 Contributors](#-contributors)
+
+### Overview
+
+#### RPC client: removed deprecated DHT API
+
+The deprecated DHT API commands in the RPC client have been removed. Instead, use the Routing API.
+
+#### Gateway: `/api/v0` is removed
+
+The legacy subset of the Kubo RPC that was available via the Gateway port and was deprecated is now completely removed. You can read more in .
+
+If you have a legacy software that relies on this behavior, and want to expose parts of `/api/v0` next to `/ipfs`, use reverse-proxy in front of Kubo to mount both Gateway and RPC on the same port. NOTE: exposing RPC to the internet comes with security risk: make sure to specify access control via [API.Authorizations](https://github.com/ipfs/kubo/blob/master/docs/config.md#apiauthorizations).
+
+#### Removed deprecated Object API commands
+
+The Object API commands deprecated back in [2021](https://github.com/ipfs/kubo/issues/7936) have been removed, except for `object diff`, `object patch add-link` and `object patch rm-link`, whose alternatives have not yet been built (see issues [4801](https://github.com/ipfs/kubo/issues/4801) and [4782](https://github.com/ipfs/kubo/issues/4782)).
+
+##### Kubo ignores loopback addresses on LAN DHT and private addresses on WAN DHT
+
+Kubo no longer keeps track of loopback and private addresses on the LAN and WAN DHTs, respectively. This means that other nodes will not try to dial likely undialable addresses.
+
+To support testing scenarios where multiple Kubo instances run on the same machine, [`Routing.LoopbackAddressesOnLanDHT`](https://github.com/ipfs/kubo/blob/master/docs/config.md#routingloopbackaddressesonlandht) is set to `true` when the `test` profile is applied.
+
+#### Pin roots are now prioritized when announcing
+
+The root CIDs of pinned content are now prioritized when announcing to the Amino DHT with [`Reprovider.Strategy`](https://github.com/ipfs/kubo/blob/master/docs/config.md#reproviderstrategy) set to `all` (default) or `pinned`, making the important CIDs accessible faster.
+
+### 📝 Changelog
+
+Full Changelog
+
+- github.com/ipfs/kubo:
+ - chore: update version
+ - chore: update version
+ - core/node: prioritize announcing pin roots, and flat strategy (#10376) ([ipfs/kubo#10376](https://github.com/ipfs/kubo/pull/10376))
+ - chore: webui v4.2.1 (#10391) ([ipfs/kubo#10391](https://github.com/ipfs/kubo/pull/10391))
+ - docs(config): clarify RPC vs Gateway
+ - chore: upgrade go-libp2p-kad-dht (#10378) ([ipfs/kubo#10378](https://github.com/ipfs/kubo/pull/10378))
+ - chore(config): make Routing.AcceleratedDHTClient a Flag (#10384) ([ipfs/kubo#10384](https://github.com/ipfs/kubo/pull/10384))
+ - fix: switch lowpower profile to autoclient
+ - core: fix some typos (#10382) ([ipfs/kubo#10382](https://github.com/ipfs/kubo/pull/10382))
+ - docs: fix some typos (#10377) ([ipfs/kubo#10377](https://github.com/ipfs/kubo/pull/10377))
+ - core/commands!: remove deprecated object APIs (#10375) ([ipfs/kubo#10375](https://github.com/ipfs/kubo/pull/10375))
+ - docs: update default ipns lifetime
+ - coreapi/unixfs: don't create an additional IpfsNode for --only-hash
+ - chore: cleanup old workaround (#10369) ([ipfs/kubo#10369](https://github.com/ipfs/kubo/pull/10369))
+ - chore: finish reframe removal
+ - docs: remove repetitive words (#10370) ([ipfs/kubo#10370](https://github.com/ipfs/kubo/pull/10370))
+ - docs: updated links and refs to external resources (#10368) ([ipfs/kubo#10368](https://github.com/ipfs/kubo/pull/10368))
+ - core/corehttp!: remove /api/v0 from gateway port
+ - client/rpc!: remove deprecated DHT commands
+ - ci: upgrade to go 1.22 (#10355) ([ipfs/kubo#10355](https://github.com/ipfs/kubo/pull/10355))
+ - chore: create next changelog
+ - Merge Release: v0.27.0 [skip changelog] ([ipfs/kubo#10362](https://github.com/ipfs/kubo/pull/10362))
+ - test: cleanup content blocking tests (#10360) ([ipfs/kubo#10360](https://github.com/ipfs/kubo/pull/10360))
+ - docs: improve release issue template
+ - chore: update version
+- github.com/ipfs/boxo (v0.18.0 -> v0.19.0):
+ - Release v0.19.0 ([ipfs/boxo#598](https://github.com/ipfs/boxo/pull/598))
+- github.com/libp2p/go-libp2p (v0.33.0 -> v0.33.2):
+ - chore: release v0.33.2 (#2755) ([libp2p/go-libp2p#2755](https://github.com/libp2p/go-libp2p/pull/2755))
+ - Update quic-go to v0.42.0. Release v0.33.1 (#2741) ([libp2p/go-libp2p#2741](https://github.com/libp2p/go-libp2p/pull/2741))
+- github.com/libp2p/go-libp2p-kad-dht (v0.24.4 -> v0.25.2):
+ - chore: release v0.25.2 ([libp2p/go-libp2p-kad-dht#961](https://github.com/libp2p/go-libp2p-kad-dht/pull/961))
+ - add ctx canceled err check ([libp2p/go-libp2p-kad-dht#960](https://github.com/libp2p/go-libp2p-kad-dht/pull/960))
+ - chore: release v0.25.1
+ - perf: don't buffer the output of FindProvidersAsync
+ - chore: use go-libp2p-routing-helpers for tracing needs
+ - fix: properly iterate in tracing for protocol messenger
+ - fix: apply addrFilters in the dht (#872) ([libp2p/go-libp2p-kad-dht#872](https://github.com/libp2p/go-libp2p-kad-dht/pull/872))
+ - Add provider record addresses to peerstore ([libp2p/go-libp2p-kad-dht#870](https://github.com/libp2p/go-libp2p-kad-dht/pull/870))
+ - chore: release v0.25.0
+ - tracing: add protocol messages client tracing
+ - Enhance handleNewMessage Server Mode Logging: Convert Error Logs to Debug Level ([libp2p/go-libp2p-kad-dht#860](https://github.com/libp2p/go-libp2p-kad-dht/pull/860))
+ - tracing: fix DHT keys as string attribute not being valid utf-8 ([libp2p/go-libp2p-kad-dht#859](https://github.com/libp2p/go-libp2p-kad-dht/pull/859))
+ - merge: fix: issues discovered in kubo v0.21.0-rc2 (#853) ([libp2p/go-libp2p-kad-dht#853](https://github.com/libp2p/go-libp2p-kad-dht/pull/853))
+ - merge: fix: issues discovered in kubo v0.21.0-rc1 (#851) ([libp2p/go-libp2p-kad-dht#851](https://github.com/libp2p/go-libp2p-kad-dht/pull/851))
+ - Release v0.24.0 ([libp2p/go-libp2p-kad-dht#844](https://github.com/libp2p/go-libp2p-kad-dht/pull/844))
+ - fix: don't add unresponsive DHT servers to the Routing Table (#820) ([libp2p/go-libp2p-kad-dht#820](https://github.com/libp2p/go-libp2p-kad-dht/pull/820))
+ - filter local addresses (for WAN) and localhost addresses (for LAN) ([libp2p/go-libp2p-kad-dht#839](https://github.com/libp2p/go-libp2p-kad-dht/pull/839))
+- github.com/multiformats/go-multiaddr (v0.12.2 -> v0.12.3):
+ - chore: release v0.12.3 ([multiformats/go-multiaddr#240](https://github.com/multiformats/go-multiaddr/pull/240))
+ - chore: Expand comment ForEach ([multiformats/go-multiaddr#238](https://github.com/multiformats/go-multiaddr/pull/238))
+ - .Decapsulate by Components ([multiformats/go-multiaddr#239](https://github.com/multiformats/go-multiaddr/pull/239))
+- github.com/whyrusleeping/cbor-gen (v0.0.0-20240109153615-66e95c3e8a87 -> v0.1.0):
+ - Nullable ints (#93) ([whyrusleeping/cbor-gen#93](https://github.com/whyrusleeping/cbor-gen/pull/93))
+ - Introduce Gen{} struct for configurability ([whyrusleeping/cbor-gen#94](https://github.com/whyrusleeping/cbor-gen/pull/94))
+ - Transparent encoding ([whyrusleeping/cbor-gen#91](https://github.com/whyrusleeping/cbor-gen/pull/91))
+ - turn max length consts into global vars ([whyrusleeping/cbor-gen#92](https://github.com/whyrusleeping/cbor-gen/pull/92))
+
+
+
+### 👨👩👧👦 Contributors
+
+| Contributor | Commits | Lines ± | Files Changed |
+|-------------|---------|---------|---------------|
+| Henrique Dias | 19 | +867/-2806 | 96 |
+| Rod Vagg | 7 | +921/-475 | 25 |
+| Marcin Rataj | 8 | +358/-344 | 18 |
+| Guillaume Michel - guissou | 1 | +145/-485 | 13 |
+| Jorropo | 8 | +429/-136 | 22 |
+| Łukasz Magiera | 4 | +284/-48 | 11 |
+| whyrusleeping | 1 | +90/-90 | 2 |
+| Michael Muré | 2 | +48/-73 | 9 |
+| Marco Munizaga | 6 | +86/-29 | 10 |
+| guillaumemichel | 3 | +93/-1 | 3 |
+| Marten Seemann | 1 | +31/-4 | 4 |
+| godeamon | 3 | +11/-8 | 3 |
+| shuangcui | 1 | +6/-6 | 5 |
+| occupyhabit | 1 | +3/-3 | 3 |
+| crazehang | 1 | +2/-2 | 1 |
+| Dennis Trautwein | 1 | +1/-2 | 1 |
+| “GheisMohammadi” | 1 | +1/-1 | 1 |
+| web3-bot | 1 | +2/-0 | 1 |
+| Daniel Norman | 1 | +1/-1 | 1 |
diff --git a/docs/changelogs/v0.29.md b/docs/changelogs/v0.29.md
new file mode 100644
index 00000000000..82ec3eab266
--- /dev/null
+++ b/docs/changelogs/v0.29.md
@@ -0,0 +1,241 @@
+# Kubo changelog v0.29
+
+- [v0.29.0](#v0290)
+
+## v0.29.0
+
+- [Overview](#overview)
+- [🔦 Highlights](#-highlights)
+ - [Add search functionality for pin names](#add-search-functionality-for-pin-names)
+ - [Customizing `ipfs add` defaults](#customizing-ipfs-add-defaults)
+- [📝 Changelog](#-changelog)
+- [👨👩👧👦 Contributors](#-contributors)
+
+### Overview
+
+### 🔦 Highlights
+
+#### Add search functionality for pin names
+
+It is now possible to search for pins by name via `ipfs pin ls --name "SomeName"`.
+The search is case-sensitive and will return all pins that contain the specified substring in their name.
+
+> [!TIP]
+> The `ipfs pin ls -n` is now a shorthand for `ipfs pin ls --name`, mirroring the behavior of `ipfs pin add`.
+> See `ipfs pin ls --help` for more information.
+
+#### Customizing `ipfs add` defaults
+
+This release supports overriding global data ingestion defaults used by commands like `ipfs add` via user-defined [`Import.*` configuration options](../config.md#import).
+The hash function, CID version, or UnixFS raw leaves and chunker behaviors can be set once, and used as the new implicit default for `ipfs add`.
+
+> [!TIP]
+> As a convenience, two CID [profiles](../config.md#profile) are provided: `legacy-cid-v0` and `test-cid-v1`.
+> A test profile that defaults to modern CIDv1 can be applied via `ipfs config profile apply test-cid-v1`.
+> We encourage users to try it and report any issues in [kubo#4143](https://github.com/ipfs/kubo/issues/4143).
+
+### 📝 Changelog
+
+Full Changelog
+
+- github.com/ipfs/kubo:
+ - fix(cli): unify --name param in ls and add (#10439) ([ipfs/kubo#10439](https://github.com/ipfs/kubo/pull/10439))
+ - chore: set version to 0.29.0-rc2
+ - fix(libp2p): streams config validation in resource manager (#10435) ([ipfs/kubo#10435](https://github.com/ipfs/kubo/pull/10435))
+ - chore: update version
+ - chore: libp2p 0.34.1 (#10429) ([ipfs/kubo#10429](https://github.com/ipfs/kubo/pull/10429))
+ - refactor: stop using github.com/pkg/errors (#10431) ([ipfs/kubo#10431](https://github.com/ipfs/kubo/pull/10431))
+ - chore: fix --help text
+ - config: introduce Import section (#10421) ([ipfs/kubo#10421](https://github.com/ipfs/kubo/pull/10421))
+ - feat: enables searching pins by name (#10412) ([ipfs/kubo#10412](https://github.com/ipfs/kubo/pull/10412))
+ - fix(fuse): ipfs path parsing (#10243) ([ipfs/kubo#10243](https://github.com/ipfs/kubo/pull/10243))
+ - core/node: fix divide by zero fatal crash for reprovide rate check (#10411) ([ipfs/kubo#10411](https://github.com/ipfs/kubo/pull/10411))
+ - chore: bump to go-ipfs-cmds @ v0.11
+ - chore: create next changelog
+ - Merge Release: v0.28.0 [skip changelog] ([ipfs/kubo#10402](https://github.com/ipfs/kubo/pull/10402))
+ - docs: update release checklist (#10401) ([ipfs/kubo#10401](https://github.com/ipfs/kubo/pull/10401))
+ - chore: update version
+- github.com/ipfs/boxo (v0.19.0 -> v0.20.0):
+ - Release v0.20.0 ([ipfs/boxo#613](https://github.com/ipfs/boxo/pull/613))
+- github.com/ipfs/go-blockservice (v0.5.0 -> v0.5.2):
+ - docs: remove contribution section
+ - chore: bump version
+ - chore: deprecate types and readme
+ - chore: release v0.5.1
+ - fix: remove busyloop in getBlocks by removing batching
+- github.com/ipfs/go-ipfs-blockstore (v1.3.0 -> v1.3.1):
+ - docs: remove contribution section
+ - chore: bump version
+ - chore: deprecate types and readme
+- github.com/ipfs/go-ipfs-cmds (v0.10.0 -> v0.11.0):
+ - chore: release v0.11.0 (#253) ([ipfs/go-ipfs-cmds#253](https://github.com/ipfs/go-ipfs-cmds/pull/253))
+ - chore: update deps (#252) ([ipfs/go-ipfs-cmds#252](https://github.com/ipfs/go-ipfs-cmds/pull/252))
+ - chore: release 0.10.2 (#251) ([ipfs/go-ipfs-cmds#251](https://github.com/ipfs/go-ipfs-cmds/pull/251))
+ - fix(http): return error in case of panic (#250) ([ipfs/go-ipfs-cmds#250](https://github.com/ipfs/go-ipfs-cmds/pull/250))
+ - chore: release v0.10.1
+- github.com/ipfs/go-ipfs-ds-help (v1.1.0 -> v1.1.1):
+ - docs: remove contribution section
+ - chore: bump version
+ - chore: deprecate types and readme
+- github.com/ipfs/go-ipfs-exchange-interface (v0.2.0 -> v0.2.1):
+ - chore: bump version
+ - Deprecate types and readme (#29) ([ipfs/go-ipfs-exchange-interface#29](https://github.com/ipfs/go-ipfs-exchange-interface/pull/29))
+ - docs: Add proper documentation to the interface.
+- github.com/ipfs/go-verifcid (v0.0.2 -> v0.0.3):
+ - chore: bump version
+ - chore: deprecate types and readme
+ - Make poseidon hashes good hashes ([ipfs/go-verifcid#19](https://github.com/ipfs/go-verifcid/pull/19))
+ - sync: update CI config files (#18) ([ipfs/go-verifcid#18](https://github.com/ipfs/go-verifcid/pull/18))
+- github.com/ipld/go-car (v0.5.0 -> v0.6.2):
+ - v0.6.2 ([ipld/go-car#464](https://github.com/ipld/go-car/pull/464))
+ - fix: opt-in way to allow empty list of roots in CAR headers ([ipld/go-car#461](https://github.com/ipld/go-car/pull/461))
+ - feat: add inverse and version to filter cmd ([ipld/go-car#457](https://github.com/ipld/go-car/pull/457))
+ - v0.6.1 bump
+ - chore: update usage of merkledag by go-car (#437) ([ipld/go-car#437](https://github.com/ipld/go-car/pull/437))
+ - feat(cmd/car): add '--no-wrap' option to 'create' command ([ipld/go-car#432](https://github.com/ipld/go-car/pull/432))
+ - fix: remove github.com/ipfs/go-ipfs-blockstore dependency
+ - feat: expose index for StorageCar
+ - perf: reduce NewCarReader allocations
+ - fix(deps): update deps for cmd (use master go-car and go-car/v2 for now)
+ - fix: new error strings from go-cid
+ - fix: tests should match stderr for verbose output
+ - fix: reading from stdin should broadcast EOF to block loaders
+ - refactor insertion index to be publicly accessible ([ipld/go-car#408](https://github.com/ipld/go-car/pull/408))
+ - chore: unmigrate from go-libipfs
+ - Create CODEOWNERS
+ - blockstore: give a direct access to the index for read operations
+ - blockstore: only close the file on error in OpenReadWrite, not OpenReadWriteFile
+ - fix: handle (and test) WholeCID vs not; fast Has() path for storage
+ - ReadWrite: faster Has() by using the in-memory index instead of reading on disk
+ - fix: let `extract` skip missing unixfs shard links
+ - fix: error when no files extracted
+ - fix: make -f optional, read from stdin if omitted
+ - fix: update cmd/car/README with latest description
+ - chore: add test cases for extract modes
+ - feat: extract accepts '-' as an output path for stdout
+ - feat: extract specific path, accept stdin as streaming input
+ - fix: if we don't read the full block data, don't error on !EOF
+ - blockstore: try to close during Finalize(), even in case of previous error
+ - ReadWrite: add an alternative FinalizeReadOnly+Close flow
+ - feat: add WithTrustedCar() reader option (#381) ([ipld/go-car#381](https://github.com/ipld/go-car/pull/381))
+ - blockstore: fast path for AllKeysChan using the index
+ - fix: switch to crypto/rand.Read
+ - stop using the deprecated io/ioutil package
+ - fix(doc): fix storage package doc formatting
+ - fix: return errors for unsupported operations
+ - chore: move insertionindex into store pkg
+ - chore: add experimental note
+ - fix: minor lint & windows fd test problems
+ - feat: docs for StorageCar interfaces
+ - feat: ReadableWritable; dedupe shared code
+ - feat: add Writable functionality to StorageCar
+ - feat: StorageCar as a Readable storage, separate from blockstore
+ - feat(blockstore): implement a streaming read only storage
+ - feat(cmd): add index create subcommand to create an external carv2 index ([ipld/go-car#350](https://github.com/ipld/go-car/pull/350))
+ - chore: bump version to 0.6.0
+ - fix: use goreleaser instead
+ - Allow using WalkOption in WriteCar function ([ipld/go-car#357](https://github.com/ipld/go-car/pull/357))
+ - fix: update go-block-format to the version that includes the stubs
+ - feat: upgrade from go-block-format to go-libipfs/blocks
+ - cleanup readme a bit to make the cli more discoverable (#353) ([ipld/go-car#353](https://github.com/ipld/go-car/pull/353))
+ - Update install instructions in README.md
+ - Add a debugging form for car files. (#341) ([ipld/go-car#341](https://github.com/ipld/go-car/pull/341))
+ - ([ipld/go-car#340](https://github.com/ipld/go-car/pull/340))
+ - 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
+- github.com/libp2p/go-libp2p (v0.33.2 -> v0.34.1):
+ - release v0.34.1 (#2811) ([libp2p/go-libp2p#2811](https://github.com/libp2p/go-libp2p/pull/2811))
+ - config: fix Insecure security constructor (#2810) ([libp2p/go-libp2p#2810](https://github.com/libp2p/go-libp2p/pull/2810))
+ - rcmgr: Backwards compatibility if you wrap default impl (#2805) ([libp2p/go-libp2p#2805](https://github.com/libp2p/go-libp2p/pull/2805))
+ - v0.34.0 (#2795) ([libp2p/go-libp2p#2795](https://github.com/libp2p/go-libp2p/pull/2795))
+ - swarm: fix addr for TestBlackHoledAddrBlocked (#2803) ([libp2p/go-libp2p#2803](https://github.com/libp2p/go-libp2p/pull/2803))
+ - Add backwards compatibility with old well-known resource (#2798) ([libp2p/go-libp2p#2798](https://github.com/libp2p/go-libp2p/pull/2798))
+ - rcmgr: remove a connection only once from the limiter (#2800) ([libp2p/go-libp2p#2800](https://github.com/libp2p/go-libp2p/pull/2800))
+ - Adhere to request.Context when roundtripping on a stream (#2796) ([libp2p/go-libp2p#2796](https://github.com/libp2p/go-libp2p/pull/2796))
+ - fix: Set missing deadlines (#2794) ([libp2p/go-libp2p#2794](https://github.com/libp2p/go-libp2p/pull/2794))
+ - rcmgr: Add conn_limiter to limit number of conns per ip cidr (#2788) ([libp2p/go-libp2p#2788](https://github.com/libp2p/go-libp2p/pull/2788))
+ - identify: refactor observed address manager to do address mapping at thin waist(IP+TCP/UDP) layer (#2793) ([libp2p/go-libp2p#2793](https://github.com/libp2p/go-libp2p/pull/2793))
+ - fix: DNS protocol address is not reserved (#2792) ([libp2p/go-libp2p#2792](https://github.com/libp2p/go-libp2p/pull/2792))
+ - Update github.com/quic-go/quic-go dependency (#2780) ([libp2p/go-libp2p#2780](https://github.com/libp2p/go-libp2p/pull/2780))
+ - webrtc: add webrtc addresses to host normalizer (#2784) ([libp2p/go-libp2p#2784](https://github.com/libp2p/go-libp2p/pull/2784))
+ - Add a "Limited" network connectivity state (#2696) ([libp2p/go-libp2p#2696](https://github.com/libp2p/go-libp2p/pull/2696))
+ - basichost: append certhash for webrtc addresses provided via address factory (#2774) ([libp2p/go-libp2p#2774](https://github.com/libp2p/go-libp2p/pull/2774))
+ - Fix comment (#2775) ([libp2p/go-libp2p#2775](https://github.com/libp2p/go-libp2p/pull/2775))
+ - Update: update incomplete readmes (#2767) ([libp2p/go-libp2p#2767](https://github.com/libp2p/go-libp2p/pull/2767))
+ - libp2phttp: Return connection: close when doing http over streams (#2756) ([libp2p/go-libp2p#2756](https://github.com/libp2p/go-libp2p/pull/2756))
+ - Identify: emit useful events after identification (#2759) ([libp2p/go-libp2p#2759](https://github.com/libp2p/go-libp2p/pull/2759))
+ - Update chat with rendezvous example (#2769) ([libp2p/go-libp2p#2769](https://github.com/libp2p/go-libp2p/pull/2769))
+ - Rename well-known resource (#2757) ([libp2p/go-libp2p#2757](https://github.com/libp2p/go-libp2p/pull/2757))
+ - quic: make server cmd use RFC 9000 instead of draft-29 (#2753) ([libp2p/go-libp2p#2753](https://github.com/libp2p/go-libp2p/pull/2753))
+ - autonat: Clean up after close (#2749) ([libp2p/go-libp2p#2749](https://github.com/libp2p/go-libp2p/pull/2749))
+ - webrtc: run onDone callback immediately on close (#2729) ([libp2p/go-libp2p#2729](https://github.com/libp2p/go-libp2p/pull/2729))
+ - fix: add NullResourceManager to webrtc, fixes panic (#2752) ([libp2p/go-libp2p#2752](https://github.com/libp2p/go-libp2p/pull/2752))
+ - feat: add tls KeyLogWriter option (#2750) ([libp2p/go-libp2p#2750](https://github.com/libp2p/go-libp2p/pull/2750))
+ - Use any port, not a specific one for examples (#2748) ([libp2p/go-libp2p#2748](https://github.com/libp2p/go-libp2p/pull/2748))
+ - quicreuse: remove workaround for quic-go listener close deadlock (#2746) ([libp2p/go-libp2p#2746](https://github.com/libp2p/go-libp2p/pull/2746))
+ - use Fx to start and stop the host, swarm, autorelay and quicreuse (#2118) ([libp2p/go-libp2p#2118](https://github.com/libp2p/go-libp2p/pull/2118))
+ - webrtc: set sctp receive buffer size to 100kB (#2745) ([libp2p/go-libp2p#2745](https://github.com/libp2p/go-libp2p/pull/2745))
+ - basichost: log more info when protocol selection fails (#2734) ([libp2p/go-libp2p#2734](https://github.com/libp2p/go-libp2p/pull/2734))
+ - chore: bump quic-go (#2742) ([libp2p/go-libp2p#2742](https://github.com/libp2p/go-libp2p/pull/2742))
+ - security: remove unnecessary noise code (#2738) ([libp2p/go-libp2p#2738](https://github.com/libp2p/go-libp2p/pull/2738))
+ - webrtc: increase receive buffer size on listener (#2730) ([libp2p/go-libp2p#2730](https://github.com/libp2p/go-libp2p/pull/2730))
+ - webrtc: fix bug with logger wrapper (#2727) ([libp2p/go-libp2p#2727](https://github.com/libp2p/go-libp2p/pull/2727))
+ - dcutr: fix log format to actually print error (#2725) ([libp2p/go-libp2p#2725](https://github.com/libp2p/go-libp2p/pull/2725))
+ - webrtc: use a common logger for all pion logging (#2718) ([libp2p/go-libp2p#2718](https://github.com/libp2p/go-libp2p/pull/2718))
+ - chore: remove unreadable code, move a test function to test code, better locking in webrtc control reader
+ - ping: use context.Afterfunc to avoid a lingering goroutine (#2723) ([libp2p/go-libp2p#2723](https://github.com/libp2p/go-libp2p/pull/2723))
+ - webrtc: close mux when closing listener (#2717) ([libp2p/go-libp2p#2717](https://github.com/libp2p/go-libp2p/pull/2717))
+ - webrtc: setup datachannel handlers before connecting to a peer (#2716) ([libp2p/go-libp2p#2716](https://github.com/libp2p/go-libp2p/pull/2716))
+- github.com/libp2p/go-libp2p-pubsub (v0.10.0 -> v0.11.0):
+ - Fix: Own our CertifiedAddrBook (#555) ([libp2p/go-libp2p-pubsub#555](https://github.com/libp2p/go-libp2p-pubsub/pull/555))
+ - chores: bump go-libp2p (#558) ([libp2p/go-libp2p-pubsub#558](https://github.com/libp2p/go-libp2p-pubsub/pull/558))
+ - fix: Don't bother parsing an empty slice (#556) ([libp2p/go-libp2p-pubsub#556](https://github.com/libp2p/go-libp2p-pubsub/pull/556))
+ - Replace fragmentRPC with appendOrMergeRPC (#557) ([libp2p/go-libp2p-pubsub#557](https://github.com/libp2p/go-libp2p-pubsub/pull/557))
+- github.com/multiformats/go-multiaddr (v0.12.3 -> v0.12.4):
+ - Release v0.12.4 ([multiformats/go-multiaddr#245](https://github.com/multiformats/go-multiaddr/pull/245))
+ - net: restrict unicast ip6 public address space (#235) ([multiformats/go-multiaddr#235](https://github.com/multiformats/go-multiaddr/pull/235))
+- github.com/whyrusleeping/cbor-gen (v0.1.0 -> v0.1.1):
+ - fix: reduce memory held by deferred objects (#96) ([whyrusleeping/cbor-gen#96](https://github.com/whyrusleeping/cbor-gen/pull/96))
+
+
+
+### 👨👩👧👦 Contributors
+
+| Contributor | Commits | Lines ± | Files Changed |
+|-------------|---------|---------|---------------|
+| Henrique Dias | 33 | +4994/-579 | 115 |
+| Rod Vagg | 29 | +3781/-1367 | 90 |
+| sukun | 12 | +2026/-1215 | 39 |
+| Marco Munizaga | 18 | +1482/-382 | 47 |
+| Will | 5 | +769/-213 | 17 |
+| Steven Allen | 5 | +540/-115 | 24 |
+| Sukun | 4 | +274/-194 | 11 |
+| Michael Muré | 7 | +372/-55 | 16 |
+| Marten Seemann | 1 | +243/-141 | 10 |
+| Marcin Rataj | 7 | +244/-134 | 13 |
+| hannahhoward | 1 | +277/-0 | 2 |
+| Will Scott | 5 | +54/-38 | 9 |
+| Hector Sanjuan | 3 | +68/-20 | 5 |
+| Jorropo | 5 | +34/-47 | 15 |
+| Andrew Gillis | 2 | +67/-7 | 3 |
+| IGP | 1 | +59/-8 | 5 |
+| Adin Schmahmann | 2 | +50/-0 | 3 |
+| Laurent Senta | 1 | +40/-4 | 2 |
+| Brad Fitzpatrick | 1 | +42/-2 | 2 |
+| Fabio Bozzo | 1 | +36/-1 | 3 |
+| Yolan Romailler | 1 | +15/-19 | 4 |
+| Hlib Kanunnikov | 2 | +14/-14 | 6 |
+| Andreas Penzkofer | 1 | +22/-2 | 3 |
+| Matthias Fasching | 1 | +8/-10 | 1 |
+| gopherfarm | 2 | +16/-1 | 2 |
+| Dreamacro | 1 | +1/-10 | 1 |
+| web3-bot | 2 | +7/-3 | 4 |
+| Rafał Leszko | 1 | +4/-4 | 1 |
+| Oleg Kovalov | 1 | +4/-4 | 3 |
+| dbeal | 1 | +5/-1 | 1 |
+| Antonio Navarro Perez | 1 | +4/-1 | 1 |
+| dozyio | 1 | +3/-0 | 1 |
+| zhiqiangxu | 1 | +1/-1 | 1 |
+| the harder the luckier | 1 | +1/-1 | 1 |
+| Lukáš Lukáč | 1 | +1/-1 | 1 |
+| Steve Loeppky | 1 | +1/-0 | 1 |
diff --git a/docs/changelogs/v0.30.md b/docs/changelogs/v0.30.md
new file mode 100644
index 00000000000..742190c0ad5
--- /dev/null
+++ b/docs/changelogs/v0.30.md
@@ -0,0 +1,341 @@
+# Kubo changelog v0.30
+
+- [v0.30.0](#v0300)
+
+## v0.30.0
+
+- [Overview](#overview)
+- [🔦 Highlights](#-highlights)
+ - [Improved P2P connectivity](#improved-p2p-connectivity)
+ - [Refactored Bitswap and dag-pb chunker](#refactored-bitswap-and-dag-pb-chunker)
+ - [WebRTC-Direct Transport enabled by default](#webrtc-direct-transport-enabled-by-default)
+ - [UnixFS 1.5: Mode and Modification Time Support](#unixfs-15-mode-and-modification-time-support)
+ - [AutoNAT V2 Service Introduced Alongside V1](#autonat-v2-service-introduced-alongside-v1)
+ - [Automated `ipfs version check`](#automated-ipfs-version-check)
+ - [Version Suffix Configuration](#version-suffix-configuration)
+ - [`/unix/` socket support in `Addresses.API`](#unix-socket-support-in-addressesapi)
+ - [Cleaned Up `ipfs daemon` Startup Log](#cleaned-up-ipfs-daemon-startup-log)
+ - [Commands Preserve Specified Hostname](#commands-preserve-specified-hostname)
+- [📝 Changelog](#-changelog)
+- [👨👩👧👦 Contributors](#-contributors)
+
+### Overview
+
+### 🔦 Highlights
+
+This release took longer and is more packed with fixes and features than usual.
+
+> [!IMPORTANT]
+> TLDR: update, it contains many, many fixes.
+
+#### Improved P2P connectivity
+
+This release comes with significant go-libp2p update from v0.34.1 to v0.36.3 ([release notes](https://github.com/libp2p/go-libp2p/releases/)).
+
+It includes multiple fixes to key protocols: [QUIC](https://github.com/libp2p/specs/tree/master/quic)/[Webtransport](https://github.com/libp2p/specs/tree/master/webtransport)/[WebRTC](https://github.com/libp2p/specs/tree/master/webrtc), Connection Upgrades through Relay ([DCUtR](https://github.com/libp2p/specs/blob/master/relay/DCUtR.md)), and [Secure WebSockets](https://github.com/libp2p/specs/pull/624).
+
+Also, peers that are behind certain types of NAT will now be more reachable. For this alone, Kubo users are highly encouraged to upgrade.
+
+#### Refactored Bitswap and dag-pb chunker
+
+Some workloads may experience improved memory profile thanks to optimizations from Boxo SDK [v0.23.0](https://github.com/ipfs/boxo/releases/tag/v0.23.0).
+
+> [!IMPORTANT]
+> Storage providers should upgrade to take advantage of the Bitswap server fix, which resolves the issue of greedy peers depleting available wantlist slots for their PeerID, resulting in stalled downloads.
+
+#### WebRTC-Direct Transport enabled by default
+
+Kubo now ships with [WebRTC Direct](https://github.com/libp2p/specs/blob/master/webrtc/webrtc-direct.md) listener enabled by default: `/udp/4001/webrtc-direct`.
+
+WebRTC Direct complements existing `/wss` (Secure WebSockets) and `/webtransport` transports. Unlike `/wss`, which requires a domain name and a CA-issued TLS certificate, WebRTC Direct works with IPs and can be enabled by default on all Kubo nodes.
+
+Learn more: [`Swarm.Transports.Network.WebRTCDirect`](https://github.com/ipfs/kubo/blob/master/docs/config.md#swarmtransportsnetworkwebrtcdirect)
+
+> [!NOTE]
+> Kubo 0.30 includes a migration for existing users that adds `/webrtc-direct` listener on the same UDP port as `/udp/{port}/quic-v1`. This supports the WebRTC-Direct rollout by reusing preexisting UDP firewall settings and port mappings created for QUIC.
+
+#### UnixFS 1.5: Mode and Modification Time Support
+
+Kubo now allows users to opt-in to store mode and modification time for files, directories, and symbolic links.
+By default, if you do not opt-in, the old behavior remains unchanged, and the same CIDs will be generated as before.
+
+The `ipfs add` CLI options `--preserve-mode` and `--preserve-mtime` can be used to store the original mode and last modified time of the file being added, and `ipfs files stat /ipfs/CID` can be used for inspecting these optional attributes:
+
+```console
+$ touch ./file
+$ chmod 654 ./file
+$ ipfs add --preserve-mode --preserve-mtime -Q ./file
+QmczQr4XS1rRnWVopyg5Chr9EQ7JKpbhgnrjpb5kTQ1DKQ
+
+$ ipfs files stat /ipfs/QmczQr4XS1rRnWVopyg5Chr9EQ7JKpbhgnrjpb5kTQ1DKQ
+QmczQr4XS1rRnWVopyg5Chr9EQ7JKpbhgnrjpb5kTQ1DKQ
+Size: 0
+CumulativeSize: 22
+ChildBlocks: 0
+Type: file
+Mode: -rw-r-xr-- (0654)
+Mtime: 13 Aug 2024, 21:15:31 UTC
+```
+
+The CLI and HTTP RPC options `--mode`, `--mtime` and `--mtime-nsecs` can be used to set them to arbitrary values.
+
+Opt-in support for `mode` and `mtime` was also added to MFS (`ipfs files --help`). For more information see `--help` text of `ipfs files touch|stat|chmod` commands.
+
+Modification time support was also added to the Gateway. If present, value from file's dag-pb is returned in `Last-Modified` HTTP header and requests made with `If-Modified-Since` can produce HTTP 304 not modified response.
+
+> [!NOTE]
+> Storing `mode` and `mtime` requires root block to be `dag-pb` and disabled `raw-leaves` setting to create envelope for storing the metadata.
+
+#### AutoNAT V2 Service Introduced Alongside V1
+
+The AutoNAT service enables nodes to determine their public reachability on the internet. [AutoNAT V2](https://github.com/libp2p/specs/pull/538) enhances this protocol with improved features. In this release, Kubo will offer both V1 and V2 services to other peers, although it will continue to use only V1 when acting as a client. Future releases will phase out V1, transitioning clients to utilize V2 exclusively.
+
+For more details, see the [Deployment Plan for AutoNAT V2](https://github.com/ipfs/kubo/issues/10091) and [`AutoNAT`](https://github.com/ipfs/kubo/blob/master/docs/config.md#autonat) configuration options.
+
+#### Automated `ipfs version check`
+
+Kubo now performs privacy-preserving version checks using the [libp2p identify protocol](https://github.com/libp2p/specs/blob/master/identify/README.md) on peers detected by the Amino DHT client.
+If more than 5% of Kubo peers seen by your node are running a newer version, you will receive a log message notification.
+
+- For manual checks, refer to `ipfs version check --help` for details.
+- To disable automated checks, set [`Version.SwarmCheckEnabled`](https://github.com/ipfs/kubo/blob/master/docs/config.md#versionswarmcheckenabled) to `false`.
+
+#### Version Suffix Configuration
+
+Defining the optional agent version suffix is now simpler. The [`Version.AgentSuffix`](https://github.com/ipfs/kubo/blob/master/docs/config.md#agentsuffix) value from the Kubo config takes precedence over any value provided via `ipfs daemon --agent-version-suffix` (which is still supported).
+
+> [!NOTE]
+> Setting a custom version suffix helps with ecosystem analysis, such as Amino DHT reports published at https://stats.ipfs.network
+
+#### `/unix/` socket support in `Addresses.API`
+
+This release fixes a bug which blocked users from using Unix domain sockets for [Kubo's RPC](https://docs.ipfs.tech/reference/kubo/rpc/) (instead of a local HTTP port).
+
+```console
+$ ipfs config Addresses.API "/unix/tmp/kubo.socket"
+$ ipfs daemon # start with rpc socket
+...
+RPC API server listening on /unix/tmp/kubo.socket
+
+$ # cli client, in different terminal can find socket via /api file
+$ cat $IPFS_PATH/api
+/unix/tmp/kubo.socket
+
+$ # or have it passed via --api
+$ ipfs --api=/unix/tmp/kubo.socket id
+```
+
+#### Cleaned Up `ipfs daemon` Startup Log
+
+The `ipfs daemon` startup output has been streamlined to enhance clarity and usability:
+
+```console
+$ ipfs daemon
+Initializing daemon...
+Kubo version: 0.30.0
+Repo version: 16
+System version: amd64/linux
+Golang version: go1.22.5
+PeerID: 12D3KooWQ73s1CQsm4jWwQvdCAtc5w8LatyQt7QLQARk5xdhK9CE
+Swarm listening on 127.0.0.1:4001 (TCP+UDP)
+Swarm listening on 192.0.2.10:4001 (TCP+UDP)
+Swarm listening on [::1]:4001 (TCP+UDP)
+Swarm listening on [2001:0db8::10]:4001 (TCP+UDP)
+Run 'ipfs id' to inspect announced and discovered multiaddrs of this node.
+RPC API server listening on /ip4/127.0.0.1/tcp/5001
+WebUI: http://127.0.0.1:5001/webui
+Gateway server listening on /ip4/127.0.0.1/tcp/8080
+Daemon is ready
+```
+
+The previous lengthy listing of all listener and announced multiaddrs has been removed due to its complexity, especially with modern libp2p nodes sharing multiple transports and long lists of `/webtransport` and `/webrtc-direct` certhashes.
+The output now features a simplified list of swarm listeners, displayed in the format `host:port (TCP+UDP)`, which provides essential information for debugging connectivity issues, particularly related to port forwarding.
+Announced libp2p addresses are no longer printed on startup, because libp2p may change or augment them based on AutoNAT, relay, and UPnP state. Instead, users are prompted to run `ipfs id` to obtain up-to-date list of listeners and announced multiaddrs in libp2p format.
+
+#### Commands Preserve Specified Hostname
+
+When executing a [CLI command](https://docs.ipfs.tech/reference/kubo/cli/) over [Kubo RPC API](https://docs.ipfs.tech/reference/kubo/rpc/), if a hostname is specified by `--api=/dns4//` the resulting HTTP request now contains the hostname, instead of the the IP address that the hostname resolved to, as was the previous behavior. This makes it easier for those trying to run Kubo behind a reverse proxy using hostname-based rules.
+
+#### Commands Preserve Specified Hostname
+
+When executing a [CLI command](https://docs.ipfs.tech/reference/kubo/cli/) over [Kubo RPC API](https://docs.ipfs.tech/reference/kubo/rpc/), if a hostname is specified by `--api=/dns4//` the resulting HTTP request now contains the hostname, instead of the the IP address that the hostname resolved to, as was the previous behavior. This makes it easier for those trying to run Kubo behind a reverse proxy using hostname-based rules.
+
+### 📝 Changelog
+
+Full Changelog
+
+- github.com/ipfs/kubo:
+ - chore: set version to 0.30.0
+ - chore: bump CurrentVersionNumber
+ - chore: boxo v0.23.0 and go-libp2p v0.36.3 (#10507) ([ipfs/kubo#10507](https://github.com/ipfs/kubo/pull/10507))
+ - fix: switch back to go 1.22 (#10502) ([ipfs/kubo#10502](https://github.com/ipfs/kubo/pull/10502))
+ - chore: update go-unixfsnode, cmds, and boxo (#10494) ([ipfs/kubo#10494](https://github.com/ipfs/kubo/pull/10494))
+ - fix(cli): preserve hostname specified with --api in http request headers (#10497) ([ipfs/kubo#10497](https://github.com/ipfs/kubo/pull/10497))
+ - chore: upgrade to go 1.23 (#10486) ([ipfs/kubo#10486](https://github.com/ipfs/kubo/pull/10486))
+ - fix: error during config when running benchmarks (#10495) ([ipfs/kubo#10495](https://github.com/ipfs/kubo/pull/10495))
+ - chore: update version to rc-2
+ - chore: update version
+ - chore: fix function name (#10481) ([ipfs/kubo#10481](https://github.com/ipfs/kubo/pull/10481))
+ - feat: Support storing UnixFS 1.5 Mode and ModTime (#10478) ([ipfs/kubo#10478](https://github.com/ipfs/kubo/pull/10478))
+ - fix(rpc): cross-platform support for /unix/ socket maddrs in Addresses.API ([ipfs/kubo#10019](https://github.com/ipfs/kubo/pull/10019))
+ - chore(daemon): sort listeners (#10480) ([ipfs/kubo#10480](https://github.com/ipfs/kubo/pull/10480))
+ - feat(daemon): improve stdout on startup (#10472) ([ipfs/kubo#10472](https://github.com/ipfs/kubo/pull/10472))
+ - fix(daemon): panic in kubo/daemon.go:595 (#10473) ([ipfs/kubo#10473](https://github.com/ipfs/kubo/pull/10473))
+ - feat: webui v4.3.0 (#10477) ([ipfs/kubo#10477](https://github.com/ipfs/kubo/pull/10477))
+ - docs(readme): add Gentoo Linux (#10474) ([ipfs/kubo#10474](https://github.com/ipfs/kubo/pull/10474))
+ - libp2p: default to preferring TLS ([ipfs/kubo#10227](https://github.com/ipfs/kubo/pull/10227))
+ - docs: document unofficial Ubuntu PPA ([ipfs/kubo#10467](https://github.com/ipfs/kubo/pull/10467))
+ - feat: run AutoNAT V2 service in addition to V1 (#10468) ([ipfs/kubo#10468](https://github.com/ipfs/kubo/pull/10468))
+ - feat: go-libp2p 0.36 and /webrtc-direct listener (#10463) ([ipfs/kubo#10463](https://github.com/ipfs/kubo/pull/10463))
+ - chore: update dependencies (#10462)(#10466) ([ipfs/kubo#10466](https://github.com/ipfs/kubo/pull/10466))
+ - feat: periodic version check and json config (#10438) ([ipfs/kubo#10438](https://github.com/ipfs/kubo/pull/10438))
+ - docs: clarify pnet limitations
+ - docs: "error mounting: could not resolve name" (#10449) ([ipfs/kubo#10449](https://github.com/ipfs/kubo/pull/10449))
+ - docs: update ipfs-swarm-key-gen example (#10453) ([ipfs/kubo#10453](https://github.com/ipfs/kubo/pull/10453))
+ - chore: update deps incl. boxo v0.21.0 (#10444) ([ipfs/kubo#10444](https://github.com/ipfs/kubo/pull/10444))
+ - chore: go-libp2p 0.35.1 (#10430) ([ipfs/kubo#10430](https://github.com/ipfs/kubo/pull/10430))
+ - docsa: update RELEASE_CHECKLIST.md
+ - chore: create next changelog (#10443) ([ipfs/kubo#10443](https://github.com/ipfs/kubo/pull/10443))
+ - Merge Release: v0.29.0 [skip changelog] ([ipfs/kubo#10442](https://github.com/ipfs/kubo/pull/10442))
+ - fix(cli): unify --name param in ls and add (#10439) ([ipfs/kubo#10439](https://github.com/ipfs/kubo/pull/10439))
+ - fix(libp2p): streams config validation in resource manager (#10435) ([ipfs/kubo#10435](https://github.com/ipfs/kubo/pull/10435))
+ - chore: fix some typos (#10396) ([ipfs/kubo#10396](https://github.com/ipfs/kubo/pull/10396))
+ - chore: update version
+- github.com/ipfs/boxo (v0.20.0 -> v0.23.0):
+ - Release v0.23.0 ([ipfs/boxo#669](https://github.com/ipfs/boxo/pull/669))
+ - docs(changelog): move entry to correct release
+ - Release v0.22.0 ([ipfs/boxo#654](https://github.com/ipfs/boxo/pull/654))
+ - Release v0.21.0 ([ipfs/boxo#622](https://github.com/ipfs/boxo/pull/622))
+- github.com/ipfs/go-ipfs-cmds (v0.11.0 -> v0.13.0):
+ - chore: release v0.13.0 (#261) ([ipfs/go-ipfs-cmds#261](https://github.com/ipfs/go-ipfs-cmds/pull/261))
+ - chore: release v0.12.0 (#259) ([ipfs/go-ipfs-cmds#259](https://github.com/ipfs/go-ipfs-cmds/pull/259))
+- github.com/ipfs/go-unixfsnode (v1.9.0 -> v1.9.1):
+ - Update release version ([ipfs/go-unixfsnode#76](https://github.com/ipfs/go-unixfsnode/pull/76))
+ - chore: update dependencies ([ipfs/go-unixfsnode#75](https://github.com/ipfs/go-unixfsnode/pull/75))
+- github.com/libp2p/go-libp2p (v0.34.1 -> v0.36.3):
+ - Release v0.36.3
+ - Fix: WebSocket: Clone TLS config before creating a new listener
+ - fix: enable dctur when interface address is public (#2931) ([libp2p/go-libp2p#2931](https://github.com/libp2p/go-libp2p/pull/2931))
+ - fix: QUIC/Webtransport Transports now will prefer their owned listeners for dialing out (#2936) ([libp2p/go-libp2p#2936](https://github.com/libp2p/go-libp2p/pull/2936))
+ - ci: uci/update-go (#2937) ([libp2p/go-libp2p#2937](https://github.com/libp2p/go-libp2p/pull/2937))
+ - fix: slice append value (#2938) ([libp2p/go-libp2p#2938](https://github.com/libp2p/go-libp2p/pull/2938))
+ - webrtc: wait for listener context before dropping connection (#2932) ([libp2p/go-libp2p#2932](https://github.com/libp2p/go-libp2p/pull/2932))
+ - ci: use go1.23, drop go1.21 (#2933) ([libp2p/go-libp2p#2933](https://github.com/libp2p/go-libp2p/pull/2933))
+ - Fail on any test timeout (#2929) ([libp2p/go-libp2p#2929](https://github.com/libp2p/go-libp2p/pull/2929))
+ - test: Try to fix test timeout (#2930) ([libp2p/go-libp2p#2930](https://github.com/libp2p/go-libp2p/pull/2930))
+ - ci: Out of the tarpit (#2923) ([libp2p/go-libp2p#2923](https://github.com/libp2p/go-libp2p/pull/2923))
+ - Fix proto import paths (#2920) ([libp2p/go-libp2p#2920](https://github.com/libp2p/go-libp2p/pull/2920))
+ - Release v0.36.2
+ - webrtc: reduce loglevel for pion logs (#2915) ([libp2p/go-libp2p#2915](https://github.com/libp2p/go-libp2p/pull/2915))
+ - webrtc: close connection when remote closes (#2914) ([libp2p/go-libp2p#2914](https://github.com/libp2p/go-libp2p/pull/2914))
+ - basic_host: close swarm on Close (#2916) ([libp2p/go-libp2p#2916](https://github.com/libp2p/go-libp2p/pull/2916))
+ - Revert "Create funding.json" (#2919) ([libp2p/go-libp2p#2919](https://github.com/libp2p/go-libp2p/pull/2919))
+ - Create funding.json
+ - Release v0.36.1
+ - Release v0.36.0 (#2905) ([libp2p/go-libp2p#2905](https://github.com/libp2p/go-libp2p/pull/2905))
+ - swarm: add a default timeout to conn.NewStream (#2907) ([libp2p/go-libp2p#2907](https://github.com/libp2p/go-libp2p/pull/2907))
+ - udpmux: Don't log an error if canceled because of shutdown (#2903) ([libp2p/go-libp2p#2903](https://github.com/libp2p/go-libp2p/pull/2903))
+ - ObsAddrManager: Infer external addresses for transports that share the same listening address. (#2892) ([libp2p/go-libp2p#2892](https://github.com/libp2p/go-libp2p/pull/2892))
+ - feat: WebRTC reuse QUIC conn (#2889) ([libp2p/go-libp2p#2889](https://github.com/libp2p/go-libp2p/pull/2889))
+ - examples/chat-with-mdns: default to a random port (#2896) ([libp2p/go-libp2p#2896](https://github.com/libp2p/go-libp2p/pull/2896))
+ - allow findpeers limit to be 0 (#2894) ([libp2p/go-libp2p#2894](https://github.com/libp2p/go-libp2p/pull/2894))
+ - quic: add support for quic-go metrics (#2823) ([libp2p/go-libp2p#2823](https://github.com/libp2p/go-libp2p/pull/2823))
+ - webrtc: remove experimental tag, enable by default (#2887) ([libp2p/go-libp2p#2887](https://github.com/libp2p/go-libp2p/pull/2887))
+ - config: fix AddrFactory for AutoNAT (#2868) ([libp2p/go-libp2p#2868](https://github.com/libp2p/go-libp2p/pull/2868))
+ - chore: /quic → /quic-v1 (#2888) ([libp2p/go-libp2p#2888](https://github.com/libp2p/go-libp2p/pull/2888))
+ - basichost: reset stream if SetProtocol fails (#2875) ([libp2p/go-libp2p#2875](https://github.com/libp2p/go-libp2p/pull/2875))
+ - feat: libp2phttp `/http-path` (#2850) ([libp2p/go-libp2p#2850](https://github.com/libp2p/go-libp2p/pull/2850))
+ - readme: update per latest multiversx rename (#2874) ([libp2p/go-libp2p#2874](https://github.com/libp2p/go-libp2p/pull/2874))
+ - websocket: don't return transport.ErrListenerClosed on closing listener (#2867) ([libp2p/go-libp2p#2867](https://github.com/libp2p/go-libp2p/pull/2867))
+ - Added tau to README.md (#2870) ([libp2p/go-libp2p#2870](https://github.com/libp2p/go-libp2p/pull/2870))
+ - basichost: reset new stream if rcmgr blocks (#2869) ([libp2p/go-libp2p#2869](https://github.com/libp2p/go-libp2p/pull/2869))
+ - transport integration tests: test conn attempt is dropped when the rcmgr blocks for WebRTC (#2856) ([libp2p/go-libp2p#2856](https://github.com/libp2p/go-libp2p/pull/2856))
+ - webtransport: close underlying h3 connection (#2862) ([libp2p/go-libp2p#2862](https://github.com/libp2p/go-libp2p/pull/2862))
+ - peerstore: don't intern protocols (#2860) ([libp2p/go-libp2p#2860](https://github.com/libp2p/go-libp2p/pull/2860))
+ - autonatv2: add server metrics for dial requests (#2848) ([libp2p/go-libp2p#2848](https://github.com/libp2p/go-libp2p/pull/2848))
+ - PR Comments
+ - Add a transport level test to ensure we close conns after rejecting them by the rcmgr
+ - Close quic conns when wrapping conn fails
+ - libp2p: use rcmgr for autonat dials (#2842) ([libp2p/go-libp2p#2842](https://github.com/libp2p/go-libp2p/pull/2842))
+ - metricshelper: improve checks for ip and transport (#2849) ([libp2p/go-libp2p#2849](https://github.com/libp2p/go-libp2p/pull/2849))
+ - Don't reuse the URL, make a new one
+ - Use default transport to make using the Host cheaper
+ - cleanup
+ - Add future test
+ - HTTP Host implements RoundTripper
+ - swarm: improve dial worker performance for common case
+ - pstoremanager: fix connectedness check
+ - autonatv2: implement autonatv2 spec (#2469) ([libp2p/go-libp2p#2469](https://github.com/libp2p/go-libp2p/pull/2469))
+ - webrtc: add a test for establishing many connections (#2801) ([libp2p/go-libp2p#2801](https://github.com/libp2p/go-libp2p/pull/2801))
+ - webrtc: fix ufrag prefix for dialing (#2832) ([libp2p/go-libp2p#2832](https://github.com/libp2p/go-libp2p/pull/2832))
+ - circuitv2: improve voucher validation (#2826) ([libp2p/go-libp2p#2826](https://github.com/libp2p/go-libp2p/pull/2826))
+ - libp2phttp: workaround for ResponseWriter's CloseNotifier (#2821) ([libp2p/go-libp2p#2821](https://github.com/libp2p/go-libp2p/pull/2821))
+ - Update README.md (#2830) ([libp2p/go-libp2p#2830](https://github.com/libp2p/go-libp2p/pull/2830))
+ - identify: add test for observed address handling (#2828) ([libp2p/go-libp2p#2828](https://github.com/libp2p/go-libp2p/pull/2828))
+ - identify: fix bug in observed address handling (#2825) ([libp2p/go-libp2p#2825](https://github.com/libp2p/go-libp2p/pull/2825))
+ - identify: Don't filter addr if remote is neither public nor private (#2820) ([libp2p/go-libp2p#2820](https://github.com/libp2p/go-libp2p/pull/2820))
+ - limit ping duration to 30s (#1358) ([libp2p/go-libp2p#1358](https://github.com/libp2p/go-libp2p/pull/1358))
+ - Remove out-dated code in example readme (#2818) ([libp2p/go-libp2p#2818](https://github.com/libp2p/go-libp2p/pull/2818))
+ - v0.35.0 (#2812) ([libp2p/go-libp2p#2812](https://github.com/libp2p/go-libp2p/pull/2812))
+ - rcmgr: Support specific network prefix in conn limiter (#2807) ([libp2p/go-libp2p#2807](https://github.com/libp2p/go-libp2p/pull/2807))
+- github.com/libp2p/go-libp2p-kad-dht (v0.25.2 -> v0.26.1):
+ - Release v0.26.1 ([libp2p/go-libp2p-kad-dht#983](https://github.com/libp2p/go-libp2p-kad-dht/pull/983))
+ - fix: Unexport hasValidConnectedness to make a patch release ([libp2p/go-libp2p-kad-dht#982](https://github.com/libp2p/go-libp2p-kad-dht/pull/982))
+ - correctly merging fix from https://github.com/libp2p/go-libp2p-kad-dht/pull/976 ([libp2p/go-libp2p-kad-dht#980](https://github.com/libp2p/go-libp2p-kad-dht/pull/980))
+ - Release v0.26.0 ([libp2p/go-libp2p-kad-dht#979](https://github.com/libp2p/go-libp2p-kad-dht/pull/979))
+ - chore: update deps ([libp2p/go-libp2p-kad-dht#974](https://github.com/libp2p/go-libp2p-kad-dht/pull/974))
+ - Upgrade to go-log v2.5.1 ([libp2p/go-libp2p-kad-dht#971](https://github.com/libp2p/go-libp2p-kad-dht/pull/971))
+ - Fix: don't perform lookupCheck if not enough peers in routing table ([libp2p/go-libp2p-kad-dht#970](https://github.com/libp2p/go-libp2p-kad-dht/pull/970))
+ - findnode(self) should return multiple peers ([libp2p/go-libp2p-kad-dht#968](https://github.com/libp2p/go-libp2p-kad-dht/pull/968))
+- github.com/libp2p/go-libp2p-routing-helpers (v0.7.3 -> v0.7.4):
+ - chore: release v0.7.4 (#85) ([libp2p/go-libp2p-routing-helpers#85](https://github.com/libp2p/go-libp2p-routing-helpers/pull/85))
+ - fix: composable parallel router tracing by index (#84) ([libp2p/go-libp2p-routing-helpers#84](https://github.com/libp2p/go-libp2p-routing-helpers/pull/84))
+- github.com/multiformats/go-multiaddr (v0.12.4 -> v0.13.0):
+ - Release v0.13.0 ([multiformats/go-multiaddr#248](https://github.com/multiformats/go-multiaddr/pull/248))
+ - Add support for http-path ([multiformats/go-multiaddr#246](https://github.com/multiformats/go-multiaddr/pull/246))
+- github.com/whyrusleeping/cbor-gen (v0.1.1 -> v0.1.2):
+ - properly extend strings (#95) ([whyrusleeping/cbor-gen#95](https://github.com/whyrusleeping/cbor-gen/pull/95))
+ - ioutil to io (#98) ([whyrusleeping/cbor-gen#98](https://github.com/whyrusleeping/cbor-gen/pull/98))
+
+
+
+### 👨👩👧👦 Contributors
+
+| Contributor | Commits | Lines ± | Files Changed |
+|-------------|---------|---------|---------------|
+| Andrew Gillis | 14 | +4920/-1714 | 145 |
+| sukun | 26 | +4402/-448 | 79 |
+| Marco Munizaga | 32 | +2287/-536 | 73 |
+| Marcin Rataj | 41 | +685/-193 | 86 |
+| Patryk | 1 | +312/-10 | 8 |
+| guillaumemichel | 7 | +134/-105 | 14 |
+| Adin Schmahmann | 5 | +145/-80 | 9 |
+| Henrique Dias | 2 | +190/-1 | 6 |
+| Josh Klopfenstein | 1 | +90/-35 | 27 |
+| gammazero | 5 | +90/-28 | 11 |
+| Jeromy Johnson | 1 | +116/-0 | 5 |
+| Daniel N | 3 | +27/-25 | 9 |
+| Daniel Norman | 2 | +28/-19 | 4 |
+| Ivan Shvedunov | 2 | +25/-10 | 2 |
+| Michael Muré | 2 | +22/-9 | 4 |
+| Dominic Della Valle | 1 | +23/-4 | 1 |
+| Andrei Vukolov | 1 | +27/-0 | 1 |
+| chris erway | 1 | +9/-9 | 9 |
+| Vitaly Zdanevich | 1 | +12/-0 | 1 |
+| Guillaume Michel | 1 | +4/-7 | 1 |
+| swedneck | 1 | +10/-0 | 1 |
+| Jorropo | 2 | +5/-5 | 3 |
+| omahs | 1 | +4/-4 | 4 |
+| THAT ONE GUY | 1 | +3/-5 | 2 |
+| vyzo | 1 | +5/-2 | 1 |
+| looklose | 1 | +3/-3 | 2 |
+| web3-bot | 2 | +2/-3 | 4 |
+| Dave Huseby | 1 | +5/-0 | 1 |
+| shenpengfeng | 1 | +1/-1 | 1 |
+| bytetigers | 1 | +1/-1 | 1 |
+| Sorin Stanculeanu | 1 | +1/-1 | 1 |
+| Lukáš Lukáč | 1 | +1/-1 | 1 |
+| Gabe | 1 | +1/-1 | 1 |
+| Bryan Stenson | 1 | +1/-1 | 1 |
+| Samy Fodil | 1 | +1/-0 | 1 |
+| Lane Rettig | 1 | +1/-0 | 1 |
diff --git a/docs/changelogs/v0.31.md b/docs/changelogs/v0.31.md
new file mode 100644
index 00000000000..b20b1586254
--- /dev/null
+++ b/docs/changelogs/v0.31.md
@@ -0,0 +1,154 @@
+# Kubo changelog v0.31
+
+- [v0.31.0](#v0310)
+
+## v0.31.0
+
+- [Overview](#overview)
+- [🔦 Highlights](#-highlights)
+ - [Experimental Pebble Datastore](#experimental-pebble-datastore)
+ - [New metrics](#new-metrics)
+ - [`lowpower` profile no longer breaks DHT announcements](#lowpower-profile-no-longer-breaks-dht-announcements)
+ - [go 1.23, boxo 0.24 and go-libp2p 0.36.5](#go-123-boxo-024-and-go-libp2p-0365)
+- [📝 Changelog](#-changelog)
+- [👨👩👧👦 Contributors](#-contributors)
+
+### Overview
+
+### 🔦 Highlights
+
+#### Experimental Pebble Datastore
+
+[Pebble](https://github.com/ipfs/kubo/blob/master/docs/config.md#pebbleds-profile) provides a high-performance alternative to leveldb as the datastore, and provides a modern replacement for [legacy badgerv1](https://github.com/ipfs/kubo/blob/master/docs/config.md#badgerds-profile).
+
+A fresh Kubo node can be initialized with [`pebbleds` profile](https://github.com/ipfs/kubo/blob/master/docs/config.md#pebbleds-profile) via `ipfs init --profile pebbleds`.
+
+There are a number of parameters available for tuning pebble's performance to your specific needs. Default values are used for any parameters that are not configured or are set to their zero-value.
+For a description of the available tuning parameters, see [kubo/docs/datastores.md#pebbleds](https://github.com/ipfs/kubo/blob/master/docs/datastores.md#pebbleds).
+
+#### New metrics
+
+- Added 3 new go metrics: `go_gc_gogc_percent`, `go_gc_gomemlimit_bytes` and `go_sched_gomaxprocs_threads` as those are [recommended by the Go team](https://github.com/prometheus/client_golang/pull/1559)
+- Added [network usage metrics](https://github.com/prometheus/client_golang/pull/1555): `process_network_receive_bytes_total` and `process_network_transmit_bytes_total`
+- Removed `go_memstat_lookups_total` metric [which was always 0](https://github.com/prometheus/client_golang/pull/1577)
+
+#### `lowpower` profile no longer breaks DHT announcements
+
+We've notices users were applying `lowpower` profile, and then reporting content routing issues. This was because `lowpower` disabled reprovider system and locally hosted data was no longer announced on Amino DHT.
+
+This release changes [`lowpower` profile](https://github.com/ipfs/kubo/blob/master/docs/config.md#lowpower-profile) to not change reprovider settings, ensuring the new users are not sabotaging themselves. It also adds [`annouce-on`](https://github.com/ipfs/kubo/blob/master/docs/config.md#announce-on-profile) and [`announce-off`](https://github.com/ipfs/kubo/blob/master/docs/config.md#announce-off-profile) profiles for controlling announcement settings separately.
+
+> [!IMPORTANT]
+> If you've ever applied the `lowpower` profile before, there is a high chance your node is not announcing to DHT anymore.
+> If you have `Reprovider.Interval` set to `0` you may want to set it to `22h` (or run `ipfs config profile apply announce-on`) to fix your system.
+>
+> As a convenience, `ipfs daemon` will warn if reprovide system is disabled, creating oportinity to fix configuration if it was not intentional.
+
+#### go 1.23, boxo 0.24 and go-libp2p 0.36.5
+
+Various bugfixes. Please update.
+
+### 📝 Changelog
+
+Full Changelog
+
+- github.com/ipfs/kubo:
+ - fix: go 1.23(.2) (#10540) ([ipfs/kubo#10540](https://github.com/ipfs/kubo/pull/10540))
+ - chore: bump version to 0.32.0-dev
+ - feat(routing/http): support IPIP-484 and streaming (#10534) ([ipfs/kubo#10534](https://github.com/ipfs/kubo/pull/10534))
+ - fix(daemon): webui URL when rpc is catch-all (#10520) ([ipfs/kubo#10520](https://github.com/ipfs/kubo/pull/10520))
+ - chore: update changelog and config doc with more info about pebble (#10533) ([ipfs/kubo#10533](https://github.com/ipfs/kubo/pull/10533))
+ - feat: pebbleds profile and plugin (#10530) ([ipfs/kubo#10530](https://github.com/ipfs/kubo/pull/10530))
+ - chore: dependency updates for 0.31 (#10511) ([ipfs/kubo#10511](https://github.com/ipfs/kubo/pull/10511))
+ - feat: explicit announce-on/off profiles (#10524) ([ipfs/kubo#10524](https://github.com/ipfs/kubo/pull/10524))
+ - fix(core): look for MFS root in local repo only (#8661) ([ipfs/kubo#8661](https://github.com/ipfs/kubo/pull/8661))
+ - Fix issue in ResourceManager and nopfsPlugin about repo path (#10492) ([ipfs/kubo#10492](https://github.com/ipfs/kubo/pull/10492))
+ - feat(bitswap): allow configuring WithWantHaveReplaceSize (#10512) ([ipfs/kubo#10512](https://github.com/ipfs/kubo/pull/10512))
+ - refactor: simplify logic for MFS pinning (#10506) ([ipfs/kubo#10506](https://github.com/ipfs/kubo/pull/10506))
+ - docs: clarify Gateway.PublicGateways (#10525) ([ipfs/kubo#10525](https://github.com/ipfs/kubo/pull/10525))
+ - chore: clarify dep update in RELEASE_CHECKLIST.md (#10518) ([ipfs/kubo#10518](https://github.com/ipfs/kubo/pull/10518))
+ - feat: ipfs-webui v4.3.2 (#10523) ([ipfs/kubo#10523](https://github.com/ipfs/kubo/pull/10523))
+ - docs(config): add useful references
+ - docs(config): improve profile descriptions (#10517) ([ipfs/kubo#10517](https://github.com/ipfs/kubo/pull/10517))
+ - docs: update RELEASE_CHECKLIST.md (#10496) ([ipfs/kubo#10496](https://github.com/ipfs/kubo/pull/10496))
+ - chore: create next changelog (#10510) ([ipfs/kubo#10510](https://github.com/ipfs/kubo/pull/10510))
+ - Merge Release: v0.30.0 [skip changelog] ([ipfs/kubo#10508](https://github.com/ipfs/kubo/pull/10508))
+ - chore: boxo v0.23.0 and go-libp2p v0.36.3 (#10507) ([ipfs/kubo#10507](https://github.com/ipfs/kubo/pull/10507))
+ - docs: replace outdated package paths described in rpc README (#10505) ([ipfs/kubo#10505](https://github.com/ipfs/kubo/pull/10505))
+ - fix: switch back to go 1.22 (#10502) ([ipfs/kubo#10502](https://github.com/ipfs/kubo/pull/10502))
+ - fix(cli): preserve hostname specified with --api in http request headers (#10497) ([ipfs/kubo#10497](https://github.com/ipfs/kubo/pull/10497))
+ - chore: upgrade to go 1.23 (#10486) ([ipfs/kubo#10486](https://github.com/ipfs/kubo/pull/10486))
+ - fix: error during config when running benchmarks (#10495) ([ipfs/kubo#10495](https://github.com/ipfs/kubo/pull/10495))
+ - chore: update go-unixfsnode, cmds, and boxo (#10494) ([ipfs/kubo#10494](https://github.com/ipfs/kubo/pull/10494))
+ - Docs fix spelling issues (#10493) ([ipfs/kubo#10493](https://github.com/ipfs/kubo/pull/10493))
+ - chore: update version (#10491) ([ipfs/kubo#10491](https://github.com/ipfs/kubo/pull/10491))
+- github.com/ipfs/boxo (v0.23.0 -> v0.24.0):
+ - Release v0.24.0 ([ipfs/boxo#683](https://github.com/ipfs/boxo/pull/683))
+- github.com/ipfs/go-ipld-cbor (v0.1.0 -> v0.2.0):
+ - v0.2.0
+ - deprecate DumpObject() in favor of better named Encode()
+ - add an EncodeWriter method, using the pooled marshallers
+ - fix expCid vs actualCid guard
+- github.com/ipld/go-car/v2 (v2.13.1 -> v2.14.2):
+ - v2.14.2 bump
+ - fix: goreleaser v2 compat, trigger release-binaries with workflow_run
+ - v2.14.1 bump
+ - chore: update fuzz to Go 1.22
+ - v2.14.0 bump
+ - fix(cmd): properly pick up --inverse and --cid-file args ([ipld/go-car#531](https://github.com/ipld/go-car/pull/531))
+ - Re-factor cmd functions to library ([ipld/go-car#524](https://github.com/ipld/go-car/pull/524))
+ - ci: uci/copy-templates ([ipld/go-car#521](https://github.com/ipld/go-car/pull/521))
+ - Add a `car ls --unixfs-blocks` to render two-column output ([ipld/go-car#514](https://github.com/ipld/go-car/pull/514))
+- github.com/libp2p/go-libp2p (v0.36.3 -> v0.36.5):
+ - chore: remove Roadmap file (#2954) ([libp2p/go-libp2p#2954](https://github.com/libp2p/go-libp2p/pull/2954))
+ - fix: Release v0.36.5
+ - autonatv2: recover from panics (#2992) ([libp2p/go-libp2p#2992](https://github.com/libp2p/go-libp2p/pull/2992))
+ - basichost: ensure no duplicates in Addrs output (#2980) ([libp2p/go-libp2p#2980](https://github.com/libp2p/go-libp2p/pull/2980))
+ - Release v0.36.4
+ - peerstore: better GC in membacked peerstore (#2960) ([libp2p/go-libp2p#2960](https://github.com/libp2p/go-libp2p/pull/2960))
+ - fix: use quic.Version instead of the deprecated quic.VersionNumber (#2955) ([libp2p/go-libp2p#2955](https://github.com/libp2p/go-libp2p/pull/2955))
+ - tcp: fix metrics for multiple calls to Close (#2953) ([libp2p/go-libp2p#2953](https://github.com/libp2p/go-libp2p/pull/2953))
+- github.com/libp2p/go-libp2p-kbucket (v0.6.3 -> v0.6.4):
+ - release v0.6.4 ([libp2p/go-libp2p-kbucket#135](https://github.com/libp2p/go-libp2p-kbucket/pull/135))
+ - feat: add log printing when peer added and removed table ([libp2p/go-libp2p-kbucket#134](https://github.com/libp2p/go-libp2p-kbucket/pull/134))
+ - Upgrade to go-log v2.5.1 ([libp2p/go-libp2p-kbucket#132](https://github.com/libp2p/go-libp2p-kbucket/pull/132))
+ - chore: update go-libp2p-asn-util
+- github.com/multiformats/go-multiaddr-dns (v0.3.1 -> v0.4.0):
+ - Release v0.4.0 (#64) ([multiformats/go-multiaddr-dns#64](https://github.com/multiformats/go-multiaddr-dns/pull/64))
+ - Limit total number of resolved addresses from DNS response (#63) ([multiformats/go-multiaddr-dns#63](https://github.com/multiformats/go-multiaddr-dns/pull/63))
+ - fix!: Only resolve the first DNS-like component (#61) ([multiformats/go-multiaddr-dns#61](https://github.com/multiformats/go-multiaddr-dns/pull/61))
+ - sync: update CI config files (#43) ([multiformats/go-multiaddr-dns#43](https://github.com/multiformats/go-multiaddr-dns/pull/43))
+ - remove deprecated types ([multiformats/go-multiaddr-dns#37](https://github.com/multiformats/go-multiaddr-dns/pull/37))
+ - remove Jenkinsfile ([multiformats/go-multiaddr-dns#40](https://github.com/multiformats/go-multiaddr-dns/pull/40))
+ - sync: update CI config files (#29) ([multiformats/go-multiaddr-dns#29](https://github.com/multiformats/go-multiaddr-dns/pull/29))
+ - use net.IP.Equal to compare IP addresses ([multiformats/go-multiaddr-dns#30](https://github.com/multiformats/go-multiaddr-dns/pull/30))
+
+
+
+### 👨👩👧👦 Contributors
+
+| Contributor | Commits | Lines ± | Files Changed |
+|-------------|---------|---------|---------------|
+| Will Scott | 3 | +731/-581 | 14 |
+| Daniel N | 17 | +1034/-191 | 33 |
+| Marco Munizaga | 5 | +721/-404 | 12 |
+| Andrew Gillis | 9 | +765/-266 | 35 |
+| Marcin Rataj | 17 | +568/-323 | 41 |
+| Daniel Norman | 3 | +232/-111 | 10 |
+| sukun | 4 | +93/-8 | 8 |
+| Jorropo | 2 | +48/-45 | 5 |
+| Marten Seemann | 3 | +19/-47 | 5 |
+| fengzie | 1 | +29/-26 | 5 |
+| Rod Vagg | 7 | +27/-11 | 9 |
+| gopherfarm | 1 | +14/-14 | 6 |
+| web3-bot | 3 | +13/-10 | 3 |
+| Michael Muré | 2 | +16/-5 | 4 |
+| i-norden | 1 | +9/-9 | 1 |
+| Elias Rad | 1 | +7/-7 | 4 |
+| Prithvi Shahi | 1 | +0/-11 | 2 |
+| Lucas Molas | 1 | +5/-4 | 1 |
+| elecbug | 1 | +6/-2 | 1 |
+| gammazero | 2 | +2/-2 | 2 |
+| chris erway | 1 | +2/-2 | 2 |
+| Russell Dempsey | 1 | +2/-1 | 1 |
+| guillaumemichel | 1 | +1/-1 | 1 |
diff --git a/docs/changelogs/v0.32.md b/docs/changelogs/v0.32.md
new file mode 100644
index 00000000000..f00cca611a7
--- /dev/null
+++ b/docs/changelogs/v0.32.md
@@ -0,0 +1,207 @@
+# Kubo changelog v0.32
+
+- [v0.32.0](#v0320)
+
+## v0.32.0
+
+- [Overview](#overview)
+- [🔦 Highlights](#-highlights)
+ - [🎯 AutoTLS: Automatic Certificates for libp2p WebSockets via `libp2p.direct`](#-autotls-automatic-certificates-for-libp2p-websockets-via-libp2pdirect)
+ - [📦️ Dependency updates](#-dependency-updates)
+- [📝 Changelog](#-changelog)
+- [👨👩👧👦 Contributors](#-contributors)
+
+### Overview
+
+### 🔦 Highlights
+
+#### 🎯 AutoTLS: Automatic Certificates for libp2p WebSockets via `libp2p.direct`
+
+
+
+This release introduces an experimental feature that significantly improves how browsers ([Helia](https://helia.io/), [Service Worker](https://inbrowser.link)) can connect to Kubo node.
+
+Opt-in configuration allows a publicly dialable Kubo nodes (public IP, port forwarding, or NAT with uPnP) to obtain CA-signed TLS certificates for [libp2p Secure WebSocket (WSS)](https://github.com/libp2p/specs/blob/master/websockets/README.md) connections automatically.
+
+> [!TIP]
+> To enable this feature, set `AutoTLS.Enabled` to `true` and add a listener for `/tls/sni/*.libp2p.direct/ws` on a separate TCP port:
+> ```diff
+> {
+> + "AutoTLS": { "Enabled": true },
+> "Addresses": {
+> "Swarm": {
+> "/ip4/0.0.0.0/tcp/4001",
+> + "/ip4/0.0.0.0/tcp/4002/tls/sni/*.libp2p.direct/ws",
+> "/ip6/::/tcp/4001",
+> + "/ip6/::/tcp/4002/tls/sni/*.libp2p.direct/ws",
+> ```
+> After restarting your node for the first time you may need to wait 5-15 minutes to pass all checks and for the changes to take effect.
+> We are working on sharing the same TCP port with other transports ([go-libp2p#2984](https://github.com/libp2p/go-libp2p/pull/2984)).
+
+See [`AutoTLS` configuration](https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls) for more details how to enable it and what to expect.
+
+This is an early preview, we appreciate you testing and filling bug reports or feedback in the tracking issue at [kubo#10560](https://github.com/ipfs/kubo/issues/10560).
+
+#### 📦️ Dependency updates
+
+- update `ipfs-webui` to [v4.4.0](https://github.com/ipfs/ipfs-webui/releases/tag/v4.4.0)
+- update `boxo` to [v0.24.1](https://github.com/ipfs/boxo/releases/tag/v0.24.1) + [v0.24.2](https://github.com/ipfs/boxo/releases/tag/v0.24.2) + [v0.24.3](https://github.com/ipfs/boxo/releases/tag/v0.24.3)
+ - This includes a number of fixes and bitswap improvements, and support for filtering from [IPIP-484](https://specs.ipfs.tech/ipips/ipip-0484/) in delegated HTTP routing and IPNI queries.
+- update `go-libp2p` to [v0.37.0](https://github.com/libp2p/go-libp2p/releases/tag/v0.37.0)
+ - This update required removal of `Swarm.RelayService.MaxReservationsPerPeer` configuration option from Kubo. If you had it set, remove it from your configuration file.
+- update `go-libp2p-kad-dht` to [v0.27.0](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.27.0) + [v0.28.0](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.28.0) + [v0.28.1](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.28.1)
+- update `go-libp2p-pubsub` to [v0.12.0](https://github.com/libp2p/go-libp2p-pubsub/releases/tag/v0.12.0)
+- update `p2p-forge/client` to [v0.0.2](https://github.com/ipshipyard/p2p-forge/releases/tag/v0.0.2)
+- removed `go-homedir`
+ - The `github.com/mitchellh/go-homedir` repo is archived, no longer needed, and no longer maintained.
+ - `homedir.Dir` is replaced by the stdlib `os.UserHomeDir`
+ - `homedir.Expand` is replaced by `fsutil.ExpandHome` in the `github.com/ipfs/kubo/misc/fsutil` package.
+ - The new `github.com/ipfs/kubo/misc/fsutil` package contains file utility code previously located elsewhere in kubo.
+
+### 📝 Changelog
+
+Full Changelog
+
+- github.com/ipfs/kubo:
+ - chore: 0.32.0
+ - fix: go-libp2p-kad-dht v0.28.0 (#10578) ([ipfs/kubo#10578](https://github.com/ipfs/kubo/pull/10578))
+ - chore: 0.32.0-rc2
+ - feat: ipfs-webui v4.4.0 (#10574) ([ipfs/kubo#10574](https://github.com/ipfs/kubo/pull/10574))
+ - chore: label implicit loggers
+ - chore: boxo v0.24.3 and p2p-forge v0.0.2 (#10572) ([ipfs/kubo#10572](https://github.com/ipfs/kubo/pull/10572))
+ - chore: stop using go-homedir (#10568) ([ipfs/kubo#10568](https://github.com/ipfs/kubo/pull/10568))
+ - fix(autotls): store certificates at the location from the repo path (#10566) ([ipfs/kubo#10566](https://github.com/ipfs/kubo/pull/10566))
+ - chore: 0.32.0-rc1
+ - docs(autotls): add note about separate port use (#10562) ([ipfs/kubo#10562](https://github.com/ipfs/kubo/pull/10562))
+ - feat(AutoTLS): opt-in WSS certs from p2p-forge at libp2p.direct (#10521) ([ipfs/kubo#10521](https://github.com/ipfs/kubo/pull/10521))
+ - chore: upgrade to boxo v0.24.2 (#10559) ([ipfs/kubo#10559](https://github.com/ipfs/kubo/pull/10559))
+ - refactor: update to go-libp2p v0.37.0 (#10554) ([ipfs/kubo#10554](https://github.com/ipfs/kubo/pull/10554))
+ - docs(config): explain what multiaddr is
+ - chore: update dependencies (#10548) ([ipfs/kubo#10548](https://github.com/ipfs/kubo/pull/10548))
+ - chore: update test dependencies (#10555) ([ipfs/kubo#10555](https://github.com/ipfs/kubo/pull/10555))
+ - chore(ci): adjust verbosity
+ - chore(ci): verbose build of test/bin deps
+ - chore(ci): build docker images for staging branch
+ - Create Changelog: v0.32 ([ipfs/kubo#10546](https://github.com/ipfs/kubo/pull/10546))
+ - Merge release v0.31.0 ([ipfs/kubo#10545](https://github.com/ipfs/kubo/pull/10545))
+ - chore: update RELEASE_CHECKLIST.md (#10544) ([ipfs/kubo#10544](https://github.com/ipfs/kubo/pull/10544))
+ - feat: ipfs-webui v4.3.3 (#10543) ([ipfs/kubo#10543](https://github.com/ipfs/kubo/pull/10543))
+ - chore: update RELEASE_CHECKLIST.md (#10542) ([ipfs/kubo#10542](https://github.com/ipfs/kubo/pull/10542))
+ - Add full changelog to release changelog
+ - fix: go 1.23(.2) (#10540) ([ipfs/kubo#10540](https://github.com/ipfs/kubo/pull/10540))
+ - chore: bump version to 0.32.0-dev
+- github.com/ipfs/boxo (v0.24.0 -> v0.24.3):
+ - Release v0.24.3 ([ipfs/boxo#713](https://github.com/ipfs/boxo/pull/713))
+ - Merge branch 'main' into release
+ - Release v0.24.2 ([ipfs/boxo#707](https://github.com/ipfs/boxo/pull/707))
+ - Release v0.24.1 ([ipfs/boxo#706](https://github.com/ipfs/boxo/pull/706))
+- github.com/ipfs/go-ipfs-cmds (v0.13.0 -> v0.14.0):
+ - chore: release v0.14.0 (#269) ([ipfs/go-ipfs-cmds#269](https://github.com/ipfs/go-ipfs-cmds/pull/269))
+- github.com/ipfs/go-ipfs-redirects-file (v0.1.1 -> v0.1.2):
+ - chore: v0.1.2 (#29) ([ipfs/go-ipfs-redirects-file#29](https://github.com/ipfs/go-ipfs-redirects-file/pull/29))
+ - docs(readme): refer specs and ipip
+ - chore: update dependencies (#28) ([ipfs/go-ipfs-redirects-file#28](https://github.com/ipfs/go-ipfs-redirects-file/pull/28))
+- github.com/ipfs/go-metrics-prometheus (v0.0.2 -> v0.0.3):
+ - chore: release v0.0.3 (#24) ([ipfs/go-metrics-prometheus#24](https://github.com/ipfs/go-metrics-prometheus/pull/24))
+ - chore: update deps and update go-log to v2 (#23) ([ipfs/go-metrics-prometheus#23](https://github.com/ipfs/go-metrics-prometheus/pull/23))
+ - sync: update CI config files (#9) ([ipfs/go-metrics-prometheus#9](https://github.com/ipfs/go-metrics-prometheus/pull/9))
+- github.com/ipfs/go-unixfsnode (v1.9.1 -> v1.9.2):
+ - New release version ([ipfs/go-unixfsnode#78](https://github.com/ipfs/go-unixfsnode/pull/78))
+ - chore: update dependencies
+- github.com/libp2p/go-flow-metrics (v0.1.0 -> v0.2.0):
+ - chore: release v0.2.0 (#33) ([libp2p/go-flow-metrics#33](https://github.com/libp2p/go-flow-metrics/pull/33))
+ - chore: cleanup readme (#31) ([libp2p/go-flow-metrics#31](https://github.com/libp2p/go-flow-metrics/pull/31))
+ - ci: uci/update-go ([libp2p/go-flow-metrics#27](https://github.com/libp2p/go-flow-metrics/pull/27))
+ - fix(ewma): reduce the chances of fake bandwidth spikes (#8) ([libp2p/go-flow-metrics#8](https://github.com/libp2p/go-flow-metrics/pull/8))
+ - chore: switch to typed atomics (#24) ([libp2p/go-flow-metrics#24](https://github.com/libp2p/go-flow-metrics/pull/24))
+ - test: use mock clocks for all tests (#25) ([libp2p/go-flow-metrics#25](https://github.com/libp2p/go-flow-metrics/pull/25))
+ - ci: uci/copy-templates ([libp2p/go-flow-metrics#21](https://github.com/libp2p/go-flow-metrics/pull/21))
+- github.com/libp2p/go-libp2p (v0.36.5 -> v0.37.0):
+ - Release v0.37.0 (#3013) ([libp2p/go-libp2p#3013](https://github.com/libp2p/go-libp2p/pull/3013))
+ - feat: Add WithFxOption (#2956) ([libp2p/go-libp2p#2956](https://github.com/libp2p/go-libp2p/pull/2956))
+ - chore: update imports to use slices package (#3007) ([libp2p/go-libp2p#3007](https://github.com/libp2p/go-libp2p/pull/3007))
+ - Change latency metrics buckets (#3012) ([libp2p/go-libp2p#3012](https://github.com/libp2p/go-libp2p/pull/3012))
+ - chore: bump deps in preparation for v0.37.0 (#3011) ([libp2p/go-libp2p#3011](https://github.com/libp2p/go-libp2p/pull/3011))
+ - autonat: fix interaction with autorelay (#2967) ([libp2p/go-libp2p#2967](https://github.com/libp2p/go-libp2p/pull/2967))
+ - swarm: add a peer dial latency metric (#2959) ([libp2p/go-libp2p#2959](https://github.com/libp2p/go-libp2p/pull/2959))
+ - peerstore: limit number of non connected peers in addrbook (#2971) ([libp2p/go-libp2p#2971](https://github.com/libp2p/go-libp2p/pull/2971))
+ - fix: swarm: refactor address resolution (#2990) ([libp2p/go-libp2p#2990](https://github.com/libp2p/go-libp2p/pull/2990))
+ - Add backoff for updating local IP addresses on error (#2999) ([libp2p/go-libp2p#2999](https://github.com/libp2p/go-libp2p/pull/2999))
+ - libp2phttp: HTTP Peer ID Authentication (#2854) ([libp2p/go-libp2p#2854](https://github.com/libp2p/go-libp2p/pull/2854))
+ - relay: make only 1 reservation per peer (#2974) ([libp2p/go-libp2p#2974](https://github.com/libp2p/go-libp2p/pull/2974))
+ - autonatv2: recover from panics (#2992) ([libp2p/go-libp2p#2992](https://github.com/libp2p/go-libp2p/pull/2992))
+ - basichost: ensure no duplicates in Addrs output (#2980) ([libp2p/go-libp2p#2980](https://github.com/libp2p/go-libp2p/pull/2980))
+ - fix(websocket): re-enable websocket transport test (#2987) ([libp2p/go-libp2p#2987](https://github.com/libp2p/go-libp2p/pull/2987))
+ - feat(websocket): switch the underlying http server logger to use ipfs/go-log (#2985) ([libp2p/go-libp2p#2985](https://github.com/libp2p/go-libp2p/pull/2985))
+ - peerstore: better GC in membacked peerstore (#2960) ([libp2p/go-libp2p#2960](https://github.com/libp2p/go-libp2p/pull/2960))
+ - connmgr: reduce log level for untagging untracked peers ([libp2p/go-libp2p#2961](https://github.com/libp2p/go-libp2p/pull/2961))
+ - fix: use quic.Version instead of the deprecated quic.VersionNumber (#2955) ([libp2p/go-libp2p#2955](https://github.com/libp2p/go-libp2p/pull/2955))
+ - tcp: fix metrics for multiple calls to Close (#2953) ([libp2p/go-libp2p#2953](https://github.com/libp2p/go-libp2p/pull/2953))
+ - chore: remove Roadmap file (#2954) ([libp2p/go-libp2p#2954](https://github.com/libp2p/go-libp2p/pull/2954))
+ - chore: add a funding JSON file to apply for Optimism rPGF round 5 (#2940) ([libp2p/go-libp2p#2940](https://github.com/libp2p/go-libp2p/pull/2940))
+ - Fix: WebSocket: Clone TLS config before creating a new listener
+ - fix: enable dctur when interface address is public (#2931) ([libp2p/go-libp2p#2931](https://github.com/libp2p/go-libp2p/pull/2931))
+ - fix: QUIC/Webtransport Transports now will prefer their owned listeners for dialing out (#2936) ([libp2p/go-libp2p#2936](https://github.com/libp2p/go-libp2p/pull/2936))
+ - ci: uci/update-go (#2937) ([libp2p/go-libp2p#2937](https://github.com/libp2p/go-libp2p/pull/2937))
+ - fix: slice append value (#2938) ([libp2p/go-libp2p#2938](https://github.com/libp2p/go-libp2p/pull/2938))
+ - webrtc: wait for listener context before dropping connection (#2932) ([libp2p/go-libp2p#2932](https://github.com/libp2p/go-libp2p/pull/2932))
+ - ci: use go1.23, drop go1.21 (#2933) ([libp2p/go-libp2p#2933](https://github.com/libp2p/go-libp2p/pull/2933))
+ - Fail on any test timeout (#2929) ([libp2p/go-libp2p#2929](https://github.com/libp2p/go-libp2p/pull/2929))
+ - test: Try to fix test timeout (#2930) ([libp2p/go-libp2p#2930](https://github.com/libp2p/go-libp2p/pull/2930))
+ - ci: Out of the tarpit (#2923) ([libp2p/go-libp2p#2923](https://github.com/libp2p/go-libp2p/pull/2923))
+ - Make BlackHoleState type public (#2917) ([libp2p/go-libp2p#2917](https://github.com/libp2p/go-libp2p/pull/2917))
+ - Fix proto import paths (#2920) ([libp2p/go-libp2p#2920](https://github.com/libp2p/go-libp2p/pull/2920))
+- github.com/libp2p/go-libp2p-kad-dht (v0.26.1 -> v0.28.0):
+ - chore: release v0.28.0 (#998) ([libp2p/go-libp2p-kad-dht#998](https://github.com/libp2p/go-libp2p-kad-dht/pull/998))
+ - fix: set context timeout for `queryPeer` (#996) ([libp2p/go-libp2p-kad-dht#996](https://github.com/libp2p/go-libp2p-kad-dht/pull/996))
+ - refactor: document and expose Amino DHT defaults (#990) ([libp2p/go-libp2p-kad-dht#990](https://github.com/libp2p/go-libp2p-kad-dht/pull/990))
+ - Use timeout context for NewStream call ([libp2p/go-libp2p-kad-dht#994](https://github.com/libp2p/go-libp2p-kad-dht/pull/994))
+ - release v0.27.0 ([libp2p/go-libp2p-kad-dht#992](https://github.com/libp2p/go-libp2p-kad-dht/pull/992))
+ - Add new DHT option to provide custom pb.MessageSender ([libp2p/go-libp2p-kad-dht#991](https://github.com/libp2p/go-libp2p-kad-dht/pull/991))
+ - fix: replace deprecated Boxo function ([libp2p/go-libp2p-kad-dht#987](https://github.com/libp2p/go-libp2p-kad-dht/pull/987))
+ - fix(query): reverting changes on TestRTEvictionOnFailedQuery ([libp2p/go-libp2p-kad-dht#984](https://github.com/libp2p/go-libp2p-kad-dht/pull/984))
+- github.com/libp2p/go-libp2p-pubsub (v0.11.0 -> v0.12.0):
+ - chore: upgrade go-libp2p (#575) ([libp2p/go-libp2p-pubsub#575](https://github.com/libp2p/go-libp2p-pubsub/pull/575))
+ - GossipSub v1.2: IDONTWANT control message and priority queue. (#553) ([libp2p/go-libp2p-pubsub#553](https://github.com/libp2p/go-libp2p-pubsub/pull/553))
+ - Re-enable disabled gossipsub test (#566) ([libp2p/go-libp2p-pubsub#566](https://github.com/libp2p/go-libp2p-pubsub/pull/566))
+ - chore: staticcheck
+ - chore: update rand usage
+ - chore: go fmt
+ - chore: add or force update version.json
+ - added missing Close call on the AddrBook member of GossipSubRouter (#568) ([libp2p/go-libp2p-pubsub#568](https://github.com/libp2p/go-libp2p-pubsub/pull/568))
+ - test: test notify protocols updated (#567) ([libp2p/go-libp2p-pubsub#567](https://github.com/libp2p/go-libp2p-pubsub/pull/567))
+ - Switch to the new peer notify mechanism (#564) ([libp2p/go-libp2p-pubsub#564](https://github.com/libp2p/go-libp2p-pubsub/pull/564))
+ - test: use the regular libp2p host (#565) ([libp2p/go-libp2p-pubsub#565](https://github.com/libp2p/go-libp2p-pubsub/pull/565))
+ - Missing flood protection check for number of message IDs when handling `Ihave` messages (#560) ([libp2p/go-libp2p-pubsub#560](https://github.com/libp2p/go-libp2p-pubsub/pull/560))
+
+
+
+### 👨👩👧👦 Contributors
+
+| Contributor | Commits | Lines ± | Files Changed |
+|-------------|---------|---------|---------------|
+| Marco Munizaga | 16 | +4253/-545 | 81 |
+| Pop Chunhapanya | 1 | +1423/-137 | 15 |
+| sukun | 10 | +752/-425 | 35 |
+| Steven Allen | 11 | +518/-541 | 35 |
+| Andrew Gillis | 19 | +348/-194 | 50 |
+| Marcin Rataj | 26 | +343/-132 | 47 |
+| Adin Schmahmann | 4 | +269/-29 | 12 |
+| gammazero | 12 | +154/-18 | 13 |
+| Josh Klopfenstein | 1 | +90/-35 | 27 |
+| galargh | 3 | +42/-44 | 13 |
+| Daniel Norman | 2 | +30/-16 | 4 |
+| Mikel Cortes | 3 | +25/-4 | 4 |
+| gopherfarm | 1 | +14/-14 | 6 |
+| Carlos Peliciari | 1 | +12/-12 | 4 |
+| Prithvi Shahi | 2 | +5/-11 | 3 |
+| web3-bot | 6 | +12/-3 | 6 |
+| guillaumemichel | 3 | +7/-6 | 3 |
+| Jorropo | 1 | +11/-0 | 1 |
+| Sorin Stanculeanu | 1 | +8/-0 | 1 |
+| Hlib Kanunnikov | 2 | +6/-2 | 4 |
+| André Bierlein | 1 | +4/-3 | 1 |
+| bytetigers | 1 | +1/-1 | 1 |
+| Wondertan | 2 | +2/-0 | 2 |
+| Alexandr Burdiyan | 1 | +1/-1 | 1 |
+| Guillaume Michel | 1 | +0/-1 | 1 |
diff --git a/docs/changelogs/v0.33.md b/docs/changelogs/v0.33.md
new file mode 100644
index 00000000000..4715aa7caa6
--- /dev/null
+++ b/docs/changelogs/v0.33.md
@@ -0,0 +1,484 @@
+# Kubo changelog v0.33
+
+- [v0.33.0](#v0330)
+- [v0.33.1](#v0331)
+- [v0.33.2](#v0332)
+
+## v0.33.0
+
+- [Overview](#overview)
+- [🔦 Highlights](#-highlights)
+ - [Shared TCP listeners](#shared-tcp-listeners)
+ - [AutoTLS takes care of Secure WebSockets setup](#autotls-takes-care-of-secure-websockets-setup)
+ - [Bitswap improvements from Boxo](#bitswap-improvements-from-boxo)
+ - [Using default `libp2p_rcmgr` metrics](#using-default-libp2p_rcmgr--metrics)
+ - [Flatfs does not `sync` on each write](#flatfs-does-not-sync-on-each-write)
+ - [`ipfs add --to-files` no longer works with `--wrap`](#ipfs-add---to-files-no-longer-works-with---wrap)
+ - [`ipfs --api` supports HTTPS RPC endpoints](#ipfs---api-supports-https-rpc-endpoints)
+ - [New options for faster writes: `WriteThrough`, `BlockKeyCacheSize`, `BatchMaxNodes`, `BatchMaxSize`](#new-options-for-faster-writes-writethrough-blockkeycachesize-batchmaxnodes-batchmaxsize)
+ - [MFS stability with large number of writes](#mfs-stability-with-large-number-of-writes)
+ - [New DoH resolvers for non-ICANN DNSLinks](#new-doh-resolvers-for-non-icann-dnslinks)
+ - [Reliability improvements to the WebRTC Direct listener](#reliability-improvements-to-the-webrtc-direct-listener)
+ - [Bitswap improvements from Boxo](#bitswap-improvements-from-boxo-1)
+ - [📦️ Important dependency updates](#-important-dependency-updates)
+ - [Escape Redirect URL for Directory](#escape-redirect-url-for-directory)
+- [📝 Changelog](#-changelog)
+- [👨👩👧👦 Contributors](#-contributors)
+
+### Overview
+
+### 🔦 Highlights
+
+#### Shared TCP listeners
+
+Kubo now supports sharing the same TCP port (`4001` by default) by both [raw TCP](https://github.com/ipfs/kubo/blob/master/docs/config.md#swarmtransportsnetworktcp) and [WebSockets](https://github.com/ipfs/kubo/blob/master/docs/config.md#swarmtransportsnetworkwebsocket) libp2p transports.
+
+This feature is not yet compatible with Private Networks and can be disabled by setting `LIBP2P_TCP_MUX=false` if causes any issues.
+
+#### AutoTLS takes care of Secure WebSockets setup
+
+It is no longer necessary to manually add `/tcp/../ws` listeners to `Addresses.Swarm` when [`AutoTLS.Enabled`](https://github.com/ipfs/kubo/blob/master/docs/config.md#autotlsenabled) is set to `true`. Kubo will detect if `/ws` listener is missing and add one on the same port as pre-existing TCP (e.g. `/tcp/4001`), removing the need for any extra configuration.
+> [!TIP]
+> Give it a try:
+> ```console
+> $ ipfs config --json AutoTLS.Enabled true
+> ```
+> And restart the node. If you are behind NAT, make sure your node is publicly diallable (uPnP or port forwarding), and wait a few minutes to pass all checks and for the changes to take effect.
+
+See [`AutoTLS`](https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls) for more information.
+
+#### Bitswap improvements from Boxo
+
+This release includes some refactorings and improvements affecting Bitswap which should improve reliability. One of the changes affects blocks providing. Previously, the bitswap layer took care itself of announcing new blocks -added or received- with the configured provider (i.e. DHT). This bypassed the "Reprovider", that is, the system that manages precisely "providing" the blocks stored by Kubo. The Reprovider knows how to take advantage of the [AcceleratedDHTClient](https://github.com/ipfs/kubo/blob/master/docs/config.md#routingaccelerateddhtclient), is able to handle priorities, logs statistics and is able to resume on daemon reboot where it left off. From now on, Bitswap will not be doing any providing on-the-side and all announcements are managed by the reprovider. In some cases, when the reproviding queue is full with other elements, this may cause additional delays, but more likely this will result in improved block-providing behaviour overall.
+
+#### Using default `libp2p_rcmgr` metrics
+
+Bespoke rcmgr metrics [were removed](https://github.com/ipfs/kubo/pull/9947), Kubo now exposes only the default `libp2p_rcmgr` metrics from go-libp2p.
+This makes it easier to compare Kubo with custom implementations based on go-libp2p.
+If you depended on removed ones, please fill an issue to add them to the upstream [go-libp2p](https://github.com/libp2p/go-libp2p).
+
+#### Flatfs does not `sync` on each write
+
+New repositories initialized with `flatfs` in `Datastore.Spec` will have `sync` set to `false`.
+
+The old default was overly conservative and caused performance issues in big repositories that did a lot of writes. There is usually no need to flush on every block write to disk before continuing. Setting this to false is safe as kubo will automatically flush writes to disk before and after performing critical operations like pinning. However, we still provide users with ability to set this to true to be extra-safe (at the cost of a slowdown when adding files in bulk).
+
+#### `ipfs add --to-files` no longer works with `--wrap`
+
+Onboarding files and directories with `ipfs add --to-files` now requires non-empty names. due to this, The `--to-files` and `--wrap` options are now mutually exclusive ([#10612](https://github.com/ipfs/kubo/issues/10612)).
+
+#### `ipfs --api` supports HTTPS RPC endpoints
+
+CLI and RPC client now supports accessing Kubo RPC over `https://` protocol when multiaddr ending with `/https` or `/tls/http` is passed to `ipfs --api`:
+
+```console
+$ ipfs id --api /dns/kubo-rpc.example.net/tcp/5001/tls/http
+# → https://kubo-rpc.example.net:5001
+```
+
+#### New options for faster writes: `WriteThrough`, `BlockKeyCacheSize`, `BatchMaxNodes`, `BatchMaxSize`
+
+Now that Kubo supports [`pebble`](https://github.com/ipfs/kubo/blob/master/docs/datastores.md#pebbleds) as an _experimental_ datastore backend, it becomes very useful to expose some additional configuration options for how the blockservice/blockstore/datastore combo behaves.
+
+Usually, LSM-tree based datastore like Pebble or Badger have very fast write performance (blocks are streamed to disk) while incurring in read-amplification penalties (blocks need to be looked up in the index to know where they are on disk), specially noticeable on spinning disks.
+
+Prior to this version, `BlockService` and `Blockstore` implementations performed a `Has(cid)` for every block that was going to be written, skipping the writes altogether if the block was already present in the datastore. The performance impact of this `Has()` call can vary. The `Datastore` implementation itself might include block-caching and things like bloom-filters to speed up lookups and mitigate read-penalties. Our `Blockstore` implementation also supports a bloom-filter (controlled by `BloomFilterSize` and disabled by default), and a two-queue cache for keys and block sizes. If we assume that most of the blocks added to Kubo are new blocks, not already present in the datastore, or that the datastore itself includes mechanisms to optimize writes and avoid writing the same data twice, the calls to `Has()` at both BlockService and Blockstore layers seem superfluous to they point they even harm write performance.
+
+For these reasons, from now on, the default is to use a "write-through" mode for the Blockservice and the Blockstore. We have added a new option `Datastore.WriteThrough`, which defaults to `true`. Previous behaviour can be obtained by manually setting it to `false`.
+
+We have also made the size of the two-queue blockstore cache configurable with another option: `Datastore.BlockKeyCacheSize`, which defaults to `65536` (64KiB). Additionally, this caching layer can be disabled altogether by setting it to `0`. In particular, this option controls the size of a blockstore caching layer that records whether the blockstore has certain block and their sizes (but does not cache the contents, so it stays relativey small in general).
+
+Finally, we have added two new options to the `Import` section to control the maximum size of write-batches: `BatchMaxNodes` and `BatchMaxSize`. These are set by default to `128` nodes and `20MiB`. Increasing them will batch more items together when importing data with `ipfs dag import`, which can speed things up. It is importance to find a balance between available memory (used to hold the batch), disk latencies (when writing the batch) and processing power (when preparing the batch, as nodes are sorted and duplicates removed).
+
+As a reminder, details from all the options are explained in the [configuration documentation](https://github.com/ipfs/kubo/blob/master/docs/config.md).
+
+We recommend users trying Pebble as a datastore backend to disable both blockstore bloom-filter and key caching layers and enable write through as a way to evaluate the raw performance of the underlying datastore, which includes its own bloom-filter and caching layers (default cache size is `8MiB` and can be configured in the [options](https://github.com/ipfs/kubo/blob/master/docs/datastores.md#pebbleds).
+
+#### MFS stability with large number of writes
+
+We have fixed a number of issues that were triggered by writing or copying many files onto an MFS folder: increased memory usage first, then CPU, disk usage, and eventually a deadlock on write operations. The details of the fixes can be read at [#10630](https://github.com/ipfs/kubo/pull/10630) and [#10623](https://github.com/ipfs/kubo/pull/10623). The result is that writing large amounts of files to an MFS folder should now be possible without major issues. It is possible, as before, to speed up the operations using the `ipfs files --flush=false ...` flag, but it is recommended to switch to `ipfs files --flush=true ...` regularly, or call `ipfs files flush` on the working directory regularly, as this will flush, clear the directory cache and speed up reads.
+
+#### New DoH resolvers for non-ICANN DNSLinks
+
+- `.eth` TLD DNSLinks are now resolved via [DNS-over-HTTPS](https://en.wikipedia.org/wiki/DNS_over_HTTPS) endpoint at `https://dns.eth.limo/dns-query`
+- `.crypto` TLD DNSLinks are now resolved via DoH endpoint at `https://resolver.unstoppable.io/dns-query`
+
+#### Reliability improvements to the WebRTC Direct listener
+
+Two fixes in go-libp2p improve the reliability of the WebRTC Direct listener in Kubo, and by extension dialability from browsers.
+
+Relevant changes in go-libp2p:
+- [Deprioritising outgoing `/webrtc-direct`](https://github.com/libp2p/go-libp2p/pull/3078) dials.
+- [Allows more concurrent handshakes by default](https://github.com/libp2p/go-libp2p/pull/3040/).
+
+#### Bitswap improvements from Boxo
+
+This release includes performance and reliability improvements and fixes for minor resource leaks.
+
+#### 📦️ Important dependency updates
+
+- update `boxo` to [v0.27.4](https://github.com/ipfs/boxo/releases/tag/v0.27.4) (incl. [v0.25.0](https://github.com/ipfs/boxo/releases/tag/v0.25.0) + [v0.26.0](https://github.com/ipfs/boxo/releases/tag/v0.26.0) + [v0.27.0](https://github.com/ipfs/boxo/releases/tag/v0.27.0) + [v0.27.1](https://github.com/ipfs/boxo/releases/tag/v0.27.1) + [v0.27.2](https://github.com/ipfs/boxo/releases/tag/v0.27.2) + [v0.27.3](https://github.com/ipfs/boxo/releases/tag/v0.27.3))
+- update `go-libp2p` to [v0.38.2](https://github.com/libp2p/go-libp2p/releases/tag/v0.38.2) (incl. [v0.37.1](https://github.com/libp2p/go-libp2p/releases/tag/v0.37.1) + [v0.37.2](https://github.com/libp2p/go-libp2p/releases/tag/v0.37.2) + [v0.38.0](https://github.com/libp2p/go-libp2p/releases/tag/v0.38.0) + [v0.38.1](https://github.com/libp2p/go-libp2p/releases/tag/v0.38.1))
+- update `go-libp2p-kad-dht` to [v0.28.2](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.28.2)
+- update `quic-go` to [v0.49.0](https://github.com/quic-go/quic-go/releases/tag/v0.49.0)
+- update `p2p-forge/client` to [v0.3.0](https://github.com/ipshipyard/p2p-forge/releases/tag/v0.3.0) (incl. [v0.1.0](https://github.com/ipshipyard/p2p-forge/releases/tag/v0.1.0), [v0.2.0](https://github.com/ipshipyard/p2p-forge/releases/tag/v0.2.0), [v0.2.1](https://github.com/ipshipyard/p2p-forge/releases/tag/v0.2.1), [v0.2.2](https://github.com/ipshipyard/p2p-forge/releases/tag/v0.2.2))
+- update `ipfs-webui` to [v4.4.2](https://github.com/ipfs/ipfs-webui/releases/tag/v4.4.2) (incl. [v4.4.1](https://github.com/ipfs/ipfs-webui/releases/tag/v4.4.1))
+
+#### Escape Redirect URL for Directory
+
+When navigating to a subdirectory, served by the Kubo web server, a subdirectory without a trailing slash gets redirected to a URL with a trailing slash. If there are special characters such as "%" in the subdirectory name then these must be escaped in the redirect URL. Previously this was not being done and was preventing navigation to such subdirectories, requiring the user to manually add a trailing slash to the subdirectory URL. This is now fixed to handle the redirect to URLs with characters that must be escaped.
+
+### 📝 Changelog
+
+Full Changelog v0.33.0
+
+- github.com/ipfs/kubo:
+ - test: fix the socat tests after the ubuntu 24.04 upgrade (#10683) ([ipfs/kubo#10683](https://github.com/ipfs/kubo/pull/10683))
+ - chore: 0.33.0-rc3
+ - fix: quic-go v0.49.0 (#10673) ([ipfs/kubo#10673](https://github.com/ipfs/kubo/pull/10673))
+ - Upgrade to Boxo v0.27.2 (#10672) ([ipfs/kubo#10672](https://github.com/ipfs/kubo/pull/10672))
+ - chore: 0.33.0-rc2
+ - Upgrade to Boxo v0.27.1 (#10671) ([ipfs/kubo#10671](https://github.com/ipfs/kubo/pull/10671))
+ - fix(autotls): renewal and AutoTLS.ShortAddrs (#10669) ([ipfs/kubo#10669](https://github.com/ipfs/kubo/pull/10669))
+ - update changelog for boxo and go-libp2p (#10668) ([ipfs/kubo#10668](https://github.com/ipfs/kubo/pull/10668))
+ - Upgrade to Boxo v0.27.0 (#10665) ([ipfs/kubo#10665](https://github.com/ipfs/kubo/pull/10665))
+ - update dependencies (#10664) ([ipfs/kubo#10664](https://github.com/ipfs/kubo/pull/10664))
+ - fix(dns): update default DNSLink resolvers (#10655) ([ipfs/kubo#10655](https://github.com/ipfs/kubo/pull/10655))
+ - chore: p2p-forge v0.2.2 + go-libp2p-kad-dht v0.28.2 (#10663) ([ipfs/kubo#10663](https://github.com/ipfs/kubo/pull/10663))
+ - fix(cli): support HTTPS in ipfs --api (#10659) ([ipfs/kubo#10659](https://github.com/ipfs/kubo/pull/10659))
+ - chore: fix typos and comment formatting (#10653) ([ipfs/kubo#10653](https://github.com/ipfs/kubo/pull/10653))
+ - fix/gateway: escape directory redirect url (#10649) ([ipfs/kubo#10649](https://github.com/ipfs/kubo/pull/10649))
+ - Add example of setting array to config command help
+ - collection of typo fixes (#10647) ([ipfs/kubo#10647](https://github.com/ipfs/kubo/pull/10647))
+ - chore: 0.33.0-rc1
+ - fix: ipfs-webui v4.4.2 (#10635) ([ipfs/kubo#10635](https://github.com/ipfs/kubo/pull/10635))
+ - feat(libp2p): shared TCP listeners and AutoTLS.AutoWSS (#10565) ([ipfs/kubo#10565](https://github.com/ipfs/kubo/pull/10565))
+ - feat(flatfs): default to sync=false (#10632) ([ipfs/kubo#10632](https://github.com/ipfs/kubo/pull/10632))
+ - Minor spelling and wording changes (#10634) ([ipfs/kubo#10634](https://github.com/ipfs/kubo/pull/10634))
+ - docs: clarify Swarm.ResourceMgr.MaxMemory (#10622) ([ipfs/kubo#10622](https://github.com/ipfs/kubo/pull/10622))
+ - feat: expose BlockKeyCacheSize and enable WriteThrough datastore options (#10614) ([ipfs/kubo#10614](https://github.com/ipfs/kubo/pull/10614))
+ - cmd/files: flush parent folders (#10630) ([ipfs/kubo#10630](https://github.com/ipfs/kubo/pull/10630))
+ - Upgrade to Boxo v0.26.0 (#10631) ([ipfs/kubo#10631](https://github.com/ipfs/kubo/pull/10631))
+ - [skip changelog] pinmfs: mitigate slow mfs writes when it triggers (#10623) ([ipfs/kubo#10623](https://github.com/ipfs/kubo/pull/10623))
+ - chore: use errors.New to replace fmt.Errorf with no parameters (#10617) ([ipfs/kubo#10617](https://github.com/ipfs/kubo/pull/10617))
+ - chore: boxo v0.25.0 (#10619) ([ipfs/kubo#10619](https://github.com/ipfs/kubo/pull/10619))
+ - fix(cmds/add): disallow --wrap with --to-files (#10612) ([ipfs/kubo#10612](https://github.com/ipfs/kubo/pull/10612))
+ - refactor(cmds): do not return errors embedded in result type (#10527) ([ipfs/kubo#10527](https://github.com/ipfs/kubo/pull/10527))
+ - fix: ipfs-webui v4.4.1 (#10608) ([ipfs/kubo#10608](https://github.com/ipfs/kubo/pull/10608))
+ - chore: fix broken url in comment (#10606) ([ipfs/kubo#10606](https://github.com/ipfs/kubo/pull/10606))
+ - refactor(rcmgr): use default libp2p rcmgr metrics (#9947) ([ipfs/kubo#9947](https://github.com/ipfs/kubo/pull/9947))
+ - docs(changelog/v0.33): bitswap reprovide changes (#10604) ([ipfs/kubo#10604](https://github.com/ipfs/kubo/pull/10604))
+ - tests(cli/harness): use unused Verbose flag to pipe daemon outputs (#10601) ([ipfs/kubo#10601](https://github.com/ipfs/kubo/pull/10601))
+ - chore: p2p-forge/client v0.1.0 (#10605) ([ipfs/kubo#10605](https://github.com/ipfs/kubo/pull/10605))
+ - fix: go-libp2p v0.37.2 (#10603) ([ipfs/kubo#10603](https://github.com/ipfs/kubo/pull/10603))
+ - docs: typos (#10602) ([ipfs/kubo#10602](https://github.com/ipfs/kubo/pull/10602))
+ - tests/cli: fix flapping tests (#10600) ([ipfs/kubo#10600](https://github.com/ipfs/kubo/pull/10600))
+ - Update to boxo with refactored providerQueryManager. (#10595) ([ipfs/kubo#10595](https://github.com/ipfs/kubo/pull/10595))
+ - fix some typos in docs (#10598) ([ipfs/kubo#10598](https://github.com/ipfs/kubo/pull/10598))
+ - feat(bootstrap): add JS-based va1.bootstrap.libp2p.io (#10575) ([ipfs/kubo#10575](https://github.com/ipfs/kubo/pull/10575))
+ - fix: increase provider sample size (#10589) ([ipfs/kubo#10589](https://github.com/ipfs/kubo/pull/10589))
+ - Typos Update config.md (#10591) ([ipfs/kubo#10591](https://github.com/ipfs/kubo/pull/10591))
+ - refactor: update to boxo without goprocess (#10567) ([ipfs/kubo#10567](https://github.com/ipfs/kubo/pull/10567))
+ - fix: go-libp2p-kad-dht v0.28.1 (#10581) ([ipfs/kubo#10581](https://github.com/ipfs/kubo/pull/10581))
+ - docs: update RELEASE_CHECKLIST.md (#10564) ([ipfs/kubo#10564](https://github.com/ipfs/kubo/pull/10564))
+ - Merge release v0.32.0 ([ipfs/kubo#10579](https://github.com/ipfs/kubo/pull/10579))
+ - fix: go-libp2p-kad-dht v0.28.0 (#10578) ([ipfs/kubo#10578](https://github.com/ipfs/kubo/pull/10578))
+ - feat: ipfs-webui v4.4.0 (#10574) ([ipfs/kubo#10574](https://github.com/ipfs/kubo/pull/10574))
+ - chore: boxo v0.24.3 and p2p-forge v0.0.2 (#10572) ([ipfs/kubo#10572](https://github.com/ipfs/kubo/pull/10572))
+ - chore: stop using go-homedir (#10568) ([ipfs/kubo#10568](https://github.com/ipfs/kubo/pull/10568))
+ - fix(autotls): store certificates at the location from the repo path (#10566) ([ipfs/kubo#10566](https://github.com/ipfs/kubo/pull/10566))
+ - chore: bump master to 0.33.0-dev
+- github.com/ipfs-shipyard/nopfs (v0.0.12 -> v0.0.14):
+ - Fix error when no doublehash db exists (#42) ([ipfs-shipyard/nopfs#42](https://github.com/ipfs-shipyard/nopfs/pull/42))
+ - Improve support for IPNS double-hashed entries (#41) ([ipfs-shipyard/nopfs#41](https://github.com/ipfs-shipyard/nopfs/pull/41))
+- github.com/ipfs-shipyard/nopfs/ipfs (v0.13.2-0.20231027223058-cde3b5ba964c -> v0.25.0):
+ failed to fetch repo
+- github.com/ipfs/boxo (v0.24.3 -> v0.27.2):
+ - Release v0.27.2 ([ipfs/boxo#811](https://github.com/ipfs/boxo/pull/811))
+ - Revert peer exclude cancel ([ipfs/boxo#809](https://github.com/ipfs/boxo/pull/809))
+ - Release v0.27.1 ([ipfs/boxo#807](https://github.com/ipfs/boxo/pull/807))
+ - fix sending cancels when excluding peer ([ipfs/boxo#805](https://github.com/ipfs/boxo/pull/805))
+ - Release v0.27.0 ([ipfs/boxo#802](https://github.com/ipfs/boxo/pull/802))
+ - Remove want-block sent tracking from sessionWantSender (#759) ([ipfs/boxo#759](https://github.com/ipfs/boxo/pull/759))
+ - Upgrade to go-libp2p v0.38.2 (#804) ([ipfs/boxo#804](https://github.com/ipfs/boxo/pull/804))
+ - [skip changelog] Use routing.ContentRouting interface (#803) ([ipfs/boxo#803](https://github.com/ipfs/boxo/pull/803))
+ - fix potential crash in unixfs directory (#798) ([ipfs/boxo#798](https://github.com/ipfs/boxo/pull/798))
+ - prefer slices.SortFunc to sort.Sort (#796) ([ipfs/boxo#796](https://github.com/ipfs/boxo/pull/796))
+ - fix: ipns protobuf namespace conflict (#794) ([ipfs/boxo#794](https://github.com/ipfs/boxo/pull/794))
+ - update release procedure (#773) ([ipfs/boxo#773](https://github.com/ipfs/boxo/pull/773))
+ - reduce default number of routing in-process requests (#793) ([ipfs/boxo#793](https://github.com/ipfs/boxo/pull/793))
+ - Do not return unused values from wantlists (#792) ([ipfs/boxo#792](https://github.com/ipfs/boxo/pull/792))
+ - Create FUNDING.json [skip changelog] (#795) ([ipfs/boxo#795](https://github.com/ipfs/boxo/pull/795))
+ - refactor: using slices.Contains to simplify the code (#791) ([ipfs/boxo#791](https://github.com/ipfs/boxo/pull/791))
+ - do not send cancel message to peer that sent block (#784) ([ipfs/boxo#784](https://github.com/ipfs/boxo/pull/784))
+ - Define a `go_package` for protobuf, rename to a more unique `ipns-record.proto` ([ipfs/boxo#789](https://github.com/ipfs/boxo/pull/789))
+ - bitswap: messagequeue: lock only needed sections (#787) ([ipfs/boxo#787](https://github.com/ipfs/boxo/pull/787))
+ - Update libp2p-kad-dht to v0.28.2 (#786) ([ipfs/boxo#786](https://github.com/ipfs/boxo/pull/786))
+ - feat(gateway): allow localhost http:// DoH resolvers (#645) ([ipfs/boxo#645](https://github.com/ipfs/boxo/pull/645))
+ - fix(gateway): update DoH resolver for .crypto DNSLink (#782) ([ipfs/boxo#782](https://github.com/ipfs/boxo/pull/782))
+ - fix(gateway): update DoH resolver for .eth DNSLink (#781) ([ipfs/boxo#781](https://github.com/ipfs/boxo/pull/781))
+ - chore: pass options to tracer start (#775) ([ipfs/boxo#775](https://github.com/ipfs/boxo/pull/775))
+ - escape redirect urls (#783) ([ipfs/boxo#783](https://github.com/ipfs/boxo/pull/783))
+ - fix/gateway: escape directory redirect url (#779) ([ipfs/boxo#779](https://github.com/ipfs/boxo/pull/779))
+ - fix spelling in comments (#778) ([ipfs/boxo#778](https://github.com/ipfs/boxo/pull/778))
+ - trivial spelling changes in comments (#777) ([ipfs/boxo#777](https://github.com/ipfs/boxo/pull/777))
+ - Release v0.26.0 ([ipfs/boxo#770](https://github.com/ipfs/boxo/pull/770))
+ - Minor spelling and wording changes (#768) ([ipfs/boxo#768](https://github.com/ipfs/boxo/pull/768))
+ - update go-libp2p and go-libp2p-kad-dht ([ipfs/boxo#767](https://github.com/ipfs/boxo/pull/767))
+ - [skip changelog] fix: Drop stream references on Close/Reset ([ipfs/boxo#760](https://github.com/ipfs/boxo/pull/760))
+ - Update go-libp2p to v0.38.0 (#764) ([ipfs/boxo#764](https://github.com/ipfs/boxo/pull/764))
+ - Fix leak due to cid queue never getting cleaned up (#756) ([ipfs/boxo#756](https://github.com/ipfs/boxo/pull/756))
+ - Do not reset the broadcast timer if there are no wants (#758) ([ipfs/boxo#758](https://github.com/ipfs/boxo/pull/758))
+ - Replace mock time implementation (#762) ([ipfs/boxo#762](https://github.com/ipfs/boxo/pull/762))
+ - mfs: clean cache on sync ([ipfs/boxo#751](https://github.com/ipfs/boxo/pull/751))
+ - Remove peer's count of first responses when peer becomes unavailable (#757) ([ipfs/boxo#757](https://github.com/ipfs/boxo/pull/757))
+ - Remove unnecessary CID copying in SessionInterestManager (#761) ([ipfs/boxo#761](https://github.com/ipfs/boxo/pull/761))
+ - [bitswap/peermanager] take read-lock for read-only operation (#755) ([ipfs/boxo#755](https://github.com/ipfs/boxo/pull/755))
+ - bitswap/client/messagequeue: expose dontHaveTimeoutMgr configuration (#750) ([ipfs/boxo#750](https://github.com/ipfs/boxo/pull/750))
+ - improve mfs republisher (#754) ([ipfs/boxo#754](https://github.com/ipfs/boxo/pull/754))
+ - blockstore/blockservice: change option to `WriteThrough(enabled bool)` ([ipfs/boxo#749](https://github.com/ipfs/boxo/pull/749))
+ - Merge release v0.25.0 ([ipfs/boxo#748](https://github.com/ipfs/boxo/pull/748))
+ - Use deque instead of slice for queues (#742) ([ipfs/boxo#742](https://github.com/ipfs/boxo/pull/742))
+ - chore: no lifecycle context to shutdown ProviderQueryManager (#734) ([ipfs/boxo#734](https://github.com/ipfs/boxo/pull/734))
+ - removed Startup function from ProviderQueryManager (#741) ([ipfs/boxo#741](https://github.com/ipfs/boxo/pull/741))
+ - Re-enable flaky bitswap tests (#740) ([ipfs/boxo#740](https://github.com/ipfs/boxo/pull/740))
+ - feat(session): do not record erroneous session want sends (#452) ([ipfs/boxo#452](https://github.com/ipfs/boxo/pull/452))
+ - feat(filestore): add mmap reader option (#665) ([ipfs/boxo#665](https://github.com/ipfs/boxo/pull/665))
+ - chore: update to latest go-libp2p (#739) ([ipfs/boxo#739](https://github.com/ipfs/boxo/pull/739))
+ - refactor(remote/pinning): `Ls` to take results channel instead of returning one (#738) ([ipfs/boxo#738](https://github.com/ipfs/boxo/pull/738))
+ - Bitswap default ProviderQueryManager uses explicit options (#737) ([ipfs/boxo#737](https://github.com/ipfs/boxo/pull/737))
+ - chore: minor examples cleanup (#736) ([ipfs/boxo#736](https://github.com/ipfs/boxo/pull/736))
+ - misc comments and spelling (#735) ([ipfs/boxo#735](https://github.com/ipfs/boxo/pull/735))
+ - chore: fix invalid url in docs (#733) ([ipfs/boxo#733](https://github.com/ipfs/boxo/pull/733))
+ - [skip changelog] bitswap/client: fix wiring when passing custom providerFinder ([ipfs/boxo#732](https://github.com/ipfs/boxo/pull/732))
+ - Add debug logging for deduplicated queries (#729) ([ipfs/boxo#729](https://github.com/ipfs/boxo/pull/729))
+ - [skip changelog] staticcheck fixes / remove unused variables (#730) ([ipfs/boxo#730](https://github.com/ipfs/boxo/pull/730))
+ - refactor: default to prometheus.DefaultRegisterer (#722) ([ipfs/boxo#722](https://github.com/ipfs/boxo/pull/722))
+ - chore: minor Improvements to providerquerymanager (#728) ([ipfs/boxo#728](https://github.com/ipfs/boxo/pull/728))
+ - dspinner: RecursiveKeys(): do not hang on cancellations (#727) ([ipfs/boxo#727](https://github.com/ipfs/boxo/pull/727))
+ - Tests can signal immediate rebroadcast (#726) ([ipfs/boxo#726](https://github.com/ipfs/boxo/pull/726))
+ - fix(bitswap/client/msgq): prevent duplicate requests (#691) ([ipfs/boxo#691](https://github.com/ipfs/boxo/pull/691))
+ - Bitswap: move providing -> Exchange-layer, providerQueryManager -> routing (#641) ([ipfs/boxo#641](https://github.com/ipfs/boxo/pull/641))
+ - fix(bitswap/client/providerquerymanager): don't end trace span until … (#725) ([ipfs/boxo#725](https://github.com/ipfs/boxo/pull/725))
+ - fix(routing/http/server): adjust bucket sizes for http metrics ([ipfs/boxo#724](https://github.com/ipfs/boxo/pull/724))
+ - fix(bitswap/client/providerquerymanager): use non-timed out context for tracing (#721) ([ipfs/boxo#721](https://github.com/ipfs/boxo/pull/721))
+ - fix(bitswap/server): pass context to server engine to register metrics (#723) ([ipfs/boxo#723](https://github.com/ipfs/boxo/pull/723))
+ - docs: fix url of tracing env vars (#719) ([ipfs/boxo#719](https://github.com/ipfs/boxo/pull/719))
+ - feat(routing/http/server): add routing timeout (#720) ([ipfs/boxo#720](https://github.com/ipfs/boxo/pull/720))
+ - feat(routing/http/server): expose prometheus metrics (#718) ([ipfs/boxo#718](https://github.com/ipfs/boxo/pull/718))
+ - Remove dependency on goprocess ([ipfs/boxo#710](https://github.com/ipfs/boxo/pull/710))
+ - Merge release v0.24.3 ([ipfs/boxo#714](https://github.com/ipfs/boxo/pull/714))
+ - fix(bitswap): log unexpected blocks to debug level (#711) ([ipfs/boxo#711](https://github.com/ipfs/boxo/pull/711))
+ - Release v0.24.2 ([ipfs/boxo#708](https://github.com/ipfs/boxo/pull/708))
+- github.com/ipfs/go-ds-pebble (v0.4.0 -> v0.4.2):
+ - new version (#44) ([ipfs/go-ds-pebble#44](https://github.com/ipfs/go-ds-pebble/pull/44))
+ - new version for pebble minor version update (#42) ([ipfs/go-ds-pebble#42](https://github.com/ipfs/go-ds-pebble/pull/42))
+- github.com/ipfs/go-ipfs-cmds (v0.14.0 -> v0.14.1):
+ - fix(NewClient): support https:// URLs (#277) ([ipfs/go-ipfs-cmds#277](https://github.com/ipfs/go-ipfs-cmds/pull/277))
+- github.com/ipfs/go-peertaskqueue (v0.8.1 -> v0.8.2):
+ - new version ([ipfs/go-peertaskqueue#39](https://github.com/ipfs/go-peertaskqueue/pull/39))
+ - Replace mock time implementation ([ipfs/go-peertaskqueue#37](https://github.com/ipfs/go-peertaskqueue/pull/37))
+ - fix: staticcheck feedback
+- github.com/libp2p/go-doh-resolver (v0.4.0 -> v0.5.0):
+ - chore: release v0.5.0
+ - fix: include url on HTTP error (#29) ([libp2p/go-doh-resolver#29](https://github.com/libp2p/go-doh-resolver/pull/29))
+ - feat: allow localhost http endpoints (#28) ([libp2p/go-doh-resolver#28](https://github.com/libp2p/go-doh-resolver/pull/28))
+ - sync: update CI config files (#20) ([libp2p/go-doh-resolver#20](https://github.com/libp2p/go-doh-resolver/pull/20))
+- github.com/libp2p/go-libp2p (v0.37.0 -> v0.38.2):
+ - Release v0.38.2 (#3147) ([libp2p/go-libp2p#3147](https://github.com/libp2p/go-libp2p/pull/3147))
+ - chore: release v0.38.1
+ - fix(httpauth): Correctly handle concurrent requests on server (#3111) ([libp2p/go-libp2p#3111](https://github.com/libp2p/go-libp2p/pull/3111))
+ - ci: Install specific protoc version when generating protobufs (#3112) ([libp2p/go-libp2p#3112](https://github.com/libp2p/go-libp2p/pull/3112))
+ - fix(autorelay): Move relayFinder peer disconnect cleanup to separate goroutine (#3105) ([libp2p/go-libp2p#3105](https://github.com/libp2p/go-libp2p/pull/3105))
+ - chore: Release v0.38.0 (#3106) ([libp2p/go-libp2p#3106](https://github.com/libp2p/go-libp2p/pull/3106))
+ - peerstore: remove sync.Pool for expiringAddrs (#3093) ([libp2p/go-libp2p#3093](https://github.com/libp2p/go-libp2p/pull/3093))
+ - webtransport: close quic conn on dial error (#3104) ([libp2p/go-libp2p#3104](https://github.com/libp2p/go-libp2p/pull/3104))
+ - peerstore: fix addressbook benchmark timing (#3092) ([libp2p/go-libp2p#3092](https://github.com/libp2p/go-libp2p/pull/3092))
+ - swarm: record conn metrics only once (#3091) ([libp2p/go-libp2p#3091](https://github.com/libp2p/go-libp2p/pull/3091))
+ - fix(sampledconn): Correctly handle slow bytes and closed conns (#3080) ([libp2p/go-libp2p#3080](https://github.com/libp2p/go-libp2p/pull/3080))
+ - peerstore: pass options to addrbook constructor (#3090) ([libp2p/go-libp2p#3090](https://github.com/libp2p/go-libp2p/pull/3090))
+ - fix(swarm): remove stray print stmt (#3086) ([libp2p/go-libp2p#3086](https://github.com/libp2p/go-libp2p/pull/3086))
+ - feat(swarm): delay /webrtc-direct dials by 1 second (#3078) ([libp2p/go-libp2p#3078](https://github.com/libp2p/go-libp2p/pull/3078))
+ - chore: Update dependencies and fix deprecated function in relay example (#3023) ([libp2p/go-libp2p#3023](https://github.com/libp2p/go-libp2p/pull/3023))
+ - chore: fix broken link to record envelope protobuf file (#3070) ([libp2p/go-libp2p#3070](https://github.com/libp2p/go-libp2p/pull/3070))
+ - chore(core): fix function name in interface comment (#3056) ([libp2p/go-libp2p#3056](https://github.com/libp2p/go-libp2p/pull/3056))
+ - basichost: avoid modifying slice returned by AddrsFactory (#3068) ([libp2p/go-libp2p#3068](https://github.com/libp2p/go-libp2p/pull/3068))
+ - fix(swarm): check after we split for empty multiaddr (#3063) ([libp2p/go-libp2p#3063](https://github.com/libp2p/go-libp2p/pull/3063))
+ - feat: allow passing options to memoryAddrBook (#3062) ([libp2p/go-libp2p#3062](https://github.com/libp2p/go-libp2p/pull/3062))
+ - fix(libp2phttp): Return ErrServerClosed on Close (#3050) ([libp2p/go-libp2p#3050](https://github.com/libp2p/go-libp2p/pull/3050))
+ - chore(dashboard/alertmanager): update api version from v1 to v2 (#3054) ([libp2p/go-libp2p#3054](https://github.com/libp2p/go-libp2p/pull/3054))
+ - fix(tcpreuse): handle connection that failed to be sampled (#3036) ([libp2p/go-libp2p#3036](https://github.com/libp2p/go-libp2p/pull/3036))
+ - fix(tcpreuse): remove windows specific code (#3039) ([libp2p/go-libp2p#3039](https://github.com/libp2p/go-libp2p/pull/3039))
+ - refactor(libp2phttp): don't require specific port for the HTTP host example (#3047) ([libp2p/go-libp2p#3047](https://github.com/libp2p/go-libp2p/pull/3047))
+ - refactor(core/routing): split ContentRouting interface (#3048) ([libp2p/go-libp2p#3048](https://github.com/libp2p/go-libp2p/pull/3048))
+ - fix(holepunch/tracer): replace inline peer struct with peerInfo type (#3049) ([libp2p/go-libp2p#3049](https://github.com/libp2p/go-libp2p/pull/3049))
+ - fix: Defer resource usage cleanup until the very end (#3042) ([libp2p/go-libp2p#3042](https://github.com/libp2p/go-libp2p/pull/3042))
+ - fix(eventbus): Idempotent wildcardSub close (#3045) ([libp2p/go-libp2p#3045](https://github.com/libp2p/go-libp2p/pull/3045))
+ - fix: obsaddr: do not record observations over relayed conn (#3043) ([libp2p/go-libp2p#3043](https://github.com/libp2p/go-libp2p/pull/3043))
+ - fix(identify): push should not dial a new connection (#3035) ([libp2p/go-libp2p#3035](https://github.com/libp2p/go-libp2p/pull/3035))
+ - webrtc: handshake more connections in parallel (#3040) ([libp2p/go-libp2p#3040](https://github.com/libp2p/go-libp2p/pull/3040))
+ - eventbus: dont panic on closing Subscription twice (#3034) ([libp2p/go-libp2p#3034](https://github.com/libp2p/go-libp2p/pull/3034))
+ - fix(swarm): incorrect error message format order (#3037) ([libp2p/go-libp2p#3037](https://github.com/libp2p/go-libp2p/pull/3037))
+ - feat: eventbus: log error on slow consumers (#3031) ([libp2p/go-libp2p#3031](https://github.com/libp2p/go-libp2p/pull/3031))
+ - chore: make funding.json uppercase to follow meta convention (#3028) ([libp2p/go-libp2p#3028](https://github.com/libp2p/go-libp2p/pull/3028))
+ - chore: add drips entry to funding.json for Filecoin rPGF round 2
+ - tcp: parameterize metrics collector (#3026) ([libp2p/go-libp2p#3026](https://github.com/libp2p/go-libp2p/pull/3026))
+ - fix: basichost: Use NegotiationTimeout as fallback timeout for NewStream (#3020) ([libp2p/go-libp2p#3020](https://github.com/libp2p/go-libp2p/pull/3020))
+ - feat(tcpreuse): add options for sharing TCP listeners amongst TCP, WS and WSS transports (#2984) ([libp2p/go-libp2p#2984](https://github.com/libp2p/go-libp2p/pull/2984))
+ - pnet: wrap underlying error when reading nonce fails (#2975) ([libp2p/go-libp2p#2975](https://github.com/libp2p/go-libp2p/pull/2975))
+- github.com/libp2p/go-libp2p-kad-dht (v0.28.1 -> v0.28.2):
+ - Release v0.28.2 (#1010) ([libp2p/go-libp2p-kad-dht#1010](https://github.com/libp2p/go-libp2p-kad-dht/pull/1010))
+ - accelerated-dht: cleanup peer from message sender on disconnection (#1009) ([libp2p/go-libp2p-kad-dht#1009](https://github.com/libp2p/go-libp2p-kad-dht/pull/1009))
+ - chore: fix some function names in comment ([libp2p/go-libp2p-kad-dht#1004](https://github.com/libp2p/go-libp2p-kad-dht/pull/1004))
+ - feat: add more attributes to traces ([libp2p/go-libp2p-kad-dht#1002](https://github.com/libp2p/go-libp2p-kad-dht/pull/1002))
+- github.com/libp2p/go-netroute (v0.2.1 -> v0.2.2):
+ - v0.2.2 Includes v4/v6 confusion fix for bsd route parsing
+ - #50, Don't transform v4 routes to their v6 form on bsd ([libp2p/go-netroute#51](https://github.com/libp2p/go-netroute/pull/51))
+ - Using syscall.RtMsg on Linux ([libp2p/go-netroute#43](https://github.com/libp2p/go-netroute/pull/43))
+ - add wasi build constraint for netroute_stub ([libp2p/go-netroute#38](https://github.com/libp2p/go-netroute/pull/38))
+ - Stricter filtering of degenerate routes ([libp2p/go-netroute#33](https://github.com/libp2p/go-netroute/pull/33))
+ - sync: update CI config files (#30) ([libp2p/go-netroute#30](https://github.com/libp2p/go-netroute/pull/30))
+- github.com/multiformats/go-multiaddr (v0.13.0 -> v0.14.0):
+ - Release v0.14.0 ([multiformats/go-multiaddr#258](https://github.com/multiformats/go-multiaddr/pull/258))
+ - feat: memory multiaddrs ([multiformats/go-multiaddr#256](https://github.com/multiformats/go-multiaddr/pull/256))
+ - nit: validate ipcidr ([multiformats/go-multiaddr#247](https://github.com/multiformats/go-multiaddr/pull/247))
+ - check for nil interfaces (#251) ([multiformats/go-multiaddr#251](https://github.com/multiformats/go-multiaddr/pull/251))
+ - Make it safe to roundtrip SplitXXX and Join (#250) ([multiformats/go-multiaddr#250](https://github.com/multiformats/go-multiaddr/pull/250))
+- github.com/multiformats/go-multiaddr-dns (v0.4.0 -> v0.4.1):
+ - Release v0.4.1
+ - fix: If decapsulating is empty, skip it. (#65) ([multiformats/go-multiaddr-dns#65](https://github.com/multiformats/go-multiaddr-dns/pull/65))
+- github.com/multiformats/go-multistream (v0.5.0 -> v0.6.0):
+ - release v0.6.0 ([multiformats/go-multistream#116](https://github.com/multiformats/go-multistream/pull/116))
+ - fix: finish reading handshake on lazyConn close
+ - feat: New error to highlight unrecognized responses
+ - release v0.5.0 (#108) ([multiformats/go-multistream#108](https://github.com/multiformats/go-multistream/pull/108))
+
+
+
+### 👨👩👧👦 Contributors
+
+| Contributor | Commits | Lines ± | Files Changed |
+|-------------|---------|---------|---------------|
+| Andrew Gillis | 57 | +1995/-1718 | 191 |
+| Adin Schmahmann | 7 | +2552/-719 | 84 |
+| Marco Munizaga | 27 | +1036/-261 | 51 |
+| Hector Sanjuan | 21 | +789/-362 | 65 |
+| gammazero | 20 | +407/-419 | 40 |
+| sukun | 13 | +519/-233 | 30 |
+| Marcin Rataj | 34 | +426/-142 | 59 |
+| Marten Seemann | 2 | +11/-261 | 5 |
+| Dreamacro | 2 | +161/-68 | 5 |
+| Hlib Kanunnikov | 1 | +34/-65 | 4 |
+| bashkarev | 1 | +78/-5 | 2 |
+| Daniel Norman | 4 | +68/-12 | 6 |
+| Andi | 1 | +37/-32 | 20 |
+| hannahhoward | 1 | +35/-17 | 7 |
+| Carlos Peliciari | 2 | +19/-26 | 2 |
+| Cole Brown | 1 | +32/-0 | 3 |
+| Will Scott | 2 | +19/-7 | 3 |
+| Guillaume Michel | 1 | +21/-2 | 4 |
+| 7sunarni | 1 | +3/-19 | 1 |
+| Srdjan S | 1 | +11/-2 | 2 |
+| web3-bot | 2 | +6/-6 | 3 |
+| dashangcun | 1 | +2/-10 | 1 |
+| John | 3 | +6/-6 | 5 |
+| Daniel N | 3 | +8/-3 | 3 |
+| Ivan Shvedunov | 1 | +4/-6 | 2 |
+| Piotr Galar | 1 | +4/-4 | 2 |
+| Derek Nola | 2 | +4/-4 | 4 |
+| Bryer | 1 | +4/-4 | 1 |
+| Prithvi Shahi | 2 | +6/-1 | 2 |
+| Cameron Wood | 1 | +7/-0 | 1 |
+| wangjingcun | 1 | +3/-3 | 2 |
+| cuibuwei | 1 | +2/-2 | 2 |
+| Jorropo | 1 | +1/-3 | 1 |
+| 未月 | 1 | +1/-1 | 1 |
+| Ubuntu | 1 | +1/-1 | 1 |
+| Ryan MacArthur | 1 | +1/-1 | 1 |
+| Reymon | 1 | +1/-1 | 1 |
+| guillaumemichel | 1 | +1/-0 | 1 |
+
+## v0.33.1
+
+### 🔦 Highlights
+
+#### Bitswap improvements from Boxo
+
+This release includes performance and reliability improvements and fixes for minor resource leaks. One of the performance changes [greatly improves the bitswap clients ability to operate under high load](https://github.com/ipfs/boxo/pull/817#pullrequestreview-2587207745), that could previously result in an out of memory condition.
+
+#### Improved IPNS interop
+
+Improved compatibility with third-party IPNS publishers by restoring support for compact binary CIDs in the `Value` field of IPNS Records ([IPNS Specs](https://specs.ipfs.tech/ipns/ipns-record/)). As long the signature is valid, Kubo will now resolve such records (likely created by non-Kubo nodes) and convert raw CIDs into valid `/ipfs/cid` content paths.
+**Note:** This only adds support for resolving externally created records—Kubo’s IPNS record creation remains unchanged. IPNS records with empty `Value` fields default to zero-length `/ipfs/bafkqaaa` to maintain backward compatibility with code expecting a valid content path.
+
+#### 📦️ Important dependency updates
+
+- update `boxo` to [v0.27.4](https://github.com/ipfs/boxo/releases/tag/v0.27.4) (incl. [v0.27.3](https://github.com/ipfs/boxo/releases/tag/v0.27.3))
+
+### 📝 Changelog
+
+Full Changelog v0.33.1
+
+- github.com/ipfs/kubo:
+ - chore: v0.33.1
+ - fix: boxo v0.27.4 (#10692) ([ipfs/kubo#10692](https://github.com/ipfs/kubo/pull/10692))
+ - docs: add webrtc-direct fixes to 0.33 release changelog (#10688) ([ipfs/kubo#10688](https://github.com/ipfs/kubo/pull/10688))
+ - fix: config help (#10686) ([ipfs/kubo#10686](https://github.com/ipfs/kubo/pull/10686))
+- github.com/ipfs/boxo (v0.27.2 -> v0.27.4):
+ - Release v0.27.4 ([ipfs/boxo#832](https://github.com/ipfs/boxo/pull/832))
+ - fix(ipns): reading records with raw []byte Value (#830) ([ipfs/boxo#830](https://github.com/ipfs/boxo/pull/830))
+ - fix(bitswap): blockpresencemanager leak (#833) ([ipfs/boxo#833](https://github.com/ipfs/boxo/pull/833))
+ - Always send cancels even if peer has no interest (#829) ([ipfs/boxo#829](https://github.com/ipfs/boxo/pull/829))
+ - tidy changelog ([ipfs/boxo#828](https://github.com/ipfs/boxo/pull/828))
+ - Update changelog (#827) ([ipfs/boxo#827](https://github.com/ipfs/boxo/pull/827))
+ - fix(bitswap): filter interests from received messages (#822) ([ipfs/boxo#822](https://github.com/ipfs/boxo/pull/822))
+ - Reduce unnecessary logging work (#826) ([ipfs/boxo#826](https://github.com/ipfs/boxo/pull/826))
+ - fix: bitswap lock contention under high load (#817) ([ipfs/boxo#817](https://github.com/ipfs/boxo/pull/817))
+ - fix: bitswap simplify cancel (#824) ([ipfs/boxo#824](https://github.com/ipfs/boxo/pull/824))
+ - fix(bitswap): simplify SessionInterestManager (#821) ([ipfs/boxo#821](https://github.com/ipfs/boxo/pull/821))
+ - feat: Better self-service commands for DHT providing (#815) ([ipfs/boxo#815](https://github.com/ipfs/boxo/pull/815))
+ - bitswap/client: fewer wantlist iterations in sendCancels (#819) ([ipfs/boxo#819](https://github.com/ipfs/boxo/pull/819))
+ - style: cleanup code by golangci-lint (#797) ([ipfs/boxo#797](https://github.com/ipfs/boxo/pull/797))
+ - Move long messagequeue comment to doc.go (#814) ([ipfs/boxo#814](https://github.com/ipfs/boxo/pull/814))
+ - Describe how bitswap message queue works ([ipfs/boxo#813](https://github.com/ipfs/boxo/pull/813))
+
+
+
+
+### 👨👩👧👦 Contributors
+
+| Contributor | Commits | Lines ± | Files Changed |
+|-------------|---------|---------|---------------|
+| Dreamacro | 1 | +304/-376 | 119 |
+| Andrew Gillis | 7 | +306/-200 | 20 |
+| Guillaume Michel | 5 | +122/-98 | 14 |
+| Marcin Rataj | 2 | +113/-7 | 4 |
+| gammazero | 6 | +41/-11 | 6 |
+| Sergey Gorbunov | 1 | +14/-2 | 2 |
+| Daniel Norman | 1 | +9/-0 | 1 |
+
+## v0.33.2
+
+### 🔦 Highlights
+
+#### 📦️ Important dependency updates
+
+- update `go-libp2p` to [v0.38.3](https://github.com/libp2p/go-libp2p/releases/tag/v0.38.3)
+
+### 📝 Changelog
+
+Full Changelog
+
+- github.com/ipfs/kubo:
+ - chore: v0.33.2
+- github.com/libp2p/go-libp2p (v0.38.2 -> v0.38.3):
+ - Release v0.38.3 (#3184) ([libp2p/go-libp2p#3184](https://github.com/libp2p/go-libp2p/pull/3184))
+
+
+
+### 👨👩👧👦 Contributors
+
+| Contributor | Commits | Lines ± | Files Changed |
+|-------------|---------|---------|---------------|
+| sukun | 1 | +122/-23 | 7 |
+| Marcin Rataj | 1 | +1/-1 | 1 |
diff --git a/docs/changelogs/v0.34.md b/docs/changelogs/v0.34.md
new file mode 100644
index 00000000000..2b4761de1f0
--- /dev/null
+++ b/docs/changelogs/v0.34.md
@@ -0,0 +1,461 @@
+# Kubo changelog v0.34
+
+
+
+This release was brought to you by the [Shipyard](http://ipshipyard.com/) team.
+
+- [v0.34.0](#v0340)
+- [v0.34.1](#v0341)
+
+## v0.34.0
+
+- [Overview](#overview)
+- [🔦 Highlights](#-highlights)
+ - [AutoTLS now enabled by default for nodes with 1 hour uptime](#autotls-now-enabled-by-default-for-nodes-with-1-hour-uptime)
+ - [New WebUI features](#new-webui-features)
+ - [RPC and CLI command changes](#rpc-and-cli-command-changes)
+ - [Bitswap improvements from Boxo](#bitswap-improvements-from-boxo)
+ - [IPNS publishing TTL change](#ipns-publishing-ttl-change)
+ - [`IPFS_LOG_LEVEL` deprecated](#ipfs_log_level-deprecated)
+ - [Pebble datastore format update](#pebble-datastore-format-update)
+ - [Badger datastore update](#badger-datastore-update)
+ - [Datastore Implementation Updates](#datastore-implementation-updates)
+ - [One Multi-error Package](#one-multi-error-package)
+ - [Fix hanging pinset operations during reprovides](#fix-hanging-pinset-operations-during-reprovides)
+ - [📦️ Important dependency updates](#-important-dependency-updates)
+- [📝 Changelog](#-changelog)
+- [👨👩👧👦 Contributors](#-contributors)
+
+### Overview
+
+### 🔦 Highlights
+
+#### AutoTLS now enabled by default for nodes with 1 hour uptime
+
+Starting now, any publicly dialable Kubo node with a `/tcp` listener that remains online for at least one hour will receive a TLS certificate through the [`AutoTLS`](https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls) feature.
+This occurs automatically, with no need for manual setup.
+
+To bypass the 1-hour delay and enable AutoTLS immediately, users can explicitly opt-in by running the following commands:
+
+```console
+$ ipfs config --json AutoTLS.Enabled true
+$ ipfs config --json AutoTLS.RegistrationDelay 0
+```
+
+AutoTLS will remain disabled under the following conditions:
+
+- The node already has a manually configured `/ws` (WebSocket) listener
+- A private network is in use with a `swarm.key`
+- TCP or WebSocket transports are disabled, or there is no `/tcp` listener
+
+To troubleshoot, use `GOLOG_LOG_LEVEL="error,autotls=info`.
+
+For more details, check out the [`AutoTLS` configuration documentation](https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls) or dive deeper with [AutoTLS libp2p blog post](https://blog.libp2p.io/autotls/).
+
+#### New WebUI features
+
+The WebUI, accessible at http://127.0.0.1:5001/webui/, now includes support for CAR file import and QR code sharing directly from the Files view. Additionally, the Peers screen has been updated with the latest [`ipfs-geoip`](https://www.npmjs.com/package/ipfs-geoip) dataset.
+
+#### RPC and CLI command changes
+
+- `ipfs config` is now validating json fields ([#10679](https://github.com/ipfs/kubo/pull/10679)).
+- Deprecated the `bitswap reprovide` command. Make sure to switch to modern `routing reprovide`. ([#10677](https://github.com/ipfs/kubo/pull/10677))
+- The `stats reprovide` command now shows additional stats for [`Routing.AcceleratedDHTClient`](https://github.com/ipfs/kubo/blob/master/docs/config.md#routingaccelerateddhtclient), indicating the last and next `reprovide` times. ([#10677](https://github.com/ipfs/kubo/pull/10677))
+- `ipfs files cp` now performs basic codec check and will error when source is not a valid UnixFS (only `dag-pb` and `raw` codecs are allowed in MFS)
+
+#### Bitswap improvements from Boxo
+
+This release includes performance and reliability improvements and fixes for minor resource leaks. One of the performance changes [greatly improves the bitswap clients ability to operate under high load](https://github.com/ipfs/boxo/pull/817#pullrequestreview-2587207745), that could previously result in an out of memory condition.
+
+#### IPNS publishing TTL change
+
+Many complaints about IPNS being slow are tied to the default `--ttl` in `ipfs name publish`, which was set to 1 hour. To address this, we’ve lowered the default [IPNS Record TTL](https://specs.ipfs.tech/ipns/ipns-record/#ttl-uint64) during publishing to 5 minutes, matching similar TTL defaults in DNS. This update is now part of `boxo/ipfs` (GO, [boxo#859](https://github.com/ipfs/boxo/pull/859)) and `@helia/ipns` (JS, [helia#749](https://github.com/ipfs/helia/pull/749)).
+
+> [!TIP]
+> IPNS TTL recommendations when even faster update propagation is desired:
+> - **As a Publisher:** Lower the `--ttl` (e.g., `ipfs name publish --ttl=1m`) to further reduce caching delays. If using DNSLink, ensure the DNS TXT record TTL matches the IPNS record TTL.
+> - **As a Gateway Operator:** Override publisher TTLs for faster updates using configurations like [`Ipns.MaxCacheTTL`](https://github.com/ipfs/kubo/blob/master/docs/config.md#ipnsmaxcachettl) in Kubo or [`RAINBOW_IPNS_MAX_CACHE_TTL`](https://github.com/ipfs/rainbow/blob/main/docs/environment-variables.md#rainbow_ipns_max_cache_ttl) in [Rainbow](https://github.com/ipfs/rainbow/).
+
+#### `IPFS_LOG_LEVEL` deprecated
+
+The variable has been deprecated. Please use [`GOLOG_LOG_LEVEL`](https://github.com/ipfs/kubo/blob/master/docs/environment-variables.md#golog_log_level) instead for configuring logging levels.
+
+#### Pebble datastore format update
+
+If the pebble database format is not explicitly set in the config, then automatically upgrade it to the latest format version supported by the release ob pebble used by kubo. This will ensure that the database format is sufficiently up-to-date to be compatible with a major version upgrade of pebble. This is necessary before upgrading to use pebble v2.
+
+#### Badger datastore update
+
+An update was made to the badger v1 datastore that avoids use of mmap in 32-bit environments, which has been seen to cause issues on some platforms. Please be aware that this could lead to a performance regression for users of badger in a 32-bit environment. Badger users are advised to move to the flatds or pebble datastore.
+
+#### Datastore Implementation Updates
+
+The go-ds-xxx datastore implementations have been updated to support the updated `go-datastore` [v0.8.2](https://github.com/ipfs/go-datastore/releases/tag/v0.8.2) query API. This update removes the datastore implementations' dependency on `goprocess` and updates the query API.
+
+#### One Multi-error Package
+
+Kubo previously depended on multiple multi-error packages, `github.com/hashicorp/go-multierror` and `go.uber.org/multierr`. These have nearly identical functionality so there was no need to use both. Therefore, `go.uber.org/multierr` was selected as the package to depend on. Any future code needing multi-error functionality should use `go.uber.org/multierr` to avoid introducing unneeded dependencies.
+
+#### Fix hanging pinset operations during reprovides
+
+The reprovide process can be quite slow. In default settings, the reprovide process will start reading CIDs that belong to the pinset. During this operation, starvation can occur for other operations that need pinset access (see https://github.com/ipfs/kubo/issues/10596).
+
+We have now switch to buffering pinset-related cids that are going to be reprovided in memory, so that we can free pinset mutexes as soon as possible so that pinset-writes and subsequent read operations can proceed. The downside is larger pinsets will need some extra memory, with an estimation of ~1GiB of RAM memory-use per 20 million items to be reprovided.
+
+Use [`Reprovider.Strategy`](https://github.com/ipfs/kubo/blob/master/docs/config.md#reproviderstrategy) to balance announcement prioritization, speed, and memory utilization.
+
+#### 📦️ Important dependency updates
+
+- update `go-libp2p` to [v0.41.0](https://github.com/libp2p/go-libp2p/releases/tag/v0.41.0) (incl. [v0.40.0](https://github.com/libp2p/go-libp2p/releases/tag/v0.40.0))
+- update `go-libp2p-kad-dht` to [v0.30.2](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.30.2) (incl. [v0.29.0](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.29.0), [v0.29.1](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.29.1), [v0.29.2](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.29.2), [v0.30.0](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.30.0), [v0.30.1](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.30.1))
+- update `boxo` to [v0.29.1](https://github.com/ipfs/boxo/releases/tag/v0.29.1) (incl. [v0.28.0](https://github.com/ipfs/boxo/releases/tag/v0.28.0) [v0.29.0](https://github.com/ipfs/boxo/releases/tag/v0.29.0))
+- update `ipfs-webui` to [v4.6.0](https://github.com/ipfs/ipfs-webui/releases/tag/v4.6.0) (incl. [v4.5.0](https://github.com/ipfs/ipfs-webui/releases/tag/v4.5.0))
+- update `p2p-forge/client` to [v0.4.0](https://github.com/ipshipyard/p2p-forge/releases/tag/v0.4.0)
+- update `go-datastore` to [v0.8.2](https://github.com/ipfs/go-datastore/releases/tag/v0.8.2) (incl. [v0.7.0](https://github.com/ipfs/go-datastore/releases/tag/v0.7.0), [v0.8.0](https://github.com/ipfs/go-datastore/releases/tag/v0.8.0))
+
+### 📝 Changelog
+
+Full Changelog
+
+- github.com/ipfs/kubo:
+ - chore: v0.34.0
+ - chore: v0.34.0-rc2
+ - docs: mention Reprovider.Strategy config
+ - docs: ipns ttl change
+ - feat: ipfs-webui v4.6 (#10756) ([ipfs/kubo#10756](https://github.com/ipfs/kubo/pull/10756))
+ - docs(readme): update min. requirements + cleanup (#10750) ([ipfs/kubo#10750](https://github.com/ipfs/kubo/pull/10750))
+ - Upgrade to Boxo v0.29.1 (#10755) ([ipfs/kubo#10755](https://github.com/ipfs/kubo/pull/10755))
+ - Nonfunctional (#10753) ([ipfs/kubo#10753](https://github.com/ipfs/kubo/pull/10753))
+ - Update docs/changelogs/v0.34.md
+ - provider: buffer pin providers.
+ - chore: 0.34.0-rc1
+ - fix(mfs): basic UnixFS sanity checks in `files cp` (#10701) ([ipfs/kubo#10701](https://github.com/ipfs/kubo/pull/10701))
+ - Upgrade to Boxo v0.29.0 (#10742) ([ipfs/kubo#10742](https://github.com/ipfs/kubo/pull/10742))
+ - use go-datastore without go-process (#10736) ([ipfs/kubo#10736](https://github.com/ipfs/kubo/pull/10736))
+ - docs(config): add security considerations for rpc (#10739) ([ipfs/kubo#10739](https://github.com/ipfs/kubo/pull/10739))
+ - chore: update go-libp2p to v0.41.0 (#10733) ([ipfs/kubo#10733](https://github.com/ipfs/kubo/pull/10733))
+ - feat: ipfs-webui v4.5.0 (#10735) ([ipfs/kubo#10735](https://github.com/ipfs/kubo/pull/10735))
+ - Create FUNDING.json (#10734) ([ipfs/kubo#10734](https://github.com/ipfs/kubo/pull/10734))
+ - feat(AutoTLS): enabled by default with 1h RegistrationDelay (#10724) ([ipfs/kubo#10724](https://github.com/ipfs/kubo/pull/10724))
+ - Upgrade to Boxo v0.28.0 (#10725) ([ipfs/kubo#10725](https://github.com/ipfs/kubo/pull/10725))
+ - Upgrade to go1.24 (#10726) ([ipfs/kubo#10726](https://github.com/ipfs/kubo/pull/10726))
+ - Replace go-random with random-data from go-test package (#10731) ([ipfs/kubo#10731](https://github.com/ipfs/kubo/pull/10731))
+ - Update to new go-test (#10729) ([ipfs/kubo#10729](https://github.com/ipfs/kubo/pull/10729))
+ - Update go-test and use new random-files generator (#10728) ([ipfs/kubo#10728](https://github.com/ipfs/kubo/pull/10728))
+ - docs(readme): update docker section (#10716) ([ipfs/kubo#10716](https://github.com/ipfs/kubo/pull/10716))
+ - Update go-ds-badger to v0.3.1 (#10722) ([ipfs/kubo#10722](https://github.com/ipfs/kubo/pull/10722))
+ - Update pebble db to latest format by default (#10720) ([ipfs/kubo#10720](https://github.com/ipfs/kubo/pull/10720))
+ - fix: switch away from IPFS_LOG_LEVEL (#10694) ([ipfs/kubo#10694](https://github.com/ipfs/kubo/pull/10694))
+ - Merge release v0.33.2 ([ipfs/kubo#10713](https://github.com/ipfs/kubo/pull/10713))
+ - Remove unused TimeParts struct (#10708) ([ipfs/kubo#10708](https://github.com/ipfs/kubo/pull/10708))
+ - fix(rpc): restore and deprecate `bitswap reprovide` (#10699) ([ipfs/kubo#10699](https://github.com/ipfs/kubo/pull/10699))
+ - docs(release): update RELEASE_CHECKLIST.md after v0.33.1 (#10697) ([ipfs/kubo#10697](https://github.com/ipfs/kubo/pull/10697))
+ - docs: update min requirements (#10687) ([ipfs/kubo#10687](https://github.com/ipfs/kubo/pull/10687))
+ - Merge release v0.33.1 ([ipfs/kubo#10698](https://github.com/ipfs/kubo/pull/10698))
+ - fix: boxo v0.27.4 (#10692) ([ipfs/kubo#10692](https://github.com/ipfs/kubo/pull/10692))
+ - fix: Issue #9364 JSON config validation (#10679) ([ipfs/kubo#10679](https://github.com/ipfs/kubo/pull/10679))
+ - docs: RELEASE_CHECKLIST.md update for 0.33 (#10674) ([ipfs/kubo#10674](https://github.com/ipfs/kubo/pull/10674))
+ - feat: Better self-service commands for DHT providing (#10677) ([ipfs/kubo#10677](https://github.com/ipfs/kubo/pull/10677))
+ - docs: add webrtc-direct fixes to 0.33 release changelog (#10688) ([ipfs/kubo#10688](https://github.com/ipfs/kubo/pull/10688))
+ - fix: config help (#10686) ([ipfs/kubo#10686](https://github.com/ipfs/kubo/pull/10686))
+ - feat: Add CI for Spell Checking (#10637) ([ipfs/kubo#10637](https://github.com/ipfs/kubo/pull/10637))
+ - Merge release v0.33.0 ([ipfs/kubo#10684](https://github.com/ipfs/kubo/pull/10684))
+ - test: fix the socat tests after the ubuntu 24.04 upgrade (#10683) ([ipfs/kubo#10683](https://github.com/ipfs/kubo/pull/10683))
+ - fix: quic-go v0.49.0 (#10673) ([ipfs/kubo#10673](https://github.com/ipfs/kubo/pull/10673))
+ - Upgrade to Boxo v0.27.2 (#10672) ([ipfs/kubo#10672](https://github.com/ipfs/kubo/pull/10672))
+ - Upgrade to Boxo v0.27.1 (#10671) ([ipfs/kubo#10671](https://github.com/ipfs/kubo/pull/10671))
+ - fix(autotls): renewal and AutoTLS.ShortAddrs (#10669) ([ipfs/kubo#10669](https://github.com/ipfs/kubo/pull/10669))
+ - update changelog for boxo and go-libp2p (#10668) ([ipfs/kubo#10668](https://github.com/ipfs/kubo/pull/10668))
+ - Upgrade to Boxo v0.27.0 (#10665) ([ipfs/kubo#10665](https://github.com/ipfs/kubo/pull/10665))
+ - update dependencies (#10664) ([ipfs/kubo#10664](https://github.com/ipfs/kubo/pull/10664))
+ - docs(readme): add unofficial Fedora COPR (#10660) ([ipfs/kubo#10660](https://github.com/ipfs/kubo/pull/10660))
+ - fix(dns): update default DNSLink resolvers (#10655) ([ipfs/kubo#10655](https://github.com/ipfs/kubo/pull/10655))
+ - chore: p2p-forge v0.2.2 + go-libp2p-kad-dht v0.28.2 (#10663) ([ipfs/kubo#10663](https://github.com/ipfs/kubo/pull/10663))
+ - fix(cli): support HTTPS in ipfs --api (#10659) ([ipfs/kubo#10659](https://github.com/ipfs/kubo/pull/10659))
+ - chore: fix typos and comment formatting (#10653) ([ipfs/kubo#10653](https://github.com/ipfs/kubo/pull/10653))
+ - fix/gateway: escape directory redirect url (#10649) ([ipfs/kubo#10649](https://github.com/ipfs/kubo/pull/10649))
+ - Add example of setting array to config command help ([ipfs/kubo#10650](https://github.com/ipfs/kubo/pull/10650))
+ - collection of typo fixes (#10647) ([ipfs/kubo#10647](https://github.com/ipfs/kubo/pull/10647))
+ - chore: bump master to 0.34.0-dev
+- github.com/ipfs/boxo (v0.27.4 -> v0.29.1):
+ - Release v0.29.1 ([ipfs/boxo#885](https://github.com/ipfs/boxo/pull/885))
+ - fix(provider): call reprovider throughput callback only if reprovide is enabled (#871) ([ipfs/boxo#871](https://github.com/ipfs/boxo/pull/871))
+ - bitswap/httpnet: do not follow redirects (#878) ([ipfs/boxo#878](https://github.com/ipfs/boxo/pull/878))
+ - Refactor(hostname): Skip DNSLink for local IP addresses to avoid DNS queries (#880) ([ipfs/boxo#880](https://github.com/ipfs/boxo/pull/880))
+ - Nonfunctional (#882) ([ipfs/boxo#882](https://github.com/ipfs/boxo/pull/882))
+ - fix(bitswap/client): dont set nil for DontHaveTimeoutConfig (#872) ([ipfs/boxo#872](https://github.com/ipfs/boxo/pull/872))
+ - provider: add a buffered KeyChanFunc. ([ipfs/boxo#870](https://github.com/ipfs/boxo/pull/870))
+ - Release v0.29.0 (#869) ([ipfs/boxo#869](https://github.com/ipfs/boxo/pull/869))
+ - Do not use multiple multi-error packages, pick one (#867) ([ipfs/boxo#867](https://github.com/ipfs/boxo/pull/867))
+ - feat(bitswap/client): MinTimeout for DontHaveTimeoutConfig (#865) ([ipfs/boxo#865](https://github.com/ipfs/boxo/pull/865))
+ - use go-datastore without go-process (#858) ([ipfs/boxo#858](https://github.com/ipfs/boxo/pull/858))
+ - minimize peermanager lock scope (#860) ([ipfs/boxo#860](https://github.com/ipfs/boxo/pull/860))
+ - chore(ipns): lower `DefaultRecordTTL` to 5m (#859) ([ipfs/boxo#859](https://github.com/ipfs/boxo/pull/859))
+ - httpnet: bitswap network for HTTP block retrieval over trustless gateway endpoints. ([ipfs/boxo#747](https://github.com/ipfs/boxo/pull/747))
+ - chore: Update FUNDING.json for Optimism RPF (#857) ([ipfs/boxo#857](https://github.com/ipfs/boxo/pull/857))
+ - Release v0.28.0 (#854) ([ipfs/boxo#854](https://github.com/ipfs/boxo/pull/854))
+ - Update deps (#852) ([ipfs/boxo#852](https://github.com/ipfs/boxo/pull/852))
+ - fix: gateway/blocks-backend: GetBlock should not perform IPLD decoding (#845) ([ipfs/boxo#845](https://github.com/ipfs/boxo/pull/845))
+ - Protobuf pkg name (#850) ([ipfs/boxo#850](https://github.com/ipfs/boxo/pull/850))
+ - Fix intermittent test failure (#849) ([ipfs/boxo#849](https://github.com/ipfs/boxo/pull/849))
+ - move `ipld/merkledag` from gogo protobuf (#841) ([ipfs/boxo#841](https://github.com/ipfs/boxo/pull/841))
+ - move `ipld/unixfs` from gogo protobuf (#840) ([ipfs/boxo#840](https://github.com/ipfs/boxo/pull/840))
+ - Start moving from gogo protobuf (#839) ([ipfs/boxo#839](https://github.com/ipfs/boxo/pull/839))
+ - ci: uci/update-go (#848) ([ipfs/boxo#848](https://github.com/ipfs/boxo/pull/848))
+ - expose DontHaveTimeoutConfig (#846) ([ipfs/boxo#846](https://github.com/ipfs/boxo/pull/846))
+ - Upgrade go-libp2p to v0.39.1 (#843) ([ipfs/boxo#843](https://github.com/ipfs/boxo/pull/843))
+ - feat: Prevent multiple instances of "ipfs routing reprovide" running together. (#834) ([ipfs/boxo#834](https://github.com/ipfs/boxo/pull/834))
+ - Upgrade to go-libp2p v0.39.0 (#837) ([ipfs/boxo#837](https://github.com/ipfs/boxo/pull/837))
+ - bitswap/client/internal/messagequeue: run tests in parallel (#835) ([ipfs/boxo#835](https://github.com/ipfs/boxo/pull/835))
+- github.com/ipfs/go-cid (v0.4.1 -> v0.5.0):
+ - v0.5.0 bump (#172) ([ipfs/go-cid#172](https://github.com/ipfs/go-cid/pull/172))
+ - move _rsrch/cidiface into an internal package
+- github.com/ipfs/go-datastore (v0.6.0 -> v0.8.2):
+ - bump version (#231) ([ipfs/go-datastore#231](https://github.com/ipfs/go-datastore/pull/231))
+ - Results.Close should return error (#230) ([ipfs/go-datastore#230](https://github.com/ipfs/go-datastore/pull/230))
+ - new version (#229) ([ipfs/go-datastore#229](https://github.com/ipfs/go-datastore/pull/229))
+ - Update fuzz module dependencies (#228) ([ipfs/go-datastore#228](https://github.com/ipfs/go-datastore/pull/228))
+ - new version (#225) ([ipfs/go-datastore#225](https://github.com/ipfs/go-datastore/pull/225))
+ - No goprocess (#223) ([ipfs/go-datastore#223](https://github.com/ipfs/go-datastore/pull/223))
+ - Release version 0.7.0 (#213) ([ipfs/go-datastore#213](https://github.com/ipfs/go-datastore/pull/213))
+ - query result ordering does not create additional goroutine (#221) ([ipfs/go-datastore#221](https://github.com/ipfs/go-datastore/pull/221))
+ - Remove unneeded dependencies (#220) ([ipfs/go-datastore#220](https://github.com/ipfs/go-datastore/pull/220))
+ - Add traced datastore (#209) ([ipfs/go-datastore#209](https://github.com/ipfs/go-datastore/pull/209))
+ - Add root namespace method to Key (#208) ([ipfs/go-datastore#208](https://github.com/ipfs/go-datastore/pull/208))
+ - ci: uci/copy-templates (#207) ([ipfs/go-datastore#207](https://github.com/ipfs/go-datastore/pull/207))
+ - test: fix fuzz commands
+ - fix fuzz tests by adding the missing context.Context argument (#198) ([ipfs/go-datastore#198](https://github.com/ipfs/go-datastore/pull/198))
+ - sync: update CI config files (#195) ([ipfs/go-datastore#195](https://github.com/ipfs/go-datastore/pull/195))
+- github.com/ipfs/go-ds-badger (v0.3.0 -> v0.3.4):
+ - new version (#137) ([ipfs/go-ds-badger#137](https://github.com/ipfs/go-ds-badger/pull/137))
+ - new version (#135) ([ipfs/go-ds-badger#135](https://github.com/ipfs/go-ds-badger/pull/135))
+ - new version (#132) ([ipfs/go-ds-badger#132](https://github.com/ipfs/go-ds-badger/pull/132))
+ - Update to use go-datastore without go-process (#131) ([ipfs/go-ds-badger#131](https://github.com/ipfs/go-ds-badger/pull/131))
+ - new version ([ipfs/go-ds-badger#128](https://github.com/ipfs/go-ds-badger/pull/128))
+ - Update dependencies and minimum go version ([ipfs/go-ds-badger#127](https://github.com/ipfs/go-ds-badger/pull/127))
+ - ci: uci/update-go ([ipfs/go-ds-badger#123](https://github.com/ipfs/go-ds-badger/pull/123))
+ - ci: uci/copy-templates ([ipfs/go-ds-badger#122](https://github.com/ipfs/go-ds-badger/pull/122))
+ - chore: check PersistentDatastore conformance at build time (#120) ([ipfs/go-ds-badger#120](https://github.com/ipfs/go-ds-badger/pull/120))
+- github.com/ipfs/go-ds-flatfs (v0.5.1 -> v0.5.5):
+ - bump version (#130) ([ipfs/go-ds-flatfs#130](https://github.com/ipfs/go-ds-flatfs/pull/130))
+ - new version (#128) ([ipfs/go-ds-flatfs#128](https://github.com/ipfs/go-ds-flatfs/pull/128))
+ - new version (#126) ([ipfs/go-ds-flatfs#126](https://github.com/ipfs/go-ds-flatfs/pull/126))
+ - Fix race condition due to concurrent use of rand source (#125) ([ipfs/go-ds-flatfs#125](https://github.com/ipfs/go-ds-flatfs/pull/125))
+ - new version ([ipfs/go-ds-flatfs#124](https://github.com/ipfs/go-ds-flatfs/pull/124))
+ - Use go-datastore without go-process ([ipfs/go-ds-flatfs#123](https://github.com/ipfs/go-ds-flatfs/pull/123))
+ - ci: uci/update-go (#122) ([ipfs/go-ds-flatfs#122](https://github.com/ipfs/go-ds-flatfs/pull/122))
+ - fix: actually use the size hint in util_windows.go
+ - perf: do not use virtual call when passing os.Rename as rename
+ - chore(logging): update go-log v2 (#117) ([ipfs/go-ds-flatfs#117](https://github.com/ipfs/go-ds-flatfs/pull/117))
+ - ci: uci/copy-templates ([ipfs/go-ds-flatfs#116](https://github.com/ipfs/go-ds-flatfs/pull/116))
+ - sync: update CI config files ([ipfs/go-ds-flatfs#111](https://github.com/ipfs/go-ds-flatfs/pull/111))
+ - possibly fix a bug in renameAndUpdateDiskUsage
+ - add documentation and comment
+ - perf: avoid syncing directories when they already existed (#107) ([ipfs/go-ds-flatfs#107](https://github.com/ipfs/go-ds-flatfs/pull/107))
+ - test: faster TestNoCluster by batching the 3200 Puts ([ipfs/go-ds-flatfs#108](https://github.com/ipfs/go-ds-flatfs/pull/108))
+ - query: also teard down on ctx done (#106) ([ipfs/go-ds-flatfs#106](https://github.com/ipfs/go-ds-flatfs/pull/106))
+- github.com/ipfs/go-ds-leveldb (v0.5.0 -> v0.5.2):
+ - new version (#75) ([ipfs/go-ds-leveldb#75](https://github.com/ipfs/go-ds-leveldb/pull/75))
+ - Results close needs to return error (#74) ([ipfs/go-ds-leveldb#74](https://github.com/ipfs/go-ds-leveldb/pull/74))
+ - new version ([ipfs/go-ds-leveldb#73](https://github.com/ipfs/go-ds-leveldb/pull/73))
+ - use go-datastore without go-process ([ipfs/go-ds-leveldb#72](https://github.com/ipfs/go-ds-leveldb/pull/72))
+ - sync: update CI config files (#62) ([ipfs/go-ds-leveldb#62](https://github.com/ipfs/go-ds-leveldb/pull/62))
+ - chore: add PersistentDatastore and Batching interface checks
+- github.com/ipfs/go-ds-measure (v0.2.0 -> v0.2.2):
+ - new version ([ipfs/go-ds-measure#54](https://github.com/ipfs/go-ds-measure/pull/54))
+ - new version ([ipfs/go-ds-measure#52](https://github.com/ipfs/go-ds-measure/pull/52))
+- github.com/ipfs/go-ds-pebble (v0.4.2 -> v0.4.4):
+ - new version (#51) ([ipfs/go-ds-pebble#51](https://github.com/ipfs/go-ds-pebble/pull/51))
+ - new version (#48) ([ipfs/go-ds-pebble#48](https://github.com/ipfs/go-ds-pebble/pull/48))
+ - Use go-datastore without go-process (#47) ([ipfs/go-ds-pebble#47](https://github.com/ipfs/go-ds-pebble/pull/47))
+- github.com/ipfs/go-metrics-interface (v0.0.1 -> v0.3.0):
+ - CounterVec: even more ergonomic ([ipfs/go-metrics-interface#22](https://github.com/ipfs/go-metrics-interface/pull/22))
+ - Improve CounterVec abstraction ([ipfs/go-metrics-interface#21](https://github.com/ipfs/go-metrics-interface/pull/21))
+ - v0.1.0 ([ipfs/go-metrics-interface#20](https://github.com/ipfs/go-metrics-interface/pull/20))
+ - Feat: Add CounterVec type. ([ipfs/go-metrics-interface#19](https://github.com/ipfs/go-metrics-interface/pull/19))
+ - sync: update CI config files (#10) ([ipfs/go-metrics-interface#10](https://github.com/ipfs/go-metrics-interface/pull/10))
+ - sync: update CI config files (#8) ([ipfs/go-metrics-interface#8](https://github.com/ipfs/go-metrics-interface/pull/8))
+ - use a struct as a key for the context ([ipfs/go-metrics-interface#4](https://github.com/ipfs/go-metrics-interface/pull/4))
+- github.com/ipfs/go-metrics-prometheus (v0.0.3 -> v0.1.0):
+ - Implement the CounterVec type. ([ipfs/go-metrics-prometheus#26](https://github.com/ipfs/go-metrics-prometheus/pull/26))
+- github.com/ipfs/go-test (v0.0.4 -> v0.2.1):
+ - new version (#20) ([ipfs/go-test#20](https://github.com/ipfs/go-test/pull/20))
+ - No newline at end of random raw data (#19) ([ipfs/go-test#19](https://github.com/ipfs/go-test/pull/19))
+ - new-version (#18) ([ipfs/go-test#18](https://github.com/ipfs/go-test/pull/18))
+ - new version (#15) ([ipfs/go-test#15](https://github.com/ipfs/go-test/pull/15))
+ - refactor: Make go-multiaddr v0.15 forward compatible change (#16) ([ipfs/go-test#16](https://github.com/ipfs/go-test/pull/16))
+ - Move cli apps (#17) ([ipfs/go-test#17](https://github.com/ipfs/go-test/pull/17))
+ - Update help text (#14) ([ipfs/go-test#14](https://github.com/ipfs/go-test/pull/14))
+ - Add package to generate random filesystem hierarchies for testing (#13) ([ipfs/go-test#13](https://github.com/ipfs/go-test/pull/13))
+- github.com/ipfs/go-unixfsnode (v1.9.2 -> v1.10.0):
+ - new version ([ipfs/go-unixfsnode#81](https://github.com/ipfs/go-unixfsnode/pull/81))
+ - upgrade to boxo v0.27.4 ([ipfs/go-unixfsnode#80](https://github.com/ipfs/go-unixfsnode/pull/80))
+- github.com/libp2p/go-libp2p (v0.38.3 -> v0.41.0):
+ - Release v0.41.0 (#3210) ([libp2p/go-libp2p#3210](https://github.com/libp2p/go-libp2p/pull/3210))
+ - fix(libp2phttp): Fix relative to absolute multiaddr URI logic (#3208) ([libp2p/go-libp2p#3208](https://github.com/libp2p/go-libp2p/pull/3208))
+ - fix(dcutr): Fix end to end tests and add legacy behavior flag (default=true) (#3044) ([libp2p/go-libp2p#3044](https://github.com/libp2p/go-libp2p/pull/3044))
+ - feat(libp2phttp): More ergonomic auth (#3188) ([libp2p/go-libp2p#3188](https://github.com/libp2p/go-libp2p/pull/3188))
+ - chore(identify): move log to debug level (#3206) ([libp2p/go-libp2p#3206](https://github.com/libp2p/go-libp2p/pull/3206))
+ - chore: Update go-multiaddr to v0.15 (#3145) ([libp2p/go-libp2p#3145](https://github.com/libp2p/go-libp2p/pull/3145))
+ - chore: update quic-go to v0.50.0 (#3204) ([libp2p/go-libp2p#3204](https://github.com/libp2p/go-libp2p/pull/3204))
+ - chore: move go-nat to internal package
+ - basichost: add certhashes to addrs in place (#3200) ([libp2p/go-libp2p#3200](https://github.com/libp2p/go-libp2p/pull/3200))
+ - autorelay: send addresses on eventbus; dont wrap address factory (#3071) ([libp2p/go-libp2p#3071](https://github.com/libp2p/go-libp2p/pull/3071))
+ - chore: update ci for go1.24 (#3195) ([libp2p/go-libp2p#3195](https://github.com/libp2p/go-libp2p/pull/3195))
+ - Release v0.40.0 (#3192) ([libp2p/go-libp2p#3192](https://github.com/libp2p/go-libp2p/pull/3192))
+ - chore: bump deps for v0.40.0 (#3191) ([libp2p/go-libp2p#3191](https://github.com/libp2p/go-libp2p/pull/3191))
+ - autonatv2: allow multiple concurrent requests per peer (#3187) ([libp2p/go-libp2p#3187](https://github.com/libp2p/go-libp2p/pull/3187))
+ - feat: add AutoTLS example (#3103) ([libp2p/go-libp2p#3103](https://github.com/libp2p/go-libp2p/pull/3103))
+ - feat(swarm): logging waitForDirectConn return error (#3183) ([libp2p/go-libp2p#3183](https://github.com/libp2p/go-libp2p/pull/3183))
+ - tcpreuse: fix Scope() for *tls.Conn (#3181) ([libp2p/go-libp2p#3181](https://github.com/libp2p/go-libp2p/pull/3181))
+ - test(p2p/protocol/identify): fix user agent assertion in Go 1.24 (#3177) ([libp2p/go-libp2p#3177](https://github.com/libp2p/go-libp2p/pull/3177))
+ - swarm: remove unnecessary error log (#3128) ([libp2p/go-libp2p#3128](https://github.com/libp2p/go-libp2p/pull/3128))
+ - Implement error codes spec (#2927) ([libp2p/go-libp2p#2927](https://github.com/libp2p/go-libp2p/pull/2927))
+ - chore: update pion/ice to v4 (#3175) ([libp2p/go-libp2p#3175](https://github.com/libp2p/go-libp2p/pull/3175))
+ - chore: release v0.39.0 (#3174) ([libp2p/go-libp2p#3174](https://github.com/libp2p/go-libp2p/pull/3174))
+ - feat(holepunch): add logging when DirectConnect execution fails (#3146) ([libp2p/go-libp2p#3146](https://github.com/libp2p/go-libp2p/pull/3146))
+ - feat: Implement Custom TCP Dialers (#3166) ([libp2p/go-libp2p#3166](https://github.com/libp2p/go-libp2p/pull/3166))
+ - Update quic-go to v0.49.0 (#3153) ([libp2p/go-libp2p#3153](https://github.com/libp2p/go-libp2p/pull/3153))
+ - feat(transport/websocket): support SOCKS proxy with ws(s) (#3137) ([libp2p/go-libp2p#3137](https://github.com/libp2p/go-libp2p/pull/3137))
+ - tcpreuse: fix rcmgr accounting when tcp metrics are enabled (#3142) ([libp2p/go-libp2p#3142](https://github.com/libp2p/go-libp2p/pull/3142))
+ - fix(net/nat): data race problem of `extAddr` (#3140) ([libp2p/go-libp2p#3140](https://github.com/libp2p/go-libp2p/pull/3140))
+ - test: fix failing test (#3141) ([libp2p/go-libp2p#3141](https://github.com/libp2p/go-libp2p/pull/3141))
+ - quicreuse: make it possible to use an application-constructed quic.Transport (#3122) ([libp2p/go-libp2p#3122](https://github.com/libp2p/go-libp2p/pull/3122))
+ - nat: ignore mapping if external port is 0 (#3094) ([libp2p/go-libp2p#3094](https://github.com/libp2p/go-libp2p/pull/3094))
+ - tcpreuse: error on using tcpreuse with pnet (#3129) ([libp2p/go-libp2p#3129](https://github.com/libp2p/go-libp2p/pull/3129))
+ - chore: Update contribution guidelines (#3134) ([libp2p/go-libp2p#3134](https://github.com/libp2p/go-libp2p/pull/3134))
+ - tcp: fix metrics test build directive (#3052) ([libp2p/go-libp2p#3052](https://github.com/libp2p/go-libp2p/pull/3052))
+ - webrtc: upgrade pion/webrtc to v4 (#3098) ([libp2p/go-libp2p#3098](https://github.com/libp2p/go-libp2p/pull/3098))
+ - webtransport: fix docstring comment for getCurrentBucketStartTime
+ - chore: release v0.38.1 (#3114) ([libp2p/go-libp2p#3114](https://github.com/libp2p/go-libp2p/pull/3114))
+- github.com/libp2p/go-libp2p-kad-dht (v0.28.2 -> v0.30.2):
+ - new version (#1059) ([libp2p/go-libp2p-kad-dht#1059](https://github.com/libp2p/go-libp2p-kad-dht/pull/1059))
+ - do not use multiple multi-error packages, pick one (#1058) ([libp2p/go-libp2p-kad-dht#1058](https://github.com/libp2p/go-libp2p-kad-dht/pull/1058))
+ - update version (#1057) ([libp2p/go-libp2p-kad-dht#1057](https://github.com/libp2p/go-libp2p-kad-dht/pull/1057))
+ - chore: release v0.30.0 (#1054) ([libp2p/go-libp2p-kad-dht#1054](https://github.com/libp2p/go-libp2p-kad-dht/pull/1054))
+ - fix: crawler polluting peerstore (#1053) ([libp2p/go-libp2p-kad-dht#1053](https://github.com/libp2p/go-libp2p-kad-dht/pull/1053))
+ - new version (#1052) ([libp2p/go-libp2p-kad-dht#1052](https://github.com/libp2p/go-libp2p-kad-dht/pull/1052))
+ - use go-datastore without go-process (#1051) ([libp2p/go-libp2p-kad-dht#1051](https://github.com/libp2p/go-libp2p-kad-dht/pull/1051))
+ - feat: use OTEL for metrics (removes opencensus) (#1045) ([libp2p/go-libp2p-kad-dht#1045](https://github.com/libp2p/go-libp2p-kad-dht/pull/1045))
+ - release v0.29.1 (#1042) ([libp2p/go-libp2p-kad-dht#1042](https://github.com/libp2p/go-libp2p-kad-dht/pull/1042))
+ - fix: flaky TestInvalidServer (#1049) ([libp2p/go-libp2p-kad-dht#1049](https://github.com/libp2p/go-libp2p-kad-dht/pull/1049))
+ - chore: update deps (#1048) ([libp2p/go-libp2p-kad-dht#1048](https://github.com/libp2p/go-libp2p-kad-dht/pull/1048))
+ - fix addrsSoFar comparison (#1046) ([libp2p/go-libp2p-kad-dht#1046](https://github.com/libp2p/go-libp2p-kad-dht/pull/1046))
+ - fix: flaky TestInvalidServer (#1043) ([libp2p/go-libp2p-kad-dht#1043](https://github.com/libp2p/go-libp2p-kad-dht/pull/1043))
+ - add verbose to TestFindProviderAsync (dual) (#1040) ([libp2p/go-libp2p-kad-dht#1040](https://github.com/libp2p/go-libp2p-kad-dht/pull/1040))
+ - test: cover dns addresses in TestAddrFilter (#1041) ([libp2p/go-libp2p-kad-dht#1041](https://github.com/libp2p/go-libp2p-kad-dht/pull/1041))
+ - fix: flaky TestSearchValue (dual) (#1038) ([libp2p/go-libp2p-kad-dht#1038](https://github.com/libp2p/go-libp2p-kad-dht/pull/1038))
+ - fix: flaky TestClientModeConnect (#1037) ([libp2p/go-libp2p-kad-dht#1037](https://github.com/libp2p/go-libp2p-kad-dht/pull/1037))
+ - fix: flaky TestFindPeerQueryMinimal (#1036) ([libp2p/go-libp2p-kad-dht#1036](https://github.com/libp2p/go-libp2p-kad-dht/pull/1036))
+ - fix: flaky TestInvalidServer (#1032) ([libp2p/go-libp2p-kad-dht#1032](https://github.com/libp2p/go-libp2p-kad-dht/pull/1032))
+ - fix: flaky TestFindPeerWithQueryFilter (#1034) ([libp2p/go-libp2p-kad-dht#1034](https://github.com/libp2p/go-libp2p-kad-dht/pull/1034))
+ - fix: Flaky TestInvalidServer (#1029) ([libp2p/go-libp2p-kad-dht#1029](https://github.com/libp2p/go-libp2p-kad-dht/pull/1029))
+ - fix: flaky TestClientModeConnect (#1028) ([libp2p/go-libp2p-kad-dht#1028](https://github.com/libp2p/go-libp2p-kad-dht/pull/1028))
+ - fix: increase timeout in TestProvidesMany (#1027) ([libp2p/go-libp2p-kad-dht#1027](https://github.com/libp2p/go-libp2p-kad-dht/pull/1027))
+ - fix(tests): cleanup of skipped tests (#1025) ([libp2p/go-libp2p-kad-dht#1025](https://github.com/libp2p/go-libp2p-kad-dht/pull/1025))
+ - fix: don't skip TestProvidesExpire (#1024) ([libp2p/go-libp2p-kad-dht#1024](https://github.com/libp2p/go-libp2p-kad-dht/pull/1024))
+ - fixing flaky TestFindPeerQueryMinimal (#1020) ([libp2p/go-libp2p-kad-dht#1020](https://github.com/libp2p/go-libp2p-kad-dht/pull/1020))
+ - fix flaky TestSkipRefreshOnGapCpls (#1021) ([libp2p/go-libp2p-kad-dht#1021](https://github.com/libp2p/go-libp2p-kad-dht/pull/1021))
+ - fix: don't skip TestContextShutDown (#1022) ([libp2p/go-libp2p-kad-dht#1022](https://github.com/libp2p/go-libp2p-kad-dht/pull/1022))
+ - comments formatting and typos (#1019) ([libp2p/go-libp2p-kad-dht#1019](https://github.com/libp2p/go-libp2p-kad-dht/pull/1019))
+ - log peers rejected for diversity (#759) ([libp2p/go-libp2p-kad-dht#759](https://github.com/libp2p/go-libp2p-kad-dht/pull/759))
+ - docs: update fullrt docs (#768) ([libp2p/go-libp2p-kad-dht#768](https://github.com/libp2p/go-libp2p-kad-dht/pull/768))
+ - query cleanup (#1017) ([libp2p/go-libp2p-kad-dht#1017](https://github.com/libp2p/go-libp2p-kad-dht/pull/1017))
+ - better variable names (#787) ([libp2p/go-libp2p-kad-dht#787](https://github.com/libp2p/go-libp2p-kad-dht/pull/787))
+ - release v0.29.0 (#1014) ([libp2p/go-libp2p-kad-dht#1014](https://github.com/libp2p/go-libp2p-kad-dht/pull/1014))
+ - Move from gogo protobuf (#975) ([libp2p/go-libp2p-kad-dht#975](https://github.com/libp2p/go-libp2p-kad-dht/pull/975))
+ - fix: don't copy message to OnRequestHook ([libp2p/go-libp2p-kad-dht#1012](https://github.com/libp2p/go-libp2p-kad-dht/pull/1012))
+ - chore: remove boxo/util deps ([libp2p/go-libp2p-kad-dht#1013](https://github.com/libp2p/go-libp2p-kad-dht/pull/1013))
+ - feat: add request callback config option ([libp2p/go-libp2p-kad-dht#1011](https://github.com/libp2p/go-libp2p-kad-dht/pull/1011))
+- github.com/libp2p/go-libp2p-kbucket (v0.6.4 -> v0.6.5):
+ - upgrading deps (#137) ([libp2p/go-libp2p-kbucket#137](https://github.com/libp2p/go-libp2p-kbucket/pull/137))
+- github.com/libp2p/go-libp2p-pubsub (v0.12.0 -> v0.13.0):
+ - Release v0.13.0 (#593) ([libp2p/go-libp2p-pubsub#593](https://github.com/libp2p/go-libp2p-pubsub/pull/593))
+ - Allow cancelling IWANT using IDONTWANT (#591) ([libp2p/go-libp2p-pubsub#591](https://github.com/libp2p/go-libp2p-pubsub/pull/591))
+ - Improve IDONTWANT Flood Protection (#590) ([libp2p/go-libp2p-pubsub#590](https://github.com/libp2p/go-libp2p-pubsub/pull/590))
+ - Fix the Router's Ability to Prune the Mesh Periodically (#589) ([libp2p/go-libp2p-pubsub#589](https://github.com/libp2p/go-libp2p-pubsub/pull/589))
+ - Add Function to Enable Application Layer to Send Direct Control Messages (#562) ([libp2p/go-libp2p-pubsub#562](https://github.com/libp2p/go-libp2p-pubsub/pull/562))
+ - Do not format expensive debug messages in non-debug levels in doDropRPC (#580) ([libp2p/go-libp2p-pubsub#580](https://github.com/libp2p/go-libp2p-pubsub/pull/580))
+- github.com/libp2p/go-libp2p-record (v0.2.0 -> v0.3.1):
+ - fix: missing protobuf package (#64) ([libp2p/go-libp2p-record#64](https://github.com/libp2p/go-libp2p-record/pull/64))
+ - release: v0.3.0 (#63) ([libp2p/go-libp2p-record#63](https://github.com/libp2p/go-libp2p-record/pull/63))
+ - fix: protobuf namespace conflicts (#62) ([libp2p/go-libp2p-record#62](https://github.com/libp2p/go-libp2p-record/pull/62))
+ - Remove gogo protobuf (#60) ([libp2p/go-libp2p-record#60](https://github.com/libp2p/go-libp2p-record/pull/60))
+- github.com/libp2p/go-libp2p-routing-helpers (v0.7.4 -> v0.7.5):
+ - new version ([libp2p/go-libp2p-routing-helpers#90](https://github.com/libp2p/go-libp2p-routing-helpers/pull/90))
+ - Consolidate multi-error packages by choosing one ([libp2p/go-libp2p-routing-helpers#88](https://github.com/libp2p/go-libp2p-routing-helpers/pull/88))
+ - update dependencies ([libp2p/go-libp2p-routing-helpers#89](https://github.com/libp2p/go-libp2p-routing-helpers/pull/89))
+- github.com/multiformats/go-multiaddr (v0.14.0 -> v0.15.0):
+ - chore: release v0.15.0 (#266) ([multiformats/go-multiaddr#266](https://github.com/multiformats/go-multiaddr/pull/266))
+ - refactor: Backwards compatible Encapsulate/Decapsulate/Join/NewComponent (#272) ([multiformats/go-multiaddr#272](https://github.com/multiformats/go-multiaddr/pull/272))
+ - refactor: keep same api as v0.14.0 for SplitFirst/SplitLast (#271) ([multiformats/go-multiaddr#271](https://github.com/multiformats/go-multiaddr/pull/271))
+ - refactor: Follows up on #261 (#264) ([multiformats/go-multiaddr#264](https://github.com/multiformats/go-multiaddr/pull/264))
+ - refactor!: make the API harder to misuse (#261) ([multiformats/go-multiaddr#261](https://github.com/multiformats/go-multiaddr/pull/261))
+
+
+
+### 👨👩👧👦 Contributors
+
+| Contributor | Commits | Lines ± | Files Changed |
+|-------------|---------|---------|---------------|
+| Hector Sanjuan | 100 | +4777/-1495 | 200 |
+| Marco Munizaga | 22 | +3482/-1632 | 122 |
+| Andrew Gillis | 69 | +1628/-1509 | 191 |
+| sukun | 13 | +1240/-288 | 67 |
+| Simon Menke | 7 | +766/-97 | 16 |
+| Guillaume Michel | 33 | +438/-383 | 62 |
+| Marcin Rataj | 24 | +494/-266 | 47 |
+| Sergey Gorbunov | 4 | +384/-103 | 20 |
+| AvyChanna | 1 | +294/-193 | 9 |
+| gammazero | 22 | +208/-217 | 28 |
+| Dennis Trautwein | 3 | +425/-0 | 8 |
+| web3-bot | 18 | +193/-184 | 46 |
+| Steven Allen | 8 | +204/-82 | 13 |
+| Marten Seemann | 5 | +215/-63 | 11 |
+| Daniel Norman | 2 | +225/-0 | 6 |
+| Abhinav Prakash | 1 | +190/-2 | 4 |
+| guillaumemichel | 3 | +93/-56 | 15 |
+| youyyytrok | 1 | +84/-63 | 29 |
+| Nishant Das | 2 | +111/-1 | 4 |
+| Pop Chunhapanya | 1 | +109/-0 | 2 |
+| Michael Muré | 7 | +78/-29 | 15 |
+| Jorropo | 4 | +53/-20 | 7 |
+| Ryan Skidmore | 1 | +62/-0 | 2 |
+| GITSRC | 1 | +44/-0 | 3 |
+| Russell Dempsey | 1 | +22/-17 | 10 |
+| Adin Schmahmann | 2 | +29/-8 | 3 |
+| Gabriel Cruz | 1 | +13/-13 | 1 |
+| Wlynxg | 3 | +12/-9 | 3 |
+| Khaled Yakdan | 1 | +11/-10 | 1 |
+| Yahya Hassanzadeh, Ph.D. | 1 | +17/-0 | 1 |
+| Can ZHANG | 2 | +15/-2 | 3 |
+| Pavel Zbitskiy | 1 | +13/-1 | 2 |
+| Yuttakhan B. | 1 | +6/-6 | 6 |
+| Hlib Kanunnikov | 2 | +9/-2 | 4 |
+| Petar Maymounkov | 1 | +7/-2 | 1 |
+| Prithvi Shahi | 2 | +8/-0 | 2 |
+| Piotr Galar | 1 | +4/-4 | 2 |
+| Michael Vorburger | 1 | +6/-0 | 1 |
+| Gus Eggert | 2 | +6/-0 | 2 |
+| Raúl Kripalani | 1 | +4/-0 | 1 |
+| linchizhen | 1 | +1/-1 | 1 |
+| achingbrain | 1 | +1/-1 | 1 |
+| Rod Vagg | 1 | +1/-1 | 1 |
+| Ian Davis | 1 | +1/-1 | 1 |
+| Fabio Bozzo | 1 | +1/-1 | 1 |
+
+## v0.34.1
+
+- [Overview](#overview)
+- [🔦 Highlights](#-highlights)
+ - [📦️ Important dependency updates](#-important-dependency-updates)
+
+### Overview
+
+### 🔦 Highlights
+
+#### 📦️ Important dependency updates
+
+- update `go-libp2p` to [v0.41.1](https://github.com/libp2p/go-libp2p/releases/tag/v0.41.1)
+ - high impact fix from [go-libp2p#3221](https://github.com/libp2p/go-libp2p/pull/3221) improves [hole punching](https://github.com/libp2p/specs/blob/master/relay/DCUtR.md) success rate
+- update `quic-go` to [v0.50.1](https://github.com/quic-go/quic-go/releases/tag/v0.50.1)
diff --git a/docs/changelogs/v0.35.md b/docs/changelogs/v0.35.md
new file mode 100644
index 00000000000..1f955182cac
--- /dev/null
+++ b/docs/changelogs/v0.35.md
@@ -0,0 +1,413 @@
+# Kubo changelog v0.35
+
+
+
+This release was brought to you by the [Shipyard](http://ipshipyard.com/) team.
+
+- [v0.35.0](#v0340)
+
+## v0.35.0
+
+- [Overview](#overview)
+- [🔦 Highlights](#-highlights)
+ - [Opt-in HTTP Retrieval client](#opt-in-http-retrieval-client)
+ - [Dedicated `Reprovider.Strategy` for MFS](#dedicated-reproviderstrategy-for-mfs)
+ - [Experimental support for MFS as a FUSE mount point](#experimental-support-for-mfs-as-a-fuse-mount-point)
+ - [Grid view in WebUI](#grid-view-in-webui)
+ - [Enhanced DAG-Shaping Controls](#enhanced-dag-shaping-controls)
+ - [New DAG-Shaping `ipfs add` Options](#new-dag-shaping-ipfs-add-options)
+ - [Persistent DAG-Shaping `Import.*` Configuration](#persistent-dag-shaping-import-configuration)
+ - [Updated DAG-Shaping `Import` Profiles](#updated-dag-shaping-import-profiles)
+ - [`Datastore` Metrics Now Opt-In](#datastore-metrics-now-opt-in)
+ - [Improved performance of data onboarding](#improved-performance-of-data-onboarding)
+ - [Fast `ipfs add` in online mode](#fast-ipfs-add-in-online-mode)
+ - [Optimized, dedicated queue for providing fresh CIDs](#optimized-dedicated-queue-for-providing-fresh-cids)
+ - [Deprecated `ipfs stats provider`](#deprecated-ipfs-stats-provider)
+ - [New `Bitswap` configuration options](#new-bitswap-configuration-options)
+ - [New `Routing` configuration options](#new-routing-configuration-options)
+ - [New Pebble database format config](#new-pebble-database-format-config)
+ - [New environment variables](#new-environment-variables)
+ - [Improved Log Output Setting](#improved-log-output-setting)
+ - [New Repo Lock Optional Wait](#new-repo-lock-optional-wait)
+ - [📦️ Important dependency updates](#-important-dependency-updates)
+- [📝 Changelog](#-changelog)
+- [👨👩👧👦 Contributors](#-contributors)
+
+### Overview
+
+This release brings significant UX and performance improvements to data onboarding, provisioning, and retrieval systems.
+
+New configuration options let you customize the shape of UnixFS DAGs generated during the data import, control the scope of DAGs announced on the Amino DHT, select which delegated routing endpoints are queried, and choose whether to enable HTTP retrieval alongside Bitswap over Libp2p.
+
+Continue reading for more details.
+
+
+### 🔦 Highlights
+
+#### Opt-in HTTP Retrieval client
+
+This release adds experimental support for retrieving blocks directly over HTTPS (HTTP/2), complementing the existing Bitswap over Libp2p.
+
+The opt-in client enables Kubo to use [delegated routing](https://github.com/ipfs/kubo/blob/master/docs/config.md#routingdelegatedrouters) results with `/tls/http` multiaddrs, connecting to HTTPS servers that support [Trustless HTTP Gateway](https://specs.ipfs.tech/http-gateways/trustless-gateway)'s Block Responses (`?format=raw`, `application/vnd.ipld.raw`). Fetching blocks via HTTPS (HTTP/2) simplifies infrastructure and reduces costs for storage providers by leveraging HTTP caching and CDNs.
+
+To enable this feature for testing and feedback, set:
+
+```console
+$ ipfs config --json HTTPRetrieval.Enabled true
+```
+
+See [`HTTPRetrieval`](https://github.com/ipfs/kubo/blob/master/docs/config.md#httpretrieval) for more details.
+
+#### Dedicated `Reprovider.Strategy` for MFS
+
+The [Mutable File System (MFS)](https://docs.ipfs.tech/concepts/glossary/#mfs) in Kubo is a UnixFS filesystem managed with [`ipfs files`](https://docs.ipfs.tech/reference/kubo/cli/#ipfs-files) commands. It supports familiar file operations like cp and mv within a folder-tree structure, automatically updating a MerkleDAG and a "root CID" that reflects the current MFS state. Files in MFS are protected from garbage collection, offering a simpler alternative to `ipfs pin`. This makes it a popular choice for tools like [IPFS Desktop](https://docs.ipfs.tech/install/ipfs-desktop/) and the [WebUI](https://github.com/ipfs/ipfs-webui/#readme).
+
+Previously, the `pinned` reprovider strategy required manual pin management: each dataset update meant pinning the new version and unpinning the old one. Now, new strategies—`mfs` and `pinned+mfs`—let users limit announcements to data explicitly placed in MFS. This simplifies updating datasets and announcing only the latest version to the Amino DHT.
+
+Users relying on the `pinned` strategy can switch to `pinned+mfs` and use MFS alone to manage updates and announcements, eliminating the need for manual pinning and unpinning. We hope this makes it easier to publish just the data that matters to you.
+
+See [`Reprovider.Strategy`](https://github.com/ipfs/kubo/blob/master/docs/config.md#reproviderstrategy) for more details.
+
+#### Experimental support for MFS as a FUSE mount point
+
+The MFS root (filesystem behind the `ipfs files` API) is now available as a read/write FUSE mount point at `Mounts.MFS`. This filesystem is mounted in the same way as `Mounts.IPFS` and `Mounts.IPNS` when running `ipfs mount` or `ipfs daemon --mount`.
+
+Note that the operations supported by the MFS FUSE mountpoint are limited, since MFS doesn't store file attributes.
+
+See [`Mounts`](https://github.com/ipfs/kubo/blob/master/docs/config.md#mounts) and [`docs/fuse.md`](https://github.com/ipfs/kubo/blob/master/docs/fuse.md) for more details.
+
+#### Grid view in WebUI
+
+The WebUI, accessible at http://127.0.0.1:5001/webui/, now includes support for the grid view on the _Files_ screen:
+
+> 
+
+#### Enhanced DAG-Shaping Controls
+
+This release advances CIDv1 support by introducing fine-grained control over UnixFS DAG shaping during data ingestion with the `ipfs add` command.
+
+Wider DAG trees (more links per node, higher fanout, larger thresholds) are beneficial for large files and directories with many files, reducing tree depth and lookup latency in high-latency networks, but they increase node size, straining memory and CPU on resource-constrained devices. Narrower trees (lower link count, lower fanout, smaller thresholds) are preferable for smaller directories, frequent updates, or low-power clients, minimizing overhead and ensuring compatibility, though they may increase traversal steps for very large datasets.
+
+Kubo now allows users to act on these tradeoffs and customize the width of the DAG created by `ipfs add` command.
+
+##### New DAG-Shaping `ipfs add` Options
+
+Three new options allow you to override default settings for specific import operations:
+
+- `--max-file-links`: Sets the maximum number of child links for a single file chunk.
+- `--max-directory-links`: Defines the maximum number of child entries in a "basic" (single-chunk) directory.
+ - Note: Directories exceeding this limit or the `Import.UnixFSHAMTDirectorySizeThreshold` are converted to HAMT-based (sharded across multiple blocks) structures.
+- `--max-hamt-fanout`: Specifies the maximum number of child nodes for HAMT internal structures.
+
+##### Persistent DAG-Shaping `Import.*` Configuration
+
+You can set default values for these options using the following configuration settings:
+- [`Import.UnixFSFileMaxLinks`](https://github.com/ipfs/kubo/blob/master/docs/config.md#importunixfsfilemaxlinks)
+- [`Import.UnixFSDirectoryMaxLinks`](https://github.com/ipfs/kubo/blob/master/docs/config.md#importunixfsdirectorymaxlinks)
+- [`Import.UnixFSHAMTDirectoryMaxFanout`](https://github.com/ipfs/kubo/blob/master/docs/config.md#importunixfshamtdirectorymaxfanout)
+- [`Import.UnixFSHAMTDirectorySizeThreshold`](https://github.com/ipfs/kubo/blob/master/docs/config.md#importunixfshamtdirectorysizethreshold)
+
+##### Updated DAG-Shaping `Import` Profiles
+
+The release updated configuration [profiles](https://github.com/ipfs/kubo/blob/master/docs/config.md#profiles) to incorporate these new `Import.*` settings:
+- Updated Profile: `test-cid-v1` now includes current defaults as explicit `Import.UnixFSFileMaxLinks=174`, `Import.UnixFSDirectoryMaxLinks=0`, `Import.UnixFSHAMTDirectoryMaxFanout=256` and `Import.UnixFSHAMTDirectorySizeThreshold=256KiB`
+- New Profile: `test-cid-v1-wide` adopts experimental directory DAG-shaping defaults, increasing the maximum file DAG width from 174 to 1024, HAMT fanout from 256 to 1024, and raising the HAMT directory sharding threshold from 256KiB to 1MiB, aligning with 1MiB file chunks.
+ - Feedback: Try it out and share your thoughts at [discuss.ipfs.tech/t/should-we-profile-cids](https://discuss.ipfs.tech/t/should-we-profile-cids/18507) or [ipfs/specs#499](https://github.com/ipfs/specs/pull/499).
+
+> [!TIP]
+> Apply one of CIDv1 test [profiles](https://github.com/ipfs/kubo/blob/master/docs/config.md#profiles) with `ipfs config profile apply test-cid-v1[-wide]`.
+
+#### `Datastore` Metrics Now Opt-In
+
+To reduce overhead in the default configuration, datastore metrics are no longer enabled by default when initializing a Kubo repository with `ipfs init`.
+Metrics prefixed with `_datastore` (e.g., `flatfs_datastore_...`, `leveldb_datastore_...`) are not exposed unless explicitly enabled. For a complete list of affected default metrics, refer to [`prometheus_metrics_added_by_measure_profile`](https://github.com/ipfs/kubo/blob/master/test/sharness/t0119-prometheus-data/prometheus_metrics_added_by_measure_profile).
+
+Convenience opt-in [profiles](https://github.com/ipfs/kubo/blob/master/docs/config.md#profiles) can be enabled at initialization time with `ipfs init --profile`: `flatfs-measure`, `pebbleds-measure`, `badgerds-measure`
+
+It is also possible to manually add the `measure` wrapper. See examples in [`Datastore.Spec`](https://github.com/ipfs/kubo/blob/master/docs/config.md#datastorespec) documentation.
+
+#### Improved performance of data onboarding
+
+This Kubo release significantly improves both the speed of ingesting data via `ipfs add` and announcing newly produced CIDs to Amino DHT.
+
+##### Fast `ipfs add` in online mode
+
+Adding a large directory of data when `ipfs daemon` was running in online mode took a long time. A significant amount of this time was spent writing to and reading from the persisted provider queue. Due to this, many users had to shut down the daemon and perform data import in offline mode. This release fixes this known limitation, significantly improving the speed of `ipfs add`.
+
+> [!IMPORTANT]
+> Performing `ipfs add` of 10GiB file would take about 30 minutes.
+> Now it takes close to 30 seconds.
+
+Kubo v0.34:
+
+```console
+$ time kubo/cmd/ipfs/ipfs add -r /tmp/testfiles-100M > /dev/null
+ 100.00 MiB / 100.00 MiB [=====================================================================] 100.00%
+real 0m6.464s
+
+$ time kubo/cmd/ipfs/ipfs add -r /tmp/testfiles-1G > /dev/null
+ 1000.00 MiB / 1000.00 MiB [===================================================================] 100.00%
+real 1m10.542s
+
+$ time kubo/cmd/ipfs/ipfs add -r /tmp/testfiles-10G > /dev/null
+ 10.00 GiB / 10.00 GiB [=======================================================================] 100.00%
+real 24m5.744s
+```
+
+Kubo v0.35:
+
+```console
+$ time kubo/cmd/ipfs/ipfs add -r /tmp/testfiles-100M > /dev/null
+ 100.00 MiB / 100.00 MiB [=====================================================================] 100.00%
+real 0m0.326s
+
+$ time kubo/cmd/ipfs/ipfs add -r /tmp/testfiles-1G > /dev/null
+ 1.00 GiB / 1.00 GiB [=========================================================================] 100.00%
+real 0m2.819s
+
+$ time kubo/cmd/ipfs/ipfs add -r /tmp/testfiles-10G > /dev/null
+ 10.00 GiB / 10.00 GiB [=======================================================================] 100.00%
+real 0m28.405s
+```
+
+##### Optimized, dedicated queue for providing fresh CIDs
+
+From `kubo` [`v0.33.0`](https://github.com/ipfs/kubo/releases/tag/v0.33.0),
+Bitswap stopped advertising newly added and received blocks to the DHT. Since
+then `boxo/provider` is responsible for the first time provide and the recurring reprovide logic. Prior
+to `v0.35.0`, provides and reprovides were handled together in batches, leading
+to delays in initial advertisements (provides).
+
+Provides and Reprovides now have separate queues, allowing for immediate
+provide of new CIDs and optimised batching of reprovides.
+
+###### New `Provider` configuration options
+
+This change introduces a new configuration options:
+
+- [`Provider.Enabled`](https://github.com/ipfs/kubo/blob/master/docs/config.md#providerenabled) is a global flag for disabling both [Provider](https://github.com/ipfs/kubo/blob/master/docs/config.md#provider) and [Reprovider](https://github.com/ipfs/kubo/blob/master/docs/config.md#reprovider) systems (announcing new/old CIDs to amino DHT).
+- [`Provider.WorkerCount`](https://github.com/ipfs/kubo/blob/master/docs/config.md#providerworkercount) for limiting the number of concurrent provide operations, allows for fine-tuning the trade-off between announcement speed and system load when announcing new CIDs.
+- Removed `Experimental.StrategicProviding`. Superseded by `Provider.Enabled`, `Reprovider.Interval` and [`Reprovider.Strategy`](https://github.com/ipfs/kubo/blob/master/docs/config.md#reproviderstrategy).
+
+> [!TIP]
+> Users who need to provide large volumes of content immediately should consider setting `Routing.AcceleratedDHTClient` to `true`. If that is not enough, consider adjusting `Provider.WorkerCount` to a higher value.
+
+###### Deprecated `ipfs stats provider`
+
+Since the `ipfs stats provider` command was displaying statistics for both
+provides and reprovides, this command isn't relevant anymore after separating
+the two queues.
+
+The successor command is `ipfs stats reprovide`, showing the same statistics,
+but for reprovides only.
+
+> [!NOTE]
+> `ipfs stats provider` still works, but is marked as deprecated and will be removed in a future release. Be mindful that the command provides only statistics about reprovides (similar to `ipfs stats reprovide`) and not the new provide queue (this will be fixed as a part of wider refactor planned for a future release).
+
+#### New `Bitswap` configuration options
+
+- [`Bitswap.Libp2pEnabled`](https://github.com/ipfs/kubo/blob/master/docs/config.md#bitswaplibp2penabled) determines whether Kubo will use Bitswap over libp2p (both client and server).
+- [`Bitswap.ServerEnabled`](https://github.com/ipfs/kubo/blob/master/docs/config.md#bitswapserverenabled) controls whether Kubo functions as a Bitswap server to host and respond to block requests.
+- [`Internal.Bitswap.ProviderSearchMaxResults`](https://github.com/ipfs/kubo/blob/master/docs/config.md#internalbitswapprovidersearchmaxresults) for adjusting the maximum number of providers bitswap client should aim at before it stops searching for new ones.
+
+#### New `Routing` configuration options
+
+- [`Routing.IgnoreProviders`](https://github.com/ipfs/kubo/blob/master/docs/config.md#routingignoreproviders) allows ignoring specific peer IDs when returned by the content routing system as providers of content.
+ - Simplifies testing `HTTPRetrieval.Enabled` in setups where Bitswap over Libp2p and HTTP retrieval is served under different PeerIDs.
+- [`Routing.DelegatedRouters`](https://github.com/ipfs/kubo/blob/master/docs/config.md#routingdelegatedrouters) allows customizing HTTP routers used by Kubo when `Routing.Type` is set to `auto` or `autoclient`.
+ - Users are now able to adjust the default routing system and directly query custom routers for increased resiliency or when dataset is too big and CIDs are not announced on Amino DHT.
+
+> [!TIP]
+>
+> For example, to use Pinata's routing endpoint in addition to IPNI at `cid.contact`:
+>
+> ```console
+> $ ipfs config --json Routing.DelegatedRouters '["https://cid.contact","https://indexer.pinata.cloud"]'
+> ```
+
+#### New Pebble database format config
+
+This Kubo release provides node operators with more control over [Pebble's `FormatMajorVersion`](https://github.com/cockroachdb/pebble/tree/master?tab=readme-ov-file#format-major-versions). This allows testing a new Kubo release without automatically migrating Pebble datastores, keeping the ability to switch back to older Kubo.
+
+When IPFS is initialized to use the pebbleds datastore (opt-in via `ipfs init --profile=pebbleds`), the latest pebble database format is configured in the pebble datastore config as `"formatMajorVersion"`. Setting this in the datastore config prevents automatically upgrading to the latest available version when Kubo is upgraded. If a later version becomes available, the Kubo daemon prints a startup message to indicate this. The user can them update the config to use the latest format when they are certain a downgrade will not be necessary.
+
+Without the `"formatMajorVersion"` in the pebble datastore config, the database format is automatically upgraded to the latest version. If this happens, then it is possible a downgrade back to the previous version of Kubo will not work if new format is not compatible with the pebble datastore in the previous version of Kubo.
+
+When installing a new version of Kubo when `"formatMajorVersion"` is configured, automatic repository migration (`ipfs daemon with --migrate=true`) does not upgrade this to the latest available version. This is done because a user may have reasons not to upgrade the pebble database format, and may want to be able to downgrade Kubo if something else is not working in the new version. If the configured pebble database format in the old Kubo is not supported in the new Kubo, then the configured version must be updated and the old Kubo run, before installing the new Kubo.
+
+See other caveats and configuration options at [`kubo/docs/datastores.md#pebbleds`](https://github.com/ipfs/kubo/blob/master/docs/datastores.md#pebbleds)
+
+#### New environment variables
+
+The [`environment-variables.md`](https://github.com/ipfs/kubo/blob/master/docs/environment-variables.md) was extended with two new features:
+
+##### Improved Log Output Setting
+
+When stderr and/or stdout options are configured or specified by the `GOLOG_OUTPUT` environ variable, log only to the output(s) specified. For example:
+
+- `GOLOG_OUTPUT="stderr"` logs only to stderr
+- `GOLOG_OUTPUT="stdout"` logs only to stdout
+- `GOLOG_OUTPUT="stderr+stdout"` logs to both stderr and stdout
+
+##### New Repo Lock Optional Wait
+
+The environment variable `IPFS_WAIT_REPO_LOCK` specifies the amount of time to wait for the repo lock. Set the value of this variable to a string that can be [parsed](https://pkg.go.dev/time@go1.24.3#ParseDuration) as a golang `time.Duration`. For example:
+```
+IPFS_WAIT_REPO_LOCK="15s"
+```
+
+If the lock cannot be acquired because someone else has the lock, and `IPFS_WAIT_REPO_LOCK` is set to a valid value, then acquiring the lock is retried every second until the lock is acquired or the specified wait time has elapsed.
+
+#### 📦️ Important dependency updates
+
+- update `boxo` to [v0.30.0](https://github.com/ipfs/boxo/releases/tag/v0.30.0)
+- update `ipfs-webui` to [v4.7.0](https://github.com/ipfs/ipfs-webui/releases/tag/v4.7.0)
+- update `go-ds-pebble` to [v0.5.0](https://github.com/ipfs/go-ds-pebble/releases/tag/v0.5.0)
+ - update `pebble` to [v2.0.3](https://github.com/cockroachdb/pebble/releases/tag/v2.0.3)
+- update `go-libp2p-pubsub` to [v0.13.1](https://github.com:/libp2p/go-libp2p-pubsub/releases/tag/v0.13.1)
+- update `go-libp2p-kad-dht` to [v0.33.1](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.33.1) (incl. [v0.33.0](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.33.0), [v0.32.0](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.32.0), [v0.31.0](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.31.0))
+- update `go-log` to [v2.6.0](https://github.com/ipfs/go-log/releases/tag/v2.6.0)
+- update `p2p-forge/client` to [v0.5.1](https://github.com/ipshipyard/p2p-forge/releases/tag/v0.5.1)
+
+### 📝 Changelog
+
+Full Changelog
+
+- github.com/ipfs/kubo:
+ - chore(version): 0.35.0
+ - fix: go-libp2p-kad-dht v0.33.1 (#10814) ([ipfs/kubo#10814](https://github.com/ipfs/kubo/pull/10814))
+ - fix: p2p-forge v0.5.1 ignoring /p2p-circuit (#10813) ([ipfs/kubo#10813](https://github.com/ipfs/kubo/pull/10813))
+ - chore(version): 0.35.0-rc2
+ - fix(fuse): ipns error handling and friendly errors (#10807) ([ipfs/kubo#10807](https://github.com/ipfs/kubo/pull/10807))
+ - fix(config): wire up `Provider.Enabled` flag (#10804) ([ipfs/kubo#10804](https://github.com/ipfs/kubo/pull/10804))
+ - docs(changelog): go-libp2p-kad-dht
+ - chore(version): 0.35.0-rc1
+ - feat: IPFS_WAIT_REPO_LOCK (#10797) ([ipfs/kubo#10797](https://github.com/ipfs/kubo/pull/10797))
+ - logging: upgrade to go-log/v2 v2.6.0 (#10798) ([ipfs/kubo#10798](https://github.com/ipfs/kubo/pull/10798))
+ - chore: ensure /mfs is present in docker
+ - feat(fuse): Expose MFS as FUSE mount point (#10781) ([ipfs/kubo#10781](https://github.com/ipfs/kubo/pull/10781))
+ - feat: opt-in http retrieval client (#10772) ([ipfs/kubo#10772](https://github.com/ipfs/kubo/pull/10772))
+ - Update go-libp2p-pubsub to v0.13.1 (#10795) ([ipfs/kubo#10795](https://github.com/ipfs/kubo/pull/10795))
+ - feat(config): ability to disable Bitswap fully or just server (#10782) ([ipfs/kubo#10782](https://github.com/ipfs/kubo/pull/10782))
+ - refactor: make datastore metrics opt-in (#10788) ([ipfs/kubo#10788](https://github.com/ipfs/kubo/pull/10788))
+ - feat(pebble): support pinning `FormatMajorVersion` (#10789) ([ipfs/kubo#10789](https://github.com/ipfs/kubo/pull/10789))
+ - feat: `Provider.WorkerCount` and `stats reprovide` (#10779) ([ipfs/kubo#10779](https://github.com/ipfs/kubo/pull/10779))
+ - Upgrade to Boxo v0.30.0 (#10794) ([ipfs/kubo#10794](https://github.com/ipfs/kubo/pull/10794))
+ - docs: use latest fuse package (#10791) ([ipfs/kubo#10791](https://github.com/ipfs/kubo/pull/10791))
+ - remove duplicate words (#10790) ([ipfs/kubo#10790](https://github.com/ipfs/kubo/pull/10790))
+ - feat(config): `ipfs add` and `Import` options for controlling UnixFS DAG Width (#10774) ([ipfs/kubo#10774](https://github.com/ipfs/kubo/pull/10774))
+ - feat(config): expose ProviderSearchMaxResults (#10773) ([ipfs/kubo#10773](https://github.com/ipfs/kubo/pull/10773))
+ - feat: ipfs-webui v4.7.0 (#10780) ([ipfs/kubo#10780](https://github.com/ipfs/kubo/pull/10780))
+ - feat: partial DAG provides with Reprovider.Strategy=mfs|pinned+mfs (#10754) ([ipfs/kubo#10754](https://github.com/ipfs/kubo/pull/10754))
+ - chore: update url
+ - docs: known issues with file/urlstores (#10768) ([ipfs/kubo#10768](https://github.com/ipfs/kubo/pull/10768))
+ - fix: Add IPFS & IPNS path details to error (re. #10762) (#10770) ([ipfs/kubo#10770](https://github.com/ipfs/kubo/pull/10770))
+ - docs: Fix typo in v0.34 changelog (#10771) ([ipfs/kubo#10771](https://github.com/ipfs/kubo/pull/10771))
+ - Support WithIgnoreProviders() in provider query manager ([ipfs/kubo#10765](https://github.com/ipfs/kubo/pull/10765))
+ - Merge release v0.34.1 ([ipfs/kubo#10766](https://github.com/ipfs/kubo/pull/10766))
+ - fix: reprovides warning (#10761) ([ipfs/kubo#10761](https://github.com/ipfs/kubo/pull/10761))
+ - Merge release v0.34.0 ([ipfs/kubo#10759](https://github.com/ipfs/kubo/pull/10759))
+ - feat: ipfs-webui v4.6 (#10756) ([ipfs/kubo#10756](https://github.com/ipfs/kubo/pull/10756))
+ - docs(readme): update min. requirements + cleanup (#10750) ([ipfs/kubo#10750](https://github.com/ipfs/kubo/pull/10750))
+ - Upgrade to Boxo v0.29.1 (#10755) ([ipfs/kubo#10755](https://github.com/ipfs/kubo/pull/10755))
+ - Nonfunctional (#10753) ([ipfs/kubo#10753](https://github.com/ipfs/kubo/pull/10753))
+ - provider: buffer pin providers ([ipfs/kubo#10746](https://github.com/ipfs/kubo/pull/10746))
+ - chore: 0.35.0-dev
+- github.com/ipfs/boxo (v0.29.1 -> v0.30.0):
+ - Release v0.30.0 ([ipfs/boxo#915](https://github.com/ipfs/boxo/pull/915))
+ - feat(bitswap): add option to disable Bitswap server (#911) ([ipfs/boxo#911](https://github.com/ipfs/boxo/pull/911))
+ - provider: dedicated provide queue (#907) ([ipfs/boxo#907](https://github.com/ipfs/boxo/pull/907))
+ - provider: deduplicate cids in queue (#910) ([ipfs/boxo#910](https://github.com/ipfs/boxo/pull/910))
+ - feat(unixfs/mfs): support MaxLinks and MaxHAMTFanout (#906) ([ipfs/boxo#906](https://github.com/ipfs/boxo/pull/906))
+ - feat(ipld/unixfs): DagModifier: allow specifying MaxLinks per file (#898) ([ipfs/boxo#898](https://github.com/ipfs/boxo/pull/898))
+ - feat: NewDAGProvider to walk partial DAGs in offline mode (#905) ([ipfs/boxo#905](https://github.com/ipfs/boxo/pull/905))
+ - gateway: check for UseSubdomains with IP addresses (#903) ([ipfs/boxo#903](https://github.com/ipfs/boxo/pull/903))
+ - feat(gateway): add cid copy button to directory listings (#899) ([ipfs/boxo#899](https://github.com/ipfs/boxo/pull/899))
+ - Improve performance of data onboarding (#888) ([ipfs/boxo#888](https://github.com/ipfs/boxo/pull/888))
+ - bitswap: add requestsInFlight metric ([ipfs/boxo#904](https://github.com/ipfs/boxo/pull/904))
+ - provider: simplify reprovide (#890) ([ipfs/boxo#890](https://github.com/ipfs/boxo/pull/890))
+ - Upgrade to go-libp2p v0.41.1 ([ipfs/boxo#896](https://github.com/ipfs/boxo/pull/896))
+ - Update RELEASE.md ([ipfs/boxo#892](https://github.com/ipfs/boxo/pull/892))
+ - changelog: document bsnet import path change ([ipfs/boxo#891](https://github.com/ipfs/boxo/pull/891))
+ - fix(gateway): preserve query parameters on _redirects ([ipfs/boxo#886](https://github.com/ipfs/boxo/pull/886))
+ - bitswap/httpnet: Add WithDenylist option ([ipfs/boxo#877](https://github.com/ipfs/boxo/pull/877))
+- github.com/ipfs/go-block-format (v0.2.0 -> v0.2.1):
+ - Update version (#60) ([ipfs/go-block-format#60](https://github.com/ipfs/go-block-format/pull/60))
+ - Update go-ipfs-util to use boxo (#52) ([ipfs/go-block-format#52](https://github.com/ipfs/go-block-format/pull/52))
+- github.com/ipfs/go-ds-pebble (v0.4.4 -> v0.5.0):
+ - new version (#53) ([ipfs/go-ds-pebble#53](https://github.com/ipfs/go-ds-pebble/pull/53))
+ - Upgrade to pebble v2.0.3 (#45) ([ipfs/go-ds-pebble#45](https://github.com/ipfs/go-ds-pebble/pull/45))
+- github.com/ipfs/go-fs-lock (v0.0.7 -> v0.1.1):
+ - new version (#48) ([ipfs/go-fs-lock#48](https://github.com/ipfs/go-fs-lock/pull/48))
+ - Return original error when WaitLock times out (#47) ([ipfs/go-fs-lock#47](https://github.com/ipfs/go-fs-lock/pull/47))
+ - new version (#45) ([ipfs/go-fs-lock#45](https://github.com/ipfs/go-fs-lock/pull/45))
+ - Add WaitLock function (#44) ([ipfs/go-fs-lock#44](https://github.com/ipfs/go-fs-lock/pull/44))
+ - sync: update CI config files ([ipfs/go-fs-lock#30](https://github.com/ipfs/go-fs-lock/pull/30))
+ - sync: update CI config files (#27) ([ipfs/go-fs-lock#27](https://github.com/ipfs/go-fs-lock/pull/27))
+ - sync: update CI config files ([ipfs/go-fs-lock#25](https://github.com/ipfs/go-fs-lock/pull/25))
+- github.com/ipfs/go-log/v2 (v2.5.1 -> v2.6.0):
+ - new version (#155) ([ipfs/go-log#155](https://github.com/ipfs/go-log/pull/155))
+ - feat: only log to stderr or to stdout or both if configured (#154) ([ipfs/go-log#154](https://github.com/ipfs/go-log/pull/154))
+ - ci: uci/copy-templates ([ipfs/go-log#145](https://github.com/ipfs/go-log/pull/145))
+ - sync: update CI config files (#137) ([ipfs/go-log#137](https://github.com/ipfs/go-log/pull/137))
+- github.com/libp2p/go-libp2p-kad-dht (v0.30.2 -> v0.33.1):
+ - chore: release v0.33.1 (#1088) ([libp2p/go-libp2p-kad-dht#1088](https://github.com/libp2p/go-libp2p-kad-dht/pull/1088))
+ - fix(fullrt): mutex cleanup (#1087) ([libp2p/go-libp2p-kad-dht#1087](https://github.com/libp2p/go-libp2p-kad-dht/pull/1087))
+ - fix: use correct mutex for reading keyToPeerMap (#1086) ([libp2p/go-libp2p-kad-dht#1086](https://github.com/libp2p/go-libp2p-kad-dht/pull/1086))
+ - fix: fullrt kMapLk unlock (#1085) ([libp2p/go-libp2p-kad-dht#1085](https://github.com/libp2p/go-libp2p-kad-dht/pull/1085))
+ - chore: release v0.33.0 (#1083) ([libp2p/go-libp2p-kad-dht#1083](https://github.com/libp2p/go-libp2p-kad-dht/pull/1083))
+ - fix/updates to use context passed in New function for context cancellation (#1081) ([libp2p/go-libp2p-kad-dht#1081](https://github.com/libp2p/go-libp2p-kad-dht/pull/1081))
+ - chore: release v0.31.1 (#1079) ([libp2p/go-libp2p-kad-dht#1079](https://github.com/libp2p/go-libp2p-kad-dht/pull/1079))
+ - fix: netsize warning (#1077) ([libp2p/go-libp2p-kad-dht#1077](https://github.com/libp2p/go-libp2p-kad-dht/pull/1077))
+ - fix: use correct message type attribute in metrics (#1076) ([libp2p/go-libp2p-kad-dht#1076](https://github.com/libp2p/go-libp2p-kad-dht/pull/1076))
+ - chore: bump go-log to v2 (#1074) ([libp2p/go-libp2p-kad-dht#1074](https://github.com/libp2p/go-libp2p-kad-dht/pull/1074))
+ - release v0.31.0 (#1072) ([libp2p/go-libp2p-kad-dht#1072](https://github.com/libp2p/go-libp2p-kad-dht/pull/1072))
+ - query: ip diversity filter (#1070) ([libp2p/go-libp2p-kad-dht#1070](https://github.com/libp2p/go-libp2p-kad-dht/pull/1070))
+ - tests: fix flaky TestProvidesExpire (#1069) ([libp2p/go-libp2p-kad-dht#1069](https://github.com/libp2p/go-libp2p-kad-dht/pull/1069))
+ - refactor: replace fmt.Errorf with errors.New when not formatting is required (#1067) ([libp2p/go-libp2p-kad-dht#1067](https://github.com/libp2p/go-libp2p-kad-dht/pull/1067))
+ - fix: error on no valid provs (#1065) ([libp2p/go-libp2p-kad-dht#1065](https://github.com/libp2p/go-libp2p-kad-dht/pull/1065))
+ - cleanup: remove deprecated opt package (#1064) ([libp2p/go-libp2p-kad-dht#1064](https://github.com/libp2p/go-libp2p-kad-dht/pull/1064))
+ - cleanup: fullrt ([libp2p/go-libp2p-kad-dht#1062](https://github.com/libp2p/go-libp2p-kad-dht/pull/1062))
+ - fix: remove peerstore no-op (#1063) ([libp2p/go-libp2p-kad-dht#1063](https://github.com/libp2p/go-libp2p-kad-dht/pull/1063))
+ - tests: flaky TestSearchValue (dual) (#1060) ([libp2p/go-libp2p-kad-dht#1060](https://github.com/libp2p/go-libp2p-kad-dht/pull/1060))
+- github.com/libp2p/go-libp2p-kbucket (v0.6.5 -> v0.7.0):
+ - chore: release v0.7.0 (#143) ([libp2p/go-libp2p-kbucket#143](https://github.com/libp2p/go-libp2p-kbucket/pull/143))
+ - peerdiversity: export IPGroupKey (#141) ([libp2p/go-libp2p-kbucket#141](https://github.com/libp2p/go-libp2p-kbucket/pull/141))
+ - fix: flaky TestUsefulNewPeer (#140) ([libp2p/go-libp2p-kbucket#140](https://github.com/libp2p/go-libp2p-kbucket/pull/140))
+ - fix: flaky TestTableFindMultipleBuckets (#139) ([libp2p/go-libp2p-kbucket#139](https://github.com/libp2p/go-libp2p-kbucket/pull/139))
+- github.com/libp2p/go-libp2p-pubsub (v0.13.0 -> v0.13.1):
+ - feat: WithValidatorData publishing option (#603) ([libp2p/go-libp2p-pubsub#603](https://github.com/libp2p/go-libp2p-pubsub/pull/603))
+ - feat: avoid repeated checksum calculations (#599) ([libp2p/go-libp2p-pubsub#599](https://github.com/libp2p/go-libp2p-pubsub/pull/599))
+- github.com/libp2p/go-yamux/v4 (v4.0.1 -> v4.0.2):
+ - Release v4.0.2 (#124) ([libp2p/go-yamux#124](https://github.com/libp2p/go-yamux/pull/124))
+ - fix: remove noisy logs (#116) ([libp2p/go-yamux#116](https://github.com/libp2p/go-yamux/pull/116))
+ - check deadline before sending a message (#114) ([libp2p/go-yamux#114](https://github.com/libp2p/go-yamux/pull/114))
+ - only check KeepAliveInterval if keep-alive are enabled (#113) ([libp2p/go-yamux#113](https://github.com/libp2p/go-yamux/pull/113))
+ - ci: uci/copy-templates ([libp2p/go-yamux#109](https://github.com/libp2p/go-yamux/pull/109))
+
+
+
+### 👨👩👧👦 Contributors
+
+| Contributor | Commits | Lines ± | Files Changed |
+|-------------|---------|---------|---------------|
+| Hector Sanjuan | 16 | +2662/-590 | 71 |
+| Guillaume Michel | 27 | +1339/-714 | 69 |
+| Andrew Gillis | 22 | +1056/-377 | 54 |
+| Sergey Gorbunov | 1 | +962/-42 | 26 |
+| Marcin Rataj | 19 | +714/-133 | 47 |
+| IGP | 2 | +419/-35 | 11 |
+| GITSRC | 1 | +90/-1 | 3 |
+| guillaumemichel | 1 | +21/-43 | 1 |
+| blockchainluffy | 1 | +27/-26 | 8 |
+| web3-bot | 9 | +21/-22 | 13 |
+| VersaliX | 1 | +31/-2 | 4 |
+| gammazero | 5 | +18/-5 | 5 |
+| Hlib Kanunnikov | 1 | +14/-4 | 1 |
+| diogo464 | 1 | +6/-7 | 1 |
+| Asutorufa | 2 | +7/-1 | 2 |
+| Russell Dempsey | 1 | +6/-1 | 1 |
+| Steven Allen | 1 | +1/-5 | 1 |
+| Michael Vorburger | 2 | +3/-3 | 2 |
+| Aayush Rajasekaran | 1 | +2/-2 | 1 |
+| sukun | 1 | +1/-1 | 1 |
diff --git a/docs/changelogs/v0.36.md b/docs/changelogs/v0.36.md
new file mode 100644
index 00000000000..0cb35085f42
--- /dev/null
+++ b/docs/changelogs/v0.36.md
@@ -0,0 +1,39 @@
+# Kubo changelog v0.36
+
+
+
+This release was brought to you by the [Shipyard](http://ipshipyard.com/) team.
+
+- [v0.36.0](#v0340)
+
+## v0.36.0
+
+- [Overview](#overview)
+- [🔦 Highlights](#-highlights)
+ - [Update go-log to v2](#update-go-log-to-v2)
+ - [📦️ Important dependency updates](#-important-dependency-updates)
+- [📝 Changelog](#-changelog)
+- [👨👩👧👦 Contributors](#-contributors)
+
+### Overview
+
+### 🔦 Highlights
+
+#### Update go-log to v2
+
+go-log v2 has been out for quite a while now and it is time to deprecate v1.
+
+- Replace all use of `go-log` with `go-log/v2`
+- Makes `/api/v0/log/tail` useful over HTTP
+- Fixes `ipfs log tail`
+- Removes support for `ContextWithLoggable` as this is not needed for tracing-like functionality
+
+#### 📦️ Important dependency updates
+
+- update `go-libp2p-kad-dht` to [v0.33.0](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.33.0)
+- update `boxo` to [v0.31.0](https://github.com/ipfs/boxo/releases/tag/v0.31.0)
+- update `gateway-conformance` to [v0.8](https://github.com/ipfs/gateway-conformance/releases/tag/v0.8.0)
+
+### 📝 Changelog
+
+### 👨👩👧👦 Contributors
diff --git a/docs/changelogs/v0.4.md b/docs/changelogs/v0.4.md
index 5abf5df67b5..2862c8b7759 100644
--- a/docs/changelogs/v0.4.md
+++ b/docs/changelogs/v0.4.md
@@ -335,7 +335,7 @@ browsers (see [#4143](https://github.com/ipfs/go-ipfs/issues/4143).
#### Human Readable Numbers
-The `ipfs bitswap stat` and and `ipfs object stat` commands now support a
+The `ipfs bitswap stat` and `ipfs object stat` commands now support a
`--humanize` flag that formats numbers with human-readable units (GiB, MiB,
etc.).
@@ -401,7 +401,7 @@ g generation.
-n, --only-hash bool - Only chunk and hash - do not
write to disk.
-w, --wrap-with-directory bool - Wrap files with a directory o
-bject.
+object.
-s, --chunker string - Chunking algorithm, size-[byt
es] or rabin-[min]-[avg]-[max]. Default: size-262144.
--pin bool - Pin this object when adding.
@@ -1593,7 +1593,7 @@ The next steps are:
- cmds: remove redundant func ([ipfs/go-ipfs#5750](https://github.com/ipfs/go-ipfs/pull/5750))
- commands/refs: use new cmds ([ipfs/go-ipfs#5679](https://github.com/ipfs/go-ipfs/pull/5679))
- commands/pin: use new cmds lib ([ipfs/go-ipfs#5674](https://github.com/ipfs/go-ipfs/pull/5674))
- - commands/boostrap: use new cmds ([ipfs/go-ipfs#5678](https://github.com/ipfs/go-ipfs/pull/5678))
+ - commands/bootstrap: use new cmds ([ipfs/go-ipfs#5678](https://github.com/ipfs/go-ipfs/pull/5678))
- fix(cmd/add): progressbar output error when input is read from stdin ([ipfs/go-ipfs#5743](https://github.com/ipfs/go-ipfs/pull/5743))
- unexport GOFLAGS ([ipfs/go-ipfs#5747](https://github.com/ipfs/go-ipfs/pull/5747))
- refactor(cmds): use new cmds ([ipfs/go-ipfs#5659](https://github.com/ipfs/go-ipfs/pull/5659))
@@ -2114,7 +2114,7 @@ approach:
a local IPFS node).
To fix the security issue, we intend to switch IPFS gateway links
-`https://ipfs.io/ipfs/CID` to to `https://CID.ipfs.dweb.link`. This way, the CID
+`https://ipfs.io/ipfs/CID` to `https://CID.ipfs.dweb.link`. This way, the CID
will be a part of the
["origin"](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin) so
each IPFS website will get a separate security origin.
@@ -3347,7 +3347,7 @@ look at all the other cool things added in 0.4.8 below.
- Features
- Implement unixfs directory sharding ([ipfs/go-ipfs#3042](https://github.com/ipfs/go-ipfs/pull/3042))
- Add DisableNatPortMap option ([ipfs/go-ipfs#3798](https://github.com/ipfs/go-ipfs/pull/3798))
- - Basic Filestore utilty commands ([ipfs/go-ipfs#3653](https://github.com/ipfs/go-ipfs/pull/3653))
+ - Basic Filestore utility commands ([ipfs/go-ipfs#3653](https://github.com/ipfs/go-ipfs/pull/3653))
- Improvements
- More Robust GC ([ipfs/go-ipfs#3712](https://github.com/ipfs/go-ipfs/pull/3712))
- Automatically fix permissions for docker volumes ([ipfs/go-ipfs#3744](https://github.com/ipfs/go-ipfs/pull/3744))
@@ -3580,7 +3580,7 @@ few other improvements to other parts of the codebase. Notably:
- Dependencies
- Update libp2p to have fixed spdystream dep ([ipfs/go-ipfs#3210](https://github.com/ipfs/go-ipfs/pull/3210))
- Update libp2p and dht packages ([ipfs/go-ipfs#3263](https://github.com/ipfs/go-ipfs/pull/3263))
- - Update to libp2p 4.0.1 and propogate other changes ([ipfs/go-ipfs#3284](https://github.com/ipfs/go-ipfs/pull/3284))
+ - Update to libp2p 4.0.1 and propagate other changes ([ipfs/go-ipfs#3284](https://github.com/ipfs/go-ipfs/pull/3284))
- Update to libp2p 4.0.4 ([ipfs/go-ipfs#3361](https://github.com/ipfs/go-ipfs/pull/3361))
- Update go-libp2p across codebase ([ipfs/go-ipfs#3406](https://github.com/ipfs/go-ipfs/pull/3406))
- Update to go-libp2p 4.1.0 ([ipfs/go-ipfs#3373](https://github.com/ipfs/go-ipfs/pull/3373))
diff --git a/docs/changelogs/v0.5.md b/docs/changelogs/v0.5.md
index dd154a6b4c2..9e49565f6be 100644
--- a/docs/changelogs/v0.5.md
+++ b/docs/changelogs/v0.5.md
@@ -357,7 +357,7 @@ It's now possible to initialize an IPFS node with an existing IPFS config by run
> ipfs init /path/to/existing/config
```
-This will re-use the existing configuration in it's entirety (including the private key) and can be useful when:
+This will reuse the existing configuration in it's entirety (including the private key) and can be useful when:
* Migrating a node's identity between machines without keeping the data.
* Resetting the datastore.
@@ -773,7 +773,7 @@ As usual, this release contains several Windows specific fixes and improvements:
- Introduce first strategic provider: do nothing ([ipfs/go-ipfs#6292](https://github.com/ipfs/go-ipfs/pull/6292))
- github.com/ipfs/go-bitswap (v0.0.8-e37498cf10d6 -> v0.2.13):
- refactor: remove WantManager ([ipfs/go-bitswap#374](https://github.com/ipfs/go-bitswap/pull/374))
- - Send CANCELs when session context is cancelled ([ipfs/go-bitswap#375](https://github.com/ipfs/go-bitswap/pull/375))
+ - Send CANCELs when session context is canceled ([ipfs/go-bitswap#375](https://github.com/ipfs/go-bitswap/pull/375))
- refactor: remove unused code ([ipfs/go-bitswap#373](https://github.com/ipfs/go-bitswap/pull/373))
- Change timing for DONT_HAVE timeouts to be more conservative ([ipfs/go-bitswap#371](https://github.com/ipfs/go-bitswap/pull/371))
- fix: avoid calling ctx.SetDeadline() every time we send a message ([ipfs/go-bitswap#369](https://github.com/ipfs/go-bitswap/pull/369))
@@ -993,7 +993,7 @@ As usual, this release contains several Windows specific fixes and improvements:
- fix(dagreader): remove a buggy workaround for a gateway issue ([ipfs/go-unixfs#80](https://github.com/ipfs/go-unixfs/pull/80))
- fix: correctly handle symlink file sizes ([ipfs/go-unixfs#78](https://github.com/ipfs/go-unixfs/pull/78))
- fix: return the correct error from RemoveChild ([ipfs/go-unixfs#76](https://github.com/ipfs/go-unixfs/pull/76))
- - update the the last go-merkledag ([ipfs/go-unixfs#75](https://github.com/ipfs/go-unixfs/pull/75))
+ - update the last go-merkledag ([ipfs/go-unixfs#75](https://github.com/ipfs/go-unixfs/pull/75))
- fix: enumerate children ([ipfs/go-unixfs#74](https://github.com/ipfs/go-unixfs/pull/74))
- github.com/ipfs/interface-go-ipfs-core (v0.0.8 -> v0.2.7):
- Add pin ls tests for indirect pin traversal and pin type precedence ([ipfs/interface-go-ipfs-core#47](https://github.com/ipfs/interface-go-ipfs-core/pull/47))
diff --git a/docs/changelogs/v0.6.md b/docs/changelogs/v0.6.md
index 960125594ba..40f5f1727e5 100644
--- a/docs/changelogs/v0.6.md
+++ b/docs/changelogs/v0.6.md
@@ -14,7 +14,7 @@ The highlights in this release include:
**MIGRATION:** This release contains a small config migration to enable listening on the QUIC transport in addition the TCP transport. This migration will:
* Normalize multiaddrs in the bootstrap list to use the `/p2p/Qm...` syntax for multiaddrs instead of the `/ipfs/Qm...` syntax.
-* Add QUIC addresses for the default bootstrapers, as necessary. If you've removed the default bootstrappers from your bootstrap config, the migration won't add them back.
+* Add QUIC addresses for the default bootstrappers, as necessary. If you've removed the default bootstrappers from your bootstrap config, the migration won't add them back.
* Add a QUIC listener address to mirror any TCP addresses present in your config. For example, if you're listening on `/ip4/0.0.0.0/tcp/1234`, this migration will add a listen address for `/ip4/0.0.0.0/udp/1234/quic`.
#### QUIC by default
@@ -114,7 +114,7 @@ Use-cases:
- docs: X-Forwarded-Proto: https ([ipfs/go-ipfs#7306](https://github.com/ipfs/go-ipfs/pull/7306))
- fix(mkreleaselog): make robust against running in different working directories ([ipfs/go-ipfs#7310](https://github.com/ipfs/go-ipfs/pull/7310))
- fix(mkreleasenotes): include commits directly to master ([ipfs/go-ipfs#7296](https://github.com/ipfs/go-ipfs/pull/7296))
- - write api file automically ([ipfs/go-ipfs#7282](https://github.com/ipfs/go-ipfs/pull/7282))
+ - write api file automatically ([ipfs/go-ipfs#7282](https://github.com/ipfs/go-ipfs/pull/7282))
- systemd: disable swap-usage for ipfs ([ipfs/go-ipfs#7299](https://github.com/ipfs/go-ipfs/pull/7299))
- systemd: add helptext ([ipfs/go-ipfs#7265](https://github.com/ipfs/go-ipfs/pull/7265))
- systemd: add the link to the docs ([ipfs/go-ipfs#7287](https://github.com/ipfs/go-ipfs/pull/7287))
@@ -177,7 +177,7 @@ Use-cases:
- feat: add peering service config section ([ipfs/go-ipfs-config#96](https://github.com/ipfs/go-ipfs-config/pull/96))
- fix: include key size in key init method ([ipfs/go-ipfs-config#95](https://github.com/ipfs/go-ipfs-config/pull/95))
- QUIC: remove experimental config option ([ipfs/go-ipfs-config#93](https://github.com/ipfs/go-ipfs-config/pull/93))
- - fix boostrap peers ([ipfs/go-ipfs-config#94](https://github.com/ipfs/go-ipfs-config/pull/94))
+ - fix bootstrap peers ([ipfs/go-ipfs-config#94](https://github.com/ipfs/go-ipfs-config/pull/94))
- default config: add QUIC listening ports + quic to mars.i.ipfs.io ([ipfs/go-ipfs-config#91](https://github.com/ipfs/go-ipfs-config/pull/91))
- feat: remove strict signing pubsub option. ([ipfs/go-ipfs-config#90](https://github.com/ipfs/go-ipfs-config/pull/90))
- Add autocomment configuration
@@ -260,7 +260,7 @@ Use-cases:
- enhancement/remove-unused-variable ([libp2p/go-libp2p-kad-dht#633](https://github.com/libp2p/go-libp2p-kad-dht/pull/633))
- Put back TestSelfWalkOnAddressChange ([libp2p/go-libp2p-kad-dht#648](https://github.com/libp2p/go-libp2p-kad-dht/pull/648))
- Routing Table Refresh manager (#601) ([libp2p/go-libp2p-kad-dht#601](https://github.com/libp2p/go-libp2p-kad-dht/pull/601))
- - Boostrap empty RT and Optimize allocs when we discover new peers (#631) ([libp2p/go-libp2p-kad-dht#631](https://github.com/libp2p/go-libp2p-kad-dht/pull/631))
+ - bootstrap empty RT and Optimize allocs when we discover new peers (#631) ([libp2p/go-libp2p-kad-dht#631](https://github.com/libp2p/go-libp2p-kad-dht/pull/631))
- fix all flaky tests ([libp2p/go-libp2p-kad-dht#628](https://github.com/libp2p/go-libp2p-kad-dht/pull/628))
- Update default concurrency parameter ([libp2p/go-libp2p-kad-dht#605](https://github.com/libp2p/go-libp2p-kad-dht/pull/605))
- clean up a channel that was dangling ([libp2p/go-libp2p-kad-dht#620](https://github.com/libp2p/go-libp2p-kad-dht/pull/620))
diff --git a/docs/changelogs/v0.7.md b/docs/changelogs/v0.7.md
index 0160916ba3e..a06602cf313 100644
--- a/docs/changelogs/v0.7.md
+++ b/docs/changelogs/v0.7.md
@@ -149,7 +149,7 @@ The scripts in https://github.com/ipfs/go-ipfs-example-plugin have been updated
- support flatfs fuzzing ([ipfs/go-datastore#157](https://github.com/ipfs/go-datastore/pull/157))
- fuzzing harness (#153) ([ipfs/go-datastore#153](https://github.com/ipfs/go-datastore/pull/153))
- feat(mount): don't give up on error ([ipfs/go-datastore#146](https://github.com/ipfs/go-datastore/pull/146))
- - /test: fix bad ElemCount/10 lenght (should not be divided) ([ipfs/go-datastore#152](https://github.com/ipfs/go-datastore/pull/152))
+ - /test: fix bad ElemCount/10 length (should not be divided) ([ipfs/go-datastore#152](https://github.com/ipfs/go-datastore/pull/152))
- github.com/ipfs/go-ds-flatfs (v0.4.4 -> v0.4.5):
- Add os.Rename wrapper for Plan 9 (#87) ([ipfs/go-ds-flatfs#87](https://github.com/ipfs/go-ds-flatfs/pull/87))
- github.com/ipfs/go-fs-lock (v0.0.5 -> v0.0.6):
@@ -390,7 +390,7 @@ The scripts in https://github.com/ipfs/go-ipfs-example-plugin have been updated
- reset the PTO count before setting the timer when dropping a PN space ([lucas-clemente/quic-go#2657](https://github.com/lucas-clemente/quic-go/pull/2657))
- enforce that a connection ID is not retired in a packet that uses that connection ID ([lucas-clemente/quic-go#2651](https://github.com/lucas-clemente/quic-go/pull/2651))
- don't retire the conn ID that's in use when receiving a retransmission ([lucas-clemente/quic-go#2652](https://github.com/lucas-clemente/quic-go/pull/2652))
- - fix flaky cancelation integration test ([lucas-clemente/quic-go#2649](https://github.com/lucas-clemente/quic-go/pull/2649))
+ - fix flaky cancellation integration test ([lucas-clemente/quic-go#2649](https://github.com/lucas-clemente/quic-go/pull/2649))
- fix crash when the qlog callbacks returns a nil io.WriteCloser ([lucas-clemente/quic-go#2648](https://github.com/lucas-clemente/quic-go/pull/2648))
- fix flaky server test on Travis ([lucas-clemente/quic-go#2645](https://github.com/lucas-clemente/quic-go/pull/2645))
- fix a typo in the logging package test suite
@@ -406,7 +406,7 @@ The scripts in https://github.com/ipfs/go-ipfs-example-plugin have been updated
- remove superfluous parameters logged when not doing 0-RTT ([lucas-clemente/quic-go#2632](https://github.com/lucas-clemente/quic-go/pull/2632))
- return an infinite bandwidth if the RTT is zero ([lucas-clemente/quic-go#2636](https://github.com/lucas-clemente/quic-go/pull/2636))
- drop support for Go 1.13 ([lucas-clemente/quic-go#2628](https://github.com/lucas-clemente/quic-go/pull/2628))
- - remove superfluos handleResetStreamFrame method on the stream ([lucas-clemente/quic-go#2623](https://github.com/lucas-clemente/quic-go/pull/2623))
+ - remove superfluous handleResetStreamFrame method on the stream ([lucas-clemente/quic-go#2623](https://github.com/lucas-clemente/quic-go/pull/2623))
- implement a token-bucket pacing algorithm ([lucas-clemente/quic-go#2615](https://github.com/lucas-clemente/quic-go/pull/2615))
- gracefully handle concurrent stream writes and cancellations ([lucas-clemente/quic-go#2624](https://github.com/lucas-clemente/quic-go/pull/2624))
- log sent packets right before sending them out ([lucas-clemente/quic-go#2613](https://github.com/lucas-clemente/quic-go/pull/2613))
diff --git a/docs/changelogs/v0.8.md b/docs/changelogs/v0.8.md
index 7f4e1d7594c..d9d42fa895a 100644
--- a/docs/changelogs/v0.8.md
+++ b/docs/changelogs/v0.8.md
@@ -1,4 +1,4 @@
-# go-ipfs changelog v0.8
+ # go-ipfs changelog v0.8
## v0.8.0 2021-02-18
@@ -160,7 +160,7 @@ Go 1.15 (the latest version of Go) [no longer supports](https://github.com/golan
- Update go-ipld-prime@v0.5.0 (#92) ([ipfs/go-graphsync#92](https://github.com/ipfs/go-graphsync/pull/92))
- refactor(metadata): use cbor-gen encoding (#96) ([ipfs/go-graphsync#96](https://github.com/ipfs/go-graphsync/pull/96))
- Release/v0.1.2 ([ipfs/go-graphsync#95](https://github.com/ipfs/go-graphsync/pull/95))
- - Return Request context cancelled error (#93) ([ipfs/go-graphsync#93](https://github.com/ipfs/go-graphsync/pull/93))
+ - Return Request context canceled error (#93) ([ipfs/go-graphsync#93](https://github.com/ipfs/go-graphsync/pull/93))
- feat(benchmarks): add p2p stress test (#91) ([ipfs/go-graphsync#91](https://github.com/ipfs/go-graphsync/pull/91))
- Benchmark framework + First memory fixes (#89) ([ipfs/go-graphsync#89](https://github.com/ipfs/go-graphsync/pull/89))
- docs(CHANGELOG): update for v0.1.1 ([ipfs/go-graphsync#85](https://github.com/ipfs/go-graphsync/pull/85))
@@ -277,7 +277,7 @@ Go 1.15 (the latest version of Go) [no longer supports](https://github.com/golan
- satisfy race detector
- clean up
- copy string topic
- - add test for score adjustment from topis params reset
+ - add test for score adjustment from topic params reset
- prettify things
- add test for topic score parameter reset method
- add test for topic score parameter reset
@@ -315,7 +315,7 @@ Go 1.15 (the latest version of Go) [no longer supports](https://github.com/golan
- pass a conn that can be type asserted to a net.UDPConn to quic-go ([libp2p/go-libp2p-quic-transport#180](https://github.com/libp2p/go-libp2p-quic-transport/pull/180))
- add more integration tests ([libp2p/go-libp2p-quic-transport#181](https://github.com/libp2p/go-libp2p-quic-transport/pull/181))
- always close the connection in the cmd client ([libp2p/go-libp2p-quic-transport#175](https://github.com/libp2p/go-libp2p-quic-transport/pull/175))
- - use GitHub Actions to test interopability of releases ([libp2p/go-libp2p-quic-transport#173](https://github.com/libp2p/go-libp2p-quic-transport/pull/173))
+ - use GitHub Actions to test interoperability of releases ([libp2p/go-libp2p-quic-transport#173](https://github.com/libp2p/go-libp2p-quic-transport/pull/173))
- Implement CloseRead/CloseWrite ([libp2p/go-libp2p-quic-transport#174](https://github.com/libp2p/go-libp2p-quic-transport/pull/174))
- enable quic-go metrics collection ([libp2p/go-libp2p-quic-transport#172](https://github.com/libp2p/go-libp2p-quic-transport/pull/172))
- github.com/libp2p/go-libp2p-swarm (v0.2.8 -> v0.4.0):
diff --git a/docs/changelogs/v0.9.md b/docs/changelogs/v0.9.md
index 7289adde7de..64b94e97e72 100644
--- a/docs/changelogs/v0.9.md
+++ b/docs/changelogs/v0.9.md
@@ -571,7 +571,7 @@ SECIO was deprecated and turned off by default given the prevalence of TLS and N
- fix retry key and nonce for draft-34 ([lucas-clemente/quic-go#3062](https://github.com/lucas-clemente/quic-go/pull/3062))
- implement DPLPMTUD ([lucas-clemente/quic-go#3028](https://github.com/lucas-clemente/quic-go/pull/3028))
- only read multiple packets at a time after handshake completion ([lucas-clemente/quic-go#3041](https://github.com/lucas-clemente/quic-go/pull/3041))
- - make the certificate verificiation integration tests more explicit ([lucas-clemente/quic-go#3040](https://github.com/lucas-clemente/quic-go/pull/3040))
+ - make the certificate verification integration tests more explicit ([lucas-clemente/quic-go#3040](https://github.com/lucas-clemente/quic-go/pull/3040))
- update gomock to v1.5.0, use mockgen source mode ([lucas-clemente/quic-go#3049](https://github.com/lucas-clemente/quic-go/pull/3049))
- trace dropping of 0-RTT keys ([lucas-clemente/quic-go#3054](https://github.com/lucas-clemente/quic-go/pull/3054))
- improve timeout measurement in the timeout test ([lucas-clemente/quic-go#3042](https://github.com/lucas-clemente/quic-go/pull/3042))
@@ -596,10 +596,10 @@ SECIO was deprecated and turned off by default given the prevalence of TLS and N
- make sure the server is stopped before closing all server sessions ([lucas-clemente/quic-go#3020](https://github.com/lucas-clemente/quic-go/pull/3020))
- increase the size of the send queue ([lucas-clemente/quic-go#3016](https://github.com/lucas-clemente/quic-go/pull/3016))
- prioritize receiving packets over sending out more packets ([lucas-clemente/quic-go#3015](https://github.com/lucas-clemente/quic-go/pull/3015))
- - reenable key updates for HTTP/3 ([lucas-clemente/quic-go#3017](https://github.com/lucas-clemente/quic-go/pull/3017))
+ - re-enable key updates for HTTP/3 ([lucas-clemente/quic-go#3017](https://github.com/lucas-clemente/quic-go/pull/3017))
- check for errors after handling each previously undecryptable packet ([lucas-clemente/quic-go#3011](https://github.com/lucas-clemente/quic-go/pull/3011))
- fix flaky streams map test on Windows ([lucas-clemente/quic-go#3013](https://github.com/lucas-clemente/quic-go/pull/3013))
- - fix flaky stream cancelation integration test ([lucas-clemente/quic-go#3014](https://github.com/lucas-clemente/quic-go/pull/3014))
+ - fix flaky stream cancellation integration test ([lucas-clemente/quic-go#3014](https://github.com/lucas-clemente/quic-go/pull/3014))
- preallocate a slice of one frame when packing a packet ([lucas-clemente/quic-go#3018](https://github.com/lucas-clemente/quic-go/pull/3018))
- allow sending of ACKs when pacing limited ([lucas-clemente/quic-go#3010](https://github.com/lucas-clemente/quic-go/pull/3010))
- fix qlogging of the packet payload length ([lucas-clemente/quic-go#3004](https://github.com/lucas-clemente/quic-go/pull/3004))
@@ -624,7 +624,7 @@ SECIO was deprecated and turned off by default given the prevalence of TLS and N
- fix flaky qlog test ([lucas-clemente/quic-go#2981](https://github.com/lucas-clemente/quic-go/pull/2981))
- only run gofumpt on .go files in pre-commit hook ([lucas-clemente/quic-go#2983](https://github.com/lucas-clemente/quic-go/pull/2983))
- fix outdated comment for the http3.Server
- - make the OpenStreamSync cancelation test less flaky ([lucas-clemente/quic-go#2978](https://github.com/lucas-clemente/quic-go/pull/2978))
+ - make the OpenStreamSync cancellation test less flaky ([lucas-clemente/quic-go#2978](https://github.com/lucas-clemente/quic-go/pull/2978))
- add some useful pre-commit hooks ([lucas-clemente/quic-go#2979](https://github.com/lucas-clemente/quic-go/pull/2979))
- publicize QUIC varint reading and writing ([lucas-clemente/quic-go#2973](https://github.com/lucas-clemente/quic-go/pull/2973))
- add a http3.RoundTripOpt to skip the request scheme check ([lucas-clemente/quic-go#2962](https://github.com/lucas-clemente/quic-go/pull/2962))
diff --git a/docs/config.md b/docs/config.md
index 82e5c0cdb22..e40ac5887e4 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -9,16 +9,6 @@ config file at runtime.
- [The Kubo config file](#the-kubo-config-file)
- [Table of Contents](#table-of-contents)
- - [Profiles](#profiles)
- - [Types](#types)
- - [`flag`](#flag)
- - [`priority`](#priority)
- - [`strings`](#strings)
- - [`duration`](#duration)
- - [`optionalInteger`](#optionalinteger)
- - [`optionalBytes`](#optionalbytes)
- - [`optionalString`](#optionalstring)
- - [`optionalDuration`](#optionalduration)
- [`Addresses`](#addresses)
- [`Addresses.API`](#addressesapi)
- [`Addresses.Gateway`](#addressesgateway)
@@ -37,6 +27,18 @@ config file at runtime.
- [`AutoNAT.Throttle.GlobalLimit`](#autonatthrottlegloballimit)
- [`AutoNAT.Throttle.PeerLimit`](#autonatthrottlepeerlimit)
- [`AutoNAT.Throttle.Interval`](#autonatthrottleinterval)
+ - [`AutoTLS`](#autotls)
+ - [`AutoTLS.Enabled`](#autotlsenabled)
+ - [`AutoTLS.AutoWSS`](#autotlsautowss)
+ - [`AutoTLS.ShortAddrs`](#autotlsshortaddrs)
+ - [`AutoTLS.DomainSuffix`](#autotlsdomainsuffix)
+ - [`AutoTLS.RegistrationEndpoint`](#autotlsregistrationendpoint)
+ - [`AutoTLS.RegistrationToken`](#autotlsregistrationtoken)
+ - [`AutoTLS.RegistrationDelay`](#autotlsregistrationdelay)
+ - [`AutoTLS.CAEndpoint`](#autotlscaendpoint)
+ - [`Bitswap`](#bitswap)
+ - [`Bitswap.Libp2pEnabled`](#bitswaplibp2penabled)
+ - [`Bitswap.ServerEnabled`](#bitswapserverenabled)
- [`Bootstrap`](#bootstrap)
- [`Datastore`](#datastore)
- [`Datastore.StorageMax`](#datastorestoragemax)
@@ -44,6 +46,8 @@ config file at runtime.
- [`Datastore.GCPeriod`](#datastoregcperiod)
- [`Datastore.HashOnRead`](#datastorehashonread)
- [`Datastore.BloomFilterSize`](#datastorebloomfiltersize)
+ - [`Datastore.WriteThrough`](#datastorewritethrough)
+ - [`Datastore.BlockKeyCacheSize`](#datastoreblockkeycachesize)
- [`Datastore.Spec`](#datastorespec)
- [`Discovery`](#discovery)
- [`Discovery.MDNS`](#discoverymdns)
@@ -78,7 +82,8 @@ config file at runtime.
- [`Internal.Bitswap.EngineBlockstoreWorkerCount`](#internalbitswapengineblockstoreworkercount)
- [`Internal.Bitswap.EngineTaskWorkerCount`](#internalbitswapenginetaskworkercount)
- [`Internal.Bitswap.MaxOutstandingBytesPerPeer`](#internalbitswapmaxoutstandingbytesperpeer)
- - [`Internal.Bitswap.ProviderSearchDelay`](#internalbitswapprovidersearchdelay)
+ - [`Internal.Bitswap.ProviderSearchDelay`](#internalbitswapprovidersearchdelay)
+ - [`Internal.Bitswap.ProviderSearchMaxResults`](#internalbitswapprovidersearchmaxresults)
- [`Internal.UnixFSShardingSizeThreshold`](#internalunixfsshardingsizethreshold)
- [`Ipns`](#ipns)
- [`Ipns.RepublishPeriod`](#ipnsrepublishperiod)
@@ -92,6 +97,7 @@ config file at runtime.
- [`Mounts`](#mounts)
- [`Mounts.IPFS`](#mountsipfs)
- [`Mounts.IPNS`](#mountsipns)
+ - [`Mounts.MFS`](#mountsmfs)
- [`Mounts.FuseAllowOther`](#mountsfuseallowother)
- [`Pinning`](#pinning)
- [`Pinning.RemoteServices`](#pinningremoteservices)
@@ -103,6 +109,10 @@ config file at runtime.
- [`Pinning.RemoteServices: Policies.MFS.Enabled`](#pinningremoteservices-policiesmfsenabled)
- [`Pinning.RemoteServices: Policies.MFS.PinName`](#pinningremoteservices-policiesmfspinname)
- [`Pinning.RemoteServices: Policies.MFS.RepinInterval`](#pinningremoteservices-policiesmfsrepininterval)
+ - [`Provider`](#provider)
+ - [`Provider.Enabled`](#providerenabled)
+ - [`Provider.Strategy`](#providerstrategy)
+ - [`Provider.WorkerCount`](#providerworkercount)
- [`Pubsub`](#pubsub)
- [`Pubsub.Enabled`](#pubsubenabled)
- [`Pubsub.Router`](#pubsubrouter)
@@ -117,6 +127,9 @@ config file at runtime.
- [`Routing`](#routing)
- [`Routing.Type`](#routingtype)
- [`Routing.AcceleratedDHTClient`](#routingaccelerateddhtclient)
+ - [`Routing.LoopbackAddressesOnLanDHT`](#routingloopbackaddressesonlandht)
+ - [`Routing.IgnoreProviders`](#routingignoreproviders)
+ - [`Routing.DelegatedRouters`](#routingdelegatedrouters)
- [`Routing.Routers`](#routingrouters)
- [`Routing.Routers: Type`](#routingrouters-type)
- [`Routing.Routers: Parameters`](#routingrouters-parameters)
@@ -174,169 +187,55 @@ config file at runtime.
- [`DNS`](#dns)
- [`DNS.Resolvers`](#dnsresolvers)
- [`DNS.MaxCacheTTL`](#dnsmaxcachettl)
-
-## Profiles
-
-Configuration profiles allow to tweak configuration quickly. Profiles can be
-applied with the `--profile` flag to `ipfs init` or with the `ipfs config profile
-apply` command. When a profile is applied a backup of the configuration file
-will be created in `$IPFS_PATH`.
-
-The available configuration profiles are listed below. You can also find them
-documented in `ipfs config profile --help`.
-
-- `server`
-
- Disables local host discovery, recommended when
- running IPFS on machines with public IPv4 addresses.
-
-- `randomports`
-
- Use a random port number for the incoming swarm connections.
-
-- `default-datastore`
-
- Configures the node to use the default datastore (flatfs).
-
- Read the "flatfs" profile description for more information on this datastore.
-
- This profile may only be applied when first initializing the node.
-
-- `local-discovery`
-
- Enables local discovery (enabled by default). Useful to re-enable local discovery after it's
- disabled by another profile (e.g., the server profile).
-
-- `test`
-
- Reduces external interference of IPFS daemon, this
- is useful when using the daemon in test environments.
-
-- `default-networking`
-
- Restores default network settings.
- Inverse profile of the test profile.
-
-- `flatfs`
-
- Configures the node to use the flatfs datastore. Flatfs is the default datastore.
-
- This is the most battle-tested and reliable datastore.
- You should use this datastore if:
-
- - You need a very simple and very reliable datastore, and you trust your
- filesystem. This datastore stores each block as a separate file in the
- underlying filesystem so it's unlikely to lose data unless there's an issue
- with the underlying file system.
- - You need to run garbage collection in a way that reclaims free space as soon as possible.
- - You want to minimize memory usage.
- - You are ok with the default speed of data import, or prefer to use `--nocopy`.
-
- This profile may only be applied when first initializing the node.
-
-
-- `badgerds`
-
- Configures the node to use the experimental badger datastore. Keep in mind that this **uses an outdated badger 1.x**.
-
- Use this datastore if some aspects of performance,
- especially the speed of adding many gigabytes of files, are critical. However, be aware that:
-
- - This datastore will not properly reclaim space when your datastore is
- smaller than several gigabytes. If you run IPFS with `--enable-gc`, you plan on storing very little data in
- your IPFS node, and disk usage is more critical than performance, consider using
- `flatfs`.
- - This datastore uses up to several gigabytes of memory.
- - Good for medium-size datastores, but may run into performance issues if your dataset is bigger than a terabyte.
- - The current implementation is based on old badger 1.x which is no longer supported by the upstream team.
-
- This profile may only be applied when first initializing the node.
-
-- `lowpower`
-
- Reduces daemon overhead on the system. Affects node
- functionality - performance of content discovery and data
- fetching may be degraded. Local data won't be announced on routing systems like Amino DHT.
-
- - `Swarm.ConnMgr` set to maintain minimum number of p2p connections at a time.
- - Disables [`Reprovider`](#reprovider) service → no CID will be announced on Amino DHT and other routing systems(!)
- - Disables AutoNAT.
-
- Use this profile with caution.
-
-## Types
-
-This document refers to the standard JSON types (e.g., `null`, `string`,
-`number`, etc.), as well as a few custom types, described below.
-
-### `flag`
-
-Flags allow enabling and disabling features. However, unlike simple booleans,
-they can also be `null` (or omitted) to indicate that the default value should
-be chosen. This makes it easier for Kubo to change the defaults in the
-future unless the user _explicitly_ sets the flag to either `true` (enabled) or
-`false` (disabled). Flags have three possible states:
-
-- `null` or missing (apply the default value).
-- `true` (enabled)
-- `false` (disabled)
-
-### `priority`
-
-Priorities allow specifying the priority of a feature/protocol and disabling the
-feature/protocol. Priorities can take one of the following values:
-
-- `null`/missing (apply the default priority, same as with flags)
-- `false` (disabled)
-- `1 - 2^63` (priority, lower is preferred)
-
-### `strings`
-
-Strings is a special type for conveniently specifying a single string, an array
-of strings, or null:
-
-- `null`
-- `"a single string"`
-- `["an", "array", "of", "strings"]`
-
-### `duration`
-
-Duration is a type for describing lengths of time, using the same format go
-does (e.g, `"1d2h4m40.01s"`).
-
-### `optionalInteger`
-
-Optional integers allow specifying some numerical value which has
-an implicit default when missing from the config file:
-
-- `null`/missing will apply the default value defined in Kubo sources (`.WithDefault(value)`)
-- an integer between `-2^63` and `2^63-1` (i.e. `-9223372036854775808` to `9223372036854775807`)
-
-### `optionalBytes`
-
-Optional Bytes allow specifying some number of bytes which has
-an implicit default when missing from the config file:
-
-- `null`/missing (apply the default value defined in Kubo sources)
-- a string value indicating the number of bytes, including human readable representations:
- - [SI sizes](https://en.wikipedia.org/wiki/Metric_prefix#List_of_SI_prefixes) (metric units, powers of 1000), e.g. `1B`, `2kB`, `3MB`, `4GB`, `5TB`, …)
- - [IEC sizes](https://en.wikipedia.org/wiki/Binary_prefix#IEC_prefixes) (binary units, powers of 1024), e.g. `1B`, `2KiB`, `3MiB`, `4GiB`, `5TiB`, …)
-
-### `optionalString`
-
-Optional strings allow specifying some string value which has
-an implicit default when missing from the config file:
-
-- `null`/missing will apply the default value defined in Kubo sources (`.WithDefault("value")`)
-- a string
-
-### `optionalDuration`
-
-Optional durations allow specifying some duration value which has
-an implicit default when missing from the config file:
-
-- `null`/missing will apply the default value defined in Kubo sources (`.WithDefault("1h2m3s")`)
-- a string with a valid [go duration](#duration) (e.g, `"1d2h4m40.01s"`).
+ - [`HTTPRetrieval`](#httpretrieval)
+ - [`HTTPRetrieval.Enabled`](#httpretrievalenabled)
+ - [`HTTPRetrieval.Allowlist`](#httpretrievalallowlist)
+ - [`HTTPRetrieval.Denylist`](#httpretrievaldenylist)
+ - [`HTTPRetrieval.NumWorkers`](#httpretrievalnumworkers)
+ - [`HTTPRetrieval.MaxBlockSize`](#httpretrievalmaxblocksize)
+ - [`HTTPRetrieval.TLSInsecureSkipVerify`](#httpretrievaltlsinsecureskipverify)
+ - [`Import`](#import)
+ - [`Import.CidVersion`](#importcidversion)
+ - [`Import.UnixFSRawLeaves`](#importunixfsrawleaves)
+ - [`Import.UnixFSChunker`](#importunixfschunker)
+ - [`Import.HashFunction`](#importhashfunction)
+ - [`Import.BatchMaxNodes`](#importbatchmaxnodes)
+ - [`Import.BatchMaxSize`](#importbatchmaxsize)
+ - [`Import.UnixFSFileMaxLinks`](#importunixfsfilemaxlinks)
+ - [`Import.UnixFSDirectoryMaxLinks`](#importunixfsdirectorymaxlinks)
+ - [`Import.UnixFSHAMTDirectoryMaxFanout`](#importunixfshamtdirectorymaxfanout)
+ - [`Import.UnixFSHAMTDirectorySizeThreshold`](#importunixfshamtdirectorysizethreshold)
+ - [`Version`](#version)
+ - [`Version.AgentSuffix`](#versionagentsuffix)
+ - [`Version.SwarmCheckEnabled`](#versionswarmcheckenabled)
+ - [`Version.SwarmCheckPercentThreshold`](#versionswarmcheckpercentthreshold)
+ - [Profiles](#profiles)
+ - [`server` profile](#server-profile)
+ - [`randomports` profile](#randomports-profile)
+ - [`default-datastore` profile](#default-datastore-profile)
+ - [`local-discovery` profile](#local-discovery-profile)
+ - [`default-networking` profile](#default-networking-profile)
+ - [`flatfs` profile](#flatfs-profile)
+ - [`flatfs-measure` profile](#flatfs-measure-profile)
+ - [`pebbleds` profile](#pebbleds-profile)
+ - [`pebbleds-measure` profile](#pebbleds-measure-profile)
+ - [`badgerds` profile](#badgerds-profile)
+ - [`badgerds-measure` profile](#badgerds-measure-profile)
+ - [`lowpower` profile](#lowpower-profile)
+ - [`announce-off` profile](#announce-off-profile)
+ - [`announce-on` profile](#announce-on-profile)
+ - [`legacy-cid-v0` profile](#legacy-cid-v0-profile)
+ - [`test-cid-v1` profile](#test-cid-v1-profile)
+ - [`test-cid-v1-wide` profile](#test-cid-v1-wide-profile)
+ - [Types](#types)
+ - [`flag`](#flag)
+ - [`priority`](#priority)
+ - [`strings`](#strings)
+ - [`duration`](#duration)
+ - [`optionalInteger`](#optionalinteger)
+ - [`optionalBytes`](#optionalbytes)
+ - [`optionalString`](#optionalstring)
+ - [`optionalDuration`](#optionalduration)
## `Addresses`
@@ -344,22 +243,35 @@ Contains information about various listener addresses to be used by this node.
### `Addresses.API`
-Multiaddr or array of multiaddrs describing the address to serve the local HTTP
-API on.
+[Multiaddr][multiaddr] or array of multiaddrs describing the addresses to serve
+the local [Kubo RPC API](https://docs.ipfs.tech/reference/kubo/rpc/) (`/api/v0`).
Supported Transports:
* tcp/ip{4,6} - `/ipN/.../tcp/...`
* unix - `/unix/path/to/socket`
+> [!CAUTION]
+> **NEVER EXPOSE UNPROTECTED ADMIN RPC TO LAN OR THE PUBLIC INTERNET**
+>
+> The RPC API grants admin-level access to your Kubo IPFS node, including
+> configuration and secret key management.
+>
+> By default, it is bound to localhost for security reasons. Exposing it to LAN
+> or the public internet is highly risky—similar to exposing a SQL database or
+> backend service without authentication middleware
+>
+> - If you need secure access to a subset of RPC, secure it with [`API.Authorizations`](#apiauthorizations) or custom auth middleware running in front of the localhost-only RPC port defined here.
+> - If you are looking for an interface designed for browsers and public internet, use [`Addresses.Gateway`](#addressesgateway) port instead.
+
Default: `/ip4/127.0.0.1/tcp/5001`
-Type: `strings` (multiaddrs)
+Type: `strings` ([multiaddrs][multiaddr])
### `Addresses.Gateway`
-Multiaddr or array of multiaddrs describing the address to serve the local
-gateway on.
+[Multiaddr][multiaddr] or array of multiaddrs describing the address to serve
+the local [HTTP gateway](https://specs.ipfs.tech/http-gateways/) (`/ipfs`, `/ipns`) on.
Supported Transports:
@@ -368,11 +280,11 @@ Supported Transports:
Default: `/ip4/127.0.0.1/tcp/8080`
-Type: `strings` (multiaddrs)
+Type: `strings` ([multiaddrs][multiaddr])
### `Addresses.Swarm`
-An array of multiaddrs describing which addresses to listen on for p2p swarm
+An array of [multiaddrs][multiaddr] describing which addresses to listen on for p2p swarm
connections.
Supported Transports:
@@ -382,6 +294,9 @@ Supported Transports:
* quicv1 (RFC9000) - `/ipN/.../udp/.../quic-v1` - can share the same two tuple with `/quic-v1/webtransport`
* webtransport `/ipN/.../udp/.../quic-v1/webtransport` - can share the same two tuple with `/quic-v1`
+> [!IMPORTANT]
+> Make sure your firewall rules allow incoming connections on both TCP and UDP ports defined here.
+
Note that quic (Draft-29) used to be supported with the format `/ipN/.../udp/.../quic`, but has since been [removed](https://github.com/libp2p/go-libp2p/releases/tag/v0.30.0).
Default:
@@ -396,7 +311,7 @@ Default:
]
```
-Type: `array[string]` (multiaddrs)
+Type: `array[string]` ([multiaddrs][multiaddr])
### `Addresses.Announce`
@@ -405,7 +320,7 @@ network. If empty, the daemon will announce inferred swarm addresses.
Default: `[]`
-Type: `array[string]` (multiaddrs)
+Type: `array[string]` ([multiaddrs][multiaddr])
### `Addresses.AppendAnnounce`
@@ -414,27 +329,35 @@ override inferred swarm addresses if non-empty.
Default: `[]`
-Type: `array[string]` (multiaddrs)
+Type: `array[string]` ([multiaddrs][multiaddr])
### `Addresses.NoAnnounce`
An array of swarm addresses not to announce to the network.
Takes precedence over `Addresses.Announce` and `Addresses.AppendAnnounce`.
+> [!TIP]
+> The [`server` configuration profile](#server-profile) fills up this list with sensible defaults,
+> preventing announcement of non-routable IP addresses (e.g., `/ip4/192.168.0.0/ipcidr/16`,
+> which is the [multiaddress][multiaddr] representation of `192.168.0.0/16`) but you should always
+> check settings against your own network and/or hosting provider.
+
Default: `[]`
-Type: `array[string]` (multiaddrs)
+Type: `array[string]` ([multiaddrs][multiaddr])
## `API`
-Contains information used by the API gateway.
+
+Contains information used by the [Kubo RPC API](https://docs.ipfs.tech/reference/kubo/rpc/).
### `API.HTTPHeaders`
-Map of HTTP headers to set on responses from the API HTTP server.
+
+Map of HTTP headers to set on responses from the RPC (`/api/v0`) HTTP server.
Example:
```json
{
- "Foo": ["bar"]
+ "Foo": ["bar"]
}
```
@@ -448,7 +371,7 @@ The `API.Authorizations` field defines user-based access restrictions for the
[Kubo RPC API](https://docs.ipfs.tech/reference/kubo/rpc/), which is located at
`Addresses.API` under `/api/v0` paths.
-By default, the RPC API is accessible without restrictions as it is only
+By default, the admin-level RPC API is accessible without restrictions as it is only
exposed on `127.0.0.1` and safeguarded with Origin check and implicit
[CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) headers that
block random websites from accessing the RPC.
@@ -458,9 +381,18 @@ unless a corresponding secret is present in the HTTP [`Authorization` header](ht
and the requested path is included in the `AllowedPaths` list for that specific
secret.
+> [!CAUTION]
+> **NEVER EXPOSE UNPROTECTED ADMIN RPC TO LAN OR THE PUBLIC INTERNET**
+>
+> The RPC API is vast. It grants admin-level access to your Kubo IPFS node, including
+> configuration and secret key management.
+>
+> - If you need secure access to a subset of RPC, make sure you understand the risk, block everything by default and allow basic auth access with [`API.Authorizations`](#apiauthorizations) or custom auth middleware running in front of the localhost-only port defined in [`Addresses.API`](#addressesapi).
+> - If you are looking for an interface designed for browsers and public internet, use [`Addresses.Gateway`](#addressesgateway) port instead.
+
Default: `null`
-Type: `object[string -> object]` (user name -> authorization object, see bellow)
+Type: `object[string -> object]` (user name -> authorization object, see below)
For example, to limit RPC access to Alice (access `id` and MFS `files` commands with HTTP Basic Auth)
and Bob (full access with Bearer token):
@@ -525,7 +457,7 @@ Type: `array[string]`
## `AutoNAT`
-Contains the configuration options for the AutoNAT service. The AutoNAT service
+Contains the configuration options for the libp2p's [AutoNAT](https://github.com/libp2p/specs/tree/master/autonat) service. The AutoNAT service
helps other nodes on the network determine if they're publicly reachable from
the rest of the internet.
@@ -534,13 +466,22 @@ the rest of the internet.
When unset (default), the AutoNAT service defaults to _enabled_. Otherwise, this
field can take one of two values:
-* "enabled" - Enable the service (unless the node determines that it, itself,
- isn't reachable by the public internet).
-* "disabled" - Disable the service.
+* `enabled` - Enable the V1+V2 service (unless the node determines that it,
+ itself, isn't reachable by the public internet).
+* `legacy-v1` - Same as `enabled` but only V1 service is enabled. Used for testing
+ during as few releases as we [transition to V2](https://github.com/ipfs/kubo/issues/10091), will be removed in the future.
+* `disabled` - Disable the service.
Additional modes may be added in the future.
-Type: `string` (one of `"enabled"` or `"disabled"`)
+> [!IMPORTANT]
+> We are in the progress of [rolling out AutoNAT V2](https://github.com/ipfs/kubo/issues/10091).
+> Right now, by default, a publicly dialable Kubo provides both V1 and V2 service to other peers,
+> but only V1 is used by Kubo as a client. In a future release we will remove V1 and switch client to use V2.
+
+Default: `enabled`
+
+Type: `optionalString`
### `AutoNAT.Throttle`
@@ -572,13 +513,163 @@ Default: 1 Minute
Type: `duration` (when `0`/unset, the default value is used)
+## `AutoTLS`
+
+The [AutoTLS](https://blog.libp2p.io/autotls/) feature enables publicly reachable Kubo nodes (those dialable from the public
+internet) to automatically obtain a wildcard TLS certificate for a DNS name
+unique to their PeerID at `*.[PeerID].libp2p.direct`. This enables direct
+libp2p connections and retrieval of IPFS content from browsers [Secure Context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts)
+using transports such as [Secure WebSockets](https://github.com/libp2p/specs/blob/master/websockets/README.md),
+without requiring user to do any manual domain registration and certificate configuration.
+
+Under the hood, [p2p-forge] client uses public utility service at `libp2p.direct` as an [ACME DNS-01 Challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge)
+broker enabling peer to obtain a wildcard TLS certificate tied to public key of their [PeerID](https://docs.libp2p.io/concepts/fundamentals/peers/#peer-id).
+
+By default, the certificates are requested from Let's Encrypt. Origin and rationale for this project can be found in [community.letsencrypt.org discussion](https://community.letsencrypt.org/t/feedback-on-raising-certificates-per-registered-domain-to-enable-peer-to-peer-networking/223003).
+
+
+
+> [!NOTE]
+> Public good DNS and [p2p-forge] infrastructure at `libp2p.direct` is run by the team at [Interplanetary Shipyard](https://ipshipyard.com).
+>
+[p2p-forge]: https://github.com/ipshipyard/p2p-forge
+
+Default: `{}`
+
+Type: `object`
+
+### `AutoTLS.Enabled`
+
+Enables the AutoTLS feature to provide DNS and TLS support for [libp2p Secure WebSocket](https://github.com/libp2p/specs/blob/master/websockets/README.md) over a `/tcp` port,
+to allow JS clients running in web browser [Secure Context](https://w3c.github.io/webappsec-secure-contexts/) to connect to Kubo directly.
+
+When activated, together with [`AutoTLS.AutoWSS`](#autotlsautowss) (default) or manually including a `/tcp/{port}/tls/sni/*.libp2p.direct/ws` multiaddr in [`Addresses.Swarm`](#addressesswarm)
+(with SNI suffix matching [`AutoTLS.DomainSuffix`](#autotlsdomainsuffix)), Kubo retrieves a trusted PKI TLS certificate for `*.{peerid}.libp2p.direct` and configures the `/ws` listener to use it.
+
+**Note:**
+
+- This feature requires a publicly reachable node. If behind NAT, manual port forwarding or UPnP (`Swarm.DisableNatPortMap=false`) is required.
+- The first time AutoTLS is used, it may take 5-15 minutes + [`AutoTLS.RegistrationDelay`](#autotlsregistrationdelay) before `/ws` listener is added. Be patient.
+- Avoid manual configuration. [`AutoTLS.AutoWSS=true`](#autotlsautowss) should automatically add `/ws` listener to existing, firewall-forwarded `/tcp` ports.
+- To troubleshoot, use `GOLOG_LOG_LEVEL="error,autotls=debug` for detailed logs, or `GOLOG_LOG_LEVEL="error,autotls=info` for quieter output.
+- Certificates are stored in `$IPFS_PATH/p2p-forge-certs`; deleting this directory and restarting the daemon forces a certificate rotation.
+- For now, the TLS cert applies solely to `/ws` libp2p WebSocket connections, not HTTP [`Gateway`](#gateway), which still need separate reverse proxy TLS setup with a custom domain.
+
+Default: `true`
+
+Type: `flag`
+
+### `AutoTLS.AutoWSS`
+
+Optional. Controls if Kubo should add `/tls/sni/*.libp2p.direct/ws` listener to every pre-existing `/tcp` port IFF no explicit `/ws` is defined in [`Addresses.Swarm`](#addressesswarm) already.
+
+Default: `true` (if `AutoTLS.Enabled`)
+
+Type: `flag`
+
+### `AutoTLS.ShortAddrs`
+
+Optional. Controls if final AutoTLS listeners are announced under shorter `/dnsX/A.B.C.D.peerid.libp2p.direct/tcp/4001/tls/ws` addresses instead of fully resolved `/ip4/A.B.C.D/tcp/4001/tls/sni/A-B-C-D.peerid.libp2p.direct/tls/ws`.
+
+The main use for AutoTLS is allowing connectivity from Secure Context in a web browser, and DNS lookup needs to happen there anyway, making `/dnsX` a more compact, more interoperable option without obvious downside.
+
+Default: `true`
+
+Type: `flag`
+
+### `AutoTLS.DomainSuffix`
+
+Optional override of the parent domain suffix that will be used in DNS+TLS+WebSockets multiaddrs generated by [p2p-forge] client.
+Do not change this unless you self-host [p2p-forge].
+
+Default: `libp2p.direct` (public good run by [Interplanetary Shipyard](https://ipshipyard.com))
+
+Type: `optionalString`
+
+### `AutoTLS.RegistrationEndpoint`
+
+Optional override of [p2p-forge] HTTP registration API.
+Do not change this unless you self-host [p2p-forge] under own domain.
+
+> [!IMPORTANT]
+> The default endpoint performs [libp2p Peer ID Authentication over HTTP](https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md)
+> (proving ownership of PeerID), probes if your Kubo node can correctly answer to a [libp2p Identify](https://github.com/libp2p/specs/tree/master/identify) query.
+> This ensures only a correctly configured, publicly dialable Kubo can initiate [ACME DNS-01 challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) for `peerid.libp2p.direct`.
+
+Default: `https://registration.libp2p.direct` (public good run by [Interplanetary Shipyard](https://ipshipyard.com))
+
+Type: `optionalString`
+
+### `AutoTLS.RegistrationToken`
+
+Optional value for `Forge-Authorization` token sent with request to `RegistrationEndpoint`
+(useful for private/self-hosted/test instances of [p2p-forge], unset by default).
+
+Default: `""`
+
+Type: `optionalString`
+
+### `AutoTLS.RegistrationDelay`
+
+An additional delay applied before sending a request to the `RegistrationEndpoint`.
+
+The default delay is bypassed if the user explicitly set `AutoTLS.Enabled=true` in the JSON configuration file.
+This ensures that ephemeral nodes using the default configuration do not spam the`AutoTLS.CAEndpoint` with unnecessary ACME requests.
+
+Default: `1h` (or `0` if explicit `AutoTLS.Enabled=true`)
+
+Type: `optionalDuration`
+
+### `AutoTLS.CAEndpoint`
+
+Optional override of CA ACME API used by [p2p-forge] system.
+Do not change this unless you self-host [p2p-forge] under own domain.
+
+> [!IMPORTANT]
+> CAA DNS record at `libp2p.direct` limits CA choice to Let's Encrypt. If you want to use a different CA, use your own domain.
+
+Default: [certmagic.LetsEncryptProductionCA](https://pkg.go.dev/github.com/caddyserver/certmagic#pkg-constants) (see [community.letsencrypt.org discussion](https://community.letsencrypt.org/t/feedback-on-raising-certificates-per-registered-domain-to-enable-peer-to-peer-networking/223003))
+
+Type: `optionalString`
+
+## `Bitswap`
+
+High level client and server configuration of the [Bitswap Protocol](https://specs.ipfs.tech/bitswap-protocol/) over libp2p.
+
+For internal configuration see [`Internal.Bitswap`](#internalbitswap).
+
+For HTTP version see [`HTTPRetrieval`](#httpretrieval).
+
+### `Bitswap.Libp2pEnabled`
+
+Determines whether Kubo will use Bitswap over libp2p.
+
+Disabling this, will remove `/ipfs/bitswap/*` protocol support from [libp2p identify](https://github.com/libp2p/specs/blob/master/identify/README.md) responses, effectively shutting down both Bitswap libp2p client and server.
+
+> [!WARNING]
+> Bitswap over libp2p is a core component of Kubo and the oldest way of exchanging blocks. Disabling it completely may cause unpredictable outcomes, such as retrieval failures, if the only providers were libp2p ones. Treat this as experimental and use it solely for testing purposes with `HTTPRetrieval.Enabled`.
+
+Default: `true`
+
+Type: `flag`
+
+### `Bitswap.ServerEnabled`
+
+Determines whether Kubo functions as a Bitswap server to host and respond to block requests.
+
+Disabling the server retains client and protocol support in [libp2p identify](https://github.com/libp2p/specs/blob/master/identify/README.md) responses but causes Kubo to reply with "don't have" to all block requests.
+
+Default: `true` (requires `Bitswap.Libp2pEnabled`)
+
+Type: `flag`
+
## `Bootstrap`
-Bootstrap is an array of multiaddrs of trusted nodes that your node connects to, to fetch other nodes of the network on startup.
+Bootstrap is an array of [multiaddrs][multiaddr] of trusted nodes that your node connects to, to fetch other nodes of the network on startup.
-Default: The ipfs.io bootstrap nodes
+Default: [`config.DefaultBootstrapAddresses`](https://github.com/ipfs/kubo/blob/master/config/bootstrap_peers.go)
-Type: `array[string]` (multiaddrs)
+Type: `array[string]` ([multiaddrs][multiaddr])
## `Datastore`
@@ -638,49 +729,106 @@ we'd want to use 1199120 bytes. As of writing, [7 hash
functions](https://github.com/ipfs/go-ipfs-blockstore/blob/547442836ade055cc114b562a3cc193d4e57c884/caching.go#L22)
are used, so the constant `k` is 7 in the formula.
+Enabling the BloomFilter can provide performance improvements specially when
+responding to many requests for inexistent blocks. It however requires a full
+sweep of all the datastore keys on daemon start. On very large datastores this
+can be a very taxing operation, particularly if the datastore does not support
+querying existing keys without reading their values at the same time (blocks).
+
Default: `0` (disabled)
Type: `integer` (non-negative, bytes)
+### `Datastore.WriteThrough`
+
+This option controls whether a block that already exist in the datastore
+should be written to it. When set to `false`, a `Has()` call is performed
+against the datastore prior to writing every block. If the block is already
+stored, the write is skipped. This check happens both on the Blockservice and
+the Blockstore layers and this setting affects both.
+
+When set to `true`, no checks are performed and blocks are written to the
+datastore, which depending on the implementation may perform its own checks.
+
+This option can affect performance and the strategy should be taken in
+conjunction with [`BlockKeyCacheSize`](#datastoreblockkeycachesize) and
+[`BloomFilterSize`](#datastoreboomfiltersize`).
+
+Default: `true`
+
+Type: `bool`
+
+### `Datastore.BlockKeyCacheSize`
+
+A number representing the maximum size in bytes of the blockstore's Two-Queue
+cache, which caches block-cids and their block-sizes. Use `0` to disable.
+
+This cache, once primed, can greatly speed up operations like `ipfs repo stat`
+as there is no need to read full blocks to know their sizes. Size should be
+adjusted depending on the number of CIDs on disk (`NumObjects in `ipfs repo stat`).
+
+Default: `65536` (64KiB)
+
+Type: `optionalInteger` (non-negative, bytes)
+
### `Datastore.Spec`
Spec defines the structure of the ipfs datastore. It is a composable structure,
where each datastore is represented by a json object. Datastores can wrap other
datastores to provide extra functionality (eg metrics, logging, or caching).
-This can be changed manually, however, if you make any changes that require a
-different on-disk structure, you will need to run the [ipfs-ds-convert
-tool](https://github.com/ipfs/ipfs-ds-convert) to migrate data into the new
-structures.
-
-For more information on possible values for this configuration option, see
-[docs/datastores.md](datastores.md)
+> [!NOTE]
+> For more information on possible values for this configuration option, see [`kubo/docs/datastores.md`](datastores.md)
Default:
```
{
"mounts": [
- {
- "child": {
- "path": "blocks",
- "shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",
- "sync": true,
- "type": "flatfs"
- },
- "mountpoint": "/blocks",
- "prefix": "flatfs.datastore",
- "type": "measure"
- },
- {
- "child": {
- "compression": "none",
- "path": "datastore",
- "type": "levelds"
- },
- "mountpoint": "/",
- "prefix": "leveldb.datastore",
- "type": "measure"
- }
+ {
+ "mountpoint": "/blocks",
+ "path": "blocks",
+ "prefix": "flatfs.datastore",
+ "shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",
+ "sync": false,
+ "type": "flatfs"
+ },
+ {
+ "compression": "none",
+ "mountpoint": "/",
+ "path": "datastore",
+ "prefix": "leveldb.datastore",
+ "type": "levelds"
+ }
+ ],
+ "type": "mount"
+}
+```
+
+With `flatfs-measure` profile:
+```
+{
+ "mounts": [
+ {
+ "child": {
+ "path": "blocks",
+ "shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",
+ "sync": true,
+ "type": "flatfs"
+ },
+ "mountpoint": "/blocks",
+ "prefix": "flatfs.datastore",
+ "type": "measure"
+ },
+ {
+ "child": {
+ "compression": "none",
+ "path": "datastore",
+ "type": "levelds"
+ },
+ "mountpoint": "/",
+ "prefix": "leveldb.datastore",
+ "type": "measure"
+ }
],
"type": "mount"
}
@@ -762,11 +910,15 @@ Type: `flag`
### `Gateway.ExposeRoutingAPI`
-An optional flag to expose Kubo `Routing` system on the gateway port as a [Routing
-V1](https://specs.ipfs.tech/routing/routing-v1/) endpoint. This only affects your
-local gateway, at `127.0.0.1`.
+An optional flag to expose Kubo `Routing` system on the gateway port
+as an [HTTP `/routing/v1`](https://specs.ipfs.tech/routing/http-routing-v1/) endpoint on `127.0.0.1`.
+Use reverse proxy to expose it on a different hostname.
-This endpoint can be used by other Kubo instance, as illustrated in [`delegated_routing_v1_http_proxy_test.go`](https://github.com/ipfs/kubo/blob/master/test/cli/delegated_routing_v1_http_proxy_test.go).
+This endpoint can be used by other Kubo instances, as illustrated in
+[`delegated_routing_v1_http_proxy_test.go`](https://github.com/ipfs/kubo/blob/master/test/cli/delegated_routing_v1_http_proxy_test.go).
+Kubo will filter out routing results which are not actionable, for example, all
+graphsync providers will be skipped. If you need a generic pass-through, see
+standalone router implementation named [someguy](https://github.com/ipfs/someguy).
Default: `false`
@@ -804,7 +956,18 @@ We are working on developing a modern replacement. To support our efforts, pleas
### `Gateway.PublicGateways`
-`PublicGateways` is a dictionary for defining gateway behavior on specified hostnames.
+> [!IMPORTANT]
+> This configuration is **NOT** for HTTP Client, it is for HTTP Server – use this ONLY if you want to run your own IPFS gateway.
+
+`PublicGateways` is a configuration map used for dictionary for customizing gateway behavior
+on specified hostnames that point at your Kubo instance.
+
+It is useful when you want to run [Path gateway](https://specs.ipfs.tech/http-gateways/path-gateway/) on `example.com/ipfs/cid`,
+and [Subdomain gateway](https://specs.ipfs.tech/http-gateways/subdomain-gateway/) on `cid.ipfs.example.org`,
+or limit `verifiable.example.net` to response types defined in [Trustless Gateway](https://specs.ipfs.tech/http-gateways/trustless-gateway/) specification.
+
+> [!CAUTION]
+> Keys (Hostnames) MUST be unique. Do not use the same parent domain for multiple gateway types, it will break origin isolation.
Hostnames can optionally be defined with one or more wildcards.
@@ -837,7 +1000,9 @@ Type: `array[string]`
#### `Gateway.PublicGateways: UseSubdomains`
-A boolean to configure whether the gateway at the hostname provides [Origin isolation](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy)
+A boolean to configure whether the gateway at the hostname should be
+a [Subdomain Gateway](https://specs.ipfs.tech/http-gateways/subdomain-gateway/)
+and provide [Origin isolation](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy)
between content roots.
- `true` - enables [subdomain gateway](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#subdomain-gateway) at `http://*.{hostname}/`
@@ -886,7 +1051,7 @@ Type: `bool`
An optional flag to explicitly configure whether subdomain gateway's redirects
(enabled by `UseSubdomains: true`) should always inline a DNSLink name (FQDN)
-into a single DNS label:
+into a single DNS label ([specification](https://specs.ipfs.tech/http-gateways/subdomain-gateway/#host-request-header)):
```
//example.com/ipns/example.net → HTTP 301 → //example-net.ipns.example.com
@@ -905,8 +1070,14 @@ Type: `flag`
#### `Gateway.PublicGateways: DeserializedResponses`
An optional flag to explicitly configure whether this gateway responds to deserialized
-requests, or not. By default, it is enabled. When disabling this option, the gateway
-operates as a Trustless Gateway only: https://specs.ipfs.tech/http-gateways/trustless-gateway/.
+requests, or not. By default, it is enabled.
+
+When disabled, the gateway operates strictly as a [Trustless Gateway](https://specs.ipfs.tech/http-gateways/trustless-gateway/).
+
+> [!TIP]
+> Disabling deserialized responses will protect you from acting as a free web hosting,
+> while still allowing trustless clients like [@helia/verified-fetch](https://www.npmjs.com/package/@helia/verified-fetch)
+> to utilize it for [trustless, verifiable data retrieval](https://docs.ipfs.tech/reference/http/gateway/#trustless-verifiable-retrieval).
Default: same as global `Gateway.DeserializedResponses`
@@ -940,7 +1111,7 @@ $ ipfs config --json Gateway.PublicGateways '{"localhost": null }'
### `Gateway` recipes
-Below is a list of the most common public gateway setups.
+Below is a list of the most common gateway setups.
* Public [subdomain gateway](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#subdomain-gateway) at `http://{cid}.ipfs.dweb.link` (each content root gets its own Origin)
```console
@@ -951,11 +1122,12 @@ Below is a list of the most common public gateway setups.
}
}'
```
+ - **Performance:** consider running with `Routing.AcceleratedDHTClient=true` and either `Provider.Enabled=false` (avoid providing newly retrieved blocks) or `Provider.WorkerCount=0` (provide as fast as possible, at the cost of increased load)
- **Backward-compatible:** this feature enables automatic redirects from content paths to subdomains:
`http://dweb.link/ipfs/{cid}` → `http://{cid}.ipfs.dweb.link`
- - **X-Forwarded-Proto:** if you run Kubo behind a reverse proxy that provides TLS, make it add a `X-Forwarded-Proto: https` HTTP header to ensure users are redirected to `https://`, not `http://`. It will also ensure DNSLink names are inlined to fit in a single DNS label, so they work fine with a wildcart TLS cert ([details](https://github.com/ipfs/in-web-browsers/issues/169)). The NGINX directive is `proxy_set_header X-Forwarded-Proto "https";`.:
+ - **X-Forwarded-Proto:** if you run Kubo behind a reverse proxy that provides TLS, make it add a `X-Forwarded-Proto: https` HTTP header to ensure users are redirected to `https://`, not `http://`. It will also ensure DNSLink names are inlined to fit in a single DNS label, so they work fine with a wildcard TLS cert ([details](https://github.com/ipfs/in-web-browsers/issues/169)). The NGINX directive is `proxy_set_header X-Forwarded-Proto "https";`.:
`http://dweb.link/ipfs/{cid}` → `https://{cid}.ipfs.dweb.link`
@@ -975,6 +1147,7 @@ Below is a list of the most common public gateway setups.
}
}'
```
+ - **Performance:** when running an open, recursive gateway consider running with `Routing.AcceleratedDHTClient=true` and either `Provider.Enabled=false` (avoid providing newly retrieved blocks) or `Provider.WorkerCount=0` (provide as fast as possible, at the cost of increased load)
* Public [DNSLink](https://dnslink.io/) gateway resolving every hostname passed in `Host` header.
```console
@@ -1024,6 +1197,10 @@ This section includes internal knobs for various subsystems to allow advanced us
### `Internal.Bitswap`
`Internal.Bitswap` contains knobs for tuning bitswap resource utilization.
+
+> [!TIP]
+> For high level configuration see [`Bitswap`](#bitswap).
+
The knobs (below) document how their value should related to each other.
Whether their values should be raised or lowered should be determined
based on the metrics `ipfs_bitswap_active_tasks`, `ipfs_bitswap_pending_tasks`,
@@ -1090,7 +1267,7 @@ deteriorate the quality provided to less aggressively-wanting peers.
Type: `optionalInteger` (byte count, `null` means default which is 1MB)
-### `Internal.Bitswap.ProviderSearchDelay`
+#### `Internal.Bitswap.ProviderSearchDelay`
This parameter determines how long to wait before looking for providers outside of bitswap.
Other routing systems like the Amino DHT are able to provide results in less than a second, so lowering
@@ -1098,17 +1275,16 @@ this number will allow faster peers lookups in some cases.
Type: `optionalDuration` (`null` means default which is 1s)
-### `Internal.UnixFSShardingSizeThreshold`
+#### `Internal.Bitswap.ProviderSearchMaxResults`
-The sharding threshold used internally to decide whether a UnixFS directory should be sharded or not.
-This value is not strictly related to the size of the UnixFS directory block and any increases in
-the threshold should come with being careful that block sizes stay under 2MiB in order for them to be
-reliably transferable through the networking stack (IPFS peers on the public swarm tend to ignore requests for blocks bigger than 2MiB).
+Maximum number of providers bitswap client should aim at before it stops searching for new ones.
+Setting to 0 means unlimited.
-Decreasing this value to 1B is functionally equivalent to the previous experimental sharding option to
-shard all directories.
+Type: `optionalInteger` (`null` means default which is 10)
-Type: `optionalBytes` (`null` means default which is 256KiB)
+### `Internal.UnixFSShardingSizeThreshold`
+
+**MOVED:** see [`Import.UnixFSHAMTDirectorySizeThreshold`](#importunixfshamtdirectorysizethreshold)
## `Ipns`
@@ -1126,7 +1302,7 @@ Type: `interval` or an empty string for the default.
A time duration specifying the value to set on ipns records for their validity
lifetime.
-Default: 24 hours.
+Default: 48 hours.
Type: `interval` or an empty string for the default.
@@ -1196,7 +1372,11 @@ Default: `cache`
## `Mounts`
-**EXPERIMENTAL:** read about current limitations at [fuse.md](./fuse.md).
+> [!CAUTION]
+> **EXPERIMENTAL:**
+> This feature is disabled by default, requires an explicit opt-in with `ipfs mount` or `ipfs daemon --mount`.
+>
+> Read about current limitations at [fuse.md](./fuse.md).
FUSE mount point configuration options.
@@ -1216,6 +1396,18 @@ Default: `/ipns`
Type: `string` (filesystem path)
+### `Mounts.MFS`
+
+Mountpoint for Mutable File System (MFS) behind the `ipfs files` API.
+
+> [!CAUTION]
+> - Write support is highly experimental and not recommended for mission-critical deployments.
+> - Avoid storing lazy-loaded datasets in MFS. Exposing a partially local, lazy-loaded DAG risks operating system search indexers crawling it, which may trigger unintended network prefetching of non-local DAG components.
+
+Default: `/mfs`
+
+Type: `string` (filesystem path)
+
### `Mounts.FuseAllowOther`
Sets the 'FUSE allow other'-option on the mount point.
@@ -1248,7 +1440,7 @@ Example:
"API" : {
"Endpoint" : "https://pinningservice.tld:1234/my/api/path",
"Key" : "someOpaqueKey"
- }
+ }
}
}
}
@@ -1309,6 +1501,56 @@ Default: `"5m"`
Type: `duration`
+## `Provider`
+
+Configuration applied to the initial one-time announcement of fresh CIDs
+created with `ipfs add`, `ipfs files`, `ipfs dag import`, `ipfs block|dag put`
+commands.
+
+For periodical DHT reprovide settings, see [`Reprovide.*`](#reprovider).
+
+### `Provider.Enabled`
+
+Controls whether Kubo provider and reprovide systems are enabled.
+
+> [!CAUTION]
+> Disabling this, will disable BOTH `Provider` system for new CIDs
+> and the periodical reprovide ([`Reprovider.Interval`](#reprovider)) of old CIDs.
+
+Default: `true`
+
+Type: `flag`
+
+### `Provider.Strategy`
+
+Legacy, not used at the moment, see [`Reprovider.Strategy`](#reproviderstrategy) instead.
+
+### `Provider.WorkerCount`
+
+Sets the maximum number of _concurrent_ DHT provide operations (announcement of new CIDs).
+
+[`Reprovider`](#reprovider) operations do **not** count against this limit.
+A value of `0` allows an unlimited number of provide workers.
+
+If the [accelerated DHT client](#routingaccelerateddhtclient) is enabled, each
+provide operation opens ~20 connections in parallel. With the standard DHT
+client (accelerated disabled), each provide opens between 20 and 60
+connections, with at most 10 active at once. Provides complete more quickly
+when using the accelerated client. Be mindful of how many simultaneous
+connections this setting can generate.
+
+> [!CAUTION]
+> For nodes without strict connection limits that need to provide large volumes
+> of content immediately, we recommend enabling the `Routing.AcceleratedDHTClient` and
+> setting `Provider.WorkerCount` to `0` (unlimited).
+>
+> At the same time, mind that raising this value too high may lead to increased load.
+> Proceed with caution, ensure proper hardware and networking are in place.
+
+Default: `16`
+
+Type: `optionalInteger` (non-negative; `0` means unlimited number of workers)
+
## `Pubsub`
**DEPRECATED**: See [#9717](https://github.com/ipfs/kubo/issues/9717)
@@ -1485,7 +1727,11 @@ system.
Note: disabling content reproviding will result in other nodes on the network
not being able to discover that you have the objects that you have. If you want
to have this disabled and keep the network aware of what you have, you must
-manually announce your content periodically.
+manually announce your content periodically or run your own routing system
+and convince users to add it to [`Routing.DelegatedRouters`](https://github.com/ipfs/kubo/blob/master/docs/config.md#routingdelegatedrouters).
+
+> [!CAUTION]
+> To maintain backward-compatibility, setting `Reprovider.Interval=0` will also disable Provider system (equivalent of `Provider.Enabled=false`)
Default: `22h` (`DefaultReproviderInterval`)
@@ -1496,8 +1742,10 @@ Type: `optionalDuration` (unset for the default)
Tells reprovider what should be announced. Valid strategies are:
- `"all"` - announce all CIDs of stored blocks
-- `"pinned"` - only announce pinned CIDs recursively (both roots and child blocks)
-- `"roots"` - only announce the root block of explicitly pinned CIDs
+ - Order: root blocks of direct and recursive pins and MFS root are announced first, then the rest of blockstore
+- `"pinned"` - only announce recursively pinned CIDs (`ipfs pin add -r`, both roots and child blocks)
+ - Order: root blocks of direct and recursive pins are announced first, then the child blocks of recursive pins
+- `"roots"` - only announce the root block of explicitly pinned CIDs (`ipfs pin add`)
- **⚠️ BE CAREFUL:** node with `roots` strategy will not announce child blocks.
It makes sense only for use cases where the entire DAG is fetched in full,
and a graceful resume does not have to be guaranteed: the lack of child
@@ -1505,6 +1753,17 @@ Tells reprovider what should be announced. Valid strategies are:
providers for the missing block in the middle of a file, unless the peer
happens to already be connected to a provider and ask for child CID over
bitswap.
+- `"mfs"` - announce only the local CIDs that are part of the MFS (`ipfs files`)
+ - Note: MFS is lazy-loaded. Only the MFS blocks present in local datastore are announced.
+- `"pinned+mfs"` - a combination of the `pinned` and `mfs` strategies.
+ - **ℹ️ NOTE:** This is the suggested strategy for users who run without GC and don't want to provide everything in cache.
+ - Order: first `pinned` and then the locally available part of `mfs`.
+- `"flat"` - same as `all`, announce all CIDs of stored blocks, but without prioritizing anything.
+
+> [!IMPORTANT]
+> Reproviding larger pinsets using the `all`, `mfs`, `pinned`, `pinned+mfs` or `roots` strategies requires additional memory, with an estimated ~1 GiB of RAM per 20 million items for reproviding to the Amino DHT.
+> This is due to the use of a buffered provider, which avoids holding a lock on the entire pinset during the reprovide cycle.
+> The `flat` strategy can be used to lower memory requirements, but only recommended if memory utilization is too high, prioritization of pins is not necessary, and it is acceptable to announce every block cached in the local repository.
Default: `"all"`
@@ -1519,7 +1778,7 @@ Contains options for content, peer, and IPNS routing mechanisms.
There are multiple routing options: "auto", "autoclient", "none", "dht", "dhtclient", and "custom".
* **DEFAULT:** If unset, or set to "auto", your node will use the public IPFS DHT (aka "Amino")
- and parallel HTTP routers listed below for additional speed.
+ and parallel [`Routing.DelegatedRouters`](#routingdelegatedrouters) for additional speed.
* If set to "autoclient", your node will behave as in "auto" but without running a DHT server.
@@ -1549,13 +1808,13 @@ To force a specific Amino DHT-only mode, client or server, set `Routing.Type` to
unless you're sure your node is reachable from the public network.
When `Routing.Type` is set to `auto` or `autoclient` 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`.
+by leveraging [`Routing.DelegatedRouters`](#routingdelegatedrouters) HTTP endpoints compatible with [Delegated Routing V1 HTTP API](https://specs.ipfs.tech/routing/http-routing-v1/)
+introduced in [IPIP-337](https://github.com/ipfs/specs/pull/337)
+in addition to the Amino DHT.
+
+[Advanced routing rules](https://github.com/ipfs/kubo/blob/master/docs/delegated-routing.md) can be configured in `Routing.Routers` after setting `Routing.Type` to `custom`.
-Default: `auto` (DHT + IPNI)
+Default: `auto` (DHT + [`Routing.DelegatedRouters`](#routingdelegatedrouters))
Type: `optionalString` (`null`/missing means the default)
@@ -1570,7 +1829,7 @@ is able to find the 20 final nodes by looking up the in-memory recorded network
This means sustained higher memory to store the routing table
and extra CPU and network bandwidth for each network scan.
However the latency of individual read/write operations should be ~10x faster
-and the provide throughput up to 6 million times faster on larger datasets!
+and provide throughput up to 6 million times faster on larger datasets!
This is not compatible with `Routing.Type` `custom`. If you are using composable routers
you can configure this individually on each router.
@@ -1604,15 +1863,60 @@ them
Default: `false`
+Type: `flag`
+
+### `Routing.LoopbackAddressesOnLanDHT`
+
+**EXPERIMENTAL: `Routing.LoopbackAddressesOnLanDHT` configuration may change in future release**
+
+Whether loopback addresses (e.g. 127.0.0.1) should not be ignored on the local LAN DHT.
+
+Most users do not need this setting. It can be useful during testing, when multiple Kubo nodes run on the same machine but some of them do not have `Discovery.MDNS.Enabled`.
+
+Default: `false`
+
Type: `bool` (missing means `false`)
+### `Routing.IgnoreProviders`
+
+An array of [string-encoded PeerIDs](https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md#string-representation). Any provider record associated to one of these peer IDs is ignored.
+
+Apart from ignoring specific providers for reasons like misbehaviour etc. this
+setting is useful to ignore providers as a way to indicate preference, when the same provider
+is found under different peerIDs (i.e. one for HTTP and one for Bitswap retrieval).
+
+> [!TIP]
+> This denylist operates on PeerIDs.
+> To deny specific HTTP Provider URL, use [`HTTPRetrieval.Denylist`](#httpretrievaldenylist) instead.
+
+Default: `[]`
+
+Type: `array[string]`
+
+### `Routing.DelegatedRouters`
+
+An array of URL hostnames for delegated routers to be queried in addition to the Amino DHT when `Routing.Type` is set to `auto` (default) or `autoclient`.
+These endpoints must support the [Delegated Routing V1 HTTP API](https://specs.ipfs.tech/routing/http-routing-v1/).
+
+> [!TIP]
+> Delegated routing allows IPFS implementations to offload tasks like content routing, peer routing, and naming to a separate process or server while also benefiting from HTTP caching.
+>
+> One can run their own delegated router either by implementing the [Delegated Routing V1 HTTP API](https://specs.ipfs.tech/routing/http-routing-v1/) themselves, or by using [Someguy](https://github.com/ipfs/someguy), a turn-key implementation that proxies requests to other routing systems. A public utility instance of Someguy is hosted at [`https://delegated-ipfs.dev`](https://docs.ipfs.tech/concepts/public-utilities/#delegated-routing).
+
+Default: `["https://cid.contact"]` (empty or `nil` will also use this default; to disable delegated routing, set `Routing.Type` to `dht` or `dhtclient`)
+
+Type: `array[string]`
+
### `Routing.Routers`
-**EXPERIMENTAL: `Routing.Routers` configuration may change in future release**
+Alternative configuration used when `Routing.Type=custom`.
-Map of additional Routers.
+> [!WARNING]
+> **EXPERIMENTAL: `Routing.Routers` configuration may change in future release**
+>
+> Consider this advanced low-level config: Most users can simply use `Routing.Type=auto` or `autoclient` and set up basic config in user-friendly [`Routing.DelegatedRouters`](https://github.com/ipfs/kubo/blob/master/docs/config.md#routingdelegatedrouters).
-Allows for extending the default routing (Amino DHT) with alternative Router
+Allows for replacing the default routing (Amino DHT) with alternative Router
implementations.
The map key is a name of a Router, and the value is its configuration.
@@ -1672,7 +1976,14 @@ Type: `object[string->string]`
### `Routing: Methods`
-`Methods:map` will define which routers will be executed per method. The key will be the name of the method: `"provide"`, `"find-providers"`, `"find-peers"`, `"put-ipns"`, `"get-ipns"`. All methods must be added to the list.
+`Methods:map` will define which routers will be executed per method used when `Routing.Type=custom`.
+
+> [!WARNING]
+> **EXPERIMENTAL: `Routing.Routers` configuration may change in future release**
+>
+> Consider this advanced low-level config: Most users can simply use `Routing.Type=auto` or `autoclient` and set up basic config in user-friendly [`Routing.DelegatedRouters`](https://github.com/ipfs/kubo/blob/master/docs/config.md#routingdelegatedrouters).
+
+The key will be the name of the method: `"provide"`, `"find-providers"`, `"find-peers"`, `"put-ipns"`, `"get-ipns"`. All methods must be added to the list.
The value will contain:
- `RouterName:string`: Name of the router. It should be one of the previously added to `Routing.Routers` list.
@@ -1756,10 +2067,11 @@ node will try to connect to one or more private IP addresses whenever dialing
another node, even if this other node is on a different network. This may
trigger netscan alerts on some hosting providers or cause strain in some setups.
-The `server` configuration profile fills up this list with sensible defaults,
-preventing dials to all non-routable IP addresses (e.g., `/ip4/192.168.0.0/ipcidr/16`,
-which is the multiaddress representation of `192.168.0.0/16`) but you should always
-check settings against your own network and/or hosting provider.
+> [!TIP]
+> The [`server` configuration profile](#server-profile) fills up this list with sensible defaults,
+> preventing dials to all non-routable IP addresses (e.g., `/ip4/192.168.0.0/ipcidr/16`,
+> which is the [multiaddress][multiaddr] representation of `192.168.0.0/16`) but you should always
+> check settings against your own network and/or hosting provider.
Default: `[]`
@@ -1777,7 +2089,7 @@ Type: `bool`
### `Swarm.DisableNatPortMap`
-Disable automatic NAT port forwarding.
+Disable automatic NAT port forwarding (turn off [UPnP](https://en.wikipedia.org/wiki/Universal_Plug_and_Play)).
When not disabled (default), Kubo asks NAT devices (e.g., routers), to open
up an external port and forward it to the port Kubo is running on. When this
@@ -1861,7 +2173,7 @@ Type: `flag`
#### `Swarm.RelayService.Limit`
-Limits applied to every relayed connection.
+Limits are applied to every relayed connection.
Default: `{}`
@@ -1922,12 +2234,7 @@ Type: `optionalInteger`
#### `Swarm.RelayService.MaxReservationsPerPeer`
-Maximum number of reservations originating from the same peer.
-
-Default: `4`
-
-Type: `optionalInteger`
-
+**REMOVED in kubo 0.32 due to [go-libp2p#2974](https://github.com/libp2p/go-libp2p/pull/2974)**
#### `Swarm.RelayService.MaxReservationsPerIP`
@@ -2055,7 +2362,8 @@ Type: `flag`
#### `Swarm.ResourceMgr.MaxMemory`
-This is the max amount of memory to allow libp2p to use.
+This is the max amount of memory to allow go-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 (discussed in [libp2p resource management](./libp2p-resource-management.md)) are used.
@@ -2063,6 +2371,11 @@ For example, increasing this value will increase the default limit for incoming
It is possible to inspect the runtime limits via `ipfs swarm resources --help`.
+> [!IMPORTANT]
+> `Swarm.ResourceMgr.MaxMemory` is the memory limit for go-libp2p networking stack alone, and not for entire Kubo or Bitswap.
+>
+> To set memory limit for the entire Kubo process, use [`GOMEMLIMIT` environment variable](http://web.archive.org/web/20240222201412/https://kupczynski.info/posts/go-container-aware/) which all Go programs recognize, and then set `Swarm.ResourceMgr.MaxMemory` to less than your custom `GOMEMLIMIT`.
+
Default: `[TOTAL_SYSTEM_MEMORY]/2`
Type: `optionalBytes`
@@ -2078,12 +2391,12 @@ Type: `optionalInteger`
#### `Swarm.ResourceMgr.Allowlist`
-A list of multiaddrs that can bypass normal system limits (but are still limited by the allowlist scope).
+A list of [multiaddrs][libp2p-multiaddrs] that can bypass normal system limits (but are still limited by the allowlist scope).
Convenience config around [go-libp2p-resource-manager#Allowlist.Add](https://pkg.go.dev/github.com/libp2p/go-libp2p/p2p/host/resource-manager#Allowlist.Add).
Default: `[]`
-Type: `array[string]` (multiaddrs)
+Type: `array[string]` ([multiaddrs][multiaddr])
### `Swarm.Transports`
@@ -2096,7 +2409,7 @@ Configuration section for libp2p _network_ transports. Transports enabled in
this section will be used for dialing. However, to receive connections on these
transports, multiaddrs for these transports must be added to `Addresses.Swarm`.
-Supported transports are: QUIC, TCP, WS, Relay and WebTransport.
+Supported transports are: QUIC, TCP, WS, Relay, WebTransport and WebRTCDirect.
Each field in this section is a `flag`.
@@ -2128,8 +2441,8 @@ Default: Enabled
Type: `flag`
Listen Addresses:
-* /ip4/0.0.0.0/tcp/4002/ws
-* /ip6/::/tcp/4002/ws
+* /ip4/0.0.0.0/tcp/4001/ws
+* /ip6/::/tcp/4001/ws
#### `Swarm.Transports.Network.QUIC`
@@ -2147,15 +2460,15 @@ Default: Enabled
Type: `flag`
Listen Addresses:
-* /ip4/0.0.0.0/udp/4001/quic-v1 (default)
-* /ip6/::/udp/4001/quic-v1 (default)
+- `/ip4/0.0.0.0/udp/4001/quic-v1` (default)
+- `/ip6/::/udp/4001/quic-v1` (default)
#### `Swarm.Transports.Network.Relay`
[Libp2p Relay](https://github.com/libp2p/specs/tree/master/relay) proxy
transport that forms connections by hopping between multiple libp2p nodes.
Allows IPFS node to connect to other peers using their `/p2p-circuit`
-multiaddrs. This transport is primarily useful for bypassing firewalls and
+[multiaddrs][libp2p-multiaddrs]. This transport is primarily useful for bypassing firewalls and
NATs.
See also:
@@ -2195,33 +2508,40 @@ Default: Enabled
Type: `flag`
-#### `Swarm.Transports.Network.WebRTCDirect`
+Listen Addresses:
+- `/ip4/0.0.0.0/udp/4001/quic-v1/webtransport` (default)
+- `/ip6/::/udp/4001/quic-v1/webtransport` (default)
-**Experimental:** the support for WebRTC Direct is currently experimental.
-This feature was introduced in [`go-libp2p@v0.32.0`](https://github.com/libp2p/go-libp2p/releases/tag/v0.32.0).
+#### `Swarm.Transports.Network.WebRTCDirect`
[WebRTC Direct](https://github.com/libp2p/specs/blob/master/webrtc/webrtc-direct.md)
is a transport protocol that provides another way for browsers to
connect to the rest of the libp2p network. WebRTC Direct allows for browser
nodes to connect to other nodes without special configuration, such as TLS
certificates. This can be useful for browser nodes that do not yet support
-[WebTransport](https://blog.libp2p.io/2022-12-19-libp2p-webtransport/).
+[WebTransport](https://blog.libp2p.io/2022-12-19-libp2p-webtransport/),
+which is still relatively new and has [known issues](https://github.com/libp2p/js-libp2p/issues/2572).
-Enabling this transport allows Kubo node to act on `/udp/4002/webrtc-direct`
+Enabling this transport allows Kubo node to act on `/udp/4001/webrtc-direct`
listeners defined in `Addresses.Swarm`, `Addresses.Announce` or
-`Addresses.AppendAnnounce`. At the moment, WebRTC Direct doesn't support listening on the same port as a QUIC or WebTransport listener
+`Addresses.AppendAnnounce`.
-**NOTE:** at the moment, WebRTC Direct cannot be used to connect to a browser
-node to a node that is behind a NAT or firewall.
-This requires using normal
-[WebRTC](https://github.com/libp2p/specs/blob/master/webrtc/webrtc.md),
-which is currently being worked on in
-[go-libp2p#2009](https://github.com/libp2p/go-libp2p/issues/2009).
+> [!NOTE]
+> WebRTC Direct is browser-to-node. It cannot be used to connect a browser
+> node to a node that is behind a NAT or firewall (without UPnP port mapping).
+> The browser-to-private requires using normal
+> [WebRTC](https://github.com/libp2p/specs/blob/master/webrtc/webrtc.md),
+> which is currently being worked on in
+> [go-libp2p#2009](https://github.com/libp2p/go-libp2p/issues/2009).
-Default: Disabled
+Default: Enabled
Type: `flag`
+Listen Addresses:
+- `/ip4/0.0.0.0/udp/4001/webrtc-direct` (default)
+- `/ip6/::/udp/4001/webrtc-direct` (default)
+
### `Swarm.Transports.Security`
Configuration section for libp2p _security_ transports. Transports enabled in
@@ -2237,9 +2557,9 @@ receiver supports. When establishing an _inbound_ connection, Kubo will let
the initiator choose the protocol, but will refuse to use any of the disabled
transports.
-Supported transports are: TLS (priority 100) and Noise (priority 300).
+Supported transports are: TLS (priority 100) and Noise (priority 200).
-No default priority will ever be less than 100.
+No default priority will ever be less than 100. Lower values have precedence.
#### `Swarm.Transports.Security.TLS`
@@ -2262,7 +2582,7 @@ TLS as the cross-platform, default libp2p protocol due to ease of
implementation. It is currently enabled by default but with low priority as it's
not yet widely supported.
-Default: `300`
+Default: `200`
Type: `priority`
@@ -2298,7 +2618,7 @@ Please remove this option from your config.
## `DNS`
-Options for configuring DNS resolution for [DNSLink](https://docs.ipfs.tech/concepts/dnslink/) and `/dns*` [Multiaddrs](https://github.com/multiformats/multiaddr/).
+Options for configuring DNS resolution for [DNSLink](https://docs.ipfs.tech/concepts/dnslink/) and `/dns*` [Multiaddrs][libp2p-multiaddrs].
### `DNS.Resolvers`
@@ -2324,11 +2644,11 @@ Example:
Be mindful that:
- Currently only `https://` URLs for [DNS over HTTPS (DoH)](https://en.wikipedia.org/wiki/DNS_over_HTTPS) endpoints are supported as values.
- The default catch-all resolver is the cleartext one provided by your operating system. It can be overridden by adding a DoH entry for the DNS root indicated by `.` as illustrated above.
-- Out-of-the-box support for selected decentralized TLDs relies on a [centralized service which is provided on best-effort basis](https://www.cloudflare.com/distributed-web-gateway-terms/). The implicit DoH resolvers are:
+- Out-of-the-box support for selected non-ICANN TLDs relies on third-party centralized services provided by respective communities on best-effort basis. The implicit DoH resolvers are:
```json
{
- "eth.": "https://resolver.cloudflare-eth.com/dns-query",
- "crypto.": "https://resolver.cloudflare-eth.com/dns-query"
+ "eth.": "https://dns.eth.limo/dns-query",
+ "crypto.": "https://resolver.unstoppable.io/dns-query"
}
```
To get all the benefits of a decentralized naming system we strongly suggest setting DoH endpoint to an empty string and running own decentralized resolver as catch-all one on localhost.
@@ -2353,3 +2673,534 @@ Note: this does NOT work with Go's default DNS resolver. To make this a global s
Default: Respect DNS Response TTL
Type: `optionalDuration`
+
+## `HTTPRetrieval`
+
+`HTTPRetrieval` is configuration for pure HTTP retrieval based on Trustless HTTP Gateways'
+[Block Responses (`application/vnd.ipld.raw`)](https://specs.ipfs.tech/http-gateways/trustless-gateway/#block-responses-application-vnd-ipld-raw)
+which can be used in addition to or instead of retrieving blocks with [Bitswap over Libp2p](#bitswap).
+
+Default: `{}`
+
+Type: `object`
+
+### `HTTPRetrieval.Enabled`
+
+> [!CAUTION]
+> This feature is **EXPERIMENTAL** and may change in future release. Enable with caution, and provide feedback via GitHub issues.
+
+Controls whether HTTP-based block retrieval is enabled.
+
+When enabled, Kubo will be able to act on `/tls/http` (HTTP/2) providers ([Trustless HTTP Gateways](https://specs.ipfs.tech/http-gateways/trustless-gateway/)) returned by the [`Routing.DelegatedRouters`](#routingdelegatedrouters)
+to perform pure HTTP [block retrievals](https://specs.ipfs.tech/http-gateways/trustless-gateway/#block-responses-application-vnd-ipld-raw)
+in addition to [Bitswap over Libp2p](#bitswap).
+
+HTTP requests for `application/vnd.ipld.raw` will be issued instead of Bitswap if a peer has a `/tls/http` multiaddr
+and the HTTPS server returns HTTP 200 for the [probe path](https://specs.ipfs.tech/http-gateways/trustless-gateway/#dedicated-probe-paths).
+
+> [!IMPORTANT]
+> - Requires TLS and HTTP/2.
+> - This feature works in the same way as Bitswap: connected HTTP-peers receive optimistic block requests even for content that they are not announcing.
+> - HTTP client does not follow redirects. Providers should keep announcements up to date.
+> - IPFS ecosystem is working towards [supporting HTTP providers on Amino DHT](https://github.com/ipfs/specs/issues/496). Currently, HTTP providers are mostly limited to results from [`Routing.DelegatedRouters`](#routingdelegatedrouters) endpoints and requires `Routing.Type=auto|autoclient`.
+
+Default: `false`
+
+Type: `flag`
+
+### `HTTPRetrieval.Allowlist`
+
+Optional list of hostnames for which HTTP retrieval is allowed for.
+If this list is not empty, only hosts matching these entries will be allowed for HTTP retrieval.
+
+> [!TIP]
+> To limit HTTP retrieval to a provider at `/dns4/example.com/tcp/443/tls/http` (which would serve `HEAD|GET https://example.com/ipfs/cid?format=raw`), set this to `["example.com"]`
+
+Default: `[]`
+
+Type: `array[string]`
+
+### `HTTPRetrieval.Denylist`
+
+Optional list of hostnames for which HTTP retrieval is not allowed.
+Denylist entries take precedence over Allowlist entries.
+
+
+> [!TIP]
+> This denylist operates on HTTP endpoint hostnames.
+> To deny specific PeerID, use [`Routing.IgnoreProviders`](#routingignoreproviders) instead.
+
+Default: `[]`
+
+Type: `array[string]`
+
+### `HTTPRetrieval.NumWorkers`
+
+The number of worker goroutines to use for concurrent HTTP retrieval operations.
+This setting controls the level of parallelism for HTTP-based block retrieval operations.
+Higher values can improve performance when retrieving many blocks but may increase resource usage.
+
+Default: `16`
+
+Type: `optionalInteger`
+
+### `HTTPRetrieval.MaxBlockSize`
+
+Sets the maximum size of a block that the HTTP retrieval client will accept.
+
+> [!NOTE]
+> This setting is a security feature designed to protect Kubo from malicious providers who might send excessively large or invalid data.
+> Increasing this value allows Kubo to retrieve larger blocks from compatible HTTP providers, but doing so reduces interoperability with Bitswap, and increases potential security risks.
+>
+> Learn more: [Supporting Large IPLD Blocks: Why block limits?](https://discuss.ipfs.tech/t/supporting-large-ipld-blocks/15093#why-block-limits-5)
+
+Default: `2MiB` (matching [Bitswap size limit](https://specs.ipfs.tech/bitswap-protocol/#block-sizes))
+
+Type: `optionalString`
+
+### `HTTPRetrieval.TLSInsecureSkipVerify`
+
+Disables TLS certificate validation.
+Allows making HTTPS connections to HTTP/2 test servers with self-signed TLS certificates.
+Only for testing, do not use in production.
+
+Default: `false`
+
+Type: `flag`
+
+## `Import`
+
+Options to configure the default options used for ingesting data, in commands such as `ipfs add` or `ipfs block put`. All affected commands are detailed per option.
+
+Note that using flags will override the options defined here.
+
+### `Import.CidVersion`
+
+The default CID version. Commands affected: `ipfs add`.
+
+Default: `0`
+
+Type: `optionalInteger`
+
+### `Import.UnixFSRawLeaves`
+
+The default UnixFS raw leaves option. Commands affected: `ipfs add`, `ipfs files write`.
+
+Default: `false` if `CidVersion=0`; `true` if `CidVersion=1`
+
+Type: `flag`
+
+### `Import.UnixFSChunker`
+
+The default UnixFS chunker. Commands affected: `ipfs add`.
+
+Default: `size-262144`
+
+Type: `optionalString`
+
+### `Import.HashFunction`
+
+The default hash function. Commands affected: `ipfs add`, `ipfs block put`, `ipfs dag put`.
+
+Default: `sha2-256`
+
+Type: `optionalString`
+
+### `Import.BatchMaxNodes`
+
+The maximum number of nodes in a write-batch. The total size of the batch is limited by `BatchMaxnodes` and `BatchMaxSize`.
+
+Increasing this will batch more items together when importing data with `ipfs dag import`, which can speed things up.
+
+Default: `128`
+
+Type: `optionalInteger`
+
+### `Import.BatchMaxSize`
+
+The maximum size of a single write-batch (computed as the sum of the sizes of the blocks). The total size of the batch is limited by `BatchMaxnodes` and `BatchMaxSize`.
+
+Increasing this will batch more items together when importing data with `ipfs dag import`, which can speed things up.
+
+Default: `20971520` (20MiB)
+
+Type: `optionalInteger`
+
+### `Import.UnixFSFileMaxLinks`
+
+The maximum number of links that a node part of a UnixFS File can have
+when building the DAG while importing.
+
+This setting controls both the fanout in files that are chunked into several
+blocks and grouped as a Unixfs (dag-pb) DAG.
+
+Default: `174`
+
+Type: `optionalInteger`
+
+### `Import.UnixFSDirectoryMaxLinks`
+
+The maximum number of links that a node part of a UnixFS basic directory can
+have when building the DAG while importing.
+
+This setting controls both the fanout for basic, non-HAMT folder nodes. It
+sets a limit after which directories are converted to a HAMT-based structure.
+
+When unset (0), no limit exists for chilcren. Directories will be converted to
+HAMTs based on their estimated size only.
+
+This setting will cause basic directories to be converted to HAMTs when they
+exceed the maximum number of children. This happens transparently during the
+add process. The fanout of HAMT nodes is controlled by `MaxHAMTFanout`.
+
+Commands affected: `ipfs add`
+
+Default: `0` (no limit, because [`Import.UnixFSHAMTDirectorySizeThreshold`](#importunixfshamtdirectorysizethreshold) triggers controls when to switch to HAMT sharding when a directory grows too big)
+
+Type: `optionalInteger`
+
+### `Import.UnixFSHAMTDirectoryMaxFanout`
+
+The maximum number of children that a node part of a Unixfs HAMT directory
+(aka sharded directory) can have.
+
+HAMT directory have unlimited children and are used when basic directories
+become too big or reach `MaxLinks`. A HAMT is an structure made of unixfs
+nodes that store the list of elements in the folder. This option controls the
+maximum number of children that the HAMT nodes can have.
+
+Needs to be a power of two (shard entry size) and multiple of 8 (bitfield size).
+
+Commands affected: `ipfs add`, `ipfs daemon` (globally overrides [`boxo/ipld/unixfs/io.DefaultShardWidth`](https://github.com/ipfs/boxo/blob/6c5a07602aed248acc86598f30ab61923a54a83e/ipld/unixfs/io/directory.go#L30C5-L30C22))
+
+Default: `256`
+
+Type: `optionalInteger`
+
+### `Import.UnixFSHAMTDirectorySizeThreshold`
+
+The sharding threshold to decide whether a basic UnixFS directory
+should be sharded (converted into HAMT Directory) or not.
+
+This value is not strictly related to the size of the UnixFS directory block
+and any increases in the threshold should come with being careful that block
+sizes stay under 2MiB in order for them to be reliably transferable through the
+networking stack. At the time of writing this, IPFS peers on the public swarm
+tend to ignore requests for blocks bigger than 2MiB.
+
+Uses implementation from `boxo/ipld/unixfs/io/directory`, where the size is not
+the *exact* block size of the encoded directory but just the estimated size
+based byte length of DAG-PB Links names and CIDs.
+
+Setting to `1B` is functionally equivalent to always using HAMT (useful in testing).
+
+Commands affected: `ipfs add`, `ipfs daemon` (globally overrides [`boxo/ipld/unixfs/io.HAMTShardingSize`](https://github.com/ipfs/boxo/blob/6c5a07602aed248acc86598f30ab61923a54a83e/ipld/unixfs/io/directory.go#L26))
+
+Default: `256KiB` (may change, inspect `DefaultUnixFSHAMTDirectorySizeThreshold` to confirm)
+
+Type: `optionalBytes`
+
+## `Version`
+
+Options to configure agent version announced to the swarm, and leveraging
+other peers version for detecting when there is time to update.
+
+### `Version.AgentSuffix`
+
+Optional suffix to the AgentVersion presented by `ipfs id` and exposed via [libp2p identify protocol](https://github.com/libp2p/specs/blob/master/identify/README.md#agentversion).
+
+The value from config takes precedence over value passed via `ipfs daemon --agent-version-suffix`.
+
+> [!NOTE]
+> Setting a custom version suffix helps with ecosystem analysis, such as Amino DHT reports published at https://stats.ipfs.network
+
+Default: `""` (no suffix, or value from `ipfs daemon --agent-version-suffix=`)
+
+Type: `optionalString`
+
+### `Version.SwarmCheckEnabled`
+
+Observe the AgentVersion of swarm peers and log warning when
+`SwarmCheckPercentThreshold` of peers runs version higher than this node.
+
+Default: `true`
+
+Type: `flag`
+
+### `Version.SwarmCheckPercentThreshold`
+
+Control the percentage of `kubo/` peers running new version required to
+trigger update warning.
+
+Default: `5`
+
+Type: `optionalInteger` (1-100)
+
+## Profiles
+
+Configuration profiles allow to tweak configuration quickly. Profiles can be
+applied with the `--profile` flag to `ipfs init` or with the `ipfs config profile
+apply` command. When a profile is applied a backup of the configuration file
+will be created in `$IPFS_PATH`.
+
+Configuration profiles can be applied additively. For example, both the `test-cid-v1` and `lowpower` profiles can be applied one after the other.
+The available configuration profiles are listed below. You can also find them
+documented in `ipfs config profile --help`.
+
+### `server` profile
+
+Disables local [`Discovery.MDNS`](#discoverymdns), [turns off uPnP NAT port mapping](#swarmdisablenatportmap), and blocks connections to
+IPv4 and IPv6 prefixes that are [private, local only, or unrouteable](https://github.com/ipfs/kubo/blob/b71cf0d15904bdef21fe2eee5f1118a274309a4d/config/profile.go#L24-L43).
+
+Recommended when running IPFS on machines with public IPv4 addresses (no NAT, no uPnP)
+at providers that interpret local IPFS discovery and traffic as netscan abuse ([example](https://github.com/ipfs/kubo/issues/10327)).
+
+### `randomports` profile
+
+Use a random port number for the incoming swarm connections.
+Used for testing.
+
+### `default-datastore` profile
+
+Configures the node to use the default datastore (flatfs).
+
+Read the "flatfs" profile description for more information on this datastore.
+
+This profile may only be applied when first initializing the node.
+
+### `local-discovery` profile
+
+Enables local [`Discovery.MDNS`](#discoverymdns) (enabled by default).
+
+Useful to re-enable local discovery after it's disabled by another profile
+(e.g., the server profile).
+
+`test` profile
+
+Reduces external interference of IPFS daemon, this
+is useful when using the daemon in test environments.
+
+### `default-networking` profile
+
+Restores default network settings.
+Inverse profile of the test profile.
+
+### `flatfs` profile
+
+Configures the node to use the flatfs datastore.
+Flatfs is the default, most battle-tested and reliable datastore.
+
+You should use this datastore if:
+
+- You need a very simple and very reliable datastore, and you trust your
+ filesystem. This datastore stores each block as a separate file in the
+ underlying filesystem so it's unlikely to lose data unless there's an issue
+ with the underlying file system.
+- You need to run garbage collection in a way that reclaims free space as soon as possible.
+- You want to minimize memory usage.
+- You are ok with the default speed of data import, or prefer to use `--nocopy`.
+
+> [!WARNING]
+> This profile may only be applied when first initializing the node via `ipfs init --profile flatfs`
+
+> [!NOTE]
+> See caveats and configuration options at [`datastores.md#flatfs`](datastores.md#flatfs)
+
+### `flatfs-measure` profile
+
+Configures the node to use the flatfs datastore with metrics. This is the same as [`flatfs` profile](#flatfs-profile) with the addition of the `measure` datastore wrapper.
+
+### `pebbleds` profile
+
+Configures the node to use the pebble high-performance datastore.
+
+Pebble is a LevelDB/RocksDB inspired key-value store focused on performance and internal usage by CockroachDB.
+You should use this datastore if:
+
+- You need a datastore that is focused on performance.
+- You need a datastore that is good for multi-terabyte data sets.
+- You need reliability by default, but may choose to disable WAL for maximum performance when reliability is not critical.
+- You want a datastore that does not need GC cycles and does not use more space than necessary
+- You want a datastore that does not take several minutes to start with large repositories
+- You want a datastore that performs well even with default settings, but can optimized by setting configuration to tune it for your specific needs.
+
+> [!WARNING]
+> This profile may only be applied when first initializing the node via `ipfs init --profile pebbleds`
+
+> [!NOTE]
+> See other caveats and configuration options at [`datastores.md#pebbleds`](datastores.md#pebbleds)
+
+### `pebbleds-measure` profile
+
+Configures the node to use the pebble datastore with metrics. This is the same as [`pebbleds` profile](#pebble-profile) with the addition of the `measure` datastore wrapper.
+
+### `badgerds` profile
+
+Configures the node to use the **legacy** badgerv1 datastore.
+
+> [!CAUTION]
+> This is based on very old badger 1.x, which has known bugs and is no longer supported by the upstream team.
+> It is provided here only for pre-existing users, allowing them to migrate away to more modern datastore.
+> Do not use it for new deployments, unless you really, really know what you are doing.
+
+Also, be aware that:
+
+- This datastore will not properly reclaim space when your datastore is
+ smaller than several gigabytes. If you run IPFS with `--enable-gc`, you plan on storing very little data in
+ your IPFS node, and disk usage is more critical than performance, consider using
+ `flatfs`.
+- This datastore uses up to several gigabytes of memory.
+- Good for medium-size datastores, but may run into performance issues if your dataset is bigger than a terabyte.
+- The current implementation is based on old badger 1.x which is no longer supported by the upstream team.
+
+> [!WARNING]
+> This profile may only be applied when first initializing the node via `ipfs init --profile badgerds`
+
+> [!NOTE]
+> See other caveats and configuration options at [`datastores.md#pebbleds`](datastores.md#pebbleds)
+
+### `badgerds-measure` profile
+
+Configures the node to use the **legacy** badgerv1 datastore with metrics. This is the same as [`badgerds` profile](#badger-profile) with the addition of the `measure` datastore wrapper.
+
+### `lowpower` profile
+
+Reduces daemon overhead on the system by disabling optional swarm services.
+
+- [`Routing.Type`](#routingtype) set to `autoclient` (no DHT server, only client).
+- `Swarm.ConnMgr` set to maintain minimum number of p2p connections at a time.
+- Disables [`AutoNAT`](#autonat).
+- Disables [`Swam.RelayService`](#swarmrelayservice).
+
+> [!NOTE]
+> This profile is provided for legacy reasons.
+> With modern Kubo setting the above should not be necessary.
+
+### `announce-off` profile
+
+Disables [Reprovider](#reprovider) system (and announcing to Amino DHT).
+
+> [!CAUTION]
+> The main use case for this is setups with manual Peering.Peers config.
+> Data from this node will not be announced on the DHT. This will make
+> DHT-based routing an data retrieval impossible if this node is the only
+> one hosting it, and other peers are not already connected to it.
+
+### `announce-on` profile
+
+(Re-)enables [Reprovider](#reprovider) system (reverts [`announce-off` profile](#annouce-off-profile).
+
+### `legacy-cid-v0` profile
+
+Makes UnixFS import (`ipfs add`) produce legacy CIDv0 with no raw leaves, sha2-256 and 256 KiB chunks.
+
+See for exact [`Import.*`](#import) settings.
+
+> [!NOTE]
+> This profile is provided for legacy users and should not be used for new projects.
+
+### `test-cid-v1` profile
+
+Makes UnixFS import (`ipfs add`) produce modern CIDv1 with raw leaves, sha2-256
+and 1 MiB chunks (max 174 links per file, 256 per HAMT node, switch dir to HAMT
+above 256KiB).
+
+See for exact [`Import.*`](#import) settings.
+
+> [!NOTE]
+> [`Import.*`](#import) settings applied by this profile MAY change in future release. Provided for testing purposes.
+>
+> Follow [kubo#4143](https://github.com/ipfs/kubo/issues/4143) for more details,
+> and provide feedback in [discuss.ipfs.tech/t/should-we-profile-cids](https://discuss.ipfs.tech/t/should-we-profile-cids/18507) or [ipfs/specs#499](https://github.com/ipfs/specs/pull/499).
+
+### `test-cid-v1-wide` profile
+
+Makes UnixFS import (`ipfs add`) produce modern CIDv1 with raw leaves, sha2-256
+and 1 MiB chunks and wider file DAGs (max 1024 links per every node type,
+switch dir to HAMT above 1MiB).
+
+See for exact [`Import.*`](#import) settings.
+
+> [!NOTE]
+> [`Import.*`](#import) settings applied by this profile MAY change in future release. Provided for testing purposes.
+>
+> Follow [kubo#4143](https://github.com/ipfs/kubo/issues/4143) for more details,
+> and provide feedback in [discuss.ipfs.tech/t/should-we-profile-cids](https://discuss.ipfs.tech/t/should-we-profile-cids/18507) or [ipfs/specs#499](https://github.com/ipfs/specs/pull/499).
+
+## Types
+
+This document refers to the standard JSON types (e.g., `null`, `string`,
+`number`, etc.), as well as a few custom types, described below.
+
+### `flag`
+
+Flags allow enabling and disabling features. However, unlike simple booleans,
+they can also be `null` (or omitted) to indicate that the default value should
+be chosen. This makes it easier for Kubo to change the defaults in the
+future unless the user _explicitly_ sets the flag to either `true` (enabled) or
+`false` (disabled). Flags have three possible states:
+
+- `null` or missing (apply the default value).
+- `true` (enabled)
+- `false` (disabled)
+
+### `priority`
+
+Priorities allow specifying the priority of a feature/protocol and disabling the
+feature/protocol. Priorities can take one of the following values:
+
+- `null`/missing (apply the default priority, same as with flags)
+- `false` (disabled)
+- `1 - 2^63` (priority, lower is preferred)
+
+### `strings`
+
+Strings is a special type for conveniently specifying a single string, an array
+of strings, or null:
+
+- `null`
+- `"a single string"`
+- `["an", "array", "of", "strings"]`
+
+### `duration`
+
+Duration is a type for describing lengths of time, using the same format go
+does (e.g, `"1d2h4m40.01s"`).
+
+### `optionalInteger`
+
+Optional integers allow specifying some numerical value which has
+an implicit default when missing from the config file:
+
+- `null`/missing will apply the default value defined in Kubo sources (`.WithDefault(value)`)
+- an integer between `-2^63` and `2^63-1` (i.e. `-9223372036854775808` to `9223372036854775807`)
+
+### `optionalBytes`
+
+Optional Bytes allow specifying some number of bytes which has
+an implicit default when missing from the config file:
+
+- `null`/missing (apply the default value defined in Kubo sources)
+- a string value indicating the number of bytes, including human readable representations:
+ - [SI sizes](https://en.wikipedia.org/wiki/Metric_prefix#List_of_SI_prefixes) (metric units, powers of 1000), e.g. `1B`, `2kB`, `3MB`, `4GB`, `5TB`, …)
+ - [IEC sizes](https://en.wikipedia.org/wiki/Binary_prefix#IEC_prefixes) (binary units, powers of 1024), e.g. `1B`, `2KiB`, `3MiB`, `4GiB`, `5TiB`, …)
+
+### `optionalString`
+
+Optional strings allow specifying some string value which has
+an implicit default when missing from the config file:
+
+- `null`/missing will apply the default value defined in Kubo sources (`.WithDefault("value")`)
+- a string
+
+### `optionalDuration`
+
+Optional durations allow specifying some duration value which has
+an implicit default when missing from the config file:
+
+- `null`/missing will apply the default value defined in Kubo sources (`.WithDefault("1h2m3s")`)
+- a string with a valid [go duration](#duration) (e.g, `"1d2h4m40.01s"`).
+
+----
+
+[multiaddr]: https://docs.ipfs.tech/concepts/glossary/#multiaddr
diff --git a/docs/content-blocking.md b/docs/content-blocking.md
index fad63ad9ed3..e894868ace2 100644
--- a/docs/content-blocking.md
+++ b/docs/content-blocking.md
@@ -44,7 +44,7 @@ caused the request to be blocked.
[NOpfs](https://github.com/ipfs-shipyard/nopfs) supports the format from [IPIP-383](https://github.com/ipfs/specs/pull/383).
Clear-text rules are simple: just put content paths to block, one per line.
-Paths with unicode and whitespace need to be percend-encoded:
+Paths with unicode and whitespace need to be percent-encoded:
```
/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR
diff --git a/docs/datastores.md b/docs/datastores.md
index db729bf97a0..f574bc6a5dd 100644
--- a/docs/datastores.md
+++ b/docs/datastores.md
@@ -3,6 +3,13 @@
This document describes the different possible values for the `Datastore.Spec`
field in the ipfs configuration file.
+- [flatfs](#flatfs)
+- [levelds](#levelds)
+- [pebbleds](#pebbleds)
+- [badgerds](#badgerds)
+- [mount](#mount)
+- [measure](#measure)
+
## flatfs
Stores each key value pair as a file on the filesystem.
@@ -22,6 +29,8 @@ The shardFunc is prefixed with `/repo/flatfs/shard/v1` then followed by a descri
}
```
+- `sync`: Flush every write to disk before continuing. Setting this to false is safe as kubo will automatically flush writes to disk before and after performing critical operations like pinning. However, you can set this to true to be extra-safe (at the cost of a slowdown when adding files).
+
NOTE: flatfs must only be used as a block store (mounted at `/blocks`) as it only partially implements the datastore interface. You can mount flatfs for /blocks only using the mount datastore (described below).
## levelds
@@ -35,12 +44,62 @@ Uses a leveldb database to store key value pairs.
}
```
+## pebbleds
+
+Uses [pebble](https://github.com/cockroachdb/pebble) as a key value store.
+
+```json
+{
+ "type": "pebbleds",
+ "path": "",
+}
+```
+
+The following options are available for tuning pebble.
+If they are not configured (or assigned their zero-valued), then default values are used.
+
+* `bytesPerSync`: int, Sync sstables periodically in order to smooth out writes to disk. (default: 512KB)
+* `disableWAL`: true|false, Disable the write-ahead log (WAL) at expense of prohibiting crash recovery. (default: false)
+* `cacheSize`: Size of pebble's shared block cache. (default: 8MB)
+* `formatVersionMajor`: int, Sets the format of pebble on-disk files. If 0 or unset, automatically convert to latest format.
+* `l0CompactionThreshold`: int, Count of L0 files necessary to trigger an L0 compaction.
+* `l0StopWritesThreshold`: int, Limit on L0 read-amplification, computed as the number of L0 sublevels.
+* `lBaseMaxBytes`: int, Maximum number of bytes for LBase. The base level is the level which L0 is compacted into.
+* `maxConcurrentCompactions`: int, Maximum number of concurrent compactions. (default: 1)
+* `memTableSize`: int, Size of a MemTable in steady state. The actual MemTable size starts at min(256KB, MemTableSize) and doubles for each subsequent MemTable up to MemTableSize (default: 4MB)
+* `memTableStopWritesThreshold`: int, Limit on the number of queued of MemTables. (default: 2)
+* `walBytesPerSync`: int: Sets the number of bytes to write to a WAL before calling Sync on it in the background. (default: 0, no background syncing)
+* `walMinSyncSeconds`: int: Sets the minimum duration between syncs of the WAL. (default: 0)
+
+> [!TIP]
+> Start using pebble with only default values and configure tuning items are needed for your needs. For a more complete description of these values, see: `https://pkg.go.dev/github.com/cockroachdb/pebble@vA.B.C#Options` (where `A.B.C` is pebble version from Kubo's `go.mod`).
+
+Using a pebble datastore can be set when initializing kubo `ipfs init --profile pebbleds`.
+
+#### Use of `formatMajorVersion`
+
+[Pebble's `FormatMajorVersion`](https://github.com/cockroachdb/pebble/tree/master?tab=readme-ov-file#format-major-versions) is a constant controlling the format of persisted data. Backwards incompatible changes to durable formats are gated behind new format major versions.
+
+At any point, a database's format major version may be bumped. However, once a database's format major version is increased, previous versions of Pebble will refuse to open the database.
+
+When IPFS is initialized to use the pebbleds datastore (`ipfs init --profile=pebbleds`), the latest pebble database format is configured in the pebble datastore config as `"formatMajorVersion"`. Setting this in the datastore config prevents automatically upgrading to the latest available version when kubo is upgraded. If a later version becomes available, the kubo daemon prints a startup message to indicate this. The user can them update the config to use the latest format when they are certain a downgrade will not be necessary.
+
+Without the `"formatMajorVersion"` in the pebble datastore config, the database format is automatically upgraded to the latest version. If this happens, then it is possible a downgrade back to the previous version of kubo will not work if new format is not compatible with the pebble datastore in the previous version of kubo.
+
+When installing a new version of kubo when `"formatMajorVersion"` is configured, migration does not upgrade this to the latest available version. This is done because a user may have reasons not to upgrade the pebble database format, and may want to be able to downgrade kubo if something else is not working in the new version. If the configured pebble database format in the old kubo is not supported in the new kubo, then the configured version must be updated and the old kubo run, before installing the new kubo.
+
## badgerds
Uses [badger](https://github.com/dgraph-io/badger) as a key value store.
+> [!CAUTION]
+> This is based on very old badger 1.x, which has known bugs and is no longer supported by the upstream team.
+> It is provided here only for pre-existing users, allowing them to migrate away to more modern datastore.
+> Do not use it for new deployments, unless you really, really know what you are doing.
+
+
* `syncWrites`: Flush every write to disk before continuing. Setting this to false is safe as kubo will automatically flush writes to disk before and after performing critical operations like pinning. However, you can set this to true to be extra-safe (at the cost of a 2-3x slowdown when adding files).
-* `truncate`: Truncate the DB if a partially written sector is found (defaults to true). There is no good reason to set this to false unless you want to manually recover partially written (and unpinned) blocks if kubo crashes half-way through a adding a file.
+* `truncate`: Truncate the DB if a partially written sector is found (defaults to true). There is no good reason to set this to false unless you want to manually recover partially written (and unpinned) blocks if kubo crashes half-way through adding a file.
```json
{
diff --git a/docs/debug-guide.md b/docs/debug-guide.md
index 9ea8a3bb6f4..74034f41f54 100644
--- a/docs/debug-guide.md
+++ b/docs/debug-guide.md
@@ -106,6 +106,6 @@ See `tracing/doc.go` for more details.
### Other
-If you have any questions, or want us to analyze some weird kubo behaviour,
+If you have any questions, or want us to analyze some weird kubo behavior,
just let us know, and be sure to include all the profiling information
mentioned at the top.
diff --git a/docs/delegated-routing.md b/docs/delegated-routing.md
index f4207f409e4..ddc4e48ed3c 100644
--- a/docs/delegated-routing.md
+++ b/docs/delegated-routing.md
@@ -11,11 +11,19 @@
Previously we only used the Amino DHT for content routing and content
providing.
-Kubo 0.14 introduced experimental support for [delegated routing using Reframe protocol](https://github.com/ipfs/kubo/pull/8997).
-Since then, Reframe got deprecated and superseded by [Routing V1 HTTP API](https://specs.ipfs.tech/routing/http-routing-v1/).
+Kubo 0.14 introduced experimental support for [delegated routing](https://github.com/ipfs/kubo/pull/8997),
+which then got changed and standardized as [Routing V1 HTTP API](https://specs.ipfs.tech/routing/http-routing-v1/).
Kubo 0.23.0 release added support for [self-hosting Routing V1 HTTP API server](https://github.com/ipfs/kubo/blob/master/docs/changelogs/v0.23.md#self-hosting-routingv1-endpoint-for-delegated-routing-needs).
+
+> [!TIP]
+> Kubo 0.35 added support for [`Routing.DelegatedRouters`](https://github.com/ipfs/kubo/blob/master/docs/config.md#routingdelegatedrouters).
+>
+> Most of users are best served by setting delegated HTTP router URLs there and `Routing.Type` to `auto` or `autoclient`, rather than custom routing with complex `Routing.Routers` and `Routing.Methods` directly.
+>
+> The rest of this documentation should be considered only by advanced users and researchers.
+
Now we need a better way to add different routers using different protocols
like [Routing V1](https://specs.ipfs.tech/routing/http-routing-v1/) or Amino
DHT, and be able to configure them (future routing systems to come) to cover different use cases.
@@ -42,15 +50,15 @@ The `Routing` configuration section will contain the following keys:
#### Routers
-`Routers` will be a key-value list of routers that will be available to use. The key is the router name and the value is all the needed configurations for that router. the `Type` will define the routing kind. The main router types will be `reframe` and `dht`, but we will implement two special routers used to execute a set of routers in parallel or sequentially: `parallel` router and `sequential` router.
+`Routers` will be a key-value list of routers that will be available to use. The key is the router name and the value is all the needed configurations for that router. the `Type` will define the routing kind. The main router types will be `http` and `dht`, but we will implement two special routers used to execute a set of routers in parallel or sequentially: `parallel` router and `sequential` router.
Depending on the routing type, it will use different parameters:
-##### Reframe
+##### HTTP
Params:
-- `"Endpoint"`: URL endpoint implementing Reframe protocol.
+- `"Endpoint"`: URL of HTTP server with endpoints that implement [Delegated Routing V1 HTTP API](https://specs.ipfs.tech/routing/http-routing-v1/) protocol.
##### Amino DHT
@@ -89,10 +97,10 @@ The value will contain:
"Routing": {
"Type": "custom",
"Routers": {
- "storetheindex": {
- "Type": "reframe",
+ "http-delegated": {
+ "Type": "http",
"Parameters": {
- "Endpoint": "https://cid.contact/reframe"
+ "Endpoint": "https://delegated-ipfs.dev" // /routing/v1 (https://specs.ipfs.tech/routing/http-routing-v1/)
}
},
"dht-lan": {
@@ -123,7 +131,7 @@ The value will contain:
"RouterName": "dht-wan"
},
{
- "RouterName": "storetheindex"
+ "RouterName": "http-delegated"
}
]
}
@@ -142,7 +150,7 @@ The value will contain:
"Timeout": "100ms"
},
{
- "RouterName": "storetheindex",
+ "RouterName": "http-delegated",
"ExecuteAfter": "100ms"
}
]
@@ -161,7 +169,7 @@ The value will contain:
"Timeout": "300ms"
},
{
- "RouterName": "storetheindex",
+ "RouterName": "http-delegated",
"Timeout": "300ms"
}
]
@@ -178,7 +186,7 @@ The value will contain:
"RouterName": "dht-wan"
},
{
- "RouterName": "storetheindex"
+ "RouterName": "http-delegated"
}
]
}
@@ -201,75 +209,6 @@ The value will contain:
}
```
-Added YAML for clarity:
-
-```yaml
----
-Type: custom
-Routers:
- storetheindex:
- Type: reframe
- Parameters:
- Endpoint: https://cid.contact/reframe
- dht-lan:
- Type: dht
- Parameters:
- Mode: server
- PublicIPNetwork: false
- AcceleratedDHTClient: false
- dht-wan:
- Type: dht
- Parameters:
- Mode: auto
- PublicIPNetwork: true
- AcceleratedDHTClient: false
- find-providers-router:
- Type: parallel
- Parameters:
- Routers:
- - RouterName: dht-lan
- IgnoreErrors: true
- - RouterName: dht-wan
- - RouterName: storetheindex
- provide-router:
- Type: parallel
- Parameters:
- Routers:
- - RouterName: dht-lan
- IgnoreErrors: true
- - RouterName: dht-wan
- ExecuteAfter: 100ms
- Timeout: 100ms
- - RouterName: storetheindex
- ExecuteAfter: 100ms
- get-ipns-router:
- Type: sequential
- Parameters:
- Routers:
- - RouterName: dht-lan
- IgnoreErrors: true
- - RouterName: dht-wan
- Timeout: 300ms
- - RouterName: storetheindex
- Timeout: 300ms
- put-ipns-router:
- Type: parallel
- Parameters:
- Routers:
- - RouterName: dht-lan
- - RouterName: dht-wan
- - RouterName: storetheindex
-Methods:
- find-providers:
- RouterName: find-providers-router
- provide:
- RouterName: provide-router
- get-ipns:
- RouterName: get-ipns-router
- put-ipns:
- RouterName: put-ipns-router
-```
-
### Error cases
- If any of the routers fails, the output will be an error by default.
- You can use `IgnoreErrors:true` to ignore errors for a specific router output
@@ -402,54 +341,12 @@ As test fixtures we can add different use cases here and see how the configurati
}
}
```
-YAML representation for clarity:
-
-```yaml
----
-Type: custom
-Routers:
- dht-lan:
- Type: dht
- Parameters:
- Mode: server
- PublicIPNetwork: false
- dht-wan:
- Type: dht
- Parameters:
- Mode: auto
- PublicIPNetwork: true
- parallel-dht-strict:
- Type: parallel
- Parameters:
- Routers:
- - RouterName: dht-lan
- - RouterName: dht-wan
- parallel-dht:
- Type: parallel
- Parameters:
- Routers:
- - RouterName: dht-lan
- IgnoreError: true
- - RouterName: dht-wan
-Methods:
- provide:
- RouterName: dht-wan
- find-providers:
- RouterName: parallel-dht-strict
- find-peers:
- RouterName: parallel-dht-strict
- get-ipns:
- RouterName: parallel-dht
- put-ipns:
- RouterName: parallel-dht
-
-```
### Compatibility
~~We need to create a config migration using [fs-repo-migrations](https://github.com/ipfs/fs-repo-migrations). We should remove the `Routing.Type` param and add the configuration specified [previously](#Mimic-previous-dual-DHT-config).~~
-We don't need to create any config migration! To avoid to the users the hassle of understanding how the new routing system works, we are gonna keep the old behavior. We will add the Type `custom` to make available the new Routing system.
+We don't need to create any config migration! To avoid to the users the hassle of understanding how the new routing system works, we are going to keep the old behavior. We will add the Type `custom` to make available the new Routing system.
### Security
diff --git a/docs/environment-variables.md b/docs/environment-variables.md
index f0f6b3f183a..2b763721b00 100644
--- a/docs/environment-variables.md
+++ b/docs/environment-variables.md
@@ -1,5 +1,32 @@
# Kubo environment variables
+- [Variables](#variables)
+ - [`IPFS_PATH`](#ipfs_path)
+ - [`IPFS_LOGGING`](#ipfs_logging)
+ - [`IPFS_LOGGING_FMT`](#ipfs_logging_fmt)
+ - [`GOLOG_LOG_LEVEL`](#golog_log_level)
+ - [`GOLOG_LOG_FMT`](#golog_log_fmt)
+ - [`GOLOG_FILE`](#golog_file)
+ - [`GOLOG_OUTPUT`](#golog_output)
+ - [`GOLOG_TRACING_FILE`](#golog_tracing_file)
+ - [`IPFS_FUSE_DEBUG`](#ipfs_fuse_debug)
+ - [`YAMUX_DEBUG`](#yamux_debug)
+ - [`IPFS_FD_MAX`](#ipfs_fd_max)
+ - [`IPFS_DIST_PATH`](#ipfs_dist_path)
+ - [`IPFS_NS_MAP`](#ipfs_ns_map)
+ - [`IPFS_HTTP_ROUTERS`](#ipfs_http_routers)
+ - [`IPFS_HTTP_ROUTERS_FILTER_PROTOCOLS`](#ipfs_http_routers_filter_protocols)
+ - [`IPFS_CONTENT_BLOCKING_DISABLE`](#ipfs_content_blocking_disable)
+ - [`IPFS_WAIT_REPO_LOCK`](#ipfs_wait_repo_lock)
+ - [`LIBP2P_TCP_REUSEPORT`](#libp2p_tcp_reuseport)
+ - [`LIBP2P_TCP_MUX`](#libp2p_tcp_mux)
+ - [`LIBP2P_MUX_PREFS`](#libp2p_mux_prefs)
+ - [`LIBP2P_RCMGR`](#libp2p_rcmgr)
+ - [`LIBP2P_DEBUG_RCMGR`](#libp2p_debug_rcmgr)
+- [Tracing](#tracing)
+
+# Variables
+
## `IPFS_PATH`
Sets the location of the IPFS repo (where the config, blocks, etc.
@@ -63,6 +90,14 @@ The logging format defaults to `color` when the output is a terminal, and `nocol
Sets the file to which Kubo logs. By default, Kubo logs to standard error.
+## `GOLOG_OUTPUT`
+
+When stderr and/or stdout options are configured or specified by the `GOLOG_OUTPUT` environ variable, log only to the output(s) specified. For example:
+
+- `GOLOG_OUTPUT="stderr"` logs only to stderr
+- `GOLOG_OUTPUT="stdout"` logs only to stdout
+- `GOLOG_OUTPUT="stderr+stdout"` logs to both stderr and stdout
+
## `GOLOG_TRACING_FILE`
Sets the file to which Kubo sends tracing events. By default, tracing is
@@ -131,19 +166,50 @@ 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).
+Default: `config.DefaultHTTPRouters`
+
+## `IPFS_HTTP_ROUTERS_FILTER_PROTOCOLS`
+
+Overrides values passed with `filter-protocols` parameter defined in IPIP-484.
+Value is space-separated.
+
+```console
+$ IPFS_HTTP_ROUTERS_FILTER_PROTOCOLS="unknown transport-bitswap transport-foo" ipfs daemon
+```
+
+Default: `config.DefaultHTTPRoutersFilterProtocols`
## `IPFS_CONTENT_BLOCKING_DISABLE`
Disables the content-blocking subsystem. No denylists will be watched and no
content will be blocked.
+## `IPFS_WAIT_REPO_LOCK`
+
+Specifies the amount of time to wait for the repo lock. Set the value of this variable to a string that can be [parsed](https://pkg.go.dev/time@go1.24.3#ParseDuration) as a golang `time.Duration`. For example:
+```
+IPFS_WAIT_REPO_LOCK="15s"
+```
+
+If the lock cannot be acquired because someone else has the lock, and `IPFS_WAIT_REPO_LOCK` is set to a valid value, then acquiring the lock is retried every second until the lock is acquired or the specified wait time has elapsed.
+
## `LIBP2P_TCP_REUSEPORT`
Kubo tries to reuse the same source port for all connections to improve NAT
traversal. If this is an issue, you can disable it by setting
`LIBP2P_TCP_REUSEPORT` to false.
-Default: true
+Default: `true`
+
+## `LIBP2P_TCP_MUX`
+
+By default Kubo tries to reuse the same listener port for raw TCP and WebSockets transports via experimental `libp2p.ShareTCPListener()` feature introduced in [go-libp2p#2984](https://github.com/libp2p/go-libp2p/pull/2984).
+If this is an issue, you can disable it by setting `LIBP2P_TCP_MUX` to `false` and use separate ports for each TCP transport.
+
+> [!CAUTION]
+> This configuration option may be removed once `libp2p.ShareTCPListener()` becomes default in go-libp2p.
+
+Default: `true`
## `LIBP2P_MUX_PREFS`
diff --git a/docs/examples/kubo-as-a-library/go.mod b/docs/examples/kubo-as-a-library/go.mod
index 25d7edb7ca4..415c5d2b453 100644
--- a/docs/examples/kubo-as-a-library/go.mod
+++ b/docs/examples/kubo-as-a-library/go.mod
@@ -1,213 +1,235 @@
module github.com/ipfs/kubo/examples/kubo-as-a-library
-go 1.20
+go 1.24
// Used to keep this in sync with the current version of kubo. You should remove
// this if you copy this example.
replace github.com/ipfs/kubo => ./../../..
require (
- github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a
+ github.com/ipfs/boxo v0.31.1-0.20250528182950-f87feb50c39c
github.com/ipfs/kubo v0.0.0-00010101000000-000000000000
- github.com/libp2p/go-libp2p v0.32.2
- github.com/multiformats/go-multiaddr v0.12.2
+ github.com/libp2p/go-libp2p v0.41.1
+ github.com/multiformats/go-multiaddr v0.15.0
)
require (
bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc // indirect
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
+ github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e // indirect
github.com/Jorropo/jsync v1.0.1 // indirect
- github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
+ github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
- github.com/cenkalti/backoff/v4 v4.2.1 // 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.2.0 // indirect
+ github.com/caddyserver/certmagic v0.21.6 // indirect
+ github.com/caddyserver/zerossl v0.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.3.0 // indirect
+ github.com/ceramicnetwork/go-dag-jose v0.1.1 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
+ github.com/cockroachdb/crlib v0.0.0-20241015224233-894974b3ad94 // indirect
+ github.com/cockroachdb/errors v1.11.3 // indirect
+ github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect
+ github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
+ github.com/cockroachdb/pebble/v2 v2.0.3 // indirect
+ github.com/cockroachdb/redact v1.1.5 // indirect
+ github.com/cockroachdb/swiss v0.0.0-20250327203710-2932b022f6df // indirect
+ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
- github.com/crackcomm/go-gitignore v0.0.0-20231225121904-e25f5bc08668 // indirect
+ github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf // indirect
github.com/cskr/pubsub v1.0.2 // indirect
- github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
- github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
+ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/dgraph-io/badger v1.6.2 // indirect
- github.com/dgraph-io/ristretto v0.0.2 // indirect
+ github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
- github.com/elastic/gosigar v0.14.2 // indirect
+ github.com/elastic/gosigar v0.14.3 // indirect
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect
- github.com/flynn/noise v1.0.1 // indirect
+ github.com/felixge/httpsnoop v1.0.4 // indirect
+ github.com/filecoin-project/go-clock v0.1.0 // indirect
+ github.com/flynn/noise v1.1.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
- github.com/fsnotify/fsnotify v1.6.0 // indirect
- github.com/gabriel-vasile/mimetype v1.4.3 // indirect
- github.com/go-logr/logr v1.4.1 // indirect
+ github.com/fsnotify/fsnotify v1.7.0 // indirect
+ github.com/gabriel-vasile/mimetype v1.4.6 // indirect
+ github.com/gammazero/chanqueue v1.1.0 // indirect
+ github.com/gammazero/deque v1.0.0 // indirect
+ github.com/getsentry/sentry-go v0.27.0 // indirect
+ github.com/go-jose/go-jose/v4 v4.0.5 // indirect
+ github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
- github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
+ github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golang/protobuf v1.5.3 // indirect
- github.com/golang/snappy v0.0.4 // indirect
+ github.com/golang/glog v1.2.4 // indirect
+ github.com/golang/protobuf v1.5.4 // indirect
+ github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect
github.com/google/gopacket v1.1.19 // indirect
- github.com/google/pprof v0.0.0-20231229205709-960ae82b1e42 // indirect
- github.com/google/uuid v1.5.0 // indirect
- github.com/gorilla/websocket v1.5.0 // indirect
- github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
- github.com/hashicorp/errwrap v1.1.0 // indirect
- github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/google/pprof v0.0.0-20250208200701-d0013a598941 // indirect
+ github.com/google/uuid v1.6.0 // indirect
+ github.com/gorilla/websocket v1.5.3 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/huin/goupnp v1.3.0 // indirect
- github.com/ipfs-shipyard/nopfs v0.0.12 // indirect
- github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c // indirect
+ github.com/ipfs-shipyard/nopfs v0.0.14 // indirect
+ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 // indirect
github.com/ipfs/bbloom v0.0.4 // indirect
github.com/ipfs/go-bitfield v1.1.0 // indirect
- github.com/ipfs/go-block-format v0.2.0 // indirect
- github.com/ipfs/go-cid v0.4.1 // indirect
+ github.com/ipfs/go-block-format v0.2.1 // indirect
+ github.com/ipfs/go-cid v0.5.0 // indirect
github.com/ipfs/go-cidutil v0.1.0 // indirect
- github.com/ipfs/go-datastore v0.6.0 // indirect
- github.com/ipfs/go-ds-badger v0.3.0 // indirect
- github.com/ipfs/go-ds-flatfs v0.5.1 // indirect
- github.com/ipfs/go-ds-leveldb v0.5.0 // indirect
- github.com/ipfs/go-ds-measure v0.2.0 // indirect
- github.com/ipfs/go-fs-lock v0.0.7 // indirect
+ github.com/ipfs/go-datastore v0.8.2 // indirect
+ github.com/ipfs/go-ds-badger v0.3.4 // indirect
+ github.com/ipfs/go-ds-flatfs v0.5.5 // indirect
+ github.com/ipfs/go-ds-leveldb v0.5.2 // indirect
+ github.com/ipfs/go-ds-measure v0.2.2 // indirect
+ github.com/ipfs/go-ds-pebble v0.5.0 // indirect
+ github.com/ipfs/go-fs-lock 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-ds-help v1.1.1 // indirect
github.com/ipfs/go-ipfs-pq v0.0.3 // indirect
- github.com/ipfs/go-ipfs-redirects-file v0.1.1 // indirect
- github.com/ipfs/go-ipfs-util v0.0.3 // indirect
- github.com/ipfs/go-ipld-cbor v0.1.0 // indirect
- github.com/ipfs/go-ipld-format v0.6.0 // indirect
+ github.com/ipfs/go-ipfs-redirects-file v0.1.2 // indirect
+ github.com/ipfs/go-ipld-cbor v0.2.0 // indirect
+ github.com/ipfs/go-ipld-format v0.6.1 // indirect
github.com/ipfs/go-ipld-git v0.1.1 // indirect
github.com/ipfs/go-ipld-legacy v0.2.1 // indirect
- github.com/ipfs/go-log v1.0.5 // indirect
- github.com/ipfs/go-log/v2 v2.5.1 // indirect
- github.com/ipfs/go-metrics-interface v0.0.1 // indirect
- github.com/ipfs/go-peertaskqueue v0.8.1 // indirect
- github.com/ipfs/go-unixfsnode v1.9.0 // indirect
- github.com/ipld/go-car/v2 v2.13.1 // indirect
- github.com/ipld/go-codec-dagpb v1.6.0 // indirect
+ github.com/ipfs/go-log/v2 v2.6.0 // indirect
+ github.com/ipfs/go-metrics-interface v0.3.0 // indirect
+ github.com/ipfs/go-peertaskqueue v0.8.2 // indirect
+ github.com/ipfs/go-unixfsnode v1.10.1 // indirect
+ github.com/ipld/go-car/v2 v2.14.3 // indirect
+ github.com/ipld/go-codec-dagpb v1.7.0 // indirect
github.com/ipld/go-ipld-prime v0.21.0 // indirect
+ github.com/ipshipyard/p2p-forge v0.5.1 // 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.17.4 // indirect
- github.com/klauspost/cpuid/v2 v2.2.6 // indirect
- github.com/koron/go-ssdp v0.0.4 // indirect
+ github.com/klauspost/compress v1.18.0 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.10 // indirect
+ github.com/koron/go-ssdp v0.0.5 // indirect
+ github.com/kr/pretty v0.3.1 // indirect
+ github.com/kr/text v0.2.0 // indirect
+ github.com/libdns/libdns v0.2.2 // 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-doh-resolver v0.5.0 // indirect
+ github.com/libp2p/go-flow-metrics v0.2.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
- github.com/libp2p/go-libp2p-kad-dht v0.24.4 // indirect
- github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect
- github.com/libp2p/go-libp2p-pubsub v0.10.0 // indirect
+ github.com/libp2p/go-libp2p-kad-dht v0.33.1 // indirect
+ github.com/libp2p/go-libp2p-kbucket v0.7.0 // indirect
+ github.com/libp2p/go-libp2p-pubsub v0.13.1 // 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.7.3 // indirect
+ github.com/libp2p/go-libp2p-record v0.3.1 // indirect
+ github.com/libp2p/go-libp2p-routing-helpers v0.7.5 // indirect
github.com/libp2p/go-libp2p-xor v0.1.0 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
- github.com/libp2p/go-nat v0.2.0 // indirect
- github.com/libp2p/go-netroute v0.2.1 // indirect
+ github.com/libp2p/go-netroute v0.2.2 // indirect
github.com/libp2p/go-reuseport v0.4.0 // indirect
- github.com/libp2p/go-yamux/v4 v4.0.1 // indirect
+ github.com/libp2p/go-yamux/v5 v5.0.0 // indirect
github.com/libp2p/zeroconf/v2 v2.2.0 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
- github.com/miekg/dns v1.1.58 // indirect
+ github.com/mholt/acmez/v3 v3.0.0 // indirect
+ github.com/miekg/dns v1.1.66 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
- github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.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-dns v0.4.1 // indirect
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
- github.com/multiformats/go-multistream v0.5.0 // indirect
+ github.com/multiformats/go-multistream v0.6.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
- github.com/onsi/ginkgo/v2 v2.13.2 // indirect
- github.com/opencontainers/runtime-spec v1.1.0 // indirect
+ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/onsi/ginkgo/v2 v2.22.2 // indirect
+ github.com/opencontainers/runtime-spec v1.2.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
- github.com/openzipkin/zipkin-go v0.4.2 // indirect
+ github.com/openzipkin/zipkin-go v0.4.3 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect
- github.com/pion/datachannel v1.5.5 // indirect
- github.com/pion/dtls/v2 v2.2.7 // indirect
- github.com/pion/ice/v2 v2.3.6 // indirect
- github.com/pion/interceptor v0.1.17 // indirect
- github.com/pion/logging v0.2.2 // indirect
- github.com/pion/mdns v0.0.7 // indirect
+ github.com/pion/datachannel v1.5.10 // indirect
+ github.com/pion/dtls/v2 v2.2.12 // indirect
+ github.com/pion/dtls/v3 v3.0.4 // indirect
+ github.com/pion/ice/v4 v4.0.8 // indirect
+ github.com/pion/interceptor v0.1.37 // indirect
+ github.com/pion/logging v0.2.3 // indirect
+ github.com/pion/mdns/v2 v2.0.7 // indirect
github.com/pion/randutil v0.1.0 // indirect
- github.com/pion/rtcp v1.2.10 // indirect
- github.com/pion/rtp v1.7.13 // indirect
- github.com/pion/sctp v1.8.7 // indirect
- github.com/pion/sdp/v3 v3.0.6 // indirect
- github.com/pion/srtp/v2 v2.0.15 // indirect
- github.com/pion/stun v0.6.0 // indirect
- github.com/pion/transport/v2 v2.2.1 // indirect
- github.com/pion/turn/v2 v2.1.0 // indirect
- github.com/pion/webrtc/v3 v3.2.9 // indirect
+ github.com/pion/rtcp v1.2.15 // indirect
+ github.com/pion/rtp v1.8.11 // indirect
+ github.com/pion/sctp v1.8.37 // indirect
+ github.com/pion/sdp/v3 v3.0.10 // indirect
+ github.com/pion/srtp/v3 v3.0.4 // indirect
+ github.com/pion/stun v0.6.1 // indirect
+ github.com/pion/stun/v3 v3.0.0 // indirect
+ github.com/pion/transport/v2 v2.2.10 // indirect
+ github.com/pion/transport/v3 v3.0.7 // indirect
+ github.com/pion/turn/v4 v4.0.0 // indirect
+ github.com/pion/webrtc/v4 v4.0.10 // indirect
github.com/pkg/errors v0.9.1 // indirect
- github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
- github.com/prometheus/client_golang v1.18.0 // indirect
- github.com/prometheus/client_model v0.5.0 // indirect
- github.com/prometheus/common v0.46.0 // indirect
- github.com/prometheus/procfs v0.12.0 // indirect
- github.com/quic-go/qpack v0.4.0 // indirect
- github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
- github.com/quic-go/quic-go v0.40.1 // indirect
- github.com/quic-go/webtransport-go v0.6.0 // indirect
+ github.com/prometheus/client_golang v1.22.0 // indirect
+ github.com/prometheus/client_model v0.6.2 // indirect
+ github.com/prometheus/common v0.63.0 // indirect
+ github.com/prometheus/procfs v0.16.1 // indirect
+ github.com/quic-go/qpack v0.5.1 // indirect
+ github.com/quic-go/quic-go v0.50.1 // indirect
+ github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
- github.com/samber/lo v1.39.0 // indirect
+ github.com/rogpeppe/go-internal v1.13.1 // indirect
+ github.com/samber/lo v1.47.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
- github.com/stretchr/testify v1.8.4 // indirect
- github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
+ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // 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 v0.0.0-20171005072247-63513f603b11 // indirect
- github.com/whyrusleeping/cbor-gen v0.0.0-20240109153615-66e95c3e8a87 // indirect
+ github.com/whyrusleeping/cbor-gen v0.1.2 // 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/wlynxg/anet v0.0.5 // indirect
+ github.com/zeebo/blake3 v0.2.4 // indirect
go.opencensus.io v0.24.0 // indirect
- go.opentelemetry.io/otel v1.22.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 // indirect
- go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0 // indirect
- go.opentelemetry.io/otel/exporters/zipkin v1.21.0 // indirect
- go.opentelemetry.io/otel/metric v1.22.0 // indirect
- go.opentelemetry.io/otel/sdk v1.21.0 // indirect
- go.opentelemetry.io/otel/trace v1.22.0 // indirect
- go.opentelemetry.io/proto/otlp v1.0.0 // indirect
- go.uber.org/dig v1.17.1 // indirect
- go.uber.org/fx v1.20.1 // indirect
- go.uber.org/mock v0.4.0 // indirect
+ go.opentelemetry.io/auto/sdk v1.1.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect
+ go.opentelemetry.io/otel v1.35.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 // indirect
+ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 // indirect
+ go.opentelemetry.io/otel/exporters/zipkin v1.31.0 // indirect
+ go.opentelemetry.io/otel/metric v1.35.0 // indirect
+ go.opentelemetry.io/otel/sdk v1.31.0 // indirect
+ go.opentelemetry.io/otel/trace v1.35.0 // indirect
+ go.opentelemetry.io/proto/otlp v1.3.1 // indirect
+ go.uber.org/dig v1.18.0 // indirect
+ go.uber.org/fx v1.23.0 // indirect
+ go.uber.org/mock v0.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.26.0 // indirect
+ go.uber.org/zap v1.27.0 // indirect
+ go.uber.org/zap/exp v0.3.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
- golang.org/x/crypto v0.18.0 // indirect
- golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
- golang.org/x/mod v0.14.0 // indirect
- golang.org/x/net v0.20.0 // indirect
- golang.org/x/sync v0.6.0 // indirect
- golang.org/x/sys v0.16.0 // indirect
- golang.org/x/text v0.14.0 // indirect
- golang.org/x/tools v0.17.0 // indirect
- golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
- gonum.org/v1/gonum v0.14.0 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20240108191215-35c7eff3a6b1 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect
- google.golang.org/grpc v1.60.1 // indirect
- google.golang.org/protobuf v1.32.0 // indirect
- gopkg.in/square/go-jose.v2 v2.5.1 // indirect
+ golang.org/x/crypto v0.38.0 // indirect
+ golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
+ golang.org/x/mod v0.24.0 // indirect
+ golang.org/x/net v0.40.0 // indirect
+ golang.org/x/sync v0.14.0 // indirect
+ golang.org/x/sys v0.33.0 // indirect
+ golang.org/x/text v0.25.0 // indirect
+ golang.org/x/tools v0.33.0 // indirect
+ golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
+ gonum.org/v1/gonum v0.16.0 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect
+ google.golang.org/grpc v1.67.1 // indirect
+ google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- lukechampine.com/blake3 v1.2.1 // indirect
+ lukechampine.com/blake3 v1.4.1 // indirect
)
diff --git a/docs/examples/kubo-as-a-library/go.sum b/docs/examples/kubo-as-a-library/go.sum
index 5db4134e89b..87753b63ed0 100644
--- a/docs/examples/kubo-as-a-library/go.sum
+++ b/docs/examples/kubo-as-a-library/go.sum
@@ -29,18 +29,20 @@ github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIo
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e h1:ZIWapoIRN1VqT8GR8jAwb1Ie9GyehWjVcGh32Y2MznE=
+github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Jorropo/jsync v1.0.1 h1:6HgRolFZnsdfzRUj+ImB9og1JYOxQoReSywkHOGSaUU=
github.com/Jorropo/jsync v1.0.1/go.mod h1:jCOZj3vrBCri3bSU3ErUYvevKlnbssrXeCivybS5ABQ=
-github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/aclements/go-perfevent v0.0.0-20240301234650-f7843625020f h1:JjxwchlOepwsUWcQwD2mLUAGE9aCp0/ehy6yCHFBOvo=
+github.com/aclements/go-perfevent v0.0.0-20240301234650-f7843625020f/go.mod h1:tMDTce/yLLN/SK8gMOxQfnyeMeCg8KGzp0D1cbECEeo=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
-github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 h1:ez/4by2iGztzR4L0zgAOR8lTQK9VlyBVVd7G4omaOQs=
-github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
+github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0=
+github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs=
github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 h1:iW0a5ljuFxkLGPNem5Ui+KBjFJzKg4Fv2fnxe4dvzpM=
github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5/go.mod h1:Y2QMoi1vgtOIfc+6DhrMOGkLoGzqSV2rKp4Sm+opsyA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
-github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
@@ -60,21 +62,45 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
-github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
-github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/caddyserver/certmagic v0.21.6 h1:1th6GfprVfsAtFNOu4StNMF5IxK5XiaI0yZhAHlZFPE=
+github.com/caddyserver/certmagic v0.21.6/go.mod h1:n1sCo7zV1Ez2j+89wrzDxo4N/T1Ws/Vx8u5NvuBFabw=
+github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
+github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
+github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
+github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/ceramicnetwork/go-dag-jose v0.1.0 h1:yJ/HVlfKpnD3LdYP03AHyTvbm3BpPiz2oZiOeReJRdU=
-github.com/ceramicnetwork/go-dag-jose v0.1.0/go.mod h1:qYA1nYt0X8u4XoMAVoOV3upUVKtrxy/I670Dg5F0wjI=
-github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
+github.com/ceramicnetwork/go-dag-jose v0.1.1 h1:7pObs22egc14vSS3AfCFfS1VmaL4lQUsAK7OGC3PlKk=
+github.com/ceramicnetwork/go-dag-jose v0.1.1/go.mod h1:8ptnYwY2Z2y/s5oJnNBn/UCxLg6CpramNJ2ZXF/5aNY=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
-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/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
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=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cockroachdb/crlib v0.0.0-20241015224233-894974b3ad94 h1:bvJv505UUfjzbaIPdNS4AEkHreDqQk6yuNpsdRHpwFA=
+github.com/cockroachdb/crlib v0.0.0-20241015224233-894974b3ad94/go.mod h1:Gq51ZeKaFCXk6QwuGM0w1dnaOqc/F5zKT2zA9D6Xeac=
+github.com/cockroachdb/datadriven v1.0.3-0.20240530155848-7682d40af056 h1:slXychO2uDM6hYRu4c0pD0udNI8uObfeKN6UInWViS8=
+github.com/cockroachdb/datadriven v1.0.3-0.20240530155848-7682d40af056/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
+github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
+github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8=
+github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4=
+github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M=
+github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
+github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
+github.com/cockroachdb/metamorphic v0.0.0-20231108215700-4ba948b56895 h1:XANOgPYtvELQ/h4IrmPAohXqe2pWA8Bwhejr3VQoZsA=
+github.com/cockroachdb/metamorphic v0.0.0-20231108215700-4ba948b56895/go.mod h1:aPd7gM9ov9M8v32Yy5NJrDyOcD8z642dqs+F0CeNXfA=
+github.com/cockroachdb/pebble/v2 v2.0.3 h1:YJ3Sc9jRN/q6OOCNyRHPbcpenbxL1DdgdpUqPlPus6o=
+github.com/cockroachdb/pebble/v2 v2.0.3/go.mod h1:NgxgNcWwyG/uxkLUZGM2aelshaLIZvc0hCX7SCfaO8s=
+github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
+github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
+github.com/cockroachdb/swiss v0.0.0-20250327203710-2932b022f6df h1:GUJ4KuZtbOcIfRlprHJFFvIqQ4irtQUl+1fJr+yNmPI=
+github.com/cockroachdb/swiss v0.0.0-20250327203710-2932b022f6df/go.mod h1:yBRu/cnL4ks9bgy4vAASdjIW+/xMlFwuHKqtmh3GZQg=
+github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
+github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ=
github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
@@ -89,25 +115,28 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
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-20231225121904-e25f5bc08668 h1:ZFUue+PNxmHlu7pYv+IYMtqlaO/0VwaGEqKepZf9JpA=
-github.com/crackcomm/go-gitignore v0.0.0-20231225121904-e25f5bc08668/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE=
+github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf h1:dwGgBWn84wUS1pVikGiruW+x5XM4amhjaZO20vCjay4=
+github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf/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=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU=
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U=
-github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
+github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
+github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8=
github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE=
-github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po=
github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
+github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
+github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
@@ -117,42 +146,59 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
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/elastic/gosigar v0.14.3 h1:xwkKwPia+hSfg9GqrCUKYdId102m9qTJIIr7egmK/uo=
+github.com/elastic/gosigar v0.14.3/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A=
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/filecoin-project/go-clock v0.1.0 h1:SFbYIM75M8NnFm1yMHhN9Ahy3W5bEZV9gd6MPfXbKVU=
+github.com/filecoin-project/go-clock v0.1.0/go.mod h1:4uB/O4PvOjlx1VCMdZ9MyDZXRm//gkj1ELEbxfI1AZs=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
-github.com/flynn/noise v1.0.1 h1:vPp/jdQLXC6ppsXSj/pM3W1BIJ5FEHE2TulSJBpb43Y=
-github.com/flynn/noise v1.0.1/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
+github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
+github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
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.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
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/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
-github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
+github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
+github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
+github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
+github.com/gammazero/chanqueue v1.1.0 h1:yiwtloc1azhgGLFo2gMloJtQvkYD936Ai7tBfa+rYJw=
+github.com/gammazero/chanqueue v1.1.0/go.mod h1:fMwpwEiuUgpab0sH4VHiVcEoji1pSi+EIzeG4TPeKPc=
+github.com/gammazero/deque v1.0.0 h1:LTmimT8H7bXkkCy6gZX7zNLtkbz4NdS2z8LZuor3j34=
+github.com/gammazero/deque v1.0.0/go.mod h1:iflpYvtGfM3U8S8j+sZEKIak3SAKYpA5/SQewgfXDKo=
+github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
+github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
+github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9 h1:r5GgOLGbza2wVHRzK7aAj6lWZjfbAwiu/RDCVOKjRyM=
+github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs=
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=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
+github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
+github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
+github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
-github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
-github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
-github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
+github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
+github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -165,10 +211,13 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc=
+github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@@ -188,11 +237,12 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e h1:4bw4WeyTYPp0smaXiJZCNnLrvVBqirQVreixayXezGc=
+github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -204,8 +254,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
@@ -214,34 +264,31 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20231229205709-960ae82b1e42 h1:dHLYa5D8/Ta0aLR2XcPsrkpAgGeFs6thhMcQK0oQ0n8=
-github.com/google/pprof v0.0.0-20231229205709-960ae82b1e42/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
+github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20250208200701-d0013a598941 h1:43XjGa6toxLpeksjcxs1jIoIyr+vUfOqY2c6HB4bpoc=
+github.com/google/pprof v0.0.0-20250208200701-d0013a598941/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
-github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
+github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
-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/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
+github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
+github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
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/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
-github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/go-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/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
@@ -253,106 +300,97 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/ipfs-shipyard/nopfs v0.0.12 h1:mvwaoefDF5VI9jyvgWCmaoTJIJFAfrbyQV5fJz35hlk=
-github.com/ipfs-shipyard/nopfs v0.0.12/go.mod h1:mQyd0BElYI2gB/kq/Oue97obP4B3os4eBmgfPZ+hnrE=
-github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c h1:7UynTbtdlt+w08ggb1UGLGaGjp1mMaZhoTZSctpn5Ak=
-github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c/go.mod h1:6EekK/jo+TynwSE/ZOiOJd4eEvRXoavEC3vquKtv4yI=
+github.com/ipfs-shipyard/nopfs v0.0.14 h1:HFepJt/MxhZ3/GsLZkkAPzIPdNYKaLO1Qb7YmPbWIKk=
+github.com/ipfs-shipyard/nopfs v0.0.14/go.mod h1:mQyd0BElYI2gB/kq/Oue97obP4B3os4eBmgfPZ+hnrE=
+github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcdHUd7SDsUOY=
+github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
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/boxo v0.17.1-0.20240126101119-fdfcfcc0708a h1:BMxa0aXrjyGh5gAkzxVsjDN71YhAWGfjbOoNvZt4/jg=
-github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a/go.mod h1:pIZgTWdm3k3pLF9Uq6MB8JEcW07UDwNJjlXW1HELW80=
+github.com/ipfs/boxo v0.31.1-0.20250528182950-f87feb50c39c h1:0jAFJxC74Gy0VwDG6WwYJq0yZdXOFIIeCwUXXln0w6A=
+github.com/ipfs/boxo v0.31.1-0.20250528182950-f87feb50c39c/go.mod h1:gEkUkBiZWtEjHd1AiUxaWEYaQApPtbeGF45fdfCwLX0=
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk=
-github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs=
-github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM=
-github.com/ipfs/go-blockservice v0.5.0 h1:B2mwhhhVQl2ntW2EIpaWPwSCxSuqr5fFA93Ms4bYLEY=
+github.com/ipfs/go-block-format v0.2.1 h1:96kW71XGNNa+mZw/MTzJrCpMhBWCrd9kBLoKm9Iip/Q=
+github.com/ipfs/go-block-format v0.2.1/go.mod h1:frtvXHMQhM6zn7HvEQu+Qz5wSTj+04oEH/I+NjDgEjk=
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.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
-github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
-github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
+github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg=
+github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk=
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.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.5.0/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-datastore v0.8.2 h1:Jy3wjqQR6sg/LhyY0NIePZC3Vux19nLtg7dx0TVqr6U=
+github.com/ipfs/go-datastore v0.8.2/go.mod h1:W+pI1NsUsz3tcsAACMtfC+IZdnQTnC/7VfPoJBQuts0=
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=
-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=
-github.com/ipfs/go-ds-flatfs v0.5.1/go.mod h1:RWTV7oZD/yZYBKdbVIFXTX2fdY2Tbvl94NsWqmoyAX4=
+github.com/ipfs/go-ds-badger v0.3.4 h1:MmqFicftE0KrwMC77WjXTrPuoUxhwyFsjKONSeWrlOo=
+github.com/ipfs/go-ds-badger v0.3.4/go.mod h1:HfqsKJcNnIr9ZhZ+rkwS1J5PpaWjJjg6Ipmxd7KPfZ8=
+github.com/ipfs/go-ds-flatfs v0.5.5 h1:lkx5C99pFBMI7T1sYF7y3v7xIYekNVNMp/95Gm9Y3tY=
+github.com/ipfs/go-ds-flatfs v0.5.5/go.mod h1:bM7+m7KFUyv5dp3RBKTr3+OHgZ6h8ydCQkO7tjeO9Z4=
github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8=
-github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo=
-github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q=
-github.com/ipfs/go-ds-measure v0.2.0 h1:sG4goQe0KDTccHMyT45CY1XyUbxe5VwTKpg2LjApYyQ=
-github.com/ipfs/go-ds-measure v0.2.0/go.mod h1:SEUD/rE2PwRa4IQEC5FuNAmjJCyYObZr9UvVh8V3JxE=
-github.com/ipfs/go-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-ipfs-blockstore v1.3.0 h1:m2EXaWgwTzAfsmt5UdJ7Is6l4gJcaM/A12XwJyvYvMM=
-github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ=
-github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8=
+github.com/ipfs/go-ds-leveldb v0.5.2 h1:6nmxlQ2zbp4LCNdJVsmHfs9GP0eylfBNxpmY1csp0x0=
+github.com/ipfs/go-ds-leveldb v0.5.2/go.mod h1:2fAwmcvD3WoRT72PzEekHBkQmBDhc39DJGoREiuGmYo=
+github.com/ipfs/go-ds-measure v0.2.2 h1:4kwvBGbbSXNYe4ANlg7qTIYoZU6mNlqzQHdVqICkqGI=
+github.com/ipfs/go-ds-measure v0.2.2/go.mod h1:b/87ak0jMgH9Ylt7oH0+XGy4P8jHx9KG09Qz+pOeTIs=
+github.com/ipfs/go-ds-pebble v0.5.0 h1:lXffYCAKVD7nLLPqwJ9D8IxgO7Kz8woiX021tezdsIM=
+github.com/ipfs/go-ds-pebble v0.5.0/go.mod h1:aiCRVcj3K60sxc6k5C+HO9C6rouqiSkjR/WKnbTcMfQ=
+github.com/ipfs/go-fs-lock v0.1.1 h1:TecsP/Uc7WqYYatasreZQiP9EGRy4ZnKoG4yXxR33nw=
+github.com/ipfs/go-fs-lock v0.1.1/go.mod h1:2goSXMCw7QfscHmSe09oXiR34DQeUdm+ei+dhonqly0=
+github.com/ipfs/go-ipfs-blockstore v1.3.1 h1:cEI9ci7V0sRNivqaOr0elDsamxXFxJMMMy7PTTDQNsQ=
+github.com/ipfs/go-ipfs-blockstore v1.3.1/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE=
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 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=
-github.com/ipfs/go-ipfs-exchange-offline v0.3.0 h1:c/Dg8GDPzixGd0MC8Jh6mjOwU57uYokgWRFidfvEkuA=
+github.com/ipfs/go-ipfs-ds-help v1.1.1 h1:B5UJOH52IbcfS56+Ul+sv8jnIV10lbjLF5eOO0C66Nw=
+github.com/ipfs/go-ipfs-ds-help v1.1.1/go.mod h1:75vrVCkSdSFidJscs8n4W+77AtTpCIAdDGAwjitJMIo=
github.com/ipfs/go-ipfs-pq v0.0.3 h1:YpoHVJB+jzK15mr/xsWC574tyDLkezVrDNeaalQBsTE=
github.com/ipfs/go-ipfs-pq v0.0.3/go.mod h1:btNw5hsHBpRcSSgZtiNm/SLj5gYIZ18AKtv3kERkRb4=
-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-redirects-file v0.1.2 h1:QCK7VtL91FH17KROVVy5KrzDx2hu68QvB2FTWk08ZQk=
+github.com/ipfs/go-ipfs-redirects-file v0.1.2/go.mod h1:yIiTlLcDEM/8lS6T3FlCEXZktPPqSOyuY6dEzVqw7Fw=
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ=
github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0=
github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs=
-github.com/ipfs/go-ipld-cbor v0.1.0 h1:dx0nS0kILVivGhfWuB6dUpMa/LAwElHPw1yOGYopoYs=
-github.com/ipfs/go-ipld-cbor v0.1.0/go.mod h1:U2aYlmVrJr2wsUBU67K4KgepApSZddGRDWBYR0H4sCk=
-github.com/ipfs/go-ipld-format v0.6.0 h1:VEJlA2kQ3LqFSIm5Vu6eIlSxD/Ze90xtc4Meten1F5U=
-github.com/ipfs/go-ipld-format v0.6.0/go.mod h1:g4QVMTn3marU3qXchwjpKPKgJv+zF+OlaKMyhJ4LHPg=
+github.com/ipfs/go-ipld-cbor v0.2.0 h1:VHIW3HVIjcMd8m4ZLZbrYpwjzqlVUfjLM7oK4T5/YF0=
+github.com/ipfs/go-ipld-cbor v0.2.0/go.mod h1:Cp8T7w1NKcu4AQJLqK0tWpd1nkgTxEVB5C6kVpLW6/0=
+github.com/ipfs/go-ipld-format v0.6.1 h1:lQLmBM/HHbrXvjIkrydRXkn+gc0DE5xO5fqelsCKYOQ=
+github.com/ipfs/go-ipld-format v0.6.1/go.mod h1:8TOH1Hj+LFyqM2PjSqI2/ZnyO0KlfhHbJLkbxFa61hs=
github.com/ipfs/go-ipld-git v0.1.1 h1:TWGnZjS0htmEmlMFEkA3ogrNCqWjIxwr16x1OsdhG+Y=
github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYDpKUkJubI=
github.com/ipfs/go-ipld-legacy v0.2.1 h1:mDFtrBpmU7b//LzLSypVrXsD8QxkEWxu5qVxN99/+tk=
github.com/ipfs/go-ipld-legacy v0.2.1/go.mod h1:782MOUghNzMO2DER0FlBR94mllfdCJCkTtDtPM51otM=
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.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
-github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0=
-github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw=
-github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
-github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g=
-github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
-github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
-github.com/ipfs/go-merkledag v0.11.0 h1:DgzwK5hprESOzS4O1t/wi6JDpyVQdvm9Bs59N/jqfBY=
-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.8.1 h1:YhxAs1+wxb5jk7RvS0LHdyiILpNmRIRnZVztekOF0pg=
-github.com/ipfs/go-peertaskqueue v0.8.1/go.mod h1:Oxxd3eaK279FxeydSPPVGHzbwVeHjatZ2GA8XD+KbPU=
-github.com/ipfs/go-unixfs v0.4.5 h1:wj8JhxvV1G6CD7swACwSKYa+NgtdWC1RUit+gFnymDU=
-github.com/ipfs/go-unixfsnode v1.9.0 h1:ubEhQhr22sPAKO2DNsyVBW7YB/zA8Zkif25aBvz8rc8=
-github.com/ipfs/go-unixfsnode v1.9.0/go.mod h1:HxRu9HYHOjK6HUqFBAi++7DVoWAHn0o4v/nZ/VA+0g8=
-github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs=
-github.com/ipld/go-car/v2 v2.13.1 h1:KnlrKvEPEzr5IZHKTXLAEub+tPrzeAFQVRlSQvuxBO4=
-github.com/ipld/go-car/v2 v2.13.1/go.mod h1:QkdjjFNGit2GIkpQ953KBwowuoukoM75nP/JI1iDJdo=
-github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc=
-github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s=
+github.com/ipfs/go-log/v2 v2.6.0 h1:2Nu1KKQQ2ayonKp4MPo6pXCjqw1ULc9iohRqWV5EYqg=
+github.com/ipfs/go-log/v2 v2.6.0/go.mod h1:p+Efr3qaY5YXpx9TX7MoLCSEZX5boSWj9wh86P5HJa8=
+github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6q/JR9V40TU=
+github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY=
+github.com/ipfs/go-peertaskqueue v0.8.2 h1:PaHFRaVFdxQk1Qo3OKiHPYjmmusQy7gKQUaL8JDszAU=
+github.com/ipfs/go-peertaskqueue v0.8.2/go.mod h1:L6QPvou0346c2qPJNiJa6BvOibxDfaiPlqHInmzg0FA=
+github.com/ipfs/go-test v0.2.2 h1:1yjYyfbdt1w93lVzde6JZ2einh3DIV40at4rVoyEcE8=
+github.com/ipfs/go-test v0.2.2/go.mod h1:cmLisgVwkdRCnKu/CFZOk2DdhOcwghr5GsHeqwexoRA=
+github.com/ipfs/go-unixfsnode v1.10.1 h1:hGKhzuH6NSzZ4y621wGuDspkjXRNG3B+HqhlyTjSwSM=
+github.com/ipfs/go-unixfsnode v1.10.1/go.mod h1:eguv/otvacjmfSbYvmamc9ssNAzLvRk0+YN30EYeOOY=
+github.com/ipld/go-car/v2 v2.14.3 h1:1Mhl82/ny8MVP+w1M4LXbj4j99oK3gnuZG2GmG1IhC8=
+github.com/ipld/go-car/v2 v2.14.3/go.mod h1:/vpSvPngOX8UnvmdFJ3o/mDgXa9LuyXsn7wxOzHDYQE=
+github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0=
+github.com/ipld/go-codec-dagpb v1.7.0/go.mod h1:rD3Zg+zub9ZnxcLwfol/OTQRVjaLzXypgy4UqHQvilM=
github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8=
-github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0=
github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E=
github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ=
github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd h1:gMlw/MhNr2Wtp5RwGdsW23cs+yCuj9k2ON7i9MiJlRo=
+github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd/go.mod h1:wZ8hH8UxeryOs4kJEJaiui/s00hDSbE37OKsL47g+Sw=
+github.com/ipshipyard/p2p-forge v0.5.1 h1:9MCpAlk+wNhy7W/yOYKgi9KlXPnyb0abmDpsRPHUDxQ=
+github.com/ipshipyard/p2p-forge v0.5.1/go.mod h1:GNDXM2CR8KRS8mJGw7ARIRVlrG9NH8MdewgNVfIIByA=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
-github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc=
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
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=
@@ -375,73 +413,73 @@ 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.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
-github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
+github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
+github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
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.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
-github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
+github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
-github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
+github.com/koron/go-ssdp v0.0.5 h1:E1iSMxIs4WqxTbIBLtmNBeOOC+1sCIXQeqTWVnpmwhk=
+github.com/koron/go-ssdp v0.0.5/go.mod h1:Qm59B7hpKpDqfyRNWRNr00jGwLdXjDyZh6y7rH6VS0w=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
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/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/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
+github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
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-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-doh-resolver v0.5.0 h1:4h7plVVW+XTS+oUBw2+8KfoM1jF6w8XmO7+skhePFdE=
+github.com/libp2p/go-doh-resolver v0.5.0/go.mod h1:aPDxfiD2hNURgd13+hfo29z9IC22fv30ee5iM31RzxU=
github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8=
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.32.2 h1:s8GYN4YJzgUoyeYNPdW7JZeZ5Ee31iNaIBfGYMAY4FQ=
-github.com/libp2p/go-libp2p v0.32.2/go.mod h1:E0LKe+diV/ZVJVnOJby8VC5xzHF0660osg71skcxJvk=
+github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw=
+github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc=
+github.com/libp2p/go-libp2p v0.41.1 h1:8ecNQVT5ev/jqALTvisSJeVNvXYJyK4NhQx1nNRXQZE=
+github.com/libp2p/go-libp2p v0.41.1/go.mod h1:DcGTovJzQl/I7HMrby5ZRjeD0kQkGiy+9w6aEkSZpRI=
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g=
github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw=
-github.com/libp2p/go-libp2p-kad-dht v0.24.4 h1:ktNiJe7ffsJ1wX3ULpMCwXts99mPqGFSE/Qn1i8pErQ=
-github.com/libp2p/go-libp2p-kad-dht v0.24.4/go.mod h1:ybWBJ5Fbvz9sSLkNtXt+2+bK0JB8+tRPvhBbRGHegRU=
+github.com/libp2p/go-libp2p-kad-dht v0.33.1 h1:hKFhHMf7WH69LDjaxsJUWOU6qZm71uO47M/a5ijkiP0=
+github.com/libp2p/go-libp2p-kad-dht v0.33.1/go.mod h1:CdmNk4VeGJa9EXM9SLNyNVySEvduKvb+5rSC/H4pLAo=
github.com/libp2p/go-libp2p-kbucket v0.3.1/go.mod h1:oyjT5O7tS9CQurok++ERgc46YLwEpuGoFq9ubvoUOio=
-github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0=
-github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEHetYSPXOaJnOiD8i0=
+github.com/libp2p/go-libp2p-kbucket v0.7.0 h1:vYDvRjkyJPeWunQXqcW2Z6E93Ywx7fX0jgzb/dGOKCs=
+github.com/libp2p/go-libp2p-kbucket v0.7.0/go.mod h1:blOINGIj1yiPYlVEX0Rj9QwEkmVnz3EP8LK1dRKBC6g=
github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs=
-github.com/libp2p/go-libp2p-pubsub v0.10.0 h1:wS0S5FlISavMaAbxyQn3dxMOe2eegMfswM471RuHJwA=
-github.com/libp2p/go-libp2p-pubsub v0.10.0/go.mod h1:1OxbaT/pFRO5h+Dpze8hdHQ63R0ke55XTs6b6NwLLkw=
+github.com/libp2p/go-libp2p-pubsub v0.13.1 h1:tV3ttzzZSCk0EtEXnxVmWIXgjVxXx+20Jwjbs/Ctzjo=
+github.com/libp2p/go-libp2p-pubsub v0.13.1/go.mod h1:MKPU5vMI8RRFyTP0HfdsF9cLmL1nHAeJm44AxJGJx44=
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-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.7.3 h1:u1LGzAMVRK9Nqq5aYDVOiq/HaB93U9WWczBzGyAC5ZY=
-github.com/libp2p/go-libp2p-routing-helpers v0.7.3/go.mod h1:cN4mJAD/7zfPKXBcs9ze31JGYAZgzdABEm+q/hkswb8=
+github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg=
+github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.5 h1:HdwZj9NKovMx0vqq6YNPTh6aaNzey5zHD7HeLJtq6fI=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.5/go.mod h1:3YaxrwP0OBPDD7my3D0KxfR89FlcX/IEbxDEDfAmj98=
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-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-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
-github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk=
-github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk=
-github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU=
-github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
+github.com/libp2p/go-netroute v0.2.2 h1:Dejd8cQ47Qx2kRABg6lPwknU7+nBnFRpko45/fFPuZ8=
+github.com/libp2p/go-netroute v0.2.2/go.mod h1:Rntq6jUAH0l9Gg17w5bFGhcC9a+vk4KNXs6s7IljKYE=
github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
-github.com/libp2p/go-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ=
-github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4=
+github.com/libp2p/go-yamux/v5 v5.0.0 h1:2djUh96d3Jiac/JpGkKs4TO49YhsfLopAoryfPmf+Po=
+github.com/libp2p/go-yamux/v5 v5.0.0/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU=
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/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
@@ -454,17 +492,16 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
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=
github.com/mattn/go-isatty v0.0.5/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.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
+github.com/mholt/acmez/v3 v3.0.0 h1:r1NcjuWR0VaKP2BTjDK9LRFBw/WvURx3jlaEUl9Ht8E=
+github.com/mholt/acmez/v3 v3.0.0/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
-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.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
-github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
+github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE=
+github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
@@ -478,7 +515,6 @@ github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
-github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -497,11 +533,10 @@ github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a
github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
-github.com/multiformats/go-multiaddr v0.12.2 h1:9G9sTY/wCYajKa9lyfWPmpZAwe6oV+Wb1zcmMS1HG24=
-github.com/multiformats/go-multiaddr v0.12.2/go.mod h1:GKyaTYjZRdcUhyOetrxTk9z0cW+jA/YrnqTOvKgi44M=
-github.com/multiformats/go-multiaddr-dns v0.3.0/go.mod h1:mNzQ4eTGDg0ll1N9jKPOUogZPoJ30W8a7zk66FQPpdQ=
-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 v0.15.0 h1:zB/HeaI/apcZiTDwhY5YqMvNVl/oQYvs3XySU+qeAVo=
+github.com/multiformats/go-multiaddr v0.15.0/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0=
+github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M=
+github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
github.com/multiformats/go-multiaddr-net v0.1.1/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ=
@@ -509,7 +544,6 @@ 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.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
-github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ=
github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg=
github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k=
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
@@ -518,129 +552,137 @@ github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpK
github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg=
-github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84=
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
-github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE=
-github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA=
+github.com/multiformats/go-multistream v0.6.0 h1:ZaHKbsL404720283o4c/IHQXiS6gb8qAN5EIJ4PN5EA=
+github.com/multiformats/go-multistream v0.6.0/go.mod h1:MOyoG5otO24cHIg8kf9QW2/NozURlkP/rvi2FQJyCPg=
github.com/multiformats/go-varint v0.0.1/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/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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
-github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
+github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
+github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.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.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.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs=
-github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
+github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
+github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
+github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
-github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
+github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
+github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
+github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
-github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
+github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
-github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
-github.com/openzipkin/zipkin-go v0.4.2 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA=
-github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY=
+github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg=
+github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
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/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8=
-github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0=
-github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8=
+github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
+github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
+github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o=
+github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
-github.com/pion/ice/v2 v2.3.6 h1:Jgqw36cAud47iD+N6rNX225uHvrgWtAlHfVyOQc3Heg=
-github.com/pion/ice/v2 v2.3.6/go.mod h1:9/TzKDRwBVAPsC+YOrKH/e3xDrubeTRACU9/sHQarsU=
-github.com/pion/interceptor v0.1.17 h1:prJtgwFh/gB8zMqGZoOgJPHivOwVAp61i2aG61Du/1w=
-github.com/pion/interceptor v0.1.17/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI=
-github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
+github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk=
+github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE=
+github.com/pion/dtls/v3 v3.0.4 h1:44CZekewMzfrn9pmGrj5BNnTMDCFwr+6sLH+cCuLM7U=
+github.com/pion/dtls/v3 v3.0.4/go.mod h1:R373CsjxWqNPf6MEkfdy3aSe9niZvL/JaKlGeFphtMg=
+github.com/pion/ice/v4 v4.0.8 h1:ajNx0idNG+S+v9Phu4LSn2cs8JEfTsA1/tEjkkAVpFY=
+github.com/pion/ice/v4 v4.0.8/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
+github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
+github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
-github.com/pion/mdns v0.0.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U=
-github.com/pion/mdns v0.0.7/go.mod h1:4iP2UbeFhLI/vWju/bw6ZfwjJzk0z8DNValjGxR/dD8=
+github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
+github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90=
+github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM=
+github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
-github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc=
-github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I=
-github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA=
-github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
-github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0=
-github.com/pion/sctp v1.8.7 h1:JnABvFakZueGAn4KU/4PSKg+GWbF6QWbKTWZOSGJjXw=
-github.com/pion/sctp v1.8.7/go.mod h1:g1Ul+ARqZq5JEmoFy87Q/4CePtKnTJ1QCL9dBBdN6AU=
-github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw=
-github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw=
-github.com/pion/srtp/v2 v2.0.15 h1:+tqRtXGsGwHC0G0IUIAzRmdkHvriF79IHVfZGfHrQoA=
-github.com/pion/srtp/v2 v2.0.15/go.mod h1:b/pQOlDrbB0HEH5EUAQXzSYxikFbNcNuKmF8tM0hCtw=
-github.com/pion/stun v0.4.0/go.mod h1:QPsh1/SbXASntw3zkkrIk3ZJVKz4saBY2G7S10P3wCw=
-github.com/pion/stun v0.6.0 h1:JHT/2iyGDPrFWE8NNC15wnddBN8KifsEDw8swQmrEmU=
-github.com/pion/stun v0.6.0/go.mod h1:HPqcfoeqQn9cuaet7AOmB5e5xkObu9DwBdurwLKO9oA=
-github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40=
-github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI=
-github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc=
-github.com/pion/transport/v2 v2.1.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ=
-github.com/pion/transport/v2 v2.2.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ=
-github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c=
+github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
+github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
+github.com/pion/rtp v1.8.11 h1:17xjnY5WO5hgO6SD3/NTIUPvSFw/PbLsIJyz1r1yNIk=
+github.com/pion/rtp v1.8.11/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
+github.com/pion/sctp v1.8.37 h1:ZDmGPtRPX9mKCiVXtMbTWybFw3z/hVKAZgU81wcOrqs=
+github.com/pion/sctp v1.8.37/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
+github.com/pion/sdp/v3 v3.0.10 h1:6MChLE/1xYB+CjumMw+gZ9ufp2DPApuVSnDT8t5MIgA=
+github.com/pion/sdp/v3 v3.0.10/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
+github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
+github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ=
+github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
+github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
+github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
+github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
-github.com/pion/turn/v2 v2.1.0 h1:5wGHSgGhJhP/RpabkUb/T9PdsAjkGLS6toYz5HNzoSI=
-github.com/pion/turn/v2 v2.1.0/go.mod h1:yrT5XbXSGX1VFSF31A3c1kCNB5bBZgk/uu5LET162qs=
-github.com/pion/webrtc/v3 v3.2.9 h1:U8NSjQDlZZ+Iy/hg42Q/u6mhEVSXYvKrOIZiZwYTfLc=
-github.com/pion/webrtc/v3 v3.2.9/go.mod h1:gjQLMZeyN3jXBGdxGmUYCyKjOuYX/c99BDjGqmadq0A=
+github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
+github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
+github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
+github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
+github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
+github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
+github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
+github.com/pion/webrtc/v4 v4.0.10 h1:Hq/JLjhqLxi+NmCtE8lnRPDr8H4LcNvwg8OxVcdv56Q=
+github.com/pion/webrtc/v4 v4.0.10/go.mod h1:ViHLVaNpiuvaH8pdiuQxuA9awuE6KVzAXx3vVWilOck=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
-github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
+github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
+github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
-github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
+github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
+github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
-github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
-github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
+github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
+github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
-github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
-github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
-github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
-github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
-github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
-github.com/quic-go/quic-go v0.40.1 h1:X3AGzUNFs0jVuO3esAGnTfvdgvL4fq655WaOi1snv1Q=
-github.com/quic-go/quic-go v0.40.1/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c=
-github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY=
-github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc=
+github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
+github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
+github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
+github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
+github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q=
+github.com/quic-go/quic-go v0.50.1/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E=
+github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 h1:4WFk6u3sOT6pLa1kQ50ZVdm8BQFgJNA117cepZxtLIg=
+github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66/go.mod h1:Vp72IJajgeOL6ddqrAhmp7IM9zbTcgkQxD/YdxrVwMw=
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
-github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
+github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
+github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
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=
-github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
-github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
-github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
+github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
+github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
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=
@@ -667,6 +709,8 @@ github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYED
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/slok/go-http-metrics v0.13.0 h1:lQDyJJx9wKhmbliyUsZ2l6peGnXRHjsjoqPt5VYzcP8=
+github.com/slok/go-http-metrics v0.13.0/go.mod h1:HIr7t/HbN2sJaunvnt9wKP9xoBBVZFo1/KiHU3b0w+4=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
@@ -690,26 +734,26 @@ 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 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.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.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
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/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs=
+github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
-github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk=
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ=
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb h1:Ywfo8sUltxogBpFuMOFRrrSifO788kAFxmvVw31PtQQ=
@@ -720,9 +764,8 @@ github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60Nt
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE=
-github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
-github.com/warpfork/go-testmark v0.9.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s=
+github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y=
github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
@@ -730,8 +773,8 @@ github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboa
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-20240109153615-66e95c3e8a87 h1:S4wCk+ZL4WGGaI+GsmqCRyt68ISbnZWsK9dD9jYL0fA=
-github.com/whyrusleeping/cbor-gen v0.0.0-20240109153615-66e95c3e8a87/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
+github.com/whyrusleeping/cbor-gen v0.1.2 h1:WQFlrPhpcQl+M2/3dP5cvlTLWPVsL6LGBb9jJt6l/cA=
+github.com/whyrusleeping/cbor-gen v0.1.2/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so=
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=
@@ -739,12 +782,20 @@ github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM=
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/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
+github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
+github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.27/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.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
+github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
+github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
+github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE=
+github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
+github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@@ -753,52 +804,47 @@ 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.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
-go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y=
-go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I=
-go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0 h1:VhlEQAPp9R1ktYfrPk5SOryw1e9LDDTZCbIPFrho0ec=
-go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0/go.mod h1:kB3ufRbfU+CQ4MlUcqtW8Z7YEOBeK2DJ6CmR5rYYF3E=
-go.opentelemetry.io/otel/exporters/zipkin v1.21.0 h1:D+Gv6lSfrFBWmQYyxKjDd0Zuld9SRXpIrEsKZvE4DO4=
-go.opentelemetry.io/otel/exporters/zipkin v1.21.0/go.mod h1:83oMKR6DzmHisFOW3I+yIMGZUTjxiWaiBI8M8+TU5zE=
-go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg=
-go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
-go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
-go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
-go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0=
-go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
-go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
-go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
-go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
-go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
-go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
+go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM=
+go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
+go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4=
+go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 h1:UGZ1QwZWY67Z6BmckTU+9Rxn04m2bD3gD6Mk0OIOCPk=
+go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0/go.mod h1:fcwWuDuaObkkChiDlhEpSq9+X1C0omv+s5mBtToAQ64=
+go.opentelemetry.io/otel/exporters/zipkin v1.31.0 h1:CgucL0tj3717DJnni7HVVB2wExzi8c2zJNEA2BhLMvI=
+go.opentelemetry.io/otel/exporters/zipkin v1.31.0/go.mod h1:rfzOVNiSwIcWtEC2J8epwG26fiaXlYvLySJ7bwsrtAE=
+go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
+go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
+go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk=
+go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0=
+go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
+go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
+go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
+go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
-go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc=
-go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
-go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk=
-go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg=
-go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
+go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
+go.uber.org/dig v1.18.0 h1:imUL1UiY0Mg4bqbFfsRQO5G4CGRBec/ZujWTvSVp3pw=
+go.uber.org/dig v1.18.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
+go.uber.org/fx v1.23.0 h1:lIr/gYWQGfTwGcSXWXu4vP5Ws6iqnNEIY+F/aFzCKTg=
+go.uber.org/fx v1.23.0/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
-go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
-go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
-go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
-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/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
+go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
-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.14.1/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.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
-go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
+go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
-go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg=
go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc=
go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
@@ -819,9 +865,10 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
-golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
-golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
+golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
+golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
+golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
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=
@@ -830,8 +877,8 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
-golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
-golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
+golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
+golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
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=
@@ -852,11 +899,10 @@ 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.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
-golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
+golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -875,27 +921,25 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220607020251-c690dde0001d/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.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
-golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
+golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
+golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
+golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
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=
@@ -914,8 +958,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
-golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
+golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -941,46 +985,39 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/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-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-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-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
+golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
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/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
+golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
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=
@@ -988,16 +1025,17 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.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/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
+golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1019,8 +1057,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -1033,19 +1069,19 @@ golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
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.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
-golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
+golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
+golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
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-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
-golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
-gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
-gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
+golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
+golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
+golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
+gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
+gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
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=
@@ -1082,11 +1118,10 @@ google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvx
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg=
-google.golang.org/genproto/googleapis/api v0.0.0-20240108191215-35c7eff3a6b1 h1:OPXtXn7fNMaXwO3JvOmF1QyTc00jsSFFz1vXXBOdCDo=
-google.golang.org/genproto/googleapis/api v0.0.0-20240108191215-35c7eff3a6b1/go.mod h1:B5xPO//w8qmBDjGReYLpR6UJPnkldGkCSMoH/2vxJeg=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 h1:gphdwh0npgs8elJ4T6J+DQJHPVF7RsuJHCfwztUb4J4=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA=
+google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg=
+google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 h1:QCqS/PdaHTSWGvupk2F/ehwHtGc0/GYkT+3GAcR1CCc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
@@ -1099,8 +1134,8 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
-google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
+google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
+google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
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=
@@ -1112,8 +1147,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
-google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
+google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
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=
@@ -1122,8 +1157,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
-gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
-gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8=
gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
@@ -1131,12 +1164,10 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
@@ -1146,11 +1177,10 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
-lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
-lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
-lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
-pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g=
-pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
+lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
+lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=
+pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw=
+pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/docs/experimental-features.md b/docs/experimental-features.md
index 09640274ea9..fbee3d480b1 100644
--- a/docs/experimental-features.md
+++ b/docs/experimental-features.md
@@ -65,6 +65,14 @@ Experimental.
### How to enable
+> [!WARNING]
+> **SECURITY CONSIDERATION**
+>
+> This feature provides the IPFS [`add` command](https://docs.ipfs.tech/reference/kubo/cli/#ipfs-add) with access to
+> the local filesystem. Consequently, any user with access to CLI or the HTTP [`/v0/add` RPC API](https://docs.ipfs.tech/reference/kubo/rpc/#api-v0-add) can read
+> files from the local filesystem with the same permissions as the Kubo daemon.
+> If you enable this, secure your RPC API using [`API.Authorizations`](https://github.com/ipfs/kubo/blob/master/docs/config.md#apiauthorizations) or custom auth middleware.
+
Modify your ipfs config:
```
ipfs config --json Experimental.FilestoreEnabled true
@@ -79,6 +87,10 @@ filestore instead of copying the files into your local IPFS repo.
- [ ] Needs more people to use and report on how well it works.
- [ ] Need to address error states and failure conditions
+ - [ ] cleanup of broken filesystem references (if file is deleted)
+ - [ ] tests that confirm ability to override preexisting filesystem links (allowing user to fix broken link)
+ - [ ] support for a single block having more than one sources in filesystem (blocks can be shared by unrelated files, and not be broken when some files are unpinned / gc'd)
+ - [ ] [other known issues](https://github.com/ipfs/kubo/issues/7161)
- [ ] Need to write docs on usage, advantages, disadvantages
- [ ] Need to merge utility commands to aid in maintenance and repair of filestore
@@ -96,6 +108,14 @@ v0.4.17
### How to enable
+> [!WARNING]
+> **SECURITY CONSIDERATION**
+>
+> This feature provides the IPFS [`add` CLI command](https://docs.ipfs.tech/reference/kubo/cli/#ipfs-add) with access to
+> the local filesystem. Consequently, any user with access to the CLI or HTTP [`/v0/add` RPC API](https://docs.ipfs.tech/reference/kubo/rpc/#api-v0-add) can read
+> files from the local filesystem with the same permissions as the Kubo daemon.
+> If you enable this, secure your RPC API using [`API.Authorizations`](https://github.com/ipfs/kubo/blob/master/docs/config.md#apiauthorizations) or custom auth middleware.
+
Modify your ipfs config:
```
ipfs config --json Experimental.UrlstoreEnabled true
@@ -106,6 +126,9 @@ And then add a file at a specific URL using `ipfs urlstore add `
### Road to being a real feature
- [ ] Needs more people to use and report on how well it works.
- [ ] Need to address error states and failure conditions
+ - [ ] cleanup of broken URL+range references (if URL starts returning 404 or error)
+ - [ ] tests that confirm ability to override preexisting URL+range links (allowing user to fix broken link)
+ - [ ] support for a single block having more than one URL+range (blocks can be shared by unrelated URLs)
- [ ] Need to write docs on usage, advantages, disadvantages
- [ ] Need to implement caching
- [ ] Need to add metrics to monitor performance
@@ -118,6 +141,9 @@ It allows ipfs to only connect to other peers who have a shared secret key.
Stable but not quite ready for prime-time.
+> [!WARNING]
+> Limited to TCP transport, comes with overhead of double-encryption. See details below.
+
### In Version
0.4.7
@@ -126,7 +152,7 @@ Stable but not quite ready for prime-time.
Generate a pre-shared-key using [ipfs-swarm-key-gen](https://github.com/Kubuxu/go-ipfs-swarm-key-gen)):
```
-go get github.com/Kubuxu/go-ipfs-swarm-key-gen/ipfs-swarm-key-gen
+go install github.com/Kubuxu/go-ipfs-swarm-key-gen/ipfs-swarm-key-gen@latest
ipfs-swarm-key-gen > ~/.ipfs/swarm.key
```
@@ -164,7 +190,12 @@ configured, the daemon will fail to start.
- [x] Needs more people to use and report on how well it works
- [ ] More documentation
-- [ ] Needs better tooling/UX.
+- [ ] Improve / future proof libp2p support (see [libp2p/specs#489](https://github.com/libp2p/specs/issues/489))
+ - [ ] Currently limited to TCP-only, and double-encrypts all data sent on TCP. This is slow.
+ - [ ] Does not work with QUIC: [go-libp2p#1432](https://github.com/libp2p/go-libp2p/issues/1432)
+- [ ] Needs better tooling/UX
+ - [ ] Detect lack of peers when swarm key is present and prompt user to set up bootstrappers/peering
+ - [ ] ipfs-webui will not load unless blocks are present in private swarm. Detect it and prompt user to import CAR with webui.
## ipfs p2p
@@ -182,6 +213,13 @@ Experimental, will be stabilized in 0.6.0
### How to enable
+> [!WARNING]
+> **SECURITY CONSIDERATION**
+>
+> This feature provides CLI and HTTP RPC user with ability to set up port forwarding for all localhost and LAN ports.
+> If you enable this and plan to expose CLI or HTTP RPC to other users or machines,
+> secure RPC API using [`API.Authorizations`](https://github.com/ipfs/kubo/blob/master/docs/config.md#apiauthorizations) or custom auth middleware.
+
The `p2p` command needs to be enabled in the config:
```sh
@@ -289,6 +327,13 @@ Experimental
### How to enable
+> [!WARNING]
+> **SECURITY CONSIDERATION**
+>
+> This feature provides CLI and HTTP RPC user with ability to set up HTTP forwarding for all localhost and LAN ports.
+> If you enable this and plan to expose CLI or HTTP RPC to other users or machines,
+> secure RPC API using [`API.Authorizations`](https://github.com/ipfs/kubo/blob/master/docs/config.md#apiauthorizations) or custom auth middleware.
+
The `p2p` command needs to be enabled in the config:
```sh
@@ -359,7 +404,7 @@ We also support the use of protocol names of the form /x/$NAME/http where $NAME
## FUSE
-FUSE makes it possible to mount `/ipfs` and `/ipns` namespaces in your OS,
+FUSE makes it possible to mount `/ipfs`, `/ipns` and `/mfs` namespaces in your OS,
allowing arbitrary apps access to IPFS using a subset of filesystem abstractions.
It is considered EXPERIMENTAL due to limited (and buggy) support on some platforms.
@@ -492,27 +537,9 @@ ipfs config --json Swarm.RelayClient.Enabled true
### State
-Experimental, disabled by default.
-
-Replaces the existing provide mechanism with a robust, strategic provider system. Currently enabling this option will provide nothing.
-
-### How to enable
-
-Modify your ipfs config:
-
-```
-ipfs config --json Experimental.StrategicProviding true
-```
-
-### Road to being a real feature
+`Experimental.StrategicProviding` was removed in Kubo v0.35.
-- [ ] needs real-world testing
-- [ ] needs adoption
-- [ ] needs to support all provider subsystem features
- - [X] provide nothing
- - [ ] provide roots
- - [ ] provide all
- - [ ] provide strategic
+Replaced by [`Provide.Enabled`](https://github.com/ipfs/kubo/blob/master/docs/config.md#providerenabled) and [`Reprovider.Strategy`](https://github.com/ipfs/kubo/blob/master/docs/config.md#reproviderstrategy).
## GraphSync
diff --git a/docs/file-transfer.md b/docs/file-transfer.md
index a1a1d1c59f9..94d809768d3 100644
--- a/docs/file-transfer.md
+++ b/docs/file-transfer.md
@@ -36,7 +36,7 @@ doesn't even know it has to connect to node A.
### Checking for existing connections
-The first thing to do is to double check that both nodes are in fact running
+The first thing to do is to double-check that both nodes are in fact running
and online. To do this, run `ipfs id` on each machine. If both nodes show some
addresses (like the example below), then your nodes are online.
@@ -68,12 +68,12 @@ pitfalls that people run into)
### Checking providers
When requesting content on ipfs, nodes search the DHT for 'provider records' to
see who has what content. Let's manually do that on node B to make sure that
-node B is able to determine that node A has the data. Run `ipfs dht findprovs
+node B is able to determine that node A has the data. Run `ipfs routing findprovs
`. We expect to see the peer ID of node A printed out. If this command
returns nothing (or returns IDs that are not node A), then no record of A
having the data exists on the network. This can happen if the data is added
while node A does not have a daemon running. If this happens, you can run `ipfs
-dht provide ` on node A to announce to the network that you have that
+routing provide ` on node A to announce to the network that you have that
hash. Then if you restart the `ipfs get` command, node B should now be able
to tell that node A has the content it wants. If node A's peer ID showed up in
the initial `findprovs` call, or manually providing the hash didn't resolve the
@@ -85,7 +85,7 @@ In the case where node B simply cannot form a connection to node A, despite
knowing that it needs to, the likely culprit is a bad NAT. When node B learns
that it needs to connect to node A, it checks the DHT for addresses for node A,
and then starts trying to connect to them. We can check those addresses by
-running `ipfs dht findpeer ` on node B. This command should
+running `ipfs routing findpeer ` on node B. This command should
return a list of addresses for node A. If it doesn't return any addresses, then
you should try running the manual providing command from the previous steps.
Example output of addresses might look something like this:
diff --git a/docs/fuse.md b/docs/fuse.md
index 2b64a7856bb..fde9307fd37 100644
--- a/docs/fuse.md
+++ b/docs/fuse.md
@@ -2,7 +2,7 @@
**EXPERIMENTAL:** FUSE support is limited, YMMV.
-Kubo makes it possible to mount `/ipfs` and `/ipns` namespaces in your OS,
+Kubo makes it possible to mount `/ipfs`, `/ipns` and `/mfs` namespaces in your OS,
allowing arbitrary apps access to IPFS.
## Install FUSE
@@ -16,7 +16,7 @@ to your distribution manual to get things working.
Install `fuse` with your favorite package manager:
```
-sudo apt-get install fuse
+sudo apt-get install fuse3
```
On some older Linux distributions, you may need to add yourself to the `fuse` group.
@@ -50,18 +50,20 @@ speak with us, or if you figure something new out, please add to this document!
## Prepare mountpoints
-By default ipfs uses `/ipfs` and `/ipns` directories for mounting, this can be
-changed in config. You will have to create the `/ipfs` and `/ipns` directories
+By default ipfs uses `/ipfs`, `/ipns` and `/mfs` directories for mounting, this can be
+changed in config. You will have to create the `/ipfs`, `/ipns` and `/mfs` directories
explicitly. Note that modifying root requires sudo permissions.
```sh
# make the directories
sudo mkdir /ipfs
sudo mkdir /ipns
+sudo mkdir /mfs
# chown them so ipfs can use them without root permissions
sudo chown /ipfs
sudo chown /ipns
+sudo chown /mfs
```
Depending on whether you are using OSX or Linux, follow the proceeding instructions.
@@ -105,6 +107,25 @@ ipfs config --json Mounts.FuseAllowOther true
ipfs daemon --mount
```
+## MFS mountpoint
+
+Kubo v0.35.0 and later supports mounting the MFS (Mutable File System) root as
+a FUSE filesystem, enabling manipulation of content-addressed data like regular
+files. The CID for any file or directory is retrievable via the `ipfs_cid`
+extended attribute.
+
+```sh
+getfattr -n ipfs_cid /mfs/welcome-to-IPFS.jpg
+getfattr: Removing leading '/' from absolute path names
+# file: mfs/welcome-to-IPFS.jpg
+ipfs_cid="QmaeXDdwpUeKQcMy7d5SFBfVB4y7LtREbhm5KizawPsBSH"
+```
+
+Please note that the operations supported by the MFS FUSE mountpoint are
+limited. Since the MFS wasn't designed to store file attributes like ownership
+information, permissions and creation date, some applications like `vim` and
+`sed` may misbehave due to missing functionality.
+
## Troubleshooting
#### `Permission denied` or `fusermount: user has no write access to mountpoint` error in Linux
@@ -145,6 +166,17 @@ set for user running `ipfs mount` command.
```
sudo umount /ipfs
sudo umount /ipns
+sudo umount /mfs
+```
+
+#### Mounting fails with "error mounting: could not resolve name"
+
+Make sure your node's IPNS address has a directory published:
+```
+$ mkdir hello/; echo 'hello' > hello/hello.txt; ipfs add -rQ ./hello/
+QmU5PLEGqjetW4RAmXgHpEFL7nVCL3vFnEyrCKUfRk4MSq
+
+$ ipfs name publish QmU5PLEGqjetW4RAmXgHpEFL7nVCL3vFnEyrCKUfRk4MSq
```
If you manage to mount on other systems (or followed an alternative path to one
diff --git a/docs/gateway.md b/docs/gateway.md
index b24d10f0c19..3a616a15803 100644
--- a/docs/gateway.md
+++ b/docs/gateway.md
@@ -12,14 +12,20 @@ Kubo's Gateway implementation follows [ipfs/specs: Specification for HTTP Gatewa
By default, Kubo nodes run
a [path gateway](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#path-gateway) at `http://127.0.0.1:8080/`
-and a [subdomain gateway](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#subdomain-gateway) at `http://localhost:8080/`
+and a [subdomain gateway](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#subdomain-gateway) at `http://localhost:8080/`.
+
+The path one also implements [trustless gateway spec](https://specs.ipfs.tech/http-gateways/trustless-gateway/)
+and supports [trustless responses](https://docs.ipfs.tech/reference/http/gateway/#trustless-verifiable-retrieval) as opt-in via `Accept` header.
Additional listening addresses and gateway behaviors can be set in the [config](#configuration) file.
### Public gateways
-Protocol Labs provides a public gateway at `https://ipfs.io` (path) and `https://dweb.link` (subdomain).
-If you've ever seen a link in the form `https://ipfs.io/ipfs/Qm...`, that's being served from *our* gateway.
+Protocol Labs provides a public gateway at
+`https://ipfs.io` ([path](https://specs.ipfs.tech/http-gateways/path-gateway/)),
+`https://dweb.link` ([subdomain](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#subdomain-gateway)),
+and `https://trustless-gateway.link` ([trustless](https://specs.ipfs.tech/http-gateways/trustless-gateway/) only).
+If you've ever seen a link in the form `https://ipfs.io/ipfs/Qm...`, that's being served from a *public goods* gateway.
There is a list of third-party public gateways provided by the IPFS community at https://ipfs.github.io/public-gateway-checker/
@@ -61,7 +67,7 @@ Gateway](https://dnslink.dev/#example-ipfs-gateway) for instructions.
When downloading files, browsers will usually guess a file's filename by looking
at the last component of the path. Unfortunately, when linking *directly* to a
file (with no containing directory), the final component is just a CID
-(`Qm...`). This isn't exactly user-friendly.
+(`bafy..` or `Qm...`). This isn't exactly user-friendly.
To work around this issue, you can add a `filename=some_filename` parameter to
your query string to explicitly specify the filename. For example:
@@ -85,6 +91,11 @@ or by sending `Accept: application/vnd.ipld.{format}` HTTP header with one of su
## Content-Types
+Majority of resources can be retrieved trustlessly by requesting specific content type via `Accept` header or `?format=raw|car|ipns-record` URL query parameter.
+
+See [trustless gateway specification](https://specs.ipfs.tech/http-gateways/trustless-gateway/)
+and [verifiable retrieval documentation](https://docs.ipfs.tech/reference/http/gateway/#trustless-verifiable-retrieval) for more details.
+
### `application/vnd.ipld.raw`
Returns a byte array for a single `raw` block.
@@ -103,11 +114,9 @@ Support for user-provided IPLD selectors is tracked in https://github.com/ipfs/k
This is a rough equivalent of `ipfs dag export`.
-## Deprecated Subset of RPC API
+### `application/vnd.ipfs.ipns-record`
-For legacy reasons, the gateway port exposes a small subset of RPC API under `/api/v0/`.
-While this read-only API exposes a read-only, "safe" subset of the normal API,
-it is deprecated and should not be used for greenfield projects.
+Only works on `/ipns/{ipns-name}` content paths that use cryptographically signed [IPNS Records](https://specs.ipfs.tech/ipns/ipns-record/).
-Where possible, leverage `/ipfs/` and `/ipns/` endpoints.
-along with `application/vnd.ipld.*` Content-Types instead.
+Returns [IPNS Record in Protobuf Serialization Format](https://specs.ipfs.tech/ipns/ipns-record/#record-serialization-format)
+which can be verified on end client, without trusting gateway.
diff --git a/docs/http-rpc-clients.md b/docs/http-rpc-clients.md
index 31448cb863c..c53c0b5d0ec 100644
--- a/docs/http-rpc-clients.md
+++ b/docs/http-rpc-clients.md
@@ -6,3 +6,8 @@ Kubo provides official HTTP RPC (`/api/v0`) clients for selected languages:
|:--------:|:-------------------:|--------------------------------------------|
| JS | kubo-rpc-client | https://github.com/ipfs/js-kubo-rpc-client |
| Go | `rpc` | [`../client/rpc`](../client/rpc) |
+
+There are community-maintained libraries for other languages,
+but the Kubo team does provide support for them, YMMV:
+
+- https://docs.ipfs.tech/reference/kubo-rpc-cli/
diff --git a/docs/implement-api-bindings.md b/docs/implement-api-bindings.md
index 996a6b8ac80..3587ac21f47 100644
--- a/docs/implement-api-bindings.md
+++ b/docs/implement-api-bindings.md
@@ -39,10 +39,9 @@ function calls. For example:
#### CLI API Transport
In the commandline, IPFS uses a traditional flag and arg-based mapping, where:
-- the first arguments selects the command, as in git - e.g. `ipfs object get`
+- the first arguments selects the command, as in git - e.g. `ipfs dag get`
- the flags specify options - e.g. `--enc=protobuf -q`
-- the rest are positional arguments - e.g.
- `ipfs object patch add-linkfoo `
+- the rest are positional arguments - e.g. `ipfs key rename `
- files are specified by filename, or through stdin
(NOTE: When kubo runs the daemon, the CLI API is actually converted to HTTP
diff --git a/docs/libp2p-resource-management.md b/docs/libp2p-resource-management.md
index 410982dab94..a778f680dd9 100644
--- a/docs/libp2p-resource-management.md
+++ b/docs/libp2p-resource-management.md
@@ -91,7 +91,7 @@ These values trump anything else and are parsed directly by go-libp2p.
## 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".
+"Protected from exceeding resource limits" log messages denote that the resource manager is working and that it prevented additional resources from 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:
@@ -133,7 +133,7 @@ Kubo performs sanity checks to ensure that some of the hard limits of the Resour
The soft limit of `Swarm.ConnMgr.HighWater` needs to be less than the resource manager hard limit `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 resource manager's `System.ConnsInbound`,
-existing low priority idle connections can prevent new high priority connections from being established.
+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 limits](#computed-default-limits) are adjusted such that:
diff --git a/docs/releases_thunderdome.md b/docs/releases_thunderdome.md
index 11057e26a30..53034b3bbda 100644
--- a/docs/releases_thunderdome.md
+++ b/docs/releases_thunderdome.md
@@ -50,7 +50,7 @@ This will build the Docker images, upload them to ECR, and then launch the exper
## Analyze Results
-Add a log entry in https://www.notion.so/pl-strflt/ce2d1bd56f3541028d960d3711465659 and link to it from the release issue, so that experiment results are publicly visible.
+Add a log entry in https://www.notion.so/ceb2047e79f2498494077a2739a6c493 and link to it from the release issue, so that experiment results are publicly visible.
The `deploy` command will output a link to the Grafana dashboard for the experiment. We don't currently have rigorous acceptance criteria, so you should look for anomalies or changes in the metrics and make sure they are tolerable and explainable. Unexplainable anomalies should be noted in the log with a screenshot, and then root caused.
diff --git a/docs/specifications/keystore.md b/docs/specifications/keystore.md
index 7e588ca9853..9609b83c231 100644
--- a/docs/specifications/keystore.md
+++ b/docs/specifications/keystore.md
@@ -175,7 +175,7 @@ OPTIONS:
DESCRIPTION:
- 'ipfs crypt encrypt' is a command used to encypt data so that only holders of a certain
+ 'ipfs crypt encrypt' is a command used to encrypt data so that only holders of a certain
key can read it.
```
diff --git a/docs/windows.md b/docs/windows.md
index 590f270af32..3ed0e4ab261 100644
--- a/docs/windows.md
+++ b/docs/windows.md
@@ -153,6 +153,6 @@ If you get authentication problems with Git, you might want to take a look at ht
`git config --global credential.helper wincred`
- **Anything else**
-Please search [https://discuss.ipfs.io](https://discuss.ipfs.io/search?q=windows%20category%3A13) for any additional issues you may encounter. If you can't find any existing resolution, feel free to post a question asking for help.
+Please search [https://discuss.ipfs.tech](https://discuss.ipfs.tech/search?q=windows%20category%3A13) for any additional issues you may encounter. If you can't find any existing resolution, feel free to post a question asking for help.
If you encounter a bug with `kubo` itself (not related to building) please use the [issue tracker](https://github.com/ipfs/kubo/issues) to report it.
diff --git a/fuse/ipns/ipns_test.go b/fuse/ipns/ipns_test.go
index d26e78c4de4..ece386bf757 100644
--- a/fuse/ipns/ipns_test.go
+++ b/fuse/ipns/ipns_test.go
@@ -19,8 +19,8 @@ import (
coreapi "github.com/ipfs/kubo/core/coreapi"
fstest "bazil.org/fuse/fs/fstestutil"
- u "github.com/ipfs/boxo/util"
racedet "github.com/ipfs/go-detect-race"
+ "github.com/ipfs/go-test/random"
ci "github.com/libp2p/go-libp2p-testing/ci"
)
@@ -32,7 +32,7 @@ func maybeSkipFuseTests(t *testing.T) {
func randBytes(size int) []byte {
b := make([]byte, size)
- _, err := io.ReadFull(u.NewTimeSeededRand(), b)
+ _, err := io.ReadFull(random.NewRand(), b)
if err != nil {
panic(err)
}
diff --git a/fuse/ipns/ipns_unix.go b/fuse/ipns/ipns_unix.go
index 23704cabd52..de475dd89b1 100644
--- a/fuse/ipns/ipns_unix.go
+++ b/fuse/ipns/ipns_unix.go
@@ -16,13 +16,14 @@ import (
dag "github.com/ipfs/boxo/ipld/merkledag"
ft "github.com/ipfs/boxo/ipld/unixfs"
+ "github.com/ipfs/boxo/namesys"
"github.com/ipfs/boxo/path"
fuse "bazil.org/fuse"
fs "bazil.org/fuse/fs"
mfs "github.com/ipfs/boxo/mfs"
cid "github.com/ipfs/go-cid"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
iface "github.com/ipfs/kubo/core/coreiface"
options "github.com/ipfs/kubo/core/coreiface/options"
)
@@ -95,7 +96,7 @@ func loadRoot(ctx context.Context, ipfs iface.CoreAPI, key iface.Key) (*mfs.Root
node, err := ipfs.ResolveNode(ctx, key.Path())
switch err {
case nil:
- case iface.ErrResolveFailed:
+ case namesys.ErrResolveFailed:
node = ft.EmptyDirNode()
default:
log.Errorf("looking up %s: %s", key.Path(), err)
diff --git a/fuse/mfs/mfs_test.go b/fuse/mfs/mfs_test.go
new file mode 100644
index 00000000000..cedbe996723
--- /dev/null
+++ b/fuse/mfs/mfs_test.go
@@ -0,0 +1,342 @@
+//go:build !nofuse && !openbsd && !netbsd && !plan9
+// +build !nofuse,!openbsd,!netbsd,!plan9
+
+package mfs
+
+import (
+ "bytes"
+ "context"
+ "crypto/rand"
+ "errors"
+ iofs "io/fs"
+ "os"
+ "slices"
+ "strconv"
+ "testing"
+ "time"
+
+ "bazil.org/fuse"
+ "bazil.org/fuse/fs"
+ "bazil.org/fuse/fs/fstestutil"
+ "github.com/ipfs/kubo/core"
+ "github.com/ipfs/kubo/core/node"
+ "github.com/libp2p/go-libp2p-testing/ci"
+)
+
+// Create an Ipfs.Node, a filesystem and a mount point.
+func setUp(t *testing.T, ipfs *core.IpfsNode) (fs.FS, *fstestutil.Mount) {
+ if ci.NoFuse() {
+ t.Skip("Skipping FUSE tests")
+ }
+
+ if ipfs == nil {
+ var err error
+ ipfs, err = core.NewNode(context.Background(), &node.BuildCfg{})
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ fs := NewFileSystem(ipfs)
+ mnt, err := fstestutil.MountedT(t, fs, nil)
+ if err == fuse.ErrOSXFUSENotFound {
+ t.Skip(err)
+ }
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ return fs, mnt
+}
+
+// Test reading and writing a file.
+func TestReadWrite(t *testing.T) {
+ _, mnt := setUp(t, nil)
+ defer mnt.Close()
+
+ path := mnt.Dir + "/testrw"
+ content := make([]byte, 8196)
+ _, err := rand.Read(content)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ t.Run("write", func(t *testing.T) {
+ f, err := os.Create(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+
+ _, err = f.Write(content)
+ if err != nil {
+ t.Fatal(err)
+ }
+ })
+ t.Run("read", func(t *testing.T) {
+ f, err := os.Open(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+
+ buf := make([]byte, 8196)
+ l, err := f.Read(buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if bytes.Equal(content, buf[:l]) != true {
+ t.Fatal("read and write not equal")
+ }
+ })
+}
+
+// Test creating a directory.
+func TestMkdir(t *testing.T) {
+ _, mnt := setUp(t, nil)
+ defer mnt.Close()
+
+ path := mnt.Dir + "/foo/bar/baz/qux/quux"
+
+ t.Run("write", func(t *testing.T) {
+ err := os.MkdirAll(path, iofs.ModeDir)
+ if err != nil {
+ t.Fatal(err)
+ }
+ })
+ t.Run("read", func(t *testing.T) {
+ stat, err := os.Stat(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !stat.IsDir() {
+ t.Fatal("not dir")
+ }
+ })
+}
+
+// Test file persistence across mounts.
+func TestPersistence(t *testing.T) {
+ ipfs, err := core.NewNode(context.Background(), &node.BuildCfg{})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ content := make([]byte, 8196)
+ _, err = rand.Read(content)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ t.Run("write", func(t *testing.T) {
+ _, mnt := setUp(t, ipfs)
+ defer mnt.Close()
+ path := mnt.Dir + "/testpersistence"
+
+ f, err := os.Create(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+
+ _, err = f.Write(content)
+ if err != nil {
+ t.Fatal(err)
+ }
+ })
+ t.Run("read", func(t *testing.T) {
+ _, mnt := setUp(t, ipfs)
+ defer mnt.Close()
+ path := mnt.Dir + "/testpersistence"
+
+ f, err := os.Open(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+
+ buf := make([]byte, 8196)
+ l, err := f.Read(buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if bytes.Equal(content, buf[:l]) != true {
+ t.Fatal("read and write not equal")
+ }
+ })
+}
+
+// Test getting the file attributes.
+func TestAttr(t *testing.T) {
+ _, mnt := setUp(t, nil)
+ defer mnt.Close()
+
+ path := mnt.Dir + "/testattr"
+ content := make([]byte, 8196)
+ _, err := rand.Read(content)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ t.Run("write", func(t *testing.T) {
+ f, err := os.Create(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+
+ _, err = f.Write(content)
+ if err != nil {
+ t.Fatal(err)
+ }
+ })
+ t.Run("read", func(t *testing.T) {
+ fi, err := os.Stat(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if fi.IsDir() {
+ t.Fatal("file is a directory")
+ }
+
+ if fi.ModTime().After(time.Now()) {
+ t.Fatal("future modtime")
+ }
+ if time.Since(fi.ModTime()) > time.Second {
+ t.Fatal("past modtime")
+ }
+
+ if fi.Name() != "testattr" {
+ t.Fatal("invalid filename")
+ }
+
+ if fi.Size() != 8196 {
+ t.Fatal("invalid size")
+ }
+ })
+}
+
+// Test concurrent access to the filesystem.
+func TestConcurrentRW(t *testing.T) {
+ _, mnt := setUp(t, nil)
+ defer mnt.Close()
+
+ files := 5
+ fileWorkers := 5
+
+ path := mnt.Dir + "/testconcurrent"
+ content := make([][]byte, files)
+
+ for i := range content {
+ content[i] = make([]byte, 8196)
+ _, err := rand.Read(content[i])
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ t.Run("write", func(t *testing.T) {
+ errs := make(chan (error), 1)
+ for i := 0; i < files; i++ {
+ go func() {
+ var err error
+ defer func() { errs <- err }()
+
+ f, err := os.Create(path + strconv.Itoa(i))
+ if err != nil {
+ return
+ }
+ defer f.Close()
+
+ _, err = f.Write(content[i])
+ if err != nil {
+ return
+ }
+ }()
+ }
+ for i := 0; i < files; i++ {
+ err := <-errs
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ })
+ t.Run("read", func(t *testing.T) {
+ errs := make(chan (error), 1)
+ for i := 0; i < files*fileWorkers; i++ {
+ go func() {
+ var err error
+ defer func() { errs <- err }()
+
+ f, err := os.Open(path + strconv.Itoa(i/fileWorkers))
+ if err != nil {
+ return
+ }
+ defer f.Close()
+
+ buf := make([]byte, 8196)
+ l, err := f.Read(buf)
+ if err != nil {
+ return
+ }
+ if bytes.Equal(content[i/fileWorkers], buf[:l]) != true {
+ err = errors.New("read and write not equal")
+ return
+ }
+ }()
+ }
+ for i := 0; i < files; i++ {
+ err := <-errs
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ })
+}
+
+// Test ipfs_cid extended attribute
+func TestMFSRootXattr(t *testing.T) {
+ ipfs, err := core.NewNode(context.Background(), &node.BuildCfg{})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ fs, mnt := setUp(t, ipfs)
+ defer mnt.Close()
+
+ node, err := fs.Root()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ root := node.(*Dir)
+
+ listReq := fuse.ListxattrRequest{}
+ listRes := fuse.ListxattrResponse{}
+ err = root.Listxattr(context.Background(), &listReq, &listRes)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if slices.Compare(listRes.Xattr, []byte("ipfs_cid\x00")) != 0 {
+ t.Fatal("list xattr returns invalid value")
+ }
+
+ getReq := fuse.GetxattrRequest{
+ Name: "ipfs_cid",
+ }
+ getRes := fuse.GetxattrResponse{}
+ err = root.Getxattr(context.Background(), &getReq, &getRes)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ipldNode, err := ipfs.FilesRoot.GetDirectory().GetNode()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if slices.Compare(getRes.Xattr, []byte(ipldNode.Cid().String())) != 0 {
+ t.Fatal("xattr cid not equal to mfs root cid")
+ }
+}
diff --git a/fuse/mfs/mfs_unix.go b/fuse/mfs/mfs_unix.go
new file mode 100644
index 00000000000..91cad257d92
--- /dev/null
+++ b/fuse/mfs/mfs_unix.go
@@ -0,0 +1,414 @@
+//go:build (linux || darwin || freebsd || netbsd || openbsd) && !nofuse
+// +build linux darwin freebsd netbsd openbsd
+// +build !nofuse
+
+package mfs
+
+import (
+ "context"
+ "io"
+ "os"
+ "sync"
+ "syscall"
+ "time"
+
+ "bazil.org/fuse"
+ "bazil.org/fuse/fs"
+
+ dag "github.com/ipfs/boxo/ipld/merkledag"
+ ft "github.com/ipfs/boxo/ipld/unixfs"
+ "github.com/ipfs/boxo/mfs"
+ "github.com/ipfs/kubo/core"
+)
+
+const (
+ ipfsCIDXattr = "ipfs_cid"
+ mfsDirMode = os.ModeDir | 0755
+ mfsFileMode = 0644
+ blockSize = 512
+ dirSize = 8
+)
+
+// FUSE filesystem mounted at /mfs.
+type FileSystem struct {
+ root Dir
+}
+
+// Get filesystem root.
+func (fs *FileSystem) Root() (fs.Node, error) {
+ return &fs.root, nil
+}
+
+// FUSE Adapter for MFS directories.
+type Dir struct {
+ mfsDir *mfs.Directory
+}
+
+// Directory attributes (stat).
+func (dir *Dir) Attr(ctx context.Context, attr *fuse.Attr) error {
+ attr.Mode = mfsDirMode
+ attr.Size = dirSize * blockSize
+ attr.Blocks = dirSize
+ return nil
+}
+
+// Access files in a directory.
+func (dir *Dir) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.LookupResponse) (fs.Node, error) {
+ mfsNode, err := dir.mfsDir.Child(req.Name)
+ switch err {
+ case os.ErrNotExist:
+ return nil, syscall.Errno(syscall.ENOENT)
+ case nil:
+ default:
+ return nil, err
+ }
+
+ switch mfsNode.Type() {
+ case mfs.TDir:
+ result := Dir{
+ mfsDir: mfsNode.(*mfs.Directory),
+ }
+ return &result, nil
+ case mfs.TFile:
+ result := File{
+ mfsFile: mfsNode.(*mfs.File),
+ }
+ return &result, nil
+ }
+
+ return nil, syscall.Errno(syscall.ENOENT)
+}
+
+// List (ls) MFS directory.
+func (dir *Dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
+ var res []fuse.Dirent
+ nodes, err := dir.mfsDir.List(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, node := range nodes {
+ nodeType := fuse.DT_File
+ if node.Type == 1 {
+ nodeType = fuse.DT_Dir
+ }
+ res = append(res, fuse.Dirent{
+ Type: nodeType,
+ Name: node.Name,
+ })
+ }
+ return res, nil
+}
+
+// Mkdir (mkdir) in MFS.
+func (dir *Dir) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, error) {
+ mfsDir, err := dir.mfsDir.Mkdir(req.Name)
+ if err != nil {
+ return nil, err
+ }
+ return &Dir{
+ mfsDir: mfsDir,
+ }, nil
+}
+
+// Remove (rm/rmdir) an MFS file.
+func (dir *Dir) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
+ // Check for empty directory.
+ if req.Dir {
+ targetNode, err := dir.mfsDir.Child(req.Name)
+ if err != nil {
+ return err
+ }
+ target := targetNode.(*mfs.Directory)
+
+ children, err := target.ListNames(ctx)
+ if err != nil {
+ return err
+ }
+ if len(children) > 0 {
+ return os.ErrExist
+ }
+ }
+ err := dir.mfsDir.Unlink(req.Name)
+ if err != nil {
+ return err
+ }
+ return dir.mfsDir.Flush()
+}
+
+// Move (mv) an MFS file.
+func (dir *Dir) Rename(ctx context.Context, req *fuse.RenameRequest, newDir fs.Node) error {
+ file, err := dir.mfsDir.Child(req.OldName)
+ if err != nil {
+ return err
+ }
+ node, err := file.GetNode()
+ if err != nil {
+ return err
+ }
+ targetDir := newDir.(*Dir)
+
+ // Remove file if exists
+ err = targetDir.mfsDir.Unlink(req.NewName)
+ if err != nil && err != os.ErrNotExist {
+ return err
+ }
+
+ err = targetDir.mfsDir.AddChild(req.NewName, node)
+ if err != nil {
+ return err
+ }
+
+ err = dir.mfsDir.Unlink(req.OldName)
+ if err != nil {
+ return err
+ }
+
+ return dir.mfsDir.Flush()
+}
+
+// Create (touch) an MFS file.
+func (dir *Dir) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (fs.Node, fs.Handle, error) {
+ node := dag.NodeWithData(ft.FilePBData(nil, 0))
+ if err := node.SetCidBuilder(dir.mfsDir.GetCidBuilder()); err != nil {
+ return nil, nil, err
+ }
+
+ if err := dir.mfsDir.AddChild(req.Name, node); err != nil {
+ return nil, nil, err
+ }
+
+ if err := dir.mfsDir.Flush(); err != nil {
+ return nil, nil, err
+ }
+
+ mfsNode, err := dir.mfsDir.Child(req.Name)
+ if err != nil {
+ return nil, nil, err
+ }
+ if err := mfsNode.SetModTime(time.Now()); err != nil {
+ return nil, nil, err
+ }
+
+ mfsFile := mfsNode.(*mfs.File)
+
+ file := File{
+ mfsFile: mfsFile,
+ }
+
+ // Read access flags and create a handler.
+ accessMode := req.Flags & fuse.OpenAccessModeMask
+ flags := mfs.Flags{
+ Read: accessMode == fuse.OpenReadOnly || accessMode == fuse.OpenReadWrite,
+ Write: accessMode == fuse.OpenWriteOnly || accessMode == fuse.OpenReadWrite,
+ Sync: req.Flags|fuse.OpenSync > 0,
+ }
+
+ fd, err := mfsFile.Open(flags)
+ if err != nil {
+ return nil, nil, err
+ }
+ handler := FileHandler{
+ mfsFD: fd,
+ }
+
+ return &file, &handler, nil
+}
+
+// List dir xattr.
+func (dir *Dir) Listxattr(ctx context.Context, req *fuse.ListxattrRequest, resp *fuse.ListxattrResponse) error {
+ resp.Append(ipfsCIDXattr)
+ return nil
+}
+
+// Get dir xattr.
+func (dir *Dir) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse) error {
+ switch req.Name {
+ case ipfsCIDXattr:
+ node, err := dir.mfsDir.GetNode()
+ if err != nil {
+ return err
+ }
+ resp.Xattr = []byte(node.Cid().String())
+ return nil
+ default:
+ return fuse.ErrNoXattr
+ }
+}
+
+// FUSE adapter for MFS files.
+type File struct {
+ mfsFile *mfs.File
+}
+
+// File attributes.
+func (file *File) Attr(ctx context.Context, attr *fuse.Attr) error {
+ size, _ := file.mfsFile.Size()
+
+ attr.Size = uint64(size)
+ if size%blockSize == 0 {
+ attr.Blocks = uint64(size / blockSize)
+ } else {
+ attr.Blocks = uint64(size/blockSize + 1)
+ }
+
+ mtime, _ := file.mfsFile.ModTime()
+ attr.Mtime = mtime
+
+ attr.Mode = mfsFileMode
+ return nil
+}
+
+// Open an MFS file.
+func (file *File) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fs.Handle, error) {
+ accessMode := req.Flags & fuse.OpenAccessModeMask
+ flags := mfs.Flags{
+ Read: accessMode == fuse.OpenReadOnly || accessMode == fuse.OpenReadWrite,
+ Write: accessMode == fuse.OpenWriteOnly || accessMode == fuse.OpenReadWrite,
+ Sync: req.Flags|fuse.OpenSync > 0,
+ }
+ fd, err := file.mfsFile.Open(flags)
+ if err != nil {
+ return nil, err
+ }
+
+ if flags.Write {
+ if err := file.mfsFile.SetModTime(time.Now()); err != nil {
+ return nil, err
+ }
+ }
+
+ return &FileHandler{
+ mfsFD: fd,
+ }, nil
+}
+
+// Sync the file's contents to MFS.
+func (file *File) Fsync(ctx context.Context, req *fuse.FsyncRequest) error {
+ return file.mfsFile.Sync()
+}
+
+// List file xattr.
+func (file *File) Listxattr(ctx context.Context, req *fuse.ListxattrRequest, resp *fuse.ListxattrResponse) error {
+ resp.Append(ipfsCIDXattr)
+ return nil
+}
+
+// Get file xattr.
+func (file *File) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse) error {
+ switch req.Name {
+ case ipfsCIDXattr:
+ node, err := file.mfsFile.GetNode()
+ if err != nil {
+ return err
+ }
+ resp.Xattr = []byte(node.Cid().String())
+ return nil
+ default:
+ return fuse.ErrNoXattr
+ }
+}
+
+// Wrapper for MFS's file descriptor that conforms to the FUSE fs.Handler
+// interface.
+type FileHandler struct {
+ mfsFD mfs.FileDescriptor
+ mu sync.Mutex
+}
+
+// Read a opened MFS file.
+func (fh *FileHandler) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
+ fh.mu.Lock()
+ defer fh.mu.Unlock()
+
+ _, err := fh.mfsFD.Seek(req.Offset, io.SeekStart)
+ if err != nil {
+ return err
+ }
+
+ buf := make([]byte, req.Size)
+ l, err := fh.mfsFD.Read(buf)
+
+ resp.Data = buf[:l]
+
+ switch err {
+ case nil, io.EOF, io.ErrUnexpectedEOF:
+ return nil
+ default:
+ return err
+ }
+}
+
+// Write writes to an opened MFS file.
+func (fh *FileHandler) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {
+ fh.mu.Lock()
+ defer fh.mu.Unlock()
+
+ l, err := fh.mfsFD.WriteAt(req.Data, req.Offset)
+ if err != nil {
+ return err
+ }
+ resp.Size = l
+
+ return nil
+}
+
+// Flushes the file's buffer.
+func (fh *FileHandler) Flush(ctx context.Context, req *fuse.FlushRequest) error {
+ fh.mu.Lock()
+ defer fh.mu.Unlock()
+
+ return fh.mfsFD.Flush()
+}
+
+// Closes the file.
+func (fh *FileHandler) Release(ctx context.Context, req *fuse.ReleaseRequest) error {
+ fh.mu.Lock()
+ defer fh.mu.Unlock()
+
+ return fh.mfsFD.Close()
+}
+
+// Create new filesystem.
+func NewFileSystem(ipfs *core.IpfsNode) fs.FS {
+ return &FileSystem{
+ root: Dir{
+ mfsDir: ipfs.FilesRoot.GetDirectory(),
+ },
+ }
+}
+
+// Check that our structs implement all the interfaces we want.
+type mfsDir interface {
+ fs.Node
+ fs.NodeGetxattrer
+ fs.NodeListxattrer
+ fs.HandleReadDirAller
+ fs.NodeRequestLookuper
+ fs.NodeMkdirer
+ fs.NodeRenamer
+ fs.NodeRemover
+ fs.NodeCreater
+}
+
+var _ mfsDir = (*Dir)(nil)
+
+type mfsFile interface {
+ fs.Node
+ fs.NodeGetxattrer
+ fs.NodeListxattrer
+ fs.NodeOpener
+ fs.NodeFsyncer
+}
+
+var _ mfsFile = (*File)(nil)
+
+type mfsHandler interface {
+ fs.Handle
+ fs.HandleReader
+ fs.HandleWriter
+ fs.HandleFlusher
+ fs.HandleReleaser
+}
+
+var _ mfsHandler = (*FileHandler)(nil)
diff --git a/fuse/mfs/mount_unix.go b/fuse/mfs/mount_unix.go
new file mode 100644
index 00000000000..7fe72e8df17
--- /dev/null
+++ b/fuse/mfs/mount_unix.go
@@ -0,0 +1,21 @@
+//go:build (linux || darwin || freebsd || netbsd || openbsd) && !nofuse
+// +build linux darwin freebsd netbsd openbsd
+// +build !nofuse
+
+package mfs
+
+import (
+ core "github.com/ipfs/kubo/core"
+ mount "github.com/ipfs/kubo/fuse/mount"
+)
+
+// Mount mounts MFS at a given location, and returns a mount.Mount instance.
+func Mount(ipfs *core.IpfsNode, mountpoint string) (mount.Mount, error) {
+ cfg, err := ipfs.Repo.Config()
+ if err != nil {
+ return nil, err
+ }
+ allowOther := cfg.Mounts.FuseAllowOther
+ fsys := NewFileSystem(ipfs)
+ return mount.NewMount(ipfs.Process, fsys, mountpoint, allowOther)
+}
diff --git a/fuse/mount/fuse.go b/fuse/mount/fuse.go
index 2dcb8ccae4f..02d733b8940 100644
--- a/fuse/mount/fuse.go
+++ b/fuse/mount/fuse.go
@@ -102,7 +102,7 @@ func (m *mount) mount() error {
return nil
}
-// umount is called exactly once to unmount this service.
+// unmount is called exactly once to unmount this service.
// note that closing the connection will not always unmount
// properly. If that happens, we bring out the big guns
// (mount.ForceUnmountManyTimes, exec unmount).
diff --git a/fuse/mount/mount.go b/fuse/mount/mount.go
index a52374dd819..b9008bc4607 100644
--- a/fuse/mount/mount.go
+++ b/fuse/mount/mount.go
@@ -8,7 +8,7 @@ import (
"runtime"
"time"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
goprocess "github.com/jbenet/goprocess"
)
diff --git a/fuse/node/mount_darwin.go b/fuse/node/mount_darwin.go
index 4d2446ecd60..88e1f248e46 100644
--- a/fuse/node/mount_darwin.go
+++ b/fuse/node/mount_darwin.go
@@ -29,7 +29,7 @@ const dontCheckOSXFUSEConfigKey = "DontCheckOSXFUSE"
const fuseVersionPkg = "github.com/jbenet/go-fuse-version/fuse-version"
// errStrFuseRequired is returned when we're sure the user does not have fuse.
-var errStrFuseRequired = `OSXFUSE not found.
+const errStrFuseRequired = `OSXFUSE not found.
OSXFUSE is required to mount, please install it.
NOTE: Version 2.7.2 or higher required; prior versions are known to kernel panic!
diff --git a/fuse/node/mount_nofuse.go b/fuse/node/mount_nofuse.go
index e6f512f8eef..7423cb24d34 100644
--- a/fuse/node/mount_nofuse.go
+++ b/fuse/node/mount_nofuse.go
@@ -9,6 +9,6 @@ import (
core "github.com/ipfs/kubo/core"
)
-func Mount(node *core.IpfsNode, fsdir, nsdir string) error {
+func Mount(node *core.IpfsNode, fsdir, nsdir, mfsdir string) error {
return errors.New("not compiled in")
}
diff --git a/fuse/node/mount_notsupp.go b/fuse/node/mount_notsupp.go
index e9762a3e4bd..79ac0e79165 100644
--- a/fuse/node/mount_notsupp.go
+++ b/fuse/node/mount_notsupp.go
@@ -9,6 +9,6 @@ import (
core "github.com/ipfs/kubo/core"
)
-func Mount(node *core.IpfsNode, fsdir, nsdir string) error {
+func Mount(node *core.IpfsNode, fsdir, nsdir, mfsdir string) error {
return errors.New("FUSE not supported on OpenBSD or NetBSD. See #5334 (https://github.com/ipfs/kubo/issues/5334).")
}
diff --git a/fuse/node/mount_test.go b/fuse/node/mount_test.go
index 178fddcf665..1947f759ffa 100644
--- a/fuse/node/mount_test.go
+++ b/fuse/node/mount_test.go
@@ -56,10 +56,12 @@ func TestExternalUnmount(t *testing.T) {
ipfsDir := dir + "/ipfs"
ipnsDir := dir + "/ipns"
+ mfsDir := dir + "/mfs"
mkdir(t, ipfsDir)
mkdir(t, ipnsDir)
+ mkdir(t, mfsDir)
- err = Mount(node, ipfsDir, ipnsDir)
+ err = Mount(node, ipfsDir, ipnsDir, mfsDir)
if err != nil {
if strings.Contains(err.Error(), "unable to check fuse version") || err == fuse.ErrOSXFUSENotFound {
t.Skip(err)
diff --git a/fuse/node/mount_unix.go b/fuse/node/mount_unix.go
index 1e509a2435c..c628a85f4d4 100644
--- a/fuse/node/mount_unix.go
+++ b/fuse/node/mount_unix.go
@@ -11,10 +11,11 @@ import (
core "github.com/ipfs/kubo/core"
ipns "github.com/ipfs/kubo/fuse/ipns"
+ mfs "github.com/ipfs/kubo/fuse/mfs"
mount "github.com/ipfs/kubo/fuse/mount"
rofs "github.com/ipfs/kubo/fuse/readonly"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
)
var log = logging.Logger("node")
@@ -31,7 +32,7 @@ var platformFuseChecks = func(*core.IpfsNode) error {
return nil
}
-func Mount(node *core.IpfsNode, fsdir, nsdir string) error {
+func Mount(node *core.IpfsNode, fsdir, nsdir, mfsdir string) error {
// check if we already have live mounts.
// if the user said "Mount", then there must be something wrong.
// so, close them and try again.
@@ -43,15 +44,19 @@ func Mount(node *core.IpfsNode, fsdir, nsdir string) error {
// best effort
_ = node.Mounts.Ipns.Unmount()
}
+ if node.Mounts.Mfs != nil && node.Mounts.Mfs.IsActive() {
+ // best effort
+ _ = node.Mounts.Mfs.Unmount()
+ }
if err := platformFuseChecks(node); err != nil {
return err
}
- return doMount(node, fsdir, nsdir)
+ return doMount(node, fsdir, nsdir, mfsdir)
}
-func doMount(node *core.IpfsNode, fsdir, nsdir string) error {
+func doMount(node *core.IpfsNode, fsdir, nsdir, mfsdir string) error {
fmtFuseErr := func(err error, mountpoint string) error {
s := err.Error()
if strings.Contains(s, fuseNoDirectory) {
@@ -67,8 +72,8 @@ func doMount(node *core.IpfsNode, fsdir, nsdir string) error {
}
// this sync stuff is so that both can be mounted simultaneously.
- var fsmount, nsmount mount.Mount
- var err1, err2 error
+ var fsmount, nsmount, mfmount mount.Mount
+ var err1, err2, err3 error
var wg sync.WaitGroup
@@ -86,32 +91,49 @@ func doMount(node *core.IpfsNode, fsdir, nsdir string) error {
}()
}
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ mfmount, err3 = mfs.Mount(node, mfsdir)
+ }()
+
wg.Wait()
if err1 != nil {
- log.Errorf("error mounting: %s", err1)
+ log.Errorf("error mounting IPFS %s: %s", fsdir, err1)
}
if err2 != nil {
- log.Errorf("error mounting: %s", err2)
+ log.Errorf("error mounting IPNS %s for IPFS %s: %s", nsdir, fsdir, err2)
+ }
+
+ if err3 != nil {
+ log.Errorf("error mounting MFS %s: %s", mfsdir, err3)
}
- if err1 != nil || err2 != nil {
+ if err1 != nil || err2 != nil || err3 != nil {
if fsmount != nil {
_ = fsmount.Unmount()
}
if nsmount != nil {
_ = nsmount.Unmount()
}
+ if mfmount != nil {
+ _ = mfmount.Unmount()
+ }
if err1 != nil {
return fmtFuseErr(err1, fsdir)
}
- return fmtFuseErr(err2, nsdir)
+ if err2 != nil {
+ return fmtFuseErr(err2, nsdir)
+ }
+ return fmtFuseErr(err3, mfsdir)
}
- // setup node state, so that it can be cancelled
+ // setup node state, so that it can be canceled
node.Mounts.Ipfs = fsmount
node.Mounts.Ipns = nsmount
+ node.Mounts.Mfs = mfmount
return nil
}
diff --git a/fuse/node/mount_windows.go b/fuse/node/mount_windows.go
index 33393f99a90..42e6bc10b9b 100644
--- a/fuse/node/mount_windows.go
+++ b/fuse/node/mount_windows.go
@@ -4,7 +4,7 @@ import (
"github.com/ipfs/kubo/core"
)
-func Mount(node *core.IpfsNode, fsdir, nsdir string) error {
+func Mount(node *core.IpfsNode, fsdir, nsdir, mfsdir string) error {
// TODO
// currently a no-op, but we don't want to return an error
return nil
diff --git a/fuse/readonly/ipfs_test.go b/fuse/readonly/ipfs_test.go
index 385ae1272c5..e7dfbcb2abd 100644
--- a/fuse/readonly/ipfs_test.go
+++ b/fuse/readonly/ipfs_test.go
@@ -29,8 +29,8 @@ import (
importer "github.com/ipfs/boxo/ipld/unixfs/importer"
uio "github.com/ipfs/boxo/ipld/unixfs/io"
"github.com/ipfs/boxo/path"
- u "github.com/ipfs/boxo/util"
ipld "github.com/ipfs/go-ipld-format"
+ "github.com/ipfs/go-test/random"
ci "github.com/libp2p/go-libp2p-testing/ci"
)
@@ -42,7 +42,7 @@ func maybeSkipFuseTests(t *testing.T) {
func randObj(t *testing.T, nd *core.IpfsNode, size int64) (ipld.Node, []byte) {
buf := make([]byte, size)
- _, err := io.ReadFull(u.NewTimeSeededRand(), buf)
+ _, err := io.ReadFull(random.NewRand(), buf)
if err != nil {
t.Fatal(err)
}
@@ -150,7 +150,10 @@ func TestIpfsStressRead(t *testing.T) {
// Now make a bunch of dirs
for i := 0; i < ndiriter; i++ {
- db := uio.NewDirectory(nd.DAG)
+ db, err := uio.NewDirectory(nd.DAG)
+ if err != nil {
+ t.Fatal(err)
+ }
for j := 0; j < 1+rand.Intn(10); j++ {
name := fmt.Sprintf("child%d", j)
@@ -245,8 +248,11 @@ func TestIpfsBasicDirRead(t *testing.T) {
fi, data := randObj(t, nd, 10000)
// Make a directory and put that file in it
- db := uio.NewDirectory(nd.DAG)
- err := db.AddChild(nd.Context(), "actual", fi)
+ db, err := uio.NewDirectory(nd.DAG)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = db.AddChild(nd.Context(), "actual", fi)
if err != nil {
t.Fatal(err)
}
diff --git a/fuse/readonly/readonly_unix.go b/fuse/readonly/readonly_unix.go
index 9dca9c1a9b2..573e80e2377 100644
--- a/fuse/readonly/readonly_unix.go
+++ b/fuse/readonly/readonly_unix.go
@@ -19,7 +19,7 @@ import (
"github.com/ipfs/boxo/path"
"github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
core "github.com/ipfs/kubo/core"
ipldprime "github.com/ipld/go-ipld-prime"
cidlink "github.com/ipld/go-ipld-prime/linking/cid"
@@ -62,7 +62,7 @@ func (s *Root) Lookup(ctx context.Context, name string) (fs.Node, error) {
return nil, syscall.Errno(syscall.ENOENT)
}
- p, err := path.NewPath(name)
+ p, err := path.NewPath("/ipfs/" + name)
if err != nil {
log.Debugf("fuse failed to parse path: %q: %s", name, err)
return nil, syscall.Errno(syscall.ENOENT)
diff --git a/gc/gc.go b/gc/gc.go
index 51df59e5408..37daa887c62 100644
--- a/gc/gc.go
+++ b/gc/gc.go
@@ -16,7 +16,7 @@ import (
cid "github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore"
ipld "github.com/ipfs/go-ipld-format"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
)
var log = logging.Logger("gc")
diff --git a/go.mod b/go.mod
index efab059a36c..7323f337c5b 100644
--- a/go.mod
+++ b/go.mod
@@ -1,172 +1,193 @@
module github.com/ipfs/kubo
+go 1.24
+
require (
bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc
contrib.go.opencensus.io/exporter/prometheus v0.4.2
- github.com/benbjohnson/clock v1.3.5
github.com/blang/semver/v4 v4.0.0
- github.com/cenkalti/backoff/v4 v4.2.1
- github.com/ceramicnetwork/go-dag-jose v0.1.0
+ github.com/caddyserver/certmagic v0.21.6
+ github.com/cenkalti/backoff/v4 v4.3.0
+ github.com/ceramicnetwork/go-dag-jose v0.1.1
github.com/cheggaaa/pb v1.0.29
+ github.com/cockroachdb/pebble/v2 v2.0.3
github.com/coreos/go-systemd/v22 v22.5.0
github.com/dustin/go-humanize v1.0.1
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/google/uuid v1.5.0
- github.com/hashicorp/go-multierror v1.1.1
- github.com/ipfs-shipyard/nopfs v0.0.12
- github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c
- github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a
- github.com/ipfs/go-block-format v0.2.0
- github.com/ipfs/go-cid v0.4.1
+ github.com/filecoin-project/go-clock v0.1.0
+ github.com/fsnotify/fsnotify v1.7.0
+ github.com/google/uuid v1.6.0
+ github.com/hashicorp/go-version v1.7.0
+ github.com/ipfs-shipyard/nopfs v0.0.14
+ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0
+ github.com/ipfs/boxo v0.31.1-0.20250528182950-f87feb50c39c
+ github.com/ipfs/go-block-format v0.2.1
+ github.com/ipfs/go-cid v0.5.0
github.com/ipfs/go-cidutil v0.1.0
- github.com/ipfs/go-datastore v0.6.0
+ github.com/ipfs/go-datastore v0.8.2
github.com/ipfs/go-detect-race v0.0.1
- github.com/ipfs/go-ds-badger v0.3.0
- github.com/ipfs/go-ds-flatfs v0.5.1
- github.com/ipfs/go-ds-leveldb v0.5.0
- github.com/ipfs/go-ds-measure v0.2.0
- github.com/ipfs/go-fs-lock v0.0.7
- github.com/ipfs/go-ipfs-cmds v0.10.0
- github.com/ipfs/go-ipld-cbor v0.1.0
- github.com/ipfs/go-ipld-format v0.6.0
+ github.com/ipfs/go-ds-badger v0.3.4
+ github.com/ipfs/go-ds-flatfs v0.5.5
+ github.com/ipfs/go-ds-leveldb v0.5.2
+ github.com/ipfs/go-ds-measure v0.2.2
+ github.com/ipfs/go-ds-pebble v0.5.0
+ github.com/ipfs/go-fs-lock v0.1.1
+ github.com/ipfs/go-ipfs-cmds v0.15.0
+ github.com/ipfs/go-ipld-cbor v0.2.0
+ github.com/ipfs/go-ipld-format v0.6.1
github.com/ipfs/go-ipld-git v0.1.1
github.com/ipfs/go-ipld-legacy v0.2.1
- github.com/ipfs/go-log v1.0.5
- github.com/ipfs/go-log/v2 v2.5.1
- github.com/ipfs/go-metrics-interface v0.0.1
- github.com/ipfs/go-metrics-prometheus v0.0.2
- github.com/ipfs/go-unixfsnode v1.9.0
- github.com/ipld/go-car v0.5.0
- github.com/ipld/go-car/v2 v2.13.1
- github.com/ipld/go-codec-dagpb v1.6.0
+ github.com/ipfs/go-log/v2 v2.6.0
+ github.com/ipfs/go-metrics-interface v0.3.0
+ github.com/ipfs/go-metrics-prometheus v0.1.0
+ github.com/ipfs/go-test v0.2.2
+ github.com/ipfs/go-unixfsnode v1.10.1
+ github.com/ipld/go-car v0.6.2
+ github.com/ipld/go-car/v2 v2.14.3
+ github.com/ipld/go-codec-dagpb v1.7.0
github.com/ipld/go-ipld-prime v0.21.0
- github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c
+ github.com/ipshipyard/p2p-forge v0.5.1
github.com/jbenet/go-temp-err-catcher v0.1.0
github.com/jbenet/goprocess v0.1.4
github.com/julienschmidt/httprouter v1.3.0
- github.com/libp2p/go-doh-resolver v0.4.0
- github.com/libp2p/go-libp2p v0.32.2
+ github.com/libp2p/go-doh-resolver v0.5.0
+ github.com/libp2p/go-libp2p v0.41.1
github.com/libp2p/go-libp2p-http v0.5.0
- github.com/libp2p/go-libp2p-kad-dht v0.24.4
- github.com/libp2p/go-libp2p-kbucket v0.6.3
- github.com/libp2p/go-libp2p-pubsub v0.10.0
+ github.com/libp2p/go-libp2p-kad-dht v0.33.1
+ github.com/libp2p/go-libp2p-kbucket v0.7.0
+ github.com/libp2p/go-libp2p-pubsub v0.13.1
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.7.3
+ github.com/libp2p/go-libp2p-record v0.3.1
+ github.com/libp2p/go-libp2p-routing-helpers v0.7.5
github.com/libp2p/go-libp2p-testing v0.12.0
- github.com/libp2p/go-socket-activation v0.1.0
- github.com/mitchellh/go-homedir v1.1.0
- github.com/multiformats/go-multiaddr v0.12.2
- github.com/multiformats/go-multiaddr-dns v0.3.1
+ github.com/libp2p/go-socket-activation v0.1.1
+ github.com/multiformats/go-multiaddr v0.15.0
+ github.com/multiformats/go-multiaddr-dns v0.4.1
github.com/multiformats/go-multibase v0.2.0
github.com/multiformats/go-multicodec v0.9.0
github.com/multiformats/go-multihash v0.2.3
github.com/opentracing/opentracing-go v1.2.0
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
- github.com/pkg/errors v0.9.1
- github.com/prometheus/client_golang v1.18.0
- github.com/stretchr/testify v1.8.4
- github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
- github.com/tidwall/gjson v1.14.4
+ github.com/prometheus/client_golang v1.22.0
+ github.com/stretchr/testify v1.10.0
+ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d
+ github.com/tidwall/gjson v1.16.0
github.com/tidwall/sjson v1.2.5
github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
go.opencensus.io v0.24.0
- go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0
go.opentelemetry.io/contrib/propagators/autoprop v0.46.1
- go.opentelemetry.io/otel v1.22.0
- go.opentelemetry.io/otel/sdk v1.21.0
- go.opentelemetry.io/otel/trace v1.22.0
- go.uber.org/dig v1.17.1
- go.uber.org/fx v1.20.1
+ go.opentelemetry.io/otel v1.35.0
+ go.opentelemetry.io/otel/sdk v1.31.0
+ go.opentelemetry.io/otel/trace v1.35.0
+ go.uber.org/dig v1.18.0
+ go.uber.org/fx v1.23.0
go.uber.org/multierr v1.11.0
- go.uber.org/zap v1.26.0
- golang.org/x/crypto v0.18.0
- golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
- golang.org/x/mod v0.14.0
- golang.org/x/sync v0.6.0
- golang.org/x/sys v0.16.0
- google.golang.org/protobuf v1.32.0
+ go.uber.org/zap v1.27.0
+ golang.org/x/crypto v0.38.0
+ golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6
+ golang.org/x/mod v0.24.0
+ golang.org/x/sync v0.14.0
+ golang.org/x/sys v0.33.0
+ google.golang.org/protobuf v1.36.6
)
require (
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
+ github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e // indirect
github.com/Jorropo/jsync v1.0.1 // indirect
- github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
+ github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect
+ github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
- github.com/cespare/xxhash v1.1.0 // indirect
- github.com/cespare/xxhash/v2 v2.2.0 // indirect
+ github.com/caddyserver/zerossl v0.1.3 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
+ github.com/cockroachdb/crlib v0.0.0-20241015224233-894974b3ad94 // indirect
+ github.com/cockroachdb/errors v1.11.3 // indirect
+ github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect
+ github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
+ github.com/cockroachdb/redact v1.1.5 // indirect
+ github.com/cockroachdb/swiss v0.0.0-20250327203710-2932b022f6df // indirect
+ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
- github.com/crackcomm/go-gitignore v0.0.0-20231225121904-e25f5bc08668 // indirect
+ github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf // indirect
github.com/cskr/pubsub v1.0.2 // indirect
- github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
- github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
+ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/dgraph-io/badger v1.6.2 // indirect
- github.com/dgraph-io/ristretto v0.0.2 // indirect
+ github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/docker/go-units v0.5.0 // indirect
- github.com/elastic/gosigar v0.14.2 // indirect
+ github.com/elastic/gosigar v0.14.3 // indirect
+ github.com/fatih/color v1.15.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
- github.com/flynn/noise v1.0.1 // indirect
+ github.com/flynn/noise v1.1.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
- github.com/gabriel-vasile/mimetype v1.4.3 // indirect
+ github.com/gabriel-vasile/mimetype v1.4.6 // indirect
+ github.com/gammazero/chanqueue v1.1.0 // indirect
+ github.com/gammazero/deque v1.0.0 // indirect
+ github.com/getsentry/sentry-go v0.27.0 // indirect
+ github.com/go-jose/go-jose/v4 v4.0.5 // indirect
github.com/go-kit/log v0.2.1 // indirect
- github.com/go-logfmt/logfmt v0.5.1 // indirect
- github.com/go-logr/logr v1.4.1 // indirect
+ github.com/go-logfmt/logfmt v0.6.0 // indirect
+ github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
- github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
+ github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/golang/glog v1.2.4 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
- github.com/golang/protobuf v1.5.3 // indirect
- github.com/golang/snappy v0.0.4 // indirect
+ github.com/golang/protobuf v1.5.4 // indirect
+ github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect
github.com/google/gopacket v1.1.19 // indirect
- github.com/google/pprof v0.0.0-20231229205709-960ae82b1e42 // indirect
+ github.com/google/pprof v0.0.0-20250208200701-d0013a598941 // indirect
github.com/gorilla/mux v1.8.1 // indirect
- github.com/gorilla/websocket v1.5.0 // indirect
- github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
- github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/gorilla/websocket v1.5.3 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/ipfs/bbloom v0.0.4 // indirect
github.com/ipfs/go-bitfield v1.1.0 // indirect
- github.com/ipfs/go-blockservice v0.5.0 // indirect
- github.com/ipfs/go-ipfs-blockstore v1.3.0 // indirect
+ github.com/ipfs/go-blockservice v0.5.2 // indirect
+ github.com/ipfs/go-ipfs-blockstore v1.3.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-exchange-interface v0.2.0 // indirect
+ github.com/ipfs/go-ipfs-ds-help v1.1.1 // indirect
+ github.com/ipfs/go-ipfs-exchange-interface v0.2.1 // indirect
github.com/ipfs/go-ipfs-pq v0.0.3 // indirect
- github.com/ipfs/go-ipfs-redirects-file v0.1.1 // indirect
+ github.com/ipfs/go-ipfs-redirects-file v0.1.2 // indirect
github.com/ipfs/go-ipfs-util v0.0.3 // indirect
+ github.com/ipfs/go-log v1.0.5 // indirect
github.com/ipfs/go-merkledag v0.11.0 // indirect
- github.com/ipfs/go-peertaskqueue v0.8.1 // indirect
- github.com/ipfs/go-verifcid v0.0.2 // indirect
+ github.com/ipfs/go-peertaskqueue v0.8.2 // indirect
+ github.com/ipfs/go-verifcid v0.0.3 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
- github.com/klauspost/compress v1.17.4 // indirect
- github.com/klauspost/cpuid/v2 v2.2.6 // indirect
- github.com/koron/go-ssdp v0.0.4 // indirect
+ github.com/klauspost/compress v1.18.0 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.10 // indirect
+ github.com/koron/go-ssdp v0.0.5 // indirect
+ github.com/kr/pretty v0.3.1 // indirect
+ github.com/kr/text v0.2.0 // indirect
+ github.com/libdns/libdns v0.2.2 // 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-flow-metrics v0.2.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
github.com/libp2p/go-libp2p-gostream v0.6.0 // indirect
github.com/libp2p/go-libp2p-xor v0.1.0 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
- github.com/libp2p/go-nat v0.2.0 // indirect
- github.com/libp2p/go-netroute v0.2.1 // indirect
+ github.com/libp2p/go-netroute v0.2.2 // indirect
github.com/libp2p/go-reuseport v0.4.0 // indirect
- github.com/libp2p/go-yamux/v4 v4.0.1 // indirect
+ github.com/libp2p/go-yamux/v5 v5.0.0 // indirect
github.com/libp2p/zeroconf/v2 v2.2.0 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
- github.com/mattn/go-colorable v0.1.6 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
- github.com/mattn/go-runewidth v0.0.4 // indirect
+ github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
- github.com/miekg/dns v1.1.58 // indirect
+ github.com/mholt/acmez/v3 v3.0.0 // indirect
+ github.com/miekg/dns v1.1.66 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
@@ -174,80 +195,87 @@ require (
github.com/multiformats/go-base32 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.5.0 // indirect
+ github.com/multiformats/go-multistream v0.6.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
- github.com/onsi/ginkgo/v2 v2.13.2 // indirect
- github.com/opencontainers/runtime-spec v1.1.0 // indirect
- github.com/openzipkin/zipkin-go v0.4.2 // indirect
+ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/onsi/ginkgo/v2 v2.22.2 // indirect
+ github.com/opencontainers/runtime-spec v1.2.0 // indirect
+ github.com/openzipkin/zipkin-go v0.4.3 // indirect
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect
- github.com/pion/datachannel v1.5.5 // indirect
- github.com/pion/dtls/v2 v2.2.7 // indirect
- github.com/pion/ice/v2 v2.3.6 // indirect
- github.com/pion/interceptor v0.1.17 // indirect
- github.com/pion/logging v0.2.2 // indirect
- github.com/pion/mdns v0.0.7 // indirect
+ github.com/pion/datachannel v1.5.10 // indirect
+ github.com/pion/dtls/v2 v2.2.12 // indirect
+ github.com/pion/dtls/v3 v3.0.4 // indirect
+ github.com/pion/ice/v4 v4.0.8 // indirect
+ github.com/pion/interceptor v0.1.37 // indirect
+ github.com/pion/logging v0.2.3 // indirect
+ github.com/pion/mdns/v2 v2.0.7 // indirect
github.com/pion/randutil v0.1.0 // indirect
- github.com/pion/rtcp v1.2.10 // indirect
- github.com/pion/rtp v1.7.13 // indirect
- github.com/pion/sctp v1.8.7 // indirect
- github.com/pion/sdp/v3 v3.0.6 // indirect
- github.com/pion/srtp/v2 v2.0.15 // indirect
- github.com/pion/stun v0.6.0 // indirect
- github.com/pion/transport/v2 v2.2.1 // indirect
- github.com/pion/turn/v2 v2.1.0 // indirect
- github.com/pion/webrtc/v3 v3.2.9 // indirect
- github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/pion/rtcp v1.2.15 // indirect
+ github.com/pion/rtp v1.8.11 // indirect
+ github.com/pion/sctp v1.8.37 // indirect
+ github.com/pion/sdp/v3 v3.0.10 // indirect
+ github.com/pion/srtp/v3 v3.0.4 // indirect
+ github.com/pion/stun v0.6.1 // indirect
+ github.com/pion/stun/v3 v3.0.0 // indirect
+ github.com/pion/transport/v2 v2.2.10 // indirect
+ github.com/pion/transport/v3 v3.0.7 // indirect
+ github.com/pion/turn/v4 v4.0.0 // indirect
+ github.com/pion/webrtc/v4 v4.0.10 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
- github.com/prometheus/client_model v0.5.0 // indirect
- github.com/prometheus/common v0.46.0 // indirect
- github.com/prometheus/procfs v0.12.0 // indirect
- github.com/prometheus/statsd_exporter v0.22.7 // indirect
- github.com/quic-go/qpack v0.4.0 // indirect
- github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
- github.com/quic-go/quic-go v0.40.1 // indirect
- github.com/quic-go/webtransport-go v0.6.0 // indirect
+ github.com/prometheus/client_model v0.6.2 // indirect
+ github.com/prometheus/common v0.63.0 // indirect
+ github.com/prometheus/procfs v0.16.1 // indirect
+ github.com/prometheus/statsd_exporter v0.27.1 // indirect
+ github.com/quic-go/qpack v0.5.1 // indirect
+ github.com/quic-go/quic-go v0.50.1 // indirect
+ github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
- github.com/rs/cors v1.7.0 // indirect
- github.com/samber/lo v1.39.0 // indirect
+ github.com/rivo/uniseg v0.4.4 // indirect
+ github.com/rogpeppe/go-internal v1.13.1 // indirect
+ github.com/rs/cors v1.11.1 // indirect
+ github.com/samber/lo v1.47.0 // indirect
+ github.com/slok/go-http-metrics v0.13.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
- github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e // indirect
+ github.com/texttheater/golang-levenshtein v1.0.1 // indirect
github.com/tidwall/match v1.1.1 // indirect
- github.com/tidwall/pretty v1.2.0 // indirect
+ github.com/tidwall/pretty v1.2.1 // 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 v0.0.0-20171005072247-63513f603b11 // indirect
- github.com/whyrusleeping/cbor-gen v0.0.0-20240109153615-66e95c3e8a87 // indirect
+ github.com/whyrusleeping/cbor-gen v0.1.2 // indirect
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
+ github.com/wlynxg/anet v0.0.5 // indirect
+ github.com/zeebo/blake3 v0.2.4 // indirect
+ go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/propagators/aws v1.21.1 // indirect
go.opentelemetry.io/contrib/propagators/b3 v1.21.1 // indirect
go.opentelemetry.io/contrib/propagators/jaeger v1.21.1 // indirect
go.opentelemetry.io/contrib/propagators/ot v1.21.1 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 // indirect
- go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0 // indirect
- go.opentelemetry.io/otel/exporters/zipkin v1.21.0 // indirect
- go.opentelemetry.io/otel/metric v1.22.0 // indirect
- go.opentelemetry.io/proto/otlp v1.0.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 // indirect
+ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 // indirect
+ go.opentelemetry.io/otel/exporters/zipkin v1.31.0 // indirect
+ go.opentelemetry.io/otel/metric v1.35.0 // indirect
+ go.opentelemetry.io/proto/otlp v1.3.1 // indirect
go.uber.org/atomic v1.11.0 // indirect
- go.uber.org/mock v0.4.0 // indirect
+ go.uber.org/mock v0.5.0 // indirect
+ go.uber.org/zap/exp v0.3.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
- golang.org/x/net v0.20.0 // indirect
- golang.org/x/oauth2 v0.16.0 // indirect
- golang.org/x/term v0.16.0 // indirect
- golang.org/x/text v0.14.0 // indirect
- golang.org/x/tools v0.17.0 // indirect
- golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
- gonum.org/v1/gonum v0.14.0 // indirect
- google.golang.org/appengine v1.6.8 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20240108191215-35c7eff3a6b1 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect
- google.golang.org/grpc v1.60.1 // indirect
- gopkg.in/square/go-jose.v2 v2.5.1 // indirect
+ golang.org/x/net v0.40.0 // indirect
+ golang.org/x/oauth2 v0.25.0 // indirect
+ golang.org/x/term v0.32.0 // indirect
+ golang.org/x/text v0.25.0 // indirect
+ golang.org/x/tools v0.33.0 // indirect
+ golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
+ gonum.org/v1/gonum v0.16.0 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect
+ google.golang.org/grpc v1.67.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- lukechampine.com/blake3 v1.2.1 // indirect
+ lukechampine.com/blake3 v1.4.1 // indirect
)
-
-go 1.20
diff --git a/go.sum b/go.sum
index 35eefb2bb6f..9e30f10fabb 100644
--- a/go.sum
+++ b/go.sum
@@ -47,10 +47,13 @@ github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIo
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e h1:ZIWapoIRN1VqT8GR8jAwb1Ie9GyehWjVcGh32Y2MznE=
+github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Jorropo/jsync v1.0.1 h1:6HgRolFZnsdfzRUj+ImB9og1JYOxQoReSywkHOGSaUU=
github.com/Jorropo/jsync v1.0.1/go.mod h1:jCOZj3vrBCri3bSU3ErUYvevKlnbssrXeCivybS5ABQ=
-github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/aclements/go-perfevent v0.0.0-20240301234650-f7843625020f h1:JjxwchlOepwsUWcQwD2mLUAGE9aCp0/ehy6yCHFBOvo=
+github.com/aclements/go-perfevent v0.0.0-20240301234650-f7843625020f/go.mod h1:tMDTce/yLLN/SK8gMOxQfnyeMeCg8KGzp0D1cbECEeo=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
@@ -58,13 +61,12 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
-github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 h1:ez/4by2iGztzR4L0zgAOR8lTQK9VlyBVVd7G4omaOQs=
-github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
+github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0=
+github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs=
github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 h1:iW0a5ljuFxkLGPNem5Ui+KBjFJzKg4Fv2fnxe4dvzpM=
github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5/go.mod h1:Y2QMoi1vgtOIfc+6DhrMOGkLoGzqSV2rKp4Sm+opsyA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
-github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
@@ -85,17 +87,20 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
-github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
-github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/caddyserver/certmagic v0.21.6 h1:1th6GfprVfsAtFNOu4StNMF5IxK5XiaI0yZhAHlZFPE=
+github.com/caddyserver/certmagic v0.21.6/go.mod h1:n1sCo7zV1Ez2j+89wrzDxo4N/T1Ws/Vx8u5NvuBFabw=
+github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
+github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
+github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
+github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/ceramicnetwork/go-dag-jose v0.1.0 h1:yJ/HVlfKpnD3LdYP03AHyTvbm3BpPiz2oZiOeReJRdU=
-github.com/ceramicnetwork/go-dag-jose v0.1.0/go.mod h1:qYA1nYt0X8u4XoMAVoOV3upUVKtrxy/I670Dg5F0wjI=
-github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
+github.com/ceramicnetwork/go-dag-jose v0.1.1 h1:7pObs22egc14vSS3AfCFfS1VmaL4lQUsAK7OGC3PlKk=
+github.com/ceramicnetwork/go-dag-jose v0.1.1/go.mod h1:8ptnYwY2Z2y/s5oJnNBn/UCxLg6CpramNJ2ZXF/5aNY=
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/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/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo=
github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@@ -104,6 +109,26 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cockroachdb/crlib v0.0.0-20241015224233-894974b3ad94 h1:bvJv505UUfjzbaIPdNS4AEkHreDqQk6yuNpsdRHpwFA=
+github.com/cockroachdb/crlib v0.0.0-20241015224233-894974b3ad94/go.mod h1:Gq51ZeKaFCXk6QwuGM0w1dnaOqc/F5zKT2zA9D6Xeac=
+github.com/cockroachdb/datadriven v1.0.3-0.20240530155848-7682d40af056 h1:slXychO2uDM6hYRu4c0pD0udNI8uObfeKN6UInWViS8=
+github.com/cockroachdb/datadriven v1.0.3-0.20240530155848-7682d40af056/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
+github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
+github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8=
+github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4=
+github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M=
+github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
+github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
+github.com/cockroachdb/metamorphic v0.0.0-20231108215700-4ba948b56895 h1:XANOgPYtvELQ/h4IrmPAohXqe2pWA8Bwhejr3VQoZsA=
+github.com/cockroachdb/metamorphic v0.0.0-20231108215700-4ba948b56895/go.mod h1:aPd7gM9ov9M8v32Yy5NJrDyOcD8z642dqs+F0CeNXfA=
+github.com/cockroachdb/pebble/v2 v2.0.3 h1:YJ3Sc9jRN/q6OOCNyRHPbcpenbxL1DdgdpUqPlPus6o=
+github.com/cockroachdb/pebble/v2 v2.0.3/go.mod h1:NgxgNcWwyG/uxkLUZGM2aelshaLIZvc0hCX7SCfaO8s=
+github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
+github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
+github.com/cockroachdb/swiss v0.0.0-20250327203710-2932b022f6df h1:GUJ4KuZtbOcIfRlprHJFFvIqQ4irtQUl+1fJr+yNmPI=
+github.com/cockroachdb/swiss v0.0.0-20250327203710-2932b022f6df/go.mod h1:yBRu/cnL4ks9bgy4vAASdjIW+/xMlFwuHKqtmh3GZQg=
+github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
+github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ=
github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
@@ -112,32 +137,34 @@ github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8Nz
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/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=
github.com/coreos/go-systemd/v22 v22.5.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-20231225121904-e25f5bc08668 h1:ZFUue+PNxmHlu7pYv+IYMtqlaO/0VwaGEqKepZf9JpA=
-github.com/crackcomm/go-gitignore v0.0.0-20231225121904-e25f5bc08668/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE=
+github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf h1:dwGgBWn84wUS1pVikGiruW+x5XM4amhjaZO20vCjay4=
+github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf/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=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU=
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U=
-github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
+github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
+github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8=
github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE=
-github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po=
github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
+github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
+github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
@@ -147,8 +174,8 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
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/elastic/gosigar v0.14.3 h1:xwkKwPia+hSfg9GqrCUKYdId102m9qTJIIr7egmK/uo=
+github.com/elastic/gosigar v0.14.3/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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -157,31 +184,47 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A=
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg=
-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/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
+github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/filecoin-project/go-clock v0.1.0 h1:SFbYIM75M8NnFm1yMHhN9Ahy3W5bEZV9gd6MPfXbKVU=
+github.com/filecoin-project/go-clock v0.1.0/go.mod h1:4uB/O4PvOjlx1VCMdZ9MyDZXRm//gkj1ELEbxfI1AZs=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
-github.com/flynn/noise v1.0.1 h1:vPp/jdQLXC6ppsXSj/pM3W1BIJ5FEHE2TulSJBpb43Y=
-github.com/flynn/noise v1.0.1/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
+github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
+github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
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.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
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/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
-github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
+github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
+github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
+github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
+github.com/gammazero/chanqueue v1.1.0 h1:yiwtloc1azhgGLFo2gMloJtQvkYD936Ai7tBfa+rYJw=
+github.com/gammazero/chanqueue v1.1.0/go.mod h1:fMwpwEiuUgpab0sH4VHiVcEoji1pSi+EIzeG4TPeKPc=
+github.com/gammazero/deque v1.0.0 h1:LTmimT8H7bXkkCy6gZX7zNLtkbz4NdS2z8LZuor3j34=
+github.com/gammazero/deque v1.0.0/go.mod h1:iflpYvtGfM3U8S8j+sZEKIak3SAKYpA5/SQewgfXDKo=
+github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
+github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
+github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9 h1:r5GgOLGbza2wVHRzK7aAj6lWZjfbAwiu/RDCVOKjRyM=
+github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs=
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=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
+github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
+github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
+github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
@@ -191,17 +234,18 @@ github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBj
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
-github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
+github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
+github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
-github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
-github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
-github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
+github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
+github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -214,6 +258,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc=
+github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -243,11 +289,12 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e h1:4bw4WeyTYPp0smaXiJZCNnLrvVBqirQVreixayXezGc=
+github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -261,9 +308,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -278,35 +325,33 @@ 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-20231229205709-960ae82b1e42 h1:dHLYa5D8/Ta0aLR2XcPsrkpAgGeFs6thhMcQK0oQ0n8=
-github.com/google/pprof v0.0.0-20231229205709-960ae82b1e42/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
+github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20250208200701-d0013a598941 h1:43XjGa6toxLpeksjcxs1jIoIyr+vUfOqY2c6HB4bpoc=
+github.com/google/pprof v0.0.0-20250208200701-d0013a598941/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
-github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
+github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
-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/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
+github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
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/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
-github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/go-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-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
+github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
@@ -318,122 +363,122 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/ipfs-shipyard/nopfs v0.0.12 h1:mvwaoefDF5VI9jyvgWCmaoTJIJFAfrbyQV5fJz35hlk=
-github.com/ipfs-shipyard/nopfs v0.0.12/go.mod h1:mQyd0BElYI2gB/kq/Oue97obP4B3os4eBmgfPZ+hnrE=
-github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c h1:7UynTbtdlt+w08ggb1UGLGaGjp1mMaZhoTZSctpn5Ak=
-github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c/go.mod h1:6EekK/jo+TynwSE/ZOiOJd4eEvRXoavEC3vquKtv4yI=
+github.com/ipfs-shipyard/nopfs v0.0.14 h1:HFepJt/MxhZ3/GsLZkkAPzIPdNYKaLO1Qb7YmPbWIKk=
+github.com/ipfs-shipyard/nopfs v0.0.14/go.mod h1:mQyd0BElYI2gB/kq/Oue97obP4B3os4eBmgfPZ+hnrE=
+github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcdHUd7SDsUOY=
+github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
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/boxo v0.17.1-0.20240126101119-fdfcfcc0708a h1:BMxa0aXrjyGh5gAkzxVsjDN71YhAWGfjbOoNvZt4/jg=
-github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a/go.mod h1:pIZgTWdm3k3pLF9Uq6MB8JEcW07UDwNJjlXW1HELW80=
+github.com/ipfs/boxo v0.31.1-0.20250528182950-f87feb50c39c h1:0jAFJxC74Gy0VwDG6WwYJq0yZdXOFIIeCwUXXln0w6A=
+github.com/ipfs/boxo v0.31.1-0.20250528182950-f87feb50c39c/go.mod h1:gEkUkBiZWtEjHd1AiUxaWEYaQApPtbeGF45fdfCwLX0=
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
github.com/ipfs/go-bitswap v0.11.0 h1:j1WVvhDX1yhG32NTC9xfxnqycqYIlhzEzLXG/cU1HyQ=
+github.com/ipfs/go-bitswap v0.11.0/go.mod h1:05aE8H3XOU+LXpTedeAS0OZpcO1WFsj5niYQH9a1Tmk=
github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk=
-github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs=
-github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM=
-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-block-format v0.2.1 h1:96kW71XGNNa+mZw/MTzJrCpMhBWCrd9kBLoKm9Iip/Q=
+github.com/ipfs/go-block-format v0.2.1/go.mod h1:frtvXHMQhM6zn7HvEQu+Qz5wSTj+04oEH/I+NjDgEjk=
+github.com/ipfs/go-blockservice v0.5.2 h1:in9Bc+QcXwd1apOVM7Un9t8tixPKdaHQFdLSUM1Xgk8=
+github.com/ipfs/go-blockservice v0.5.2/go.mod h1:VpMblFEqG67A/H2sHKAemeH9vlURVavlysbdUI632yk=
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.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
-github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
-github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
+github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg=
+github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk=
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.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.5.0/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-datastore v0.8.2 h1:Jy3wjqQR6sg/LhyY0NIePZC3Vux19nLtg7dx0TVqr6U=
+github.com/ipfs/go-datastore v0.8.2/go.mod h1:W+pI1NsUsz3tcsAACMtfC+IZdnQTnC/7VfPoJBQuts0=
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=
-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=
-github.com/ipfs/go-ds-flatfs v0.5.1/go.mod h1:RWTV7oZD/yZYBKdbVIFXTX2fdY2Tbvl94NsWqmoyAX4=
+github.com/ipfs/go-ds-badger v0.3.4 h1:MmqFicftE0KrwMC77WjXTrPuoUxhwyFsjKONSeWrlOo=
+github.com/ipfs/go-ds-badger v0.3.4/go.mod h1:HfqsKJcNnIr9ZhZ+rkwS1J5PpaWjJjg6Ipmxd7KPfZ8=
+github.com/ipfs/go-ds-flatfs v0.5.5 h1:lkx5C99pFBMI7T1sYF7y3v7xIYekNVNMp/95Gm9Y3tY=
+github.com/ipfs/go-ds-flatfs v0.5.5/go.mod h1:bM7+m7KFUyv5dp3RBKTr3+OHgZ6h8ydCQkO7tjeO9Z4=
github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8=
-github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo=
-github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q=
-github.com/ipfs/go-ds-measure v0.2.0 h1:sG4goQe0KDTccHMyT45CY1XyUbxe5VwTKpg2LjApYyQ=
-github.com/ipfs/go-ds-measure v0.2.0/go.mod h1:SEUD/rE2PwRa4IQEC5FuNAmjJCyYObZr9UvVh8V3JxE=
-github.com/ipfs/go-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-ipfs-blockstore v1.3.0 h1:m2EXaWgwTzAfsmt5UdJ7Is6l4gJcaM/A12XwJyvYvMM=
-github.com/ipfs/go-ipfs-blockstore v1.3.0/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE=
+github.com/ipfs/go-ds-leveldb v0.5.2 h1:6nmxlQ2zbp4LCNdJVsmHfs9GP0eylfBNxpmY1csp0x0=
+github.com/ipfs/go-ds-leveldb v0.5.2/go.mod h1:2fAwmcvD3WoRT72PzEekHBkQmBDhc39DJGoREiuGmYo=
+github.com/ipfs/go-ds-measure v0.2.2 h1:4kwvBGbbSXNYe4ANlg7qTIYoZU6mNlqzQHdVqICkqGI=
+github.com/ipfs/go-ds-measure v0.2.2/go.mod h1:b/87ak0jMgH9Ylt7oH0+XGy4P8jHx9KG09Qz+pOeTIs=
+github.com/ipfs/go-ds-pebble v0.5.0 h1:lXffYCAKVD7nLLPqwJ9D8IxgO7Kz8woiX021tezdsIM=
+github.com/ipfs/go-ds-pebble v0.5.0/go.mod h1:aiCRVcj3K60sxc6k5C+HO9C6rouqiSkjR/WKnbTcMfQ=
+github.com/ipfs/go-fs-lock v0.1.1 h1:TecsP/Uc7WqYYatasreZQiP9EGRy4ZnKoG4yXxR33nw=
+github.com/ipfs/go-fs-lock v0.1.1/go.mod h1:2goSXMCw7QfscHmSe09oXiR34DQeUdm+ei+dhonqly0=
+github.com/ipfs/go-ipfs-blockstore v1.3.1 h1:cEI9ci7V0sRNivqaOr0elDsamxXFxJMMMy7PTTDQNsQ=
+github.com/ipfs/go-ipfs-blockstore v1.3.1/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE=
github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ=
-github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8=
-github.com/ipfs/go-ipfs-cmds v0.10.0 h1:ZB4+RgYaH4UARfJY0uLKl5UXgApqnRjKbuCiJVcErYk=
-github.com/ipfs/go-ipfs-cmds v0.10.0/go.mod h1:sX5d7jkCft9XLPnkgEfXY0z2UBOB5g6fh/obBS0enJE=
+github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk=
+github.com/ipfs/go-ipfs-cmds v0.15.0 h1:nQDgKadrzyiFyYoZMARMIoVoSwe3gGTAfGvrWLeAQbQ=
+github.com/ipfs/go-ipfs-cmds v0.15.0/go.mod h1:VABf/mv/wqvYX6hLG6Z+40eNAEw3FQO0bSm370Or3Wk=
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 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=
-github.com/ipfs/go-ipfs-exchange-interface v0.2.0/go.mod h1:z6+RhJuDQbqKguVyslSOuVDhqF9JtTrO3eptSAiW2/Y=
+github.com/ipfs/go-ipfs-ds-help v1.1.1 h1:B5UJOH52IbcfS56+Ul+sv8jnIV10lbjLF5eOO0C66Nw=
+github.com/ipfs/go-ipfs-ds-help v1.1.1/go.mod h1:75vrVCkSdSFidJscs8n4W+77AtTpCIAdDGAwjitJMIo=
+github.com/ipfs/go-ipfs-exchange-interface v0.2.1 h1:jMzo2VhLKSHbVe+mHNzYgs95n0+t0Q69GQ5WhRDZV/s=
+github.com/ipfs/go-ipfs-exchange-interface v0.2.1/go.mod h1:MUsYn6rKbG6CTtsDp+lKJPmVt3ZrCViNyH3rfPGsZ2E=
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-pq v0.0.3 h1:YpoHVJB+jzK15mr/xsWC574tyDLkezVrDNeaalQBsTE=
github.com/ipfs/go-ipfs-pq v0.0.3/go.mod h1:btNw5hsHBpRcSSgZtiNm/SLj5gYIZ18AKtv3kERkRb4=
-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-redirects-file v0.1.2 h1:QCK7VtL91FH17KROVVy5KrzDx2hu68QvB2FTWk08ZQk=
+github.com/ipfs/go-ipfs-redirects-file v0.1.2/go.mod h1:yIiTlLcDEM/8lS6T3FlCEXZktPPqSOyuY6dEzVqw7Fw=
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/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ=
github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0=
github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs=
-github.com/ipfs/go-ipld-cbor v0.1.0 h1:dx0nS0kILVivGhfWuB6dUpMa/LAwElHPw1yOGYopoYs=
-github.com/ipfs/go-ipld-cbor v0.1.0/go.mod h1:U2aYlmVrJr2wsUBU67K4KgepApSZddGRDWBYR0H4sCk=
-github.com/ipfs/go-ipld-format v0.6.0 h1:VEJlA2kQ3LqFSIm5Vu6eIlSxD/Ze90xtc4Meten1F5U=
-github.com/ipfs/go-ipld-format v0.6.0/go.mod h1:g4QVMTn3marU3qXchwjpKPKgJv+zF+OlaKMyhJ4LHPg=
+github.com/ipfs/go-ipld-cbor v0.2.0 h1:VHIW3HVIjcMd8m4ZLZbrYpwjzqlVUfjLM7oK4T5/YF0=
+github.com/ipfs/go-ipld-cbor v0.2.0/go.mod h1:Cp8T7w1NKcu4AQJLqK0tWpd1nkgTxEVB5C6kVpLW6/0=
+github.com/ipfs/go-ipld-format v0.6.1 h1:lQLmBM/HHbrXvjIkrydRXkn+gc0DE5xO5fqelsCKYOQ=
+github.com/ipfs/go-ipld-format v0.6.1/go.mod h1:8TOH1Hj+LFyqM2PjSqI2/ZnyO0KlfhHbJLkbxFa61hs=
github.com/ipfs/go-ipld-git v0.1.1 h1:TWGnZjS0htmEmlMFEkA3ogrNCqWjIxwr16x1OsdhG+Y=
github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYDpKUkJubI=
github.com/ipfs/go-ipld-legacy v0.2.1 h1:mDFtrBpmU7b//LzLSypVrXsD8QxkEWxu5qVxN99/+tk=
github.com/ipfs/go-ipld-legacy v0.2.1/go.mod h1:782MOUghNzMO2DER0FlBR94mllfdCJCkTtDtPM51otM=
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.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
-github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0=
-github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw=
github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
-github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g=
-github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
-github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
+github.com/ipfs/go-log/v2 v2.6.0 h1:2Nu1KKQQ2ayonKp4MPo6pXCjqw1ULc9iohRqWV5EYqg=
+github.com/ipfs/go-log/v2 v2.6.0/go.mod h1:p+Efr3qaY5YXpx9TX7MoLCSEZX5boSWj9wh86P5HJa8=
github.com/ipfs/go-merkledag v0.11.0 h1:DgzwK5hprESOzS4O1t/wi6JDpyVQdvm9Bs59N/jqfBY=
github.com/ipfs/go-merkledag v0.11.0/go.mod h1:Q4f/1ezvBiJV0YCIXvt51W/9/kqJGH4I1LsA7+djsM4=
-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-peertaskqueue v0.8.1 h1:YhxAs1+wxb5jk7RvS0LHdyiILpNmRIRnZVztekOF0pg=
-github.com/ipfs/go-peertaskqueue v0.8.1/go.mod h1:Oxxd3eaK279FxeydSPPVGHzbwVeHjatZ2GA8XD+KbPU=
-github.com/ipfs/go-unixfs v0.4.5 h1:wj8JhxvV1G6CD7swACwSKYa+NgtdWC1RUit+gFnymDU=
-github.com/ipfs/go-unixfsnode v1.9.0 h1:ubEhQhr22sPAKO2DNsyVBW7YB/zA8Zkif25aBvz8rc8=
-github.com/ipfs/go-unixfsnode v1.9.0/go.mod h1:HxRu9HYHOjK6HUqFBAi++7DVoWAHn0o4v/nZ/VA+0g8=
-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/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.13.1 h1:KnlrKvEPEzr5IZHKTXLAEub+tPrzeAFQVRlSQvuxBO4=
-github.com/ipld/go-car/v2 v2.13.1/go.mod h1:QkdjjFNGit2GIkpQ953KBwowuoukoM75nP/JI1iDJdo=
-github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc=
-github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s=
+github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6q/JR9V40TU=
+github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY=
+github.com/ipfs/go-metrics-prometheus v0.1.0 h1:bApWOHkrH3VTBHzTHrZSfq4n4weOZDzZFxUXv+HyKcA=
+github.com/ipfs/go-metrics-prometheus v0.1.0/go.mod h1:2GtL525C/4yxtvSXpRJ4dnE45mCX9AS0XRa03vHx7G0=
+github.com/ipfs/go-peertaskqueue v0.8.2 h1:PaHFRaVFdxQk1Qo3OKiHPYjmmusQy7gKQUaL8JDszAU=
+github.com/ipfs/go-peertaskqueue v0.8.2/go.mod h1:L6QPvou0346c2qPJNiJa6BvOibxDfaiPlqHInmzg0FA=
+github.com/ipfs/go-test v0.2.2 h1:1yjYyfbdt1w93lVzde6JZ2einh3DIV40at4rVoyEcE8=
+github.com/ipfs/go-test v0.2.2/go.mod h1:cmLisgVwkdRCnKu/CFZOk2DdhOcwghr5GsHeqwexoRA=
+github.com/ipfs/go-unixfsnode v1.10.1 h1:hGKhzuH6NSzZ4y621wGuDspkjXRNG3B+HqhlyTjSwSM=
+github.com/ipfs/go-unixfsnode v1.10.1/go.mod h1:eguv/otvacjmfSbYvmamc9ssNAzLvRk0+YN30EYeOOY=
+github.com/ipfs/go-verifcid v0.0.3 h1:gmRKccqhWDocCRkC+a59g5QW7uJw5bpX9HWBevXa0zs=
+github.com/ipfs/go-verifcid v0.0.3/go.mod h1:gcCtGniVzelKrbk9ooUSX/pM3xlH73fZZJDzQJRvOUw=
+github.com/ipld/go-car v0.6.2 h1:Hlnl3Awgnq8icK+ze3iRghk805lu8YNq3wlREDTF2qc=
+github.com/ipld/go-car v0.6.2/go.mod h1:oEGXdwp6bmxJCZ+rARSkDliTeYnVzv3++eXajZ+Bmr8=
+github.com/ipld/go-car/v2 v2.14.3 h1:1Mhl82/ny8MVP+w1M4LXbj4j99oK3gnuZG2GmG1IhC8=
+github.com/ipld/go-car/v2 v2.14.3/go.mod h1:/vpSvPngOX8UnvmdFJ3o/mDgXa9LuyXsn7wxOzHDYQE=
+github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0=
+github.com/ipld/go-codec-dagpb v1.7.0/go.mod h1:rD3Zg+zub9ZnxcLwfol/OTQRVjaLzXypgy4UqHQvilM=
github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8=
-github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0=
github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E=
github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ=
github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd h1:gMlw/MhNr2Wtp5RwGdsW23cs+yCuj9k2ON7i9MiJlRo=
+github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd/go.mod h1:wZ8hH8UxeryOs4kJEJaiui/s00hDSbE37OKsL47g+Sw=
+github.com/ipshipyard/p2p-forge v0.5.1 h1:9MCpAlk+wNhy7W/yOYKgi9KlXPnyb0abmDpsRPHUDxQ=
+github.com/ipshipyard/p2p-forge v0.5.1/go.mod h1:GNDXM2CR8KRS8mJGw7ARIRVlrG9NH8MdewgNVfIIByA=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-cienv v0.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.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk=
github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY=
@@ -462,41 +507,44 @@ 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.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
-github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
+github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
+github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
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.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
-github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
+github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
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.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
-github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
+github.com/koron/go-ssdp v0.0.5 h1:E1iSMxIs4WqxTbIBLtmNBeOOC+1sCIXQeqTWVnpmwhk=
+github.com/koron/go-ssdp v0.0.5/go.mod h1:Qm59B7hpKpDqfyRNWRNr00jGwLdXjDyZh6y7rH6VS0w=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
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/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
+github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
+github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
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-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-doh-resolver v0.5.0 h1:4h7plVVW+XTS+oUBw2+8KfoM1jF6w8XmO7+skhePFdE=
+github.com/libp2p/go-doh-resolver v0.5.0/go.mod h1:aPDxfiD2hNURgd13+hfo29z9IC22fv30ee5iM31RzxU=
github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8=
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.32.2 h1:s8GYN4YJzgUoyeYNPdW7JZeZ5Ee31iNaIBfGYMAY4FQ=
-github.com/libp2p/go-libp2p v0.32.2/go.mod h1:E0LKe+diV/ZVJVnOJby8VC5xzHF0660osg71skcxJvk=
+github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw=
+github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc=
+github.com/libp2p/go-libp2p v0.41.1 h1:8ecNQVT5ev/jqALTvisSJeVNvXYJyK4NhQx1nNRXQZE=
+github.com/libp2p/go-libp2p v0.41.1/go.mod h1:DcGTovJzQl/I7HMrby5ZRjeD0kQkGiy+9w6aEkSZpRI=
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g=
@@ -505,20 +553,20 @@ github.com/libp2p/go-libp2p-gostream v0.6.0 h1:QfAiWeQRce6pqnYfmIVWJFXNdDyfiR/qk
github.com/libp2p/go-libp2p-gostream v0.6.0/go.mod h1:Nywu0gYZwfj7Jc91PQvbGU8dIpqbQQkjWgDuOrFaRdA=
github.com/libp2p/go-libp2p-http v0.5.0 h1:+x0AbLaUuLBArHubbbNRTsgWz0RjNTy6DJLOxQ3/QBc=
github.com/libp2p/go-libp2p-http v0.5.0/go.mod h1:glh87nZ35XCQyFsdzZps6+F4HYI6DctVFY5u1fehwSg=
-github.com/libp2p/go-libp2p-kad-dht v0.24.4 h1:ktNiJe7ffsJ1wX3ULpMCwXts99mPqGFSE/Qn1i8pErQ=
-github.com/libp2p/go-libp2p-kad-dht v0.24.4/go.mod h1:ybWBJ5Fbvz9sSLkNtXt+2+bK0JB8+tRPvhBbRGHegRU=
+github.com/libp2p/go-libp2p-kad-dht v0.33.1 h1:hKFhHMf7WH69LDjaxsJUWOU6qZm71uO47M/a5ijkiP0=
+github.com/libp2p/go-libp2p-kad-dht v0.33.1/go.mod h1:CdmNk4VeGJa9EXM9SLNyNVySEvduKvb+5rSC/H4pLAo=
github.com/libp2p/go-libp2p-kbucket v0.3.1/go.mod h1:oyjT5O7tS9CQurok++ERgc46YLwEpuGoFq9ubvoUOio=
-github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0=
-github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEHetYSPXOaJnOiD8i0=
+github.com/libp2p/go-libp2p-kbucket v0.7.0 h1:vYDvRjkyJPeWunQXqcW2Z6E93Ywx7fX0jgzb/dGOKCs=
+github.com/libp2p/go-libp2p-kbucket v0.7.0/go.mod h1:blOINGIj1yiPYlVEX0Rj9QwEkmVnz3EP8LK1dRKBC6g=
github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs=
-github.com/libp2p/go-libp2p-pubsub v0.10.0 h1:wS0S5FlISavMaAbxyQn3dxMOe2eegMfswM471RuHJwA=
-github.com/libp2p/go-libp2p-pubsub v0.10.0/go.mod h1:1OxbaT/pFRO5h+Dpze8hdHQ63R0ke55XTs6b6NwLLkw=
+github.com/libp2p/go-libp2p-pubsub v0.13.1 h1:tV3ttzzZSCk0EtEXnxVmWIXgjVxXx+20Jwjbs/Ctzjo=
+github.com/libp2p/go-libp2p-pubsub v0.13.1/go.mod h1:MKPU5vMI8RRFyTP0HfdsF9cLmL1nHAeJm44AxJGJx44=
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-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.7.3 h1:u1LGzAMVRK9Nqq5aYDVOiq/HaB93U9WWczBzGyAC5ZY=
-github.com/libp2p/go-libp2p-routing-helpers v0.7.3/go.mod h1:cN4mJAD/7zfPKXBcs9ze31JGYAZgzdABEm+q/hkswb8=
+github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg=
+github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.5 h1:HdwZj9NKovMx0vqq6YNPTh6aaNzey5zHD7HeLJtq6fI=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.5/go.mod h1:3YaxrwP0OBPDD7my3D0KxfR89FlcX/IEbxDEDfAmj98=
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-xor v0.1.0 h1:hhQwT4uGrBcuAkUGXADuPltalOdpf9aag9kaYNT2tLA=
@@ -526,18 +574,16 @@ github.com/libp2p/go-libp2p-xor v0.1.0/go.mod h1:LSTM5yRnjGZbWNTA/hRwq2gGFrvRIbQ
github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
-github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk=
-github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk=
-github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU=
-github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
+github.com/libp2p/go-netroute v0.2.2 h1:Dejd8cQ47Qx2kRABg6lPwknU7+nBnFRpko45/fFPuZ8=
+github.com/libp2p/go-netroute v0.2.2/go.mod h1:Rntq6jUAH0l9Gg17w5bFGhcC9a+vk4KNXs6s7IljKYE=
github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
-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-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ=
-github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4=
+github.com/libp2p/go-socket-activation v0.1.1 h1:wkLBj6RqKffjt7BI794ewoSt241UV52NKYvIbpzhn4Q=
+github.com/libp2p/go-socket-activation v0.1.1/go.mod h1:NBfVUPXTRL/FU6UmSOM+1O7/vJkpS523sQiriw0Qln8=
+github.com/libp2p/go-yamux/v5 v5.0.0 h1:2djUh96d3Jiac/JpGkKs4TO49YhsfLopAoryfPmf+Po=
+github.com/libp2p/go-yamux/v5 v5.0.0/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU=
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/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
@@ -549,27 +595,27 @@ github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs
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.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
-github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
-github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
+github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
+github.com/mholt/acmez/v3 v3.0.0 h1:r1NcjuWR0VaKP2BTjDK9LRFBw/WvURx3jlaEUl9Ht8E=
+github.com/mholt/acmez/v3 v3.0.0/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
-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.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
-github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
+github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE=
+github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
@@ -583,7 +629,6 @@ github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
-github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -605,12 +650,10 @@ github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a
github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
-github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc=
-github.com/multiformats/go-multiaddr v0.12.2 h1:9G9sTY/wCYajKa9lyfWPmpZAwe6oV+Wb1zcmMS1HG24=
-github.com/multiformats/go-multiaddr v0.12.2/go.mod h1:GKyaTYjZRdcUhyOetrxTk9z0cW+jA/YrnqTOvKgi44M=
-github.com/multiformats/go-multiaddr-dns v0.3.0/go.mod h1:mNzQ4eTGDg0ll1N9jKPOUogZPoJ30W8a7zk66FQPpdQ=
-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 v0.15.0 h1:zB/HeaI/apcZiTDwhY5YqMvNVl/oQYvs3XySU+qeAVo=
+github.com/multiformats/go-multiaddr v0.15.0/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0=
+github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M=
+github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
github.com/multiformats/go-multiaddr-net v0.1.1/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ=
@@ -618,7 +661,6 @@ 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.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
-github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ=
github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg=
github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k=
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
@@ -627,160 +669,169 @@ github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpK
github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg=
-github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84=
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
-github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE=
-github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA=
+github.com/multiformats/go-multistream v0.6.0 h1:ZaHKbsL404720283o4c/IHQXiS6gb8qAN5EIJ4PN5EA=
+github.com/multiformats/go-multistream v0.6.0/go.mod h1:MOyoG5otO24cHIg8kf9QW2/NozURlkP/rvi2FQJyCPg=
github.com/multiformats/go-varint v0.0.1/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/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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
-github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
+github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
+github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.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.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.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs=
-github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
+github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
+github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
+github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
-github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
+github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
+github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
+github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
-github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
+github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
-github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
-github.com/openzipkin/zipkin-go v0.4.2 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA=
-github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY=
+github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg=
+github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
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/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8=
-github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0=
-github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8=
+github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
+github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
+github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o=
+github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
-github.com/pion/ice/v2 v2.3.6 h1:Jgqw36cAud47iD+N6rNX225uHvrgWtAlHfVyOQc3Heg=
-github.com/pion/ice/v2 v2.3.6/go.mod h1:9/TzKDRwBVAPsC+YOrKH/e3xDrubeTRACU9/sHQarsU=
-github.com/pion/interceptor v0.1.17 h1:prJtgwFh/gB8zMqGZoOgJPHivOwVAp61i2aG61Du/1w=
-github.com/pion/interceptor v0.1.17/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI=
-github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
+github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk=
+github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE=
+github.com/pion/dtls/v3 v3.0.4 h1:44CZekewMzfrn9pmGrj5BNnTMDCFwr+6sLH+cCuLM7U=
+github.com/pion/dtls/v3 v3.0.4/go.mod h1:R373CsjxWqNPf6MEkfdy3aSe9niZvL/JaKlGeFphtMg=
+github.com/pion/ice/v4 v4.0.8 h1:ajNx0idNG+S+v9Phu4LSn2cs8JEfTsA1/tEjkkAVpFY=
+github.com/pion/ice/v4 v4.0.8/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
+github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
+github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
-github.com/pion/mdns v0.0.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U=
-github.com/pion/mdns v0.0.7/go.mod h1:4iP2UbeFhLI/vWju/bw6ZfwjJzk0z8DNValjGxR/dD8=
+github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
+github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90=
+github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM=
+github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
-github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc=
-github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I=
-github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA=
-github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
-github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0=
-github.com/pion/sctp v1.8.7 h1:JnABvFakZueGAn4KU/4PSKg+GWbF6QWbKTWZOSGJjXw=
-github.com/pion/sctp v1.8.7/go.mod h1:g1Ul+ARqZq5JEmoFy87Q/4CePtKnTJ1QCL9dBBdN6AU=
-github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw=
-github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw=
-github.com/pion/srtp/v2 v2.0.15 h1:+tqRtXGsGwHC0G0IUIAzRmdkHvriF79IHVfZGfHrQoA=
-github.com/pion/srtp/v2 v2.0.15/go.mod h1:b/pQOlDrbB0HEH5EUAQXzSYxikFbNcNuKmF8tM0hCtw=
-github.com/pion/stun v0.4.0/go.mod h1:QPsh1/SbXASntw3zkkrIk3ZJVKz4saBY2G7S10P3wCw=
-github.com/pion/stun v0.6.0 h1:JHT/2iyGDPrFWE8NNC15wnddBN8KifsEDw8swQmrEmU=
-github.com/pion/stun v0.6.0/go.mod h1:HPqcfoeqQn9cuaet7AOmB5e5xkObu9DwBdurwLKO9oA=
-github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40=
-github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI=
-github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc=
-github.com/pion/transport/v2 v2.1.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ=
-github.com/pion/transport/v2 v2.2.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ=
-github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c=
+github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
+github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
+github.com/pion/rtp v1.8.11 h1:17xjnY5WO5hgO6SD3/NTIUPvSFw/PbLsIJyz1r1yNIk=
+github.com/pion/rtp v1.8.11/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
+github.com/pion/sctp v1.8.37 h1:ZDmGPtRPX9mKCiVXtMbTWybFw3z/hVKAZgU81wcOrqs=
+github.com/pion/sctp v1.8.37/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
+github.com/pion/sdp/v3 v3.0.10 h1:6MChLE/1xYB+CjumMw+gZ9ufp2DPApuVSnDT8t5MIgA=
+github.com/pion/sdp/v3 v3.0.10/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
+github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
+github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ=
+github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
+github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
+github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
+github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
-github.com/pion/turn/v2 v2.1.0 h1:5wGHSgGhJhP/RpabkUb/T9PdsAjkGLS6toYz5HNzoSI=
-github.com/pion/turn/v2 v2.1.0/go.mod h1:yrT5XbXSGX1VFSF31A3c1kCNB5bBZgk/uu5LET162qs=
-github.com/pion/webrtc/v3 v3.2.9 h1:U8NSjQDlZZ+Iy/hg42Q/u6mhEVSXYvKrOIZiZwYTfLc=
-github.com/pion/webrtc/v3 v3.2.9/go.mod h1:gjQLMZeyN3jXBGdxGmUYCyKjOuYX/c99BDjGqmadq0A=
+github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
+github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
+github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
+github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
+github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
+github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
+github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
+github.com/pion/webrtc/v4 v4.0.10 h1:Hq/JLjhqLxi+NmCtE8lnRPDr8H4LcNvwg8OxVcdv56Q=
+github.com/pion/webrtc/v4 v4.0.10/go.mod h1:ViHLVaNpiuvaH8pdiuQxuA9awuE6KVzAXx3vVWilOck=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
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/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
-github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
-github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
+github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
+github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
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=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
-github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
+github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
+github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
-github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
-github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
-github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
+github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
+github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/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/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
-github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
-github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
-github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0=
+github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
+github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI=
-github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
-github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
-github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
-github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
-github.com/quic-go/quic-go v0.40.1 h1:X3AGzUNFs0jVuO3esAGnTfvdgvL4fq655WaOi1snv1Q=
-github.com/quic-go/quic-go v0.40.1/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c=
-github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY=
-github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc=
+github.com/prometheus/statsd_exporter v0.27.1 h1:tcRJOmwlA83HPfWzosAgr2+zEN5XDFv+M2mn/uYkn5Y=
+github.com/prometheus/statsd_exporter v0.27.1/go.mod h1:vA6ryDfsN7py/3JApEst6nLTJboq66XsNcJGNmC88NQ=
+github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
+github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
+github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q=
+github.com/quic-go/quic-go v0.50.1/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E=
+github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 h1:4WFk6u3sOT6pLa1kQ50ZVdm8BQFgJNA117cepZxtLIg=
+github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66/go.mod h1:Vp72IJajgeOL6ddqrAhmp7IM9zbTcgkQxD/YdxrVwMw=
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
+github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
-github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
-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/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
+github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
+github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
+github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
+github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
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=
-github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
-github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
-github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
+github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
+github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
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=
@@ -809,6 +860,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/slok/go-http-metrics v0.13.0 h1:lQDyJJx9wKhmbliyUsZ2l6peGnXRHjsjoqPt5VYzcP8=
+github.com/slok/go-http-metrics v0.13.0/go.mod h1:HIr7t/HbN2sJaunvnt9wKP9xoBBVZFo1/KiHU3b0w+4=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
@@ -832,38 +885,40 @@ 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 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.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.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
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/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs=
+github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
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=
+github.com/texttheater/golang-levenshtein v1.0.1 h1:+cRNoVrfiwufQPhoMzB6N0Yf/Mqajr6t1lOv8GyGE2U=
+github.com/texttheater/golang-levenshtein v1.0.1/go.mod h1:PYAKrbF5sAiq9wd+H82hs7gNaen0CplQ9uvm6+enD/8=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
-github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
-github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
+github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
-github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
+github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
-github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk=
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ=
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb h1:Ywfo8sUltxogBpFuMOFRrrSifO788kAFxmvVw31PtQQ=
@@ -874,9 +929,8 @@ github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60Nt
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE=
-github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
-github.com/warpfork/go-testmark v0.9.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s=
+github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y=
github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
@@ -884,8 +938,8 @@ github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboa
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-20240109153615-66e95c3e8a87 h1:S4wCk+ZL4WGGaI+GsmqCRyt68ISbnZWsK9dD9jYL0fA=
-github.com/whyrusleeping/cbor-gen v0.0.0-20240109153615-66e95c3e8a87/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
+github.com/whyrusleeping/cbor-gen v0.1.2 h1:WQFlrPhpcQl+M2/3dP5cvlTLWPVsL6LGBb9jJt6l/cA=
+github.com/whyrusleeping/cbor-gen v0.1.2/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so=
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=
@@ -895,14 +949,22 @@ github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1 h1:ctS9An
github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1/go.mod h1:tKH72zYNt/exx6/5IQO6L9LoQ0rEjd5SbbWaDTs9Zso=
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/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
+github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
+github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
+github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
+github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
+github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE=
+github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
+github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@@ -913,8 +975,10 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
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.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo=
+go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
+go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM=
go.opentelemetry.io/contrib/propagators/autoprop v0.46.1 h1:cXTYcMjY0dsYokAuo8LbNBQxpF8VgTHdiHJJ1zlIXl4=
go.opentelemetry.io/contrib/propagators/autoprop v0.46.1/go.mod h1:WZxgny1/6+j67B1s72PLJ4bGjidoWFzSmLNfJKVt2bo=
go.opentelemetry.io/contrib/propagators/aws v1.21.1 h1:uQIQIDWb0gzyvon2ICnghpLAf9w7ADOCUiIiwCQgR2o=
@@ -925,53 +989,49 @@ go.opentelemetry.io/contrib/propagators/jaeger v1.21.1 h1:f4beMGDKiVzg9IcX7/VuWV
go.opentelemetry.io/contrib/propagators/jaeger v1.21.1/go.mod h1:U9jhkEl8d1LL+QXY7q3kneJWJugiN3kZJV2OWz3hkBY=
go.opentelemetry.io/contrib/propagators/ot v1.21.1 h1:3TN5vkXjKYWp0YdMcnUEC/A+pBPvqz9V3nCS2xmcurk=
go.opentelemetry.io/contrib/propagators/ot v1.21.1/go.mod h1:oy0MYCbS/b3cqUDW37wBWtlwBIsutngS++Lklpgh+fc=
-go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y=
-go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I=
-go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0 h1:VhlEQAPp9R1ktYfrPk5SOryw1e9LDDTZCbIPFrho0ec=
-go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0/go.mod h1:kB3ufRbfU+CQ4MlUcqtW8Z7YEOBeK2DJ6CmR5rYYF3E=
-go.opentelemetry.io/otel/exporters/zipkin v1.21.0 h1:D+Gv6lSfrFBWmQYyxKjDd0Zuld9SRXpIrEsKZvE4DO4=
-go.opentelemetry.io/otel/exporters/zipkin v1.21.0/go.mod h1:83oMKR6DzmHisFOW3I+yIMGZUTjxiWaiBI8M8+TU5zE=
-go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg=
-go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
-go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
-go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
-go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0=
-go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
-go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
-go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
-go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
+go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4=
+go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 h1:UGZ1QwZWY67Z6BmckTU+9Rxn04m2bD3gD6Mk0OIOCPk=
+go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0/go.mod h1:fcwWuDuaObkkChiDlhEpSq9+X1C0omv+s5mBtToAQ64=
+go.opentelemetry.io/otel/exporters/zipkin v1.31.0 h1:CgucL0tj3717DJnni7HVVB2wExzi8c2zJNEA2BhLMvI=
+go.opentelemetry.io/otel/exporters/zipkin v1.31.0/go.mod h1:rfzOVNiSwIcWtEC2J8epwG26fiaXlYvLySJ7bwsrtAE=
+go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
+go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
+go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk=
+go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0=
+go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
+go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
+go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
+go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
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.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
-go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc=
-go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
-go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk=
-go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg=
-go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
+go.uber.org/dig v1.18.0 h1:imUL1UiY0Mg4bqbFfsRQO5G4CGRBec/ZujWTvSVp3pw=
+go.uber.org/dig v1.18.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
+go.uber.org/fx v1.23.0 h1:lIr/gYWQGfTwGcSXWXu4vP5Ws6iqnNEIY+F/aFzCKTg=
+go.uber.org/fx v1.23.0/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
-go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
-go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
-go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
+go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
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.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
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.14.1/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.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
-go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
+go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
-go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg=
go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc=
go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
@@ -992,9 +1052,10 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
-golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
-golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
+golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
+golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
+golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
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=
@@ -1005,8 +1066,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-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
-golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
+golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
+golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
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=
@@ -1028,18 +1089,16 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
-golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
+golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1067,28 +1126,26 @@ 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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-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-20220607020251-c690dde0001d/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.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
-golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
+golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
+golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
+golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
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=
@@ -1098,8 +1155,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
-golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
+golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
+golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1115,8 +1172,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
-golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
+golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1147,7 +1204,6 @@ golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1159,52 +1215,47 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-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-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-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-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.4.0/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-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
+golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
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/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
+golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
+golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
+golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
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=
@@ -1212,18 +1263,18 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.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.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
-golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
+golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
+golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1275,19 +1326,19 @@ 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.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
-golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
+golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
+golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
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-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
-golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
-gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
-gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
+golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
+golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
+golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
+gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
+gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
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=
@@ -1315,8 +1366,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
-google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
@@ -1350,11 +1399,10 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg=
-google.golang.org/genproto/googleapis/api v0.0.0-20240108191215-35c7eff3a6b1 h1:OPXtXn7fNMaXwO3JvOmF1QyTc00jsSFFz1vXXBOdCDo=
-google.golang.org/genproto/googleapis/api v0.0.0-20240108191215-35c7eff3a6b1/go.mod h1:B5xPO//w8qmBDjGReYLpR6UJPnkldGkCSMoH/2vxJeg=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 h1:gphdwh0npgs8elJ4T6J+DQJHPVF7RsuJHCfwztUb4J4=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA=
+google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg=
+google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 h1:QCqS/PdaHTSWGvupk2F/ehwHtGc0/GYkT+3GAcR1CCc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
@@ -1371,8 +1419,8 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
-google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
+google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
+google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
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=
@@ -1387,8 +1435,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
-google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
+google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -1398,8 +1446,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
-gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
-gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8=
gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
@@ -1408,12 +1454,10 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
@@ -1425,11 +1469,10 @@ 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=
-lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
-lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
-lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
-pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g=
-pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
+lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
+lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=
+pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw=
+pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/misc/fsutil/fsutil.go b/misc/fsutil/fsutil.go
new file mode 100644
index 00000000000..6773ec12fa5
--- /dev/null
+++ b/misc/fsutil/fsutil.go
@@ -0,0 +1,82 @@
+package fsutil
+
+import (
+ "errors"
+ "fmt"
+ "io/fs"
+ "os"
+ "path/filepath"
+)
+
+// DirWritable checks if a directory is writable. If the directory does
+// not exist it is created with writable permission.
+func DirWritable(dir string) error {
+ if dir == "" {
+ return errors.New("directory not specified")
+ }
+
+ var err error
+ dir, err = ExpandHome(dir)
+ if err != nil {
+ return err
+ }
+
+ fi, err := os.Stat(dir)
+ if err != nil {
+ if errors.Is(err, fs.ErrNotExist) {
+ // Directory does not exist, so create it.
+ err = os.Mkdir(dir, 0775)
+ if err == nil {
+ return nil
+ }
+ }
+ if errors.Is(err, fs.ErrPermission) {
+ err = fs.ErrPermission
+ }
+ return fmt.Errorf("directory not writable: %s: %w", dir, err)
+ }
+ if !fi.IsDir() {
+ return fmt.Errorf("not a directory: %s", dir)
+ }
+
+ // Directory exists, check that a file can be written.
+ file, err := os.CreateTemp(dir, "writetest")
+ if err != nil {
+ if errors.Is(err, fs.ErrPermission) {
+ err = fs.ErrPermission
+ }
+ return fmt.Errorf("directory not writable: %s: %w", dir, err)
+ }
+ file.Close()
+ return os.Remove(file.Name())
+}
+
+// ExpandHome expands the path to include the home directory if the path is
+// prefixed with `~`. If it isn't prefixed with `~`, the path is returned
+// as-is.
+func ExpandHome(path string) (string, error) {
+ if path == "" {
+ return path, nil
+ }
+
+ if path[0] != '~' {
+ return path, nil
+ }
+
+ if len(path) > 1 && path[1] != '/' && path[1] != '\\' {
+ return "", errors.New("cannot expand user-specific home dir")
+ }
+
+ dir, err := os.UserHomeDir()
+ if err != nil {
+ return "", err
+ }
+
+ return filepath.Join(dir, path[1:]), nil
+}
+
+// FileExists return true if the file exists
+func FileExists(filename string) bool {
+ _, err := os.Lstat(filename)
+ return !errors.Is(err, os.ErrNotExist)
+}
diff --git a/misc/fsutil/fsutil_test.go b/misc/fsutil/fsutil_test.go
new file mode 100644
index 00000000000..72834ac10ed
--- /dev/null
+++ b/misc/fsutil/fsutil_test.go
@@ -0,0 +1,92 @@
+package fsutil_test
+
+import (
+ "io/fs"
+ "os"
+ "path/filepath"
+ "runtime"
+ "testing"
+
+ "github.com/ipfs/kubo/misc/fsutil"
+ "github.com/stretchr/testify/require"
+)
+
+func TestDirWritable(t *testing.T) {
+ err := fsutil.DirWritable("")
+ require.Error(t, err)
+
+ err = fsutil.DirWritable("~nosuchuser/tmp")
+ require.Error(t, err)
+
+ tmpDir := t.TempDir()
+
+ wrDir := filepath.Join(tmpDir, "readwrite")
+ err = fsutil.DirWritable(wrDir)
+ require.NoError(t, err)
+
+ // Check that DirWritable created directory.
+ fi, err := os.Stat(wrDir)
+ require.NoError(t, err)
+ require.True(t, fi.IsDir())
+
+ err = fsutil.DirWritable(wrDir)
+ require.NoError(t, err)
+
+ // If running on Windows, skip read-only directory tests.
+ if runtime.GOOS == "windows" {
+ t.SkipNow()
+ }
+
+ roDir := filepath.Join(tmpDir, "readonly")
+ require.NoError(t, os.Mkdir(roDir, 0500))
+ err = fsutil.DirWritable(roDir)
+ require.ErrorIs(t, err, fs.ErrPermission)
+
+ roChild := filepath.Join(roDir, "child")
+ err = fsutil.DirWritable(roChild)
+ require.ErrorIs(t, err, fs.ErrPermission)
+}
+
+func TestFileExists(t *testing.T) {
+ fileName := filepath.Join(t.TempDir(), "somefile")
+ require.False(t, fsutil.FileExists(fileName))
+
+ file, err := os.Create(fileName)
+ require.NoError(t, err)
+ file.Close()
+
+ require.True(t, fsutil.FileExists(fileName))
+}
+
+func TestExpandHome(t *testing.T) {
+ dir, err := fsutil.ExpandHome("")
+ require.NoError(t, err)
+ require.Equal(t, "", dir)
+
+ origDir := filepath.Join("somedir", "somesub")
+ dir, err = fsutil.ExpandHome(origDir)
+ require.NoError(t, err)
+ require.Equal(t, origDir, dir)
+
+ _, err = fsutil.ExpandHome(filepath.FromSlash("~nosuchuser/somedir"))
+ require.Error(t, err)
+
+ homeEnv := "HOME"
+ if runtime.GOOS == "windows" {
+ homeEnv = "USERPROFILE"
+ }
+ origHome := os.Getenv(homeEnv)
+ defer os.Setenv(homeEnv, origHome)
+ homeDir := filepath.Join(t.TempDir(), "testhome")
+ os.Setenv(homeEnv, homeDir)
+
+ const subDir = "mytmp"
+ origDir = filepath.Join("~", subDir)
+ dir, err = fsutil.ExpandHome(origDir)
+ require.NoError(t, err)
+ require.Equal(t, filepath.Join(homeDir, subDir), dir)
+
+ os.Unsetenv(homeEnv)
+ _, err = fsutil.ExpandHome(origDir)
+ require.Error(t, err)
+}
diff --git a/p2p/p2p.go b/p2p/p2p.go
index 1d098942145..1d14dfb80be 100644
--- a/p2p/p2p.go
+++ b/p2p/p2p.go
@@ -1,7 +1,7 @@
package p2p
import (
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
p2phost "github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/peer"
pstore "github.com/libp2p/go-libp2p/core/peerstore"
diff --git a/plugin/loader/loader.go b/plugin/loader/loader.go
index 80cc9a1b635..62490761437 100644
--- a/plugin/loader/loader.go
+++ b/plugin/loader/loader.go
@@ -2,6 +2,7 @@ package loader
import (
"encoding/json"
+ "errors"
"fmt"
"io"
"os"
@@ -17,7 +18,7 @@ import (
plugin "github.com/ipfs/kubo/plugin"
fsrepo "github.com/ipfs/kubo/repo/fsrepo"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
opentracing "github.com/opentracing/opentracing-go"
)
@@ -361,7 +362,7 @@ func (loader *PluginLoader) Close() error {
}
if errs != nil {
loader.state = loaderFailed
- return fmt.Errorf(strings.Join(errs, "\n"))
+ return errors.New(strings.Join(errs, "\n"))
}
loader.state = loaderClosed
return nil
diff --git a/plugin/loader/preload.go b/plugin/loader/preload.go
index 2ad84e59489..75e21270c92 100644
--- a/plugin/loader/preload.go
+++ b/plugin/loader/preload.go
@@ -8,6 +8,7 @@ import (
pluginipldgit "github.com/ipfs/kubo/plugin/plugins/git"
pluginlevelds "github.com/ipfs/kubo/plugin/plugins/levelds"
pluginnopfs "github.com/ipfs/kubo/plugin/plugins/nopfs"
+ pluginpebbleds "github.com/ipfs/kubo/plugin/plugins/pebbleds"
pluginpeerlog "github.com/ipfs/kubo/plugin/plugins/peerlog"
)
@@ -21,6 +22,7 @@ func init() {
Preload(pluginbadgerds.Plugins...)
Preload(pluginflatfs.Plugins...)
Preload(pluginlevelds.Plugins...)
+ Preload(pluginpebbleds.Plugins...)
Preload(pluginpeerlog.Plugins...)
Preload(pluginfxtest.Plugins...)
Preload(pluginnopfs.Plugins...)
diff --git a/plugin/loader/preload_list b/plugin/loader/preload_list
index 462a3f39337..190cc65d716 100644
--- a/plugin/loader/preload_list
+++ b/plugin/loader/preload_list
@@ -9,6 +9,7 @@ iplddagjose github.com/ipfs/kubo/plugin/plugins/dagjose *
badgerds github.com/ipfs/kubo/plugin/plugins/badgerds *
flatfs github.com/ipfs/kubo/plugin/plugins/flatfs *
levelds github.com/ipfs/kubo/plugin/plugins/levelds *
+pebbleds github.com/ipfs/kubo/plugin/plugins/pebbleds *
peerlog github.com/ipfs/kubo/plugin/plugins/peerlog *
fxtest github.com/ipfs/kubo/plugin/plugins/fxtest *
-nopfs github.com/ipfs/kubo/plugin/plugins/nopfs *
\ No newline at end of file
+nopfs github.com/ipfs/kubo/plugin/plugins/nopfs *
diff --git a/plugin/plugins/badgerds/badgerds.go b/plugin/plugins/badgerds/badgerds.go
index 5f5781f8fc3..2410f196c60 100644
--- a/plugin/plugins/badgerds/badgerds.go
+++ b/plugin/plugins/badgerds/badgerds.go
@@ -108,6 +108,7 @@ func (c *datastoreConfig) DiskSpec() fsrepo.DiskSpec {
}
func (c *datastoreConfig) Create(path string) (repo.Datastore, error) {
+ fmt.Fprintln(os.Stderr, "⚠️ badgerds is based on badger 1.x, which has known bugs and is no longer supported by the upstream team. Please switch to a newer datastore such as pebbleds or flatfs.")
p := c.path
if !filepath.IsAbs(p) {
p = filepath.Join(path, p)
diff --git a/plugin/plugins/flatfs/flatfs.go b/plugin/plugins/flatfs/flatfs.go
index 1a23dfcca9d..397c2656c76 100644
--- a/plugin/plugins/flatfs/flatfs.go
+++ b/plugin/plugins/flatfs/flatfs.go
@@ -42,7 +42,7 @@ type datastoreConfig struct {
syncField bool
}
-// BadgerdsDatastoreConfig returns a configuration stub for a badger datastore
+// BadgerdsDatastoreConfig returns a configuration stub for a flatfs datastore
// from the given parameters.
func (*flatfsPlugin) DatastoreConfigParser() fsrepo.ConfigFromMap {
return func(params map[string]interface{}) (fsrepo.DatastoreConfig, error) {
diff --git a/plugin/plugins/fxtest/fxtest.go b/plugin/plugins/fxtest/fxtest.go
index 175dc6ec62b..4205e3eb829 100644
--- a/plugin/plugins/fxtest/fxtest.go
+++ b/plugin/plugins/fxtest/fxtest.go
@@ -3,7 +3,7 @@ package fxtest
import (
"os"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
"github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/plugin"
"go.uber.org/fx"
diff --git a/plugin/plugins/levelds/levelds.go b/plugin/plugins/levelds/levelds.go
index b08872de63d..78331730ed3 100644
--- a/plugin/plugins/levelds/levelds.go
+++ b/plugin/plugins/levelds/levelds.go
@@ -42,7 +42,7 @@ type datastoreConfig struct {
compression ldbopts.Compression
}
-// BadgerdsDatastoreConfig returns a configuration stub for a badger datastore
+// DatastoreConfigParser returns a configuration stub for a badger datastore
// from the given parameters.
func (*leveldsPlugin) DatastoreConfigParser() fsrepo.ConfigFromMap {
return func(params map[string]interface{}) (fsrepo.DatastoreConfig, error) {
diff --git a/plugin/plugins/nopfs/nopfs.go b/plugin/plugins/nopfs/nopfs.go
index 64350830f94..c32d7533f55 100644
--- a/plugin/plugins/nopfs/nopfs.go
+++ b/plugin/plugins/nopfs/nopfs.go
@@ -6,7 +6,6 @@ import (
"github.com/ipfs-shipyard/nopfs"
"github.com/ipfs-shipyard/nopfs/ipfs"
- "github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/core/node"
"github.com/ipfs/kubo/plugin"
@@ -20,7 +19,10 @@ var Plugins = []plugin.Plugin{
// fxtestPlugin is used for testing the fx plugin.
// It merely adds an fx option that logs a debug statement, so we can verify that it works in tests.
-type nopfsPlugin struct{}
+type nopfsPlugin struct {
+ // Path to the IPFS repo.
+ repo string
+}
var _ plugin.PluginFx = (*nopfsPlugin)(nil)
@@ -33,29 +35,28 @@ func (p *nopfsPlugin) Version() string {
}
func (p *nopfsPlugin) Init(env *plugin.Environment) error {
+ p.repo = env.Repo
+
return nil
}
// MakeBlocker is a factory for the blocker so that it can be provided with Fx.
-func MakeBlocker() (*nopfs.Blocker, error) {
- ipfsPath, err := config.PathRoot()
- if err != nil {
- return nil, err
- }
+func MakeBlocker(repoPath string) func() (*nopfs.Blocker, error) {
+ return func() (*nopfs.Blocker, error) {
+ defaultFiles, err := nopfs.GetDenylistFiles()
+ if err != nil {
+ return nil, err
+ }
- defaultFiles, err := nopfs.GetDenylistFiles()
- if err != nil {
- return nil, err
- }
+ kuboFiles, err := nopfs.GetDenylistFilesInDir(filepath.Join(repoPath, "denylists"))
+ if err != nil {
+ return nil, err
+ }
- kuboFiles, err := nopfs.GetDenylistFilesInDir(filepath.Join(ipfsPath, "denylists"))
- if err != nil {
- return nil, err
- }
-
- files := append(defaultFiles, kuboFiles...)
+ files := append(defaultFiles, kuboFiles...)
- return nopfs.NewBlocker(files)
+ return nopfs.NewBlocker(files)
+ }
}
// PathResolvers returns wrapped PathResolvers for Kubo.
@@ -76,7 +77,7 @@ func (p *nopfsPlugin) Options(info core.FXNodeInfo) ([]fx.Option, error) {
opts := append(
info.FXOptions,
- fx.Provide(MakeBlocker),
+ fx.Provide(MakeBlocker(p.repo)),
fx.Decorate(ipfs.WrapBlockService),
fx.Decorate(ipfs.WrapNameSystem),
fx.Decorate(PathResolvers),
diff --git a/plugin/plugins/pebbleds/pebbleds.go b/plugin/plugins/pebbleds/pebbleds.go
new file mode 100644
index 00000000000..fab1cc16a88
--- /dev/null
+++ b/plugin/plugins/pebbleds/pebbleds.go
@@ -0,0 +1,195 @@
+package pebbleds
+
+import (
+ "fmt"
+ "path/filepath"
+ "time"
+
+ "github.com/cockroachdb/pebble/v2"
+ pebbleds "github.com/ipfs/go-ds-pebble"
+ "github.com/ipfs/kubo/misc/fsutil"
+ "github.com/ipfs/kubo/plugin"
+ "github.com/ipfs/kubo/repo"
+ "github.com/ipfs/kubo/repo/fsrepo"
+)
+
+// Plugins is exported list of plugins that will be loaded.
+var Plugins = []plugin.Plugin{
+ &pebbledsPlugin{},
+}
+
+type pebbledsPlugin struct{}
+
+var _ plugin.PluginDatastore = (*pebbledsPlugin)(nil)
+
+func (*pebbledsPlugin) Name() string {
+ return "ds-pebble"
+}
+
+func (*pebbledsPlugin) Version() string {
+ return "0.1.0"
+}
+
+func (*pebbledsPlugin) Init(_ *plugin.Environment) error {
+ return nil
+}
+
+func (*pebbledsPlugin) DatastoreTypeName() string {
+ return "pebbleds"
+}
+
+type datastoreConfig struct {
+ path string
+ cacheSize int64
+
+ // Documentation of these values: https://pkg.go.dev/github.com/cockroachdb/pebble@v1.1.2#Options
+ pebbleOpts *pebble.Options
+}
+
+// PebbleDatastoreConfig returns a configuration stub for a pebble datastore
+// from the given parameters.
+func (*pebbledsPlugin) DatastoreConfigParser() fsrepo.ConfigFromMap {
+ return func(params map[string]any) (fsrepo.DatastoreConfig, error) {
+ var c datastoreConfig
+ var ok bool
+
+ c.path, ok = params["path"].(string)
+ if !ok {
+ return nil, fmt.Errorf("'path' field is missing or not string")
+ }
+
+ cacheSize, err := getConfigInt("cacheSize", params)
+ if err != nil {
+ return nil, err
+ }
+ c.cacheSize = int64(cacheSize)
+
+ bytesPerSync, err := getConfigInt("bytesPerSync", params)
+ if err != nil {
+ return nil, err
+ }
+ disableWAL, err := getConfigBool("disableWAL", params)
+ if err != nil {
+ return nil, err
+ }
+ fmv, err := getConfigInt("formatMajorVersion", params)
+ if err != nil {
+ return nil, err
+ }
+ formatMajorVersion := pebble.FormatMajorVersion(fmv)
+ l0CompactionThreshold, err := getConfigInt("l0CompactionThreshold", params)
+ if err != nil {
+ return nil, err
+ }
+ l0StopWritesThreshold, err := getConfigInt("l0StopWritesThreshold", params)
+ if err != nil {
+ return nil, err
+ }
+ lBaseMaxBytes, err := getConfigInt("lBaseMaxBytes", params)
+ if err != nil {
+ return nil, err
+ }
+ maxConcurrentCompactions, err := getConfigInt("maxConcurrentCompactions", params)
+ if err != nil {
+ return nil, err
+ }
+ memTableSize, err := getConfigInt("memTableSize", params)
+ if err != nil {
+ return nil, err
+ }
+ memTableStopWritesThreshold, err := getConfigInt("memTableStopWritesThreshold", params)
+ if err != nil {
+ return nil, err
+ }
+ walBytesPerSync, err := getConfigInt("walBytesPerSync", params)
+ if err != nil {
+ return nil, err
+ }
+ walMinSyncSec, err := getConfigInt("walMinSyncIntervalSeconds", params)
+ if err != nil {
+ return nil, err
+ }
+
+ if formatMajorVersion == 0 {
+ // Pebble DB format not configured. Automatically ratchet the
+ // database to the latest format. This may prevent downgrade.
+ formatMajorVersion = pebble.FormatNewest
+ } else if formatMajorVersion < pebble.FormatNewest {
+ // Pebble DB format is configured, but is not the latest.
+ fmt.Println("⚠️ A newer pebble db format is available.")
+ fmt.Println(" To upgrade, set the following in the pebble datastore config:")
+ fmt.Println(" \"formatMajorVersion\":", int(pebble.FormatNewest))
+ }
+
+ if bytesPerSync != 0 || disableWAL || formatMajorVersion != 0 || l0CompactionThreshold != 0 || l0StopWritesThreshold != 0 || lBaseMaxBytes != 0 || maxConcurrentCompactions != 0 || memTableSize != 0 || memTableStopWritesThreshold != 0 || walBytesPerSync != 0 || walMinSyncSec != 0 {
+ c.pebbleOpts = &pebble.Options{
+ BytesPerSync: bytesPerSync,
+ DisableWAL: disableWAL,
+ FormatMajorVersion: formatMajorVersion,
+ L0CompactionThreshold: l0CompactionThreshold,
+ L0StopWritesThreshold: l0StopWritesThreshold,
+ LBaseMaxBytes: int64(lBaseMaxBytes),
+ MemTableSize: uint64(memTableSize),
+ MemTableStopWritesThreshold: memTableStopWritesThreshold,
+ WALBytesPerSync: walBytesPerSync,
+ }
+ if maxConcurrentCompactions != 0 {
+ c.pebbleOpts.MaxConcurrentCompactions = func() int { return maxConcurrentCompactions }
+ }
+ if walMinSyncSec != 0 {
+ c.pebbleOpts.WALMinSyncInterval = func() time.Duration { return time.Duration(walMinSyncSec) * time.Second }
+ }
+ }
+
+ return &c, nil
+ }
+}
+
+func getConfigBool(name string, params map[string]any) (bool, error) {
+ val, ok := params[name]
+ if ok {
+ bval, ok := val.(bool)
+ if !ok {
+ return false, fmt.Errorf("%q field was not a bool", name)
+ }
+ return bval, nil
+ }
+ return false, nil
+}
+
+func getConfigInt(name string, params map[string]any) (int, error) {
+ val, ok := params[name]
+ if ok {
+ // TODO: see why val may be an int or a float64.
+ ival, ok := val.(int)
+ if !ok {
+ fval, ok := val.(float64)
+ if !ok {
+ return 0, fmt.Errorf("%q field was not an integer or a float64", name)
+ }
+ return int(fval), nil
+ }
+ return ival, nil
+ }
+ return 0, nil
+}
+
+func (c *datastoreConfig) DiskSpec() fsrepo.DiskSpec {
+ return map[string]interface{}{
+ "type": "pebbleds",
+ "path": c.path,
+ }
+}
+
+func (c *datastoreConfig) Create(path string) (repo.Datastore, error) {
+ p := c.path
+ if !filepath.IsAbs(p) {
+ p = filepath.Join(path, p)
+ }
+
+ if err := fsutil.DirWritable(p); err != nil {
+ return nil, err
+ }
+
+ return pebbleds.NewDatastore(p, pebbleds.WithCacheSize(c.cacheSize), pebbleds.WithPebbleOpts(c.pebbleOpts))
+}
diff --git a/plugin/plugins/peerlog/peerlog.go b/plugin/plugins/peerlog/peerlog.go
index d55a7f0b9e1..822a636c8fa 100644
--- a/plugin/plugins/peerlog/peerlog.go
+++ b/plugin/plugins/peerlog/peerlog.go
@@ -5,7 +5,7 @@ import (
"sync/atomic"
"time"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
core "github.com/ipfs/kubo/core"
plugin "github.com/ipfs/kubo/plugin"
event "github.com/libp2p/go-libp2p/core/event"
@@ -40,7 +40,7 @@ type plEvent struct {
//
// Usage:
//
-// GOLOG_FILE=~/peer.log IPFS_LOGGING_FMT=json ipfs daemon
+// GOLOG_FILE=~/peer.log GOLOG_LOG_FMT=json ipfs daemon
//
// Output:
//
@@ -186,7 +186,7 @@ func (pl *peerLogPlugin) Start(node *core.IpfsNode) error {
return nil
}
- // Ensure logs from this plugin get printed regardless of global IPFS_LOGGING value
+ // Ensure logs from this plugin get printed regardless of global GOLOG_LOG_LEVEL value
if err := logging.SetLogLevel("plugin/peerlog", "info"); err != nil {
return fmt.Errorf("failed to set log level: %w", err)
}
diff --git a/profile/profile.go b/profile/profile.go
index be1e5adbb62..32df334e3d8 100644
--- a/profile/profile.go
+++ b/profile/profile.go
@@ -14,7 +14,7 @@ import (
"sync"
"time"
- "github.com/ipfs/go-log"
+ "github.com/ipfs/go-log/v2"
version "github.com/ipfs/kubo"
)
diff --git a/repo/common/common.go b/repo/common/common.go
index ab74ffca853..6a6dee6ddf4 100644
--- a/repo/common/common.go
+++ b/repo/common/common.go
@@ -61,8 +61,8 @@ func MapSetKV(v map[string]interface{}, key string, value interface{}) error {
return nil
}
-// Merges the right map into the left map, recursively traversing child maps
-// until a non-map value is found.
+// MapMergeDeep merges the right map into the left map, recursively traversing
+// child maps until a non-map value is found.
func MapMergeDeep(left, right map[string]interface{}) map[string]interface{} {
// We want to alter a copy of the map, not the original
result := make(map[string]interface{})
diff --git a/repo/fsrepo/datastores.go b/repo/fsrepo/datastores.go
index 86ed0a86308..a8c6fa45cda 100644
--- a/repo/fsrepo/datastores.go
+++ b/repo/fsrepo/datastores.go
@@ -17,16 +17,15 @@ import (
// ConfigFromMap creates a new datastore config from a map.
type ConfigFromMap func(map[string]interface{}) (DatastoreConfig, error)
-// DatastoreConfig is an abstraction of a datastore config. A "spec"
-// is first converted to a DatastoreConfig and then Create() is called
-// to instantiate a new datastore.
+// DatastoreConfig is an abstraction of a datastore config. A "spec" is first
+// converted to a DatastoreConfig and then Create() is called to instantiate a
+// new datastore.
type DatastoreConfig interface {
- // DiskSpec returns a minimal configuration of the datastore
- // represting what is stored on disk. Run time values are
- // excluded.
+ // DiskSpec returns a minimal configuration of the datastore representing
+ // what is stored on disk. Run time values are excluded.
DiskSpec() DiskSpec
- // Create instantiate a new datastore from this config
+ // Create instantiates a new datastore from this config.
Create(path string) (repo.Datastore, error)
}
diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go
index 591d25aee58..7c3093b7aef 100644
--- a/repo/fsrepo/fsrepo.go
+++ b/repo/fsrepo/fsrepo.go
@@ -10,6 +10,7 @@ import (
"path/filepath"
"strings"
"sync"
+ "time"
filestore "github.com/ipfs/boxo/filestore"
keystore "github.com/ipfs/boxo/keystore"
@@ -18,15 +19,14 @@ import (
dir "github.com/ipfs/kubo/thirdparty/dir"
rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
- util "github.com/ipfs/boxo/util"
ds "github.com/ipfs/go-datastore"
measure "github.com/ipfs/go-ds-measure"
lockfile "github.com/ipfs/go-fs-lock"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
config "github.com/ipfs/kubo/config"
serialize "github.com/ipfs/kubo/config/serialize"
+ "github.com/ipfs/kubo/misc/fsutil"
"github.com/ipfs/kubo/repo/fsrepo/migrations"
- homedir "github.com/mitchellh/go-homedir"
ma "github.com/multiformats/go-multiaddr"
)
@@ -37,7 +37,7 @@ const LockFile = "repo.lock"
var log = logging.Logger("fsrepo")
// RepoVersion is the version number that we are currently expecting to see.
-var RepoVersion = 15
+var RepoVersion = 16
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.`
@@ -147,7 +147,23 @@ func open(repoPath string, userConfigFilePath string) (repo.Repo, error) {
return nil, err
}
- r.lockfile, err = lockfile.Lock(r.path, LockFile)
+ text := os.Getenv("IPFS_WAIT_REPO_LOCK")
+ if text != "" {
+ var lockWaitTime time.Duration
+ lockWaitTime, err = time.ParseDuration(text)
+ if err != nil {
+ log.Errorw("Cannot parse value of IPFS_WAIT_REPO_LOCK as duration, not waiting for repo lock", "err", err, "value", text)
+ r.lockfile, err = lockfile.Lock(r.path, LockFile)
+ } else if lockWaitTime <= 0 {
+ r.lockfile, err = lockfile.WaitLock(context.Background(), r.path, LockFile)
+ } else {
+ ctx, cancel := context.WithTimeout(context.Background(), lockWaitTime)
+ r.lockfile, err = lockfile.WaitLock(ctx, r.path, LockFile)
+ cancel()
+ }
+ } else {
+ r.lockfile, err = lockfile.Lock(r.path, LockFile)
+ }
if err != nil {
return nil, err
}
@@ -207,7 +223,7 @@ func open(repoPath string, userConfigFilePath string) (repo.Repo, error) {
}
func newFSRepo(rpath string, userConfigFilePath string) (*FSRepo, error) {
- expPath, err := homedir.Expand(filepath.Clean(rpath))
+ expPath, err := fsutil.ExpandHome(filepath.Clean(rpath))
if err != nil {
return nil, err
}
@@ -239,7 +255,7 @@ func configIsInitialized(path string) bool {
if err != nil {
return false
}
- if !util.FileExists(configFilename) {
+ if !fsutil.FileExists(configFilename) {
return false
}
return true
@@ -269,7 +285,7 @@ func initSpec(path string, conf map[string]interface{}) error {
return err
}
- if util.FileExists(fn) {
+ if fsutil.FileExists(fn) {
return nil
}
@@ -677,6 +693,12 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error {
return errors.New("repo is closed")
}
+ // Validate the key's presence in the config structure.
+ err := config.CheckKey(key)
+ if err != nil {
+ return err
+ }
+
// Load into a map so we don't end up writing any additional defaults to the config file.
var mapconf map[string]interface{}
if err := serialize.ReadConfigFile(r.configFilePath, &mapconf); err != nil {
diff --git a/repo/fsrepo/migrations/fetch_test.go b/repo/fsrepo/migrations/fetch_test.go
index 27452d386af..6e87c966bbe 100644
--- a/repo/fsrepo/migrations/fetch_test.go
+++ b/repo/fsrepo/migrations/fetch_test.go
@@ -5,56 +5,13 @@ import (
"bytes"
"context"
"fmt"
- "io"
- "net/http"
- "net/http/httptest"
"os"
- "path"
"path/filepath"
"runtime"
"strings"
"testing"
)
-func createTestServer() *httptest.Server {
- reqHandler := func(w http.ResponseWriter, r *http.Request) {
- defer r.Body.Close()
- if strings.Contains(r.URL.Path, "not-here") {
- http.NotFound(w, r)
- } else if strings.HasSuffix(r.URL.Path, "versions") {
- fmt.Fprint(w, "v1.0.0\nv1.1.0\nv1.1.2\nv2.0.0-rc1\n2.0.0\nv2.0.1\n")
- } else if strings.HasSuffix(r.URL.Path, ".tar.gz") {
- createFakeArchive(r.URL.Path, false, w)
- } else if strings.HasSuffix(r.URL.Path, "zip") {
- createFakeArchive(r.URL.Path, true, w)
- } else {
- http.NotFound(w, r)
- }
- }
- return httptest.NewServer(http.HandlerFunc(reqHandler))
-}
-
-func createFakeArchive(name string, archZip bool, w io.Writer) {
- fileName := strings.Split(path.Base(name), "_")[0]
- root := path.Base(path.Dir(path.Dir(name)))
-
- // Simulate fetching go-ipfs, which has "ipfs" as the name in the archive.
- if fileName == "go-ipfs" {
- fileName = "ipfs"
- }
- fileName = ExeName(fileName)
-
- var err error
- if archZip {
- err = writeZip(root, fileName, "FAKE DATA", w)
- } else {
- err = writeTarGzip(root, fileName, "FAKE DATA", w)
- }
- if err != nil {
- panic(err)
- }
-}
-
func TestGetDistPath(t *testing.T) {
os.Unsetenv(envIpfsDistPath)
distPath := GetDistPathEnv("")
@@ -91,12 +48,9 @@ func TestHttpFetch(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- ts := createTestServer()
- defer ts.Close()
-
- fetcher := NewHttpFetcher("", ts.URL, "", 0)
+ fetcher := NewHttpFetcher(testIpfsDist, testServer.URL, "", 0)
- out, err := fetcher.Fetch(ctx, "/versions")
+ out, err := fetcher.Fetch(ctx, "/kubo/versions")
if err != nil {
t.Fatal(err)
}
@@ -120,7 +74,7 @@ func TestHttpFetch(t *testing.T) {
// Check not found
_, err = fetcher.Fetch(ctx, "/no_such_file")
- if err == nil || !strings.Contains(err.Error(), "404") {
+ if err == nil || !strings.Contains(err.Error(), "no link") {
t.Fatal("expected error 404")
}
}
@@ -131,10 +85,7 @@ func TestFetchBinary(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- ts := createTestServer()
- defer ts.Close()
-
- fetcher := NewHttpFetcher("", ts.URL, "", 0)
+ fetcher := NewHttpFetcher(testIpfsDist, testServer.URL, "", 0)
vers, err := DistVersions(ctx, fetcher, distFSRM, false)
if err != nil {
@@ -154,7 +105,7 @@ func TestFetchBinary(t *testing.T) {
t.Log("downloaded and unpacked", fi.Size(), "byte file:", fi.Name())
- bin, err = FetchBinary(ctx, fetcher, "go-ipfs", "v0.3.5", "ipfs", tmpDir)
+ bin, err = FetchBinary(ctx, fetcher, "go-ipfs", "v1.0.0", "ipfs", tmpDir)
if err != nil {
t.Fatal(err)
}
@@ -167,12 +118,12 @@ func TestFetchBinary(t *testing.T) {
t.Log("downloaded and unpacked", fi.Size(), "byte file:", fi.Name())
// Check error is destination already exists and is not directory
- _, err = FetchBinary(ctx, fetcher, "go-ipfs", "v0.3.5", "ipfs", bin)
+ _, err = FetchBinary(ctx, fetcher, "go-ipfs", "v1.0.0", "ipfs", bin)
if !os.IsExist(err) {
t.Fatal("expected 'exists' error, got", err)
}
- _, err = FetchBinary(ctx, fetcher, "go-ipfs", "v0.3.5", "ipfs", tmpDir)
+ _, err = FetchBinary(ctx, fetcher, "go-ipfs", "v1.0.0", "ipfs", tmpDir)
if !os.IsExist(err) {
t.Error("expected 'exists' error, got:", err)
}
@@ -192,7 +143,7 @@ func TestFetchBinary(t *testing.T) {
if err != nil {
panic(err)
}
- _, err = FetchBinary(ctx, fetcher, "go-ipfs", "v0.3.5", "ipfs", tmpDir)
+ _, err = FetchBinary(ctx, fetcher, "go-ipfs", "v1.0.0", "ipfs", tmpDir)
if !os.IsPermission(err) {
t.Error("expected 'permission' error, got:", err)
}
@@ -207,13 +158,13 @@ func TestFetchBinary(t *testing.T) {
}
// Check error if failure to fetch due to bad dist
- _, err = FetchBinary(ctx, fetcher, "not-here", "v0.3.5", "ipfs", tmpDir)
- if err == nil || !strings.Contains(err.Error(), "Not Found") {
+ _, err = FetchBinary(ctx, fetcher, "not-here", "v1.0.0", "ipfs", tmpDir)
+ if err == nil || !strings.Contains(err.Error(), "no link") {
t.Error("expected 'Not Found' error, got:", err)
}
// Check error if failure to unpack archive
- _, err = FetchBinary(ctx, fetcher, "go-ipfs", "v0.3.5", "not-such-bin", tmpDir)
+ _, err = FetchBinary(ctx, fetcher, "go-ipfs", "v1.0.0", "not-such-bin", tmpDir)
if err == nil || err.Error() != "no binary found in archive" {
t.Error("expected 'no binary found in archive' error")
}
@@ -223,15 +174,12 @@ func TestMultiFetcher(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- ts := createTestServer()
- defer ts.Close()
-
badFetcher := NewHttpFetcher("", "bad-url", "", 0)
- fetcher := NewHttpFetcher("", ts.URL, "", 0)
+ fetcher := NewHttpFetcher(testIpfsDist, testServer.URL, "", 0)
mf := NewMultiFetcher(badFetcher, fetcher)
- vers, err := mf.Fetch(ctx, "/versions")
+ vers, err := mf.Fetch(ctx, "/kubo/versions")
if err != nil {
t.Fatal(err)
}
diff --git a/repo/fsrepo/migrations/fetcher.go b/repo/fsrepo/migrations/fetcher.go
index 880492b92e6..c81554c3c47 100644
--- a/repo/fsrepo/migrations/fetcher.go
+++ b/repo/fsrepo/migrations/fetcher.go
@@ -6,12 +6,12 @@ import (
"io"
"os"
- "github.com/hashicorp/go-multierror"
+ "go.uber.org/multierr"
)
const (
// Current distribution to fetch migrations from.
- CurrentIpfsDist = "/ipfs/QmZPedUiZNe6Gq9oDvoizuuCMVoeb7shwq9xKhysq7exMo" // fs-repo-14-to-15 v1.0.1
+ CurrentIpfsDist = "/ipfs/QmRzRGJEjYDfbHHaALnHBuhzzrkXGdwcPMrgd5fgM7hqbe" // fs-repo-15-to-16 v1.0.1
// Latest distribution path. Default for fetchers.
LatestIpfsDist = "/ipns/dist.ipfs.tech"
@@ -56,7 +56,7 @@ func (f *MultiFetcher) Fetch(ctx context.Context, ipfsPath string) ([]byte, erro
return out, nil
}
fmt.Printf("Error fetching: %s\n", err.Error())
- errs = multierror.Append(errs, err)
+ errs = multierr.Append(errs, err)
}
return nil, errs
}
@@ -65,7 +65,7 @@ func (f *MultiFetcher) Close() error {
var errs error
for _, fetcher := range f.fetchers {
if err := fetcher.Close(); err != nil {
- errs = multierror.Append(errs, err)
+ errs = multierr.Append(errs, err)
}
}
return errs
@@ -79,7 +79,7 @@ func (f *MultiFetcher) Fetchers() []Fetcher {
return f.fetchers
}
-// NewLimitReadCloser returns a new io.ReadCloser with the reader wrappen in a
+// NewLimitReadCloser returns a new io.ReadCloser with the reader wrapped in a
// io.LimitedReader limited to reading the amount specified.
func NewLimitReadCloser(rc io.ReadCloser, limit int64) io.ReadCloser {
return limitReadCloser{
@@ -93,7 +93,7 @@ func NewLimitReadCloser(rc io.ReadCloser, limit int64) io.ReadCloser {
// variable is not set, then returns the provided distPath, and if that is not set
// then returns the IPNS path.
//
-// To get the IPFS path of the latest distribution, if not overriddin by the
+// To get the IPFS path of the latest distribution, if not overridden by the
// environ variable: GetDistPathEnv(CurrentIpfsDist).
func GetDistPathEnv(distPath string) string {
if dist := os.Getenv(envIpfsDistPath); dist != "" {
diff --git a/repo/fsrepo/migrations/httpfetcher.go b/repo/fsrepo/migrations/httpfetcher.go
index 9665a1e98ce..2ae180b1ea2 100644
--- a/repo/fsrepo/migrations/httpfetcher.go
+++ b/repo/fsrepo/migrations/httpfetcher.go
@@ -2,21 +2,40 @@ package migrations
import (
"context"
+ "errors"
"fmt"
"io"
"net/http"
- "path"
+ gopath "path"
"strings"
+
+ "github.com/ipfs/boxo/blockservice"
+ "github.com/ipfs/boxo/blockstore"
+ "github.com/ipfs/boxo/exchange/offline"
+ bsfetcher "github.com/ipfs/boxo/fetcher/impl/blockservice"
+ files "github.com/ipfs/boxo/files"
+ "github.com/ipfs/boxo/ipld/merkledag"
+ unixfile "github.com/ipfs/boxo/ipld/unixfs/file"
+ "github.com/ipfs/boxo/ipns"
+ "github.com/ipfs/boxo/namesys"
+ "github.com/ipfs/boxo/path"
+ "github.com/ipfs/boxo/path/resolver"
+ "github.com/ipfs/go-datastore"
+ dssync "github.com/ipfs/go-datastore/sync"
+ "github.com/ipfs/go-unixfsnode"
+ gocarv2 "github.com/ipld/go-car/v2"
+ dagpb "github.com/ipld/go-codec-dagpb"
+ madns "github.com/multiformats/go-multiaddr-dns"
)
const (
// default is different name than ipfs.io which is being blocked by some ISPs
- defaultGatewayURL = "https://dweb.link"
+ defaultGatewayURL = "https://trustless-gateway.link"
// Default maximum download size.
defaultFetchLimit = 1024 * 1024 * 512
)
-// HttpFetcher fetches files over HTTP.
+// HttpFetcher fetches files over HTTP using verifiable CAR archives.
type HttpFetcher struct { //nolint
distPath string
gateway string
@@ -26,7 +45,7 @@ type HttpFetcher struct { //nolint
var _ Fetcher = (*HttpFetcher)(nil)
-// NewHttpFetcher creates a new HttpFetcher
+// NewHttpFetcher creates a new [HttpFetcher].
//
// Specifying "" for distPath sets the default IPNS path.
// Specifying "" for gateway sets the default.
@@ -62,13 +81,89 @@ func NewHttpFetcher(distPath, gateway, userAgent string, fetchLimit int64) *Http
// Fetch attempts to fetch the file at the given path, from the distribution
// site configured for this HttpFetcher.
func (f *HttpFetcher) Fetch(ctx context.Context, filePath string) ([]byte, error) {
- gwURL := f.gateway + path.Join(f.distPath, filePath)
- fmt.Printf("Fetching with HTTP: %q\n", gwURL)
+ imPath, err := f.resolvePath(ctx, gopath.Join(f.distPath, filePath))
+ if err != nil {
+ return nil, fmt.Errorf("path could not be resolved: %w", err)
+ }
+
+ rc, err := f.httpRequest(ctx, imPath, "application/vnd.ipld.car")
+ if err != nil {
+ return nil, fmt.Errorf("failed to fetch CAR: %w", err)
+ }
+
+ return carStreamToFileBytes(ctx, rc, imPath)
+}
+
+func (f *HttpFetcher) Close() error {
+ return nil
+}
+
+func (f *HttpFetcher) resolvePath(ctx context.Context, pathStr string) (path.ImmutablePath, error) {
+ p, err := path.NewPath(pathStr)
+ if err != nil {
+ return path.ImmutablePath{}, fmt.Errorf("path is invalid: %w", err)
+ }
+
+ for p.Mutable() {
+ // Download IPNS record and verify through the gateway, or resolve the
+ // DNSLink with the default DNS resolver.
+ name, err := ipns.NameFromString(p.Segments()[1])
+ if err == nil {
+ p, err = f.resolveIPNS(ctx, name)
+ } else {
+ p, err = f.resolveDNSLink(ctx, p)
+ }
- req, err := http.NewRequestWithContext(ctx, http.MethodGet, gwURL, nil)
+ if err != nil {
+ return path.ImmutablePath{}, err
+ }
+ }
+
+ return path.NewImmutablePath(p)
+}
+
+func (f *HttpFetcher) resolveIPNS(ctx context.Context, name ipns.Name) (path.Path, error) {
+ rc, err := f.httpRequest(ctx, name.AsPath(), "application/vnd.ipfs.ipns-record")
+ if err != nil {
+ return path.ImmutablePath{}, err
+ }
+
+ rc = NewLimitReadCloser(rc, int64(ipns.MaxRecordSize))
+ rawRecord, err := io.ReadAll(rc)
+ if err != nil {
+ return path.ImmutablePath{}, err
+ }
+
+ rec, err := ipns.UnmarshalRecord(rawRecord)
+ if err != nil {
+ return path.ImmutablePath{}, err
+ }
+
+ err = ipns.ValidateWithName(rec, name)
+ if err != nil {
+ return path.ImmutablePath{}, err
+ }
+
+ return rec.Value()
+}
+
+func (f *HttpFetcher) resolveDNSLink(ctx context.Context, p path.Path) (path.Path, error) {
+ dnsResolver := namesys.NewDNSResolver(madns.DefaultResolver.LookupTXT)
+ res, err := dnsResolver.Resolve(ctx, p)
+ if err != nil {
+ return nil, err
+ }
+ return res.Path, nil
+}
+
+func (f *HttpFetcher) httpRequest(ctx context.Context, p path.Path, accept string) (io.ReadCloser, error) {
+ url := f.gateway + p.String()
+ fmt.Printf("Fetching with HTTP: %q\n", url)
+ req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, fmt.Errorf("http.NewRequest error: %w", err)
}
+ req.Header.Set("Accept", accept)
if f.userAgent != "" {
req.Header.Set("User-Agent", f.userAgent)
@@ -85,7 +180,7 @@ func (f *HttpFetcher) Fetch(ctx context.Context, filePath string) ([]byte, error
if err != nil {
return nil, fmt.Errorf("error reading error body: %w", err)
}
- return nil, fmt.Errorf("GET %s error: %s: %s", gwURL, resp.Status, string(mes))
+ return nil, fmt.Errorf("GET %s error: %s: %s", url, resp.Status, string(mes))
}
var rc io.ReadCloser
@@ -94,11 +189,69 @@ func (f *HttpFetcher) Fetch(ctx context.Context, filePath string) ([]byte, error
} else {
rc = resp.Body
}
- defer rc.Close()
- return io.ReadAll(rc)
+ return rc, nil
}
-func (f *HttpFetcher) Close() error {
- return nil
+func carStreamToFileBytes(ctx context.Context, r io.ReadCloser, imPath path.ImmutablePath) ([]byte, error) {
+ defer r.Close()
+
+ // Create temporary block datastore and dag service.
+ dataStore := dssync.MutexWrap(datastore.NewMapDatastore())
+ blockStore := blockstore.NewBlockstore(dataStore)
+ blockService := blockservice.New(blockStore, offline.Exchange(blockStore))
+ dagService := merkledag.NewDAGService(blockService)
+
+ defer dagService.Blocks.Close()
+ defer dataStore.Close()
+
+ // Create CAR reader
+ car, err := gocarv2.NewBlockReader(r)
+ if err != nil {
+ fmt.Println(err)
+ return nil, fmt.Errorf("error creating car reader: %s", err)
+ }
+
+ // Add all blocks to the blockstore.
+ for {
+ block, err := car.Next()
+ if err != nil && err != io.EOF {
+ return nil, fmt.Errorf("error reading block from car: %s", err)
+ } else if block == nil {
+ break
+ }
+
+ err = blockStore.Put(ctx, block)
+ if err != nil {
+ return nil, fmt.Errorf("error putting block in blockstore: %s", err)
+ }
+ }
+
+ fetcherCfg := bsfetcher.NewFetcherConfig(blockService)
+ fetcherCfg.PrototypeChooser = dagpb.AddSupportToChooser(bsfetcher.DefaultPrototypeChooser)
+ fetcher := fetcherCfg.WithReifier(unixfsnode.Reify)
+ resolver := resolver.NewBasicResolver(fetcher)
+
+ cid, _, err := resolver.ResolveToLastNode(ctx, imPath)
+ if err != nil {
+ return nil, fmt.Errorf("failed to resolve: %w", err)
+ }
+
+ nd, err := dagService.Get(ctx, cid)
+ if err != nil {
+ return nil, fmt.Errorf("failed to resolve: %w", err)
+ }
+
+ // Make UnixFS file out of the node.
+ uf, err := unixfile.NewUnixfsFile(ctx, dagService, nd)
+ if err != nil {
+ return nil, fmt.Errorf("error building unixfs file: %s", err)
+ }
+
+ // Check if it's a file and return.
+ if f, ok := uf.(files.File); ok {
+ return io.ReadAll(f)
+ }
+
+ return nil, errors.New("unexpected unixfs node type")
}
diff --git a/repo/fsrepo/migrations/ipfsdir.go b/repo/fsrepo/migrations/ipfsdir.go
index 464118d1c12..8cb087d5345 100644
--- a/repo/fsrepo/migrations/ipfsdir.go
+++ b/repo/fsrepo/migrations/ipfsdir.go
@@ -8,7 +8,7 @@ import (
"strconv"
"strings"
- "github.com/mitchellh/go-homedir"
+ "github.com/ipfs/kubo/misc/fsutil"
)
const (
@@ -17,10 +17,6 @@ const (
versionFile = "version"
)
-func init() {
- homedir.DisableCache = true
-}
-
// IpfsDir returns the path of the ipfs directory. If dir specified, then
// returns the expanded version dir. If dir is "", then return the directory
// set by IPFS_PATH, or if IPFS_PATH is not set, then return the default
@@ -31,14 +27,14 @@ func IpfsDir(dir string) (string, error) {
dir = os.Getenv(envIpfsPath)
}
if dir != "" {
- dir, err = homedir.Expand(dir)
+ dir, err = fsutil.ExpandHome(dir)
if err != nil {
return "", err
}
return dir, nil
}
- home, err := homedir.Dir()
+ home, err := os.UserHomeDir()
if err != nil {
return "", err
}
diff --git a/repo/fsrepo/migrations/migrations_test.go b/repo/fsrepo/migrations/migrations_test.go
index 2fd75b7e9de..96370f864e8 100644
--- a/repo/fsrepo/migrations/migrations_test.go
+++ b/repo/fsrepo/migrations/migrations_test.go
@@ -110,9 +110,7 @@ func TestFetchMigrations(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- ts := createTestServer()
- defer ts.Close()
- fetcher := NewHttpFetcher(CurrentIpfsDist, ts.URL, "", 0)
+ fetcher := NewHttpFetcher(testIpfsDist, testServer.URL, "", 0)
tmpDir := t.TempDir()
@@ -162,9 +160,7 @@ func TestRunMigrations(t *testing.T) {
t.Fatal(err)
}
- ts := createTestServer()
- defer ts.Close()
- fetcher := NewHttpFetcher(CurrentIpfsDist, ts.URL, "", 0)
+ fetcher := NewHttpFetcher(testIpfsDist, testServer.URL, "", 0)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
diff --git a/repo/fsrepo/migrations/setup_test.go b/repo/fsrepo/migrations/setup_test.go
new file mode 100644
index 00000000000..9761edb942f
--- /dev/null
+++ b/repo/fsrepo/migrations/setup_test.go
@@ -0,0 +1,231 @@
+package migrations
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "io"
+ "net/http/httptest"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/ipfs/boxo/blockservice"
+ "github.com/ipfs/boxo/exchange/offline"
+ "github.com/ipfs/boxo/gateway"
+ blocks "github.com/ipfs/go-block-format"
+ "github.com/ipfs/go-cid"
+ "github.com/ipfs/go-unixfsnode/data/builder"
+ "github.com/ipld/go-car/v2"
+ carblockstore "github.com/ipld/go-car/v2/blockstore"
+ "github.com/ipld/go-ipld-prime"
+ cidlink "github.com/ipld/go-ipld-prime/linking/cid"
+ "github.com/multiformats/go-multicodec"
+ "github.com/multiformats/go-multihash"
+)
+
+var (
+ testIpfsDist string
+ testServer *httptest.Server
+)
+
+func TestMain(m *testing.M) {
+ t := &testing.T{}
+
+ // Setup test data
+ testDataDir := makeTestData(t)
+
+ testCar := makeTestCar(testDataDir)
+ defer os.RemoveAll(testCar)
+
+ // Setup test gateway
+ fd := setupTestGateway(testCar)
+ defer fd.Close()
+
+ // Run tests
+ os.Exit(m.Run())
+}
+
+func makeTestData(t testing.TB) string {
+ tempDir := t.TempDir()
+
+ versions := []string{"v1.0.0", "v1.1.0", "v1.1.2", "v2.0.0-rc1", "2.0.0", "v2.0.1"}
+ packages := []string{"kubo", "go-ipfs", "fs-repo-migrations", "fs-repo-1-to-2", "fs-repo-2-to-3", "fs-repo-9-to-10", "fs-repo-10-to-11"}
+
+ // Generate fake data
+ for _, name := range packages {
+ err := os.MkdirAll(filepath.Join(tempDir, name), 0777)
+ if err != nil {
+ panic(err)
+ }
+
+ err = os.WriteFile(filepath.Join(tempDir, name, "versions"), []byte(strings.Join(versions, "\n")+"\n"), 0666)
+ if err != nil {
+ panic(err)
+ }
+
+ for _, version := range versions {
+ filename, archName := makeArchivePath(name, name, version, "tar.gz")
+ createFakeArchive(filepath.Join(tempDir, filename), archName, false)
+
+ filename, archName = makeArchivePath(name, name, version, "zip")
+ createFakeArchive(filepath.Join(tempDir, filename), archName, true)
+ }
+ }
+
+ return tempDir
+}
+
+func createFakeArchive(archName, name string, archZip bool) {
+ err := os.MkdirAll(filepath.Dir(archName), 0777)
+ if err != nil {
+ panic(err)
+ }
+
+ fileName := strings.Split(path.Base(name), "_")[0]
+ root := fileName
+
+ // Simulate fetching go-ipfs, which has "ipfs" as the name in the archive.
+ if fileName == "go-ipfs" || fileName == "kubo" {
+ fileName = "ipfs"
+ }
+ fileName = ExeName(fileName)
+
+ if archZip {
+ err = writeZipFile(archName, root, fileName, "FAKE DATA")
+ } else {
+ err = writeTarGzipFile(archName, root, fileName, "FAKE DATA")
+ }
+ if err != nil {
+ panic(err)
+ }
+}
+
+// makeTestCar makes a CAR file with the directory [testData]. This code is mostly
+// sourced from https://github.com/ipld/go-car/blob/1e2f0bd2c44ee31f48a8f602b25b5671cc0c4687/cmd/car/create.go
+func makeTestCar(testData string) string {
+ // make a cid with the right length that we eventually will patch with the root.
+ hasher, err := multihash.GetHasher(multihash.SHA2_256)
+ if err != nil {
+ panic(err)
+ }
+ digest := hasher.Sum([]byte{})
+ hash, err := multihash.Encode(digest, multihash.SHA2_256)
+ if err != nil {
+ panic(err)
+ }
+ proxyRoot := cid.NewCidV1(uint64(multicodec.DagPb), hash)
+
+ // Make CAR file
+ fd, err := os.CreateTemp("", "kubo-migrations-test-*.car")
+ if err != nil {
+ panic(err)
+ }
+ defer fd.Close()
+ filename := fd.Name()
+
+ rw, err := carblockstore.OpenReadWriteFile(fd, []cid.Cid{proxyRoot}, carblockstore.WriteAsCarV1(true))
+ if err != nil {
+ panic(err)
+ }
+ defer rw.Close()
+
+ ctx := context.Background()
+
+ ls := cidlink.DefaultLinkSystem()
+ ls.TrustedStorage = true
+ ls.StorageReadOpener = func(_ ipld.LinkContext, l ipld.Link) (io.Reader, error) {
+ cl, ok := l.(cidlink.Link)
+ if !ok {
+ return nil, fmt.Errorf("not a cidlink")
+ }
+ blk, err := rw.Get(ctx, cl.Cid)
+ if err != nil {
+ return nil, err
+ }
+ return bytes.NewBuffer(blk.RawData()), nil
+ }
+ ls.StorageWriteOpener = func(_ ipld.LinkContext) (io.Writer, ipld.BlockWriteCommitter, error) {
+ buf := bytes.NewBuffer(nil)
+ return buf, func(l ipld.Link) error {
+ cl, ok := l.(cidlink.Link)
+ if !ok {
+ return fmt.Errorf("not a cidlink")
+ }
+ blk, err := blocks.NewBlockWithCid(buf.Bytes(), cl.Cid)
+ if err != nil {
+ return err
+ }
+ return rw.Put(ctx, blk)
+ }, nil
+ }
+
+ l, _, err := builder.BuildUnixFSRecursive(testData, &ls)
+ if err != nil {
+ panic(err)
+ }
+
+ rcl, ok := l.(cidlink.Link)
+ if !ok {
+ panic(fmt.Errorf("could not interpret %s", l))
+ }
+
+ if err := rw.Finalize(); err != nil {
+ panic(err)
+ }
+ // re-open/finalize with the final root.
+ err = car.ReplaceRootsInFile(filename, []cid.Cid{rcl.Cid})
+ if err != nil {
+ panic(err)
+ }
+
+ return filename
+}
+
+func setupTestGateway(testCar string) io.Closer {
+ blockService, roots, fd, err := newBlockServiceFromCAR(testCar)
+ if err != nil {
+ panic(err)
+ }
+
+ if len(roots) != 1 {
+ panic("expected car with 1 root")
+ }
+
+ backend, err := gateway.NewBlocksBackend(blockService)
+ if err != nil {
+ panic(err)
+ }
+ conf := gateway.Config{
+ NoDNSLink: false,
+ DeserializedResponses: false,
+ }
+
+ testIpfsDist = "/ipfs/" + roots[0].String()
+ testServer = httptest.NewServer(gateway.NewHandler(conf, backend))
+
+ return fd
+}
+
+func newBlockServiceFromCAR(filepath string) (blockservice.BlockService, []cid.Cid, io.Closer, error) {
+ r, err := os.Open(filepath)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+
+ bs, err := carblockstore.NewReadOnly(r, nil)
+ if err != nil {
+ _ = r.Close()
+ return nil, nil, nil, err
+ }
+
+ roots, err := bs.Roots()
+ if err != nil {
+ return nil, nil, nil, err
+ }
+
+ blockService := blockservice.New(bs, offline.Exchange(bs))
+ return blockService, roots, r, nil
+}
diff --git a/repo/fsrepo/migrations/versions_test.go b/repo/fsrepo/migrations/versions_test.go
index 18de72b779c..dd62f9bde8d 100644
--- a/repo/fsrepo/migrations/versions_test.go
+++ b/repo/fsrepo/migrations/versions_test.go
@@ -13,9 +13,7 @@ func TestDistVersions(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- ts := createTestServer()
- defer ts.Close()
- fetcher := NewHttpFetcher("", ts.URL, "", 0)
+ fetcher := NewHttpFetcher(testIpfsDist, testServer.URL, "", 0)
vers, err := DistVersions(ctx, fetcher, testDist, true)
if err != nil {
@@ -32,9 +30,7 @@ func TestLatestDistVersion(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- ts := createTestServer()
- defer ts.Close()
- fetcher := NewHttpFetcher("", ts.URL, "", 0)
+ fetcher := NewHttpFetcher(testIpfsDist, testServer.URL, "", 0)
latest, err := LatestDistVersion(ctx, fetcher, testDist, false)
if err != nil {
diff --git a/repo/fsrepo/misc.go b/repo/fsrepo/misc.go
index 7824f2f4f0a..fa5b235e2dc 100644
--- a/repo/fsrepo/misc.go
+++ b/repo/fsrepo/misc.go
@@ -4,7 +4,7 @@ import (
"os"
config "github.com/ipfs/kubo/config"
- homedir "github.com/mitchellh/go-homedir"
+ "github.com/ipfs/kubo/misc/fsutil"
)
// BestKnownPath returns the best known fsrepo path. If the ENV override is
@@ -15,7 +15,7 @@ func BestKnownPath() (string, error) {
if os.Getenv(config.EnvDir) != "" {
ipfsPath = os.Getenv(config.EnvDir)
}
- ipfsPath, err := homedir.Expand(ipfsPath)
+ ipfsPath, err := fsutil.ExpandHome(ipfsPath)
if err != nil {
return "", err
}
diff --git a/repo/mock.go b/repo/mock.go
index 46bb0cb4210..2ac60615d26 100644
--- a/repo/mock.go
+++ b/repo/mock.go
@@ -27,6 +27,10 @@ func (m *Mock) Config() (*config.Config, error) {
return &m.C, nil // FIXME threadsafety
}
+func (m *Mock) Path() string {
+ return ""
+}
+
func (m *Mock) UserResourceOverrides() (rcmgr.PartialLimitConfig, error) {
return rcmgr.PartialLimitConfig{}, nil
}
diff --git a/repo/repo.go b/repo/repo.go
index 9abdf867e47..f345e89b417 100644
--- a/repo/repo.go
+++ b/repo/repo.go
@@ -23,6 +23,9 @@ type Repo interface {
// to the returned config are not automatically persisted.
Config() (*config.Config, error)
+ // Path is the repo file-system path
+ Path() string
+
// UserResourceOverrides returns optional user resource overrides for the
// libp2p resource manager.
UserResourceOverrides() (rcmgr.PartialLimitConfig, error)
diff --git a/routing/composer.go b/routing/composer.go
index 3541fc7dd24..a100bb49852 100644
--- a/routing/composer.go
+++ b/routing/composer.go
@@ -4,12 +4,12 @@ import (
"context"
"errors"
- "github.com/hashicorp/go-multierror"
"github.com/ipfs/go-cid"
routinghelpers "github.com/libp2p/go-libp2p-routing-helpers"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/routing"
"github.com/multiformats/go-multihash"
+ "go.uber.org/multierr"
)
var (
@@ -124,7 +124,7 @@ func (c *Composer) Bootstrap(ctx context.Context) error {
errgv := c.GetValueRouter.Bootstrap(ctx)
errpv := c.PutValueRouter.Bootstrap(ctx)
errp := c.ProvideRouter.Bootstrap(ctx)
- err := multierror.Append(errfp, errfps, errgv, errpv, errp)
+ err := multierr.Combine(errfp, errfps, errgv, errpv, errp)
if err != nil {
log.Debug("composer: calling bootstrap error: ", err)
}
diff --git a/routing/delegated.go b/routing/delegated.go
index e830c1aa197..fb89e815027 100644
--- a/routing/delegated.go
+++ b/routing/delegated.go
@@ -10,7 +10,7 @@ import (
drclient "github.com/ipfs/boxo/routing/http/client"
"github.com/ipfs/boxo/routing/http/contentrouter"
"github.com/ipfs/go-datastore"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
version "github.com/ipfs/kubo"
"github.com/ipfs/kubo/config"
dht "github.com/libp2p/go-libp2p-kad-dht"
@@ -149,12 +149,13 @@ func parse(visited map[string]bool,
}
type ExtraHTTPParams struct {
- PeerID string
- Addrs []string
- PrivKeyB64 string
+ PeerID string
+ Addrs []string
+ PrivKeyB64 string
+ HTTPRetrieval bool
}
-func ConstructHTTPRouter(endpoint string, peerID string, addrs []string, privKey string) (routing.Routing, error) {
+func ConstructHTTPRouter(endpoint string, peerID string, addrs []string, privKey string, httpRetrieval bool) (routing.Routing, error) {
return httpRoutingFromConfig(
config.Router{
Type: "http",
@@ -163,9 +164,10 @@ func ConstructHTTPRouter(endpoint string, peerID string, addrs []string, privKey
},
},
&ExtraHTTPParams{
- PeerID: peerID,
- Addrs: addrs,
- PrivKeyB64: privKey,
+ PeerID: peerID,
+ Addrs: addrs,
+ PrivKeyB64: privKey,
+ HTTPRetrieval: httpRetrieval,
},
)
}
@@ -200,12 +202,20 @@ func httpRoutingFromConfig(conf config.Router, extraHTTP *ExtraHTTPParams) (rout
return nil, err
}
+ protocols := config.DefaultHTTPRoutersFilterProtocols
+ if extraHTTP.HTTPRetrieval {
+ protocols = append(protocols, "transport-ipfs-gateway-http")
+ }
+
cli, err := drclient.New(
params.Endpoint,
drclient.WithHTTPClient(delegateHTTPClient),
drclient.WithIdentity(key),
drclient.WithProviderInfo(addrInfo.ID, addrInfo.Addrs),
drclient.WithUserAgent(version.GetUserAgentVersion()),
+ drclient.WithProtocolFilter(protocols),
+ drclient.WithStreamResultsRequired(), // https://specs.ipfs.tech/routing/http-routing-v1/#streaming
+ drclient.WithDisabledLocalFiltering(false), // force local filtering in case remote server does not support IPIP-484
)
if err != nil {
return nil, err
diff --git a/test/3nodetest/bin/save_profiling_data.sh b/test/3nodetest/bin/save_profiling_data.sh
index 03c0cbabec4..639b5d38342 100644
--- a/test/3nodetest/bin/save_profiling_data.sh
+++ b/test/3nodetest/bin/save_profiling_data.sh
@@ -6,7 +6,7 @@ for container in 3nodetest_bootstrap_1 3nodetest_client_1 3nodetest_server_1; do
done
# since the nodes are executed with the --debug flag, profiling data is written
-# to the the working dir. by default, the working dir is /go.
+# to the working dir. by default, the working dir is /go.
for container in 3nodetest_bootstrap_1 3nodetest_client_1 3nodetest_server_1; do
docker cp $container:/go/ipfs.cpuprof build/profiling_data_$container
diff --git a/test/3nodetest/bootstrap/Dockerfile b/test/3nodetest/bootstrap/Dockerfile
index ed8ac9ffa52..e5423f11660 100644
--- a/test/3nodetest/bootstrap/Dockerfile
+++ b/test/3nodetest/bootstrap/Dockerfile
@@ -6,6 +6,6 @@ RUN mv -f /tmp/id/config /root/.ipfs/config
RUN ipfs id
ENV IPFS_PROF true
-ENV IPFS_LOGGING_FMT nocolor
+ENV GOLOG_LOG_FMT nocolor
EXPOSE 4011 4012/udp
diff --git a/test/3nodetest/bootstrap/config b/test/3nodetest/bootstrap/config
index ac441a19f16..e22f25e909b 100644
--- a/test/3nodetest/bootstrap/config
+++ b/test/3nodetest/bootstrap/config
@@ -15,7 +15,8 @@
},
"Mounts": {
"IPFS": "/ipfs",
- "IPNS": "/ipns"
+ "IPNS": "/ipns",
+ "MFS": "/mfs"
},
"Version": {
"Current": "0.1.7",
diff --git a/test/3nodetest/client/Dockerfile b/test/3nodetest/client/Dockerfile
index d4e1ffa36d4..3e7ada6c05d 100644
--- a/test/3nodetest/client/Dockerfile
+++ b/test/3nodetest/client/Dockerfile
@@ -8,7 +8,7 @@ RUN ipfs id
EXPOSE 4031 4032/udp
ENV IPFS_PROF true
-ENV IPFS_LOGGING_FMT nocolor
+ENV GOLOG_LOG_FMT nocolor
ENTRYPOINT ["/bin/bash"]
CMD ["/tmp/id/run.sh"]
diff --git a/test/3nodetest/client/config b/test/3nodetest/client/config
index 86ef0668d72..fa8f923d5c3 100644
--- a/test/3nodetest/client/config
+++ b/test/3nodetest/client/config
@@ -17,7 +17,8 @@
},
"Mounts": {
"IPFS": "/ipfs",
- "IPNS": "/ipns"
+ "IPNS": "/ipns",
+ "MFS": "/mfs"
},
"Version": {
"AutoUpdate": "minor",
diff --git a/test/3nodetest/fig.yml b/test/3nodetest/fig.yml
index 18a28c8ff75..f163398c2af 100644
--- a/test/3nodetest/fig.yml
+++ b/test/3nodetest/fig.yml
@@ -11,7 +11,7 @@ bootstrap:
- "4011"
- "4012/udp"
environment:
- IPFS_LOGGING: debug
+ GOLOG_LOG_LEVEL: debug
server:
build: ./server
@@ -23,7 +23,7 @@ server:
- "4021"
- "4022/udp"
environment:
- IPFS_LOGGING: debug
+ GOLOG_LOG_LEVEL: debug
client:
build: ./client
@@ -35,4 +35,4 @@ client:
- "4031"
- "4032/udp"
environment:
- IPFS_LOGGING: debug
+ GOLOG_LOG_LEVEL: debug
diff --git a/test/3nodetest/server/Dockerfile b/test/3nodetest/server/Dockerfile
index 935d2e1b022..72f6fdf57ef 100644
--- a/test/3nodetest/server/Dockerfile
+++ b/test/3nodetest/server/Dockerfile
@@ -9,7 +9,7 @@ RUN chmod +x /tmp/test/run.sh
EXPOSE 4021 4022/udp
ENV IPFS_PROF true
-ENV IPFS_LOGGING_FMT nocolor
+ENV GOLOG_LOG_FMT nocolor
ENTRYPOINT ["/bin/bash"]
CMD ["/tmp/test/run.sh"]
diff --git a/test/3nodetest/server/config b/test/3nodetest/server/config
index fb16a6d7a87..1e9db2a6332 100644
--- a/test/3nodetest/server/config
+++ b/test/3nodetest/server/config
@@ -17,7 +17,8 @@
},
"Mounts": {
"IPFS": "/ipfs",
- "IPNS": "/ipns"
+ "IPNS": "/ipns",
+ "MFS": "/mfs"
},
"Version": {
"AutoUpdate": "minor",
diff --git a/test/3nodetest/server/run.sh b/test/3nodetest/server/run.sh
index dfe586310ea..17ae38736ad 100644
--- a/test/3nodetest/server/run.sh
+++ b/test/3nodetest/server/run.sh
@@ -9,7 +9,7 @@ echo "3nodetest> starting server daemon"
# run daemon in debug mode to collect profiling data
ipfs daemon --debug &
sleep 3
-# TODO instead of bootrapping: ipfs swarm connect /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/p2p/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE
+# TODO instead of bootstrapping: ipfs swarm connect /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/p2p/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE
# change dir before running add commands so ipfs client profiling data doesn't
# overwrite the daemon profiling data
diff --git a/test/bench/bench_cli_ipfs_add/main.go b/test/bench/bench_cli_ipfs_add/main.go
index e7fe90e0407..2c39ba63680 100644
--- a/test/bench/bench_cli_ipfs_add/main.go
+++ b/test/bench/bench_cli_ipfs_add/main.go
@@ -3,6 +3,7 @@ package main
import (
"flag"
"fmt"
+ "io"
"log"
"os"
"os/exec"
@@ -11,8 +12,8 @@ import (
"github.com/ipfs/kubo/thirdparty/unit"
+ random "github.com/ipfs/go-test/random"
config "github.com/ipfs/kubo/config"
- random "github.com/jbenet/go-random"
)
var (
@@ -59,7 +60,7 @@ func benchmarkAdd(amount int64) (*testing.BenchmarkResult, error) {
}
}
- initCmd := exec.Command("ipfs", "init", "-b=2048")
+ initCmd := exec.Command("ipfs", "init")
setupCmd(initCmd)
if err := initCmd.Run(); err != nil {
benchmarkError = err
@@ -74,7 +75,11 @@ func benchmarkAdd(amount int64) (*testing.BenchmarkResult, error) {
}
defer os.Remove(f.Name())
- if err := random.WritePseudoRandomBytes(amount, f, seed); err != nil {
+ randReader := &io.LimitedReader{
+ R: random.NewSeededRand(seed),
+ N: amount,
+ }
+ if _, err := io.Copy(f, randReader); err != nil {
benchmarkError = err
b.Fatal(err)
}
diff --git a/test/bench/offline_add/main.go b/test/bench/offline_add/main.go
index 338a5f6ac24..7c00d30f409 100644
--- a/test/bench/offline_add/main.go
+++ b/test/bench/offline_add/main.go
@@ -2,6 +2,7 @@ package main
import (
"fmt"
+ "io"
"log"
"os"
"os/exec"
@@ -10,8 +11,8 @@ import (
"github.com/ipfs/kubo/thirdparty/unit"
+ random "github.com/ipfs/go-test/random"
config "github.com/ipfs/kubo/config"
- random "github.com/jbenet/go-random"
)
func main() {
@@ -44,7 +45,7 @@ func benchmarkAdd(amount int64) (*testing.BenchmarkResult, error) {
cmd.Env = env
}
- cmd := exec.Command("ipfs", "init", "-b=2048")
+ cmd := exec.Command("ipfs", "init")
setupCmd(cmd)
if err := cmd.Run(); err != nil {
b.Fatal(err)
@@ -57,7 +58,11 @@ func benchmarkAdd(amount int64) (*testing.BenchmarkResult, error) {
}
defer os.Remove(f.Name())
- err = random.WritePseudoRandomBytes(amount, f, seed)
+ randReader := &io.LimitedReader{
+ R: random.NewSeededRand(seed),
+ N: amount,
+ }
+ _, err = io.Copy(f, randReader)
if err != nil {
b.Fatal(err)
}
diff --git a/test/bin/Rules.mk b/test/bin/Rules.mk
index 4e264106a95..aaa46695be1 100644
--- a/test/bin/Rules.mk
+++ b/test/bin/Rules.mk
@@ -5,7 +5,7 @@ TGTS_$(d) :=
define go-build-testdep
OUT="$(CURDIR)/$@" ; \
cd "test/dependencies" ; \
- $(GOCC) build $(go-flags-with-tags) -o "$${OUT}" "$<"
+ $(GOCC) build $(go-flags-with-tags) -o "$${OUT}" "$<" 2>&1
endef
.PHONY: github.com/ipfs/kubo/test/dependencies/pollEndpoint
@@ -58,13 +58,13 @@ $(d)/cid-fmt: github.com/ipfs/go-cidutil/cid-fmt
$(go-build-testdep)
TGTS_$(d) += $(d)/cid-fmt
-.PHONY: github.com/jbenet/go-random/random
-$(d)/random: github.com/jbenet/go-random/random
+.PHONY: github.com/ipfs/go-test/cli/random-data
+$(d)/random-data: github.com/ipfs/go-test/cli/random-data
$(go-build-testdep)
-TGTS_$(d) += $(d)/random
+TGTS_$(d) += $(d)/random-data
-.PHONY: github.com/jbenet/go-random-files/random-files
-$(d)/random-files: github.com/jbenet/go-random-files/random-files
+.PHONY: github.com/ipfs/go-test/cli/random-files
+$(d)/random-files: github.com/ipfs/go-test/cli/random-files
$(go-build-testdep)
TGTS_$(d) += $(d)/random-files
diff --git a/test/cli/add_test.go b/test/cli/add_test.go
new file mode 100644
index 00000000000..775a6063baa
--- /dev/null
+++ b/test/cli/add_test.go
@@ -0,0 +1,451 @@
+package cli
+
+import (
+ "io"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/dustin/go-humanize"
+ "github.com/ipfs/kubo/config"
+ "github.com/ipfs/kubo/test/cli/harness"
+ "github.com/ipfs/kubo/test/cli/testutils"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestAdd(t *testing.T) {
+ t.Parallel()
+
+ var (
+ shortString = "hello world"
+ shortStringCidV0 = "Qmf412jQZiuVUtdgnB36FXFX7xg5V6KEbSJ4dpQuhkLyfD" // cidv0 - dag-pb - sha2-256
+ shortStringCidV1 = "bafkreifzjut3te2nhyekklss27nh3k72ysco7y32koao5eei66wof36n5e" // cidv1 - raw - sha2-256
+ shortStringCidV1NoRawLeaves = "bafybeihykld7uyxzogax6vgyvag42y7464eywpf55gxi5qpoisibh3c5wa" // cidv1 - dag-pb - sha2-256
+ shortStringCidV1Sha512 = "bafkrgqbqt3gerhas23vuzrapkdeqf4vu2dwxp3srdj6hvg6nhsug2tgyn6mj3u23yx7utftq3i2ckw2fwdh5qmhid5qf3t35yvkc5e5ottlw6"
+ )
+
+ const (
+ cidV0Length = 34 // cidv0 sha2-256
+ cidV1Length = 36 // cidv1 sha2-256
+ )
+
+ t.Run("produced cid version: implicit default (CIDv0)", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init().StartDaemon()
+ defer node.StopDaemon()
+
+ cidStr := node.IPFSAddStr(shortString)
+ require.Equal(t, shortStringCidV0, cidStr)
+ })
+
+ t.Run("produced cid version: follows user-set configuration Import.CidVersion=0", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init()
+ node.UpdateConfig(func(cfg *config.Config) {
+ cfg.Import.CidVersion = *config.NewOptionalInteger(0)
+ })
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ cidStr := node.IPFSAddStr(shortString)
+ require.Equal(t, shortStringCidV0, cidStr)
+ })
+
+ t.Run("produced cid multihash: follows user-set configuration in Import.HashFunction", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init()
+ node.UpdateConfig(func(cfg *config.Config) {
+ cfg.Import.HashFunction = *config.NewOptionalString("sha2-512")
+ })
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ cidStr := node.IPFSAddStr(shortString)
+ require.Equal(t, shortStringCidV1Sha512, cidStr)
+ })
+
+ t.Run("produced cid version: follows user-set configuration Import.CidVersion=1", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init()
+ node.UpdateConfig(func(cfg *config.Config) {
+ cfg.Import.CidVersion = *config.NewOptionalInteger(1)
+ })
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ cidStr := node.IPFSAddStr(shortString)
+ require.Equal(t, shortStringCidV1, cidStr)
+ })
+
+ t.Run("produced cid version: command flag overrides configuration in Import.CidVersion", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init()
+ node.UpdateConfig(func(cfg *config.Config) {
+ cfg.Import.CidVersion = *config.NewOptionalInteger(1)
+ })
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ cidStr := node.IPFSAddStr(shortString, "--cid-version", "0")
+ require.Equal(t, shortStringCidV0, cidStr)
+ })
+
+ t.Run("produced unixfs raw leaves: follows user-set configuration Import.UnixFSRawLeaves", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init()
+ node.UpdateConfig(func(cfg *config.Config) {
+ // CIDv1 defaults to raw-leaves=true
+ cfg.Import.CidVersion = *config.NewOptionalInteger(1)
+ // disable manually
+ cfg.Import.UnixFSRawLeaves = config.False
+ })
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ cidStr := node.IPFSAddStr(shortString)
+ require.Equal(t, shortStringCidV1NoRawLeaves, cidStr)
+ })
+
+ t.Run("produced unixfs max file links: command flag --max-file-links overrides configuration in Import.UnixFSFileMaxLinks", func(t *testing.T) {
+ t.Parallel()
+
+ //
+ // UnixFSChunker=size-262144 (256KiB)
+ // Import.UnixFSFileMaxLinks=174
+ node := harness.NewT(t).NewNode().Init("--profile=legacy-cid-v0") // legacy-cid-v0 for determinism across all params
+ node.UpdateConfig(func(cfg *config.Config) {
+ cfg.Import.UnixFSChunker = *config.NewOptionalString("size-262144") // 256 KiB chunks
+ cfg.Import.UnixFSFileMaxLinks = *config.NewOptionalInteger(174) // max 174 per level
+ })
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ // Add 174MiB file:
+ // 1024 * 256KiB should fit in single layer
+ seed := shortString
+ cidStr := node.IPFSAddDeterministic("262144KiB", seed, "--max-file-links", "1024")
+ root, err := node.InspectPBNode(cidStr)
+ assert.NoError(t, err)
+
+ // Expect 1024 links due to cli parameter raising link limit from 174 to 1024
+ require.Equal(t, 1024, len(root.Links))
+ // expect same CID every time
+ require.Equal(t, "QmbBftNHWmjSWKLC49dMVrfnY8pjrJYntiAXirFJ7oJrNk", cidStr)
+ })
+
+ t.Run("ipfs init --profile=legacy-cid-v0 sets config that produces legacy CIDv0", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init("--profile=legacy-cid-v0")
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ cidStr := node.IPFSAddStr(shortString)
+ require.Equal(t, shortStringCidV0, cidStr)
+ })
+
+ t.Run("ipfs init --profile=legacy-cid-v0 applies UnixFSChunker=size-262144 and UnixFSFileMaxLinks", func(t *testing.T) {
+ t.Parallel()
+ seed := "v0-seed"
+ profile := "--profile=legacy-cid-v0"
+
+ t.Run("under UnixFSFileMaxLinks=174", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init(profile)
+ node.StartDaemon()
+ defer node.StopDaemon()
+ // Add 44544KiB file:
+ // 174 * 256KiB should fit in single DAG layer
+ cidStr := node.IPFSAddDeterministic("44544KiB", seed)
+ root, err := node.InspectPBNode(cidStr)
+ assert.NoError(t, err)
+ require.Equal(t, 174, len(root.Links))
+ // expect same CID every time
+ require.Equal(t, "QmUbBALi174SnogsUzLpYbD4xPiBSFANF4iztWCsHbMKh2", cidStr)
+ })
+
+ t.Run("above UnixFSFileMaxLinks=174", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init(profile)
+ node.StartDaemon()
+ defer node.StopDaemon()
+ // add 256KiB (one more block), it should force rebalancing DAG and moving most to second layer
+ cidStr := node.IPFSAddDeterministic("44800KiB", seed)
+ root, err := node.InspectPBNode(cidStr)
+ assert.NoError(t, err)
+ require.Equal(t, 2, len(root.Links))
+ // expect same CID every time
+ require.Equal(t, "QmepeWtdmS1hHXx1oZXsPUv6bMrfRRKfZcoPPU4eEfjnbf", cidStr)
+ })
+ })
+
+ t.Run("ipfs init --profile=legacy-cid-v0 applies UnixFSHAMTDirectoryMaxFanout=256 and UnixFSHAMTDirectorySizeThreshold=256KiB", func(t *testing.T) {
+ t.Parallel()
+ seed := "hamt-legacy-cid-v0"
+ profile := "--profile=legacy-cid-v0"
+
+ t.Run("under UnixFSHAMTDirectorySizeThreshold=256KiB", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init(profile)
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ randDir, err := os.MkdirTemp(node.Dir, seed)
+ require.NoError(t, err)
+
+ // Create directory with a lot of files that have filenames which together take close to UnixFSHAMTDirectorySizeThreshold in total
+ err = createDirectoryForHAMT(randDir, cidV0Length, "255KiB", seed)
+ require.NoError(t, err)
+ cidStr := node.IPFS("add", "-r", "-Q", randDir).Stdout.Trimmed()
+
+ // Confirm the number of links is more than UnixFSHAMTDirectorySizeThreshold (indicating regular "basic" directory"
+ root, err := node.InspectPBNode(cidStr)
+ assert.NoError(t, err)
+ require.Equal(t, 903, len(root.Links))
+ })
+
+ t.Run("above UnixFSHAMTDirectorySizeThreshold=256KiB", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init(profile)
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ randDir, err := os.MkdirTemp(node.Dir, seed)
+ require.NoError(t, err)
+
+ // Create directory with a lot of files that have filenames which together take close to UnixFSHAMTDirectorySizeThreshold in total
+ err = createDirectoryForHAMT(randDir, cidV0Length, "257KiB", seed)
+ require.NoError(t, err)
+ cidStr := node.IPFS("add", "-r", "-Q", randDir).Stdout.Trimmed()
+
+ // Confirm this time, the number of links is less than UnixFSHAMTDirectorySizeThreshold
+ root, err := node.InspectPBNode(cidStr)
+ assert.NoError(t, err)
+ require.Equal(t, 252, len(root.Links))
+ })
+ })
+
+ t.Run("ipfs init --profile=test-cid-v1 produces CIDv1 with raw leaves", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init("--profile=test-cid-v1")
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ cidStr := node.IPFSAddStr(shortString)
+ require.Equal(t, shortStringCidV1, cidStr) // raw leaf
+ })
+
+ t.Run("ipfs init --profile=test-cid-v1 applies UnixFSChunker=size-1048576", func(t *testing.T) {
+ t.Parallel()
+ seed := "v1-seed"
+ profile := "--profile=test-cid-v1"
+
+ t.Run("under UnixFSFileMaxLinks=174", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init(profile)
+ node.StartDaemon()
+ defer node.StopDaemon()
+ // Add 174MiB file:
+ // 174 * 1MiB should fit in single layer
+ cidStr := node.IPFSAddDeterministic("174MiB", seed)
+ root, err := node.InspectPBNode(cidStr)
+ assert.NoError(t, err)
+ require.Equal(t, 174, len(root.Links))
+ // expect same CID every time
+ require.Equal(t, "bafybeigwduxcf2aawppv3isnfeshnimkyplvw3hthxjhr2bdeje4tdaicu", cidStr)
+ })
+
+ t.Run("above UnixFSFileMaxLinks=174", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init(profile)
+ node.StartDaemon()
+ defer node.StopDaemon()
+ // add +1MiB (one more block), it should force rebalancing DAG and moving most to second layer
+ cidStr := node.IPFSAddDeterministic("175MiB", seed)
+ root, err := node.InspectPBNode(cidStr)
+ assert.NoError(t, err)
+ require.Equal(t, 2, len(root.Links))
+ // expect same CID every time
+ require.Equal(t, "bafybeidhd7lo2n2v7lta5yamob3xwhbxcczmmtmhquwhjesi35jntf7mpu", cidStr)
+ })
+ })
+
+ t.Run("ipfs init --profile=test-cid-v1 applies UnixFSHAMTDirectoryMaxFanout=256 and UnixFSHAMTDirectorySizeThreshold=256KiB", func(t *testing.T) {
+ t.Parallel()
+ seed := "hamt-cid-v1"
+ profile := "--profile=test-cid-v1"
+
+ t.Run("under UnixFSHAMTDirectorySizeThreshold=256KiB", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init(profile)
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ randDir, err := os.MkdirTemp(node.Dir, seed)
+ require.NoError(t, err)
+
+ // Create directory with a lot of files that have filenames which together take close to UnixFSHAMTDirectorySizeThreshold in total
+ err = createDirectoryForHAMT(randDir, cidV1Length, "255KiB", seed)
+ require.NoError(t, err)
+ cidStr := node.IPFS("add", "-r", "-Q", randDir).Stdout.Trimmed()
+
+ // Confirm the number of links is more than UnixFSHAMTDirectoryMaxFanout (indicating regular "basic" directory"
+ root, err := node.InspectPBNode(cidStr)
+ assert.NoError(t, err)
+ require.Equal(t, 897, len(root.Links))
+ })
+
+ t.Run("above UnixFSHAMTDirectorySizeThreshold=256KiB", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init(profile)
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ randDir, err := os.MkdirTemp(node.Dir, seed)
+ require.NoError(t, err)
+
+ // Create directory with a lot of files that have filenames which together take close to UnixFSHAMTDirectorySizeThreshold in total
+ err = createDirectoryForHAMT(randDir, cidV1Length, "257KiB", seed)
+ require.NoError(t, err)
+ cidStr := node.IPFS("add", "-r", "-Q", randDir).Stdout.Trimmed()
+
+ // Confirm this time, the number of links is less than UnixFSHAMTDirectoryMaxFanout
+ root, err := node.InspectPBNode(cidStr)
+ assert.NoError(t, err)
+ require.Equal(t, 252, len(root.Links))
+ })
+ })
+
+ t.Run("ipfs init --profile=test-cid-v1-wide applies UnixFSChunker=size-1048576 and UnixFSFileMaxLinks=1024", func(t *testing.T) {
+ t.Parallel()
+ seed := "v1-seed-1024"
+ profile := "--profile=test-cid-v1-wide"
+
+ t.Run("under UnixFSFileMaxLinks=1024", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init(profile)
+ node.StartDaemon()
+ defer node.StopDaemon()
+ // Add 174MiB file:
+ // 1024 * 1MiB should fit in single layer
+ cidStr := node.IPFSAddDeterministic("1024MiB", seed)
+ root, err := node.InspectPBNode(cidStr)
+ assert.NoError(t, err)
+ require.Equal(t, 1024, len(root.Links))
+ // expect same CID every time
+ require.Equal(t, "bafybeiej5w63ir64oxgkr5htqmlerh5k2rqflurn2howimexrlkae64xru", cidStr)
+ })
+
+ t.Run("above UnixFSFileMaxLinks=1024", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init(profile)
+ node.StartDaemon()
+ defer node.StopDaemon()
+ // add +1MiB (one more block), it should force rebalancing DAG and moving most to second layer
+ cidStr := node.IPFSAddDeterministic("1025MiB", seed)
+ root, err := node.InspectPBNode(cidStr)
+ assert.NoError(t, err)
+ require.Equal(t, 2, len(root.Links))
+ // expect same CID every time
+ require.Equal(t, "bafybeieilp2qx24pe76hxrxe6bpef5meuxto3kj5dd6mhb5kplfeglskdm", cidStr)
+ })
+ })
+
+ t.Run("ipfs init --profile=test-cid-v1-wide applies UnixFSHAMTDirectoryMaxFanout=256 and UnixFSHAMTDirectorySizeThreshold=1MiB", func(t *testing.T) {
+ t.Parallel()
+ seed := "hamt-cid-v1"
+ profile := "--profile=test-cid-v1-wide"
+
+ t.Run("under UnixFSHAMTDirectorySizeThreshold=1MiB", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init(profile)
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ randDir, err := os.MkdirTemp(node.Dir, seed)
+ require.NoError(t, err)
+
+ // Create directory with a lot of files that have filenames which together take close to UnixFSHAMTDirectorySizeThreshold in total
+ err = createDirectoryForHAMT(randDir, cidV1Length, "1023KiB", seed)
+ require.NoError(t, err)
+ cidStr := node.IPFS("add", "-r", "-Q", randDir).Stdout.Trimmed()
+
+ // Confirm the number of links is more than UnixFSHAMTDirectoryMaxFanout (indicating regular "basic" directory"
+ root, err := node.InspectPBNode(cidStr)
+ assert.NoError(t, err)
+ require.Equal(t, 3599, len(root.Links))
+ })
+
+ t.Run("above UnixFSHAMTDirectorySizeThreshold=1MiB", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init(profile)
+ node.StartDaemon()
+ defer node.StopDaemon()
+
+ randDir, err := os.MkdirTemp(node.Dir, seed)
+ require.NoError(t, err)
+
+ // Create directory with a lot of files that have filenames which together take close to UnixFSHAMTDirectorySizeThreshold in total
+ err = createDirectoryForHAMT(randDir, cidV1Length, "1025KiB", seed)
+ require.NoError(t, err)
+ cidStr := node.IPFS("add", "-r", "-Q", randDir).Stdout.Trimmed()
+
+ // Confirm this time, the number of links is less than UnixFSHAMTDirectoryMaxFanout
+ root, err := node.InspectPBNode(cidStr)
+ assert.NoError(t, err)
+ require.Equal(t, 992, len(root.Links))
+ })
+ })
+
+}
+
+// createDirectoryForHAMT aims to create enough files with long names for the directory block to be close to the UnixFSHAMTDirectorySizeThreshold.
+// The calculation is based on boxo's HAMTShardingSize and sizeBelowThreshold which calculates ballpark size of the block
+// by adding length of link names and the binary cid length.
+// See https://github.com/ipfs/boxo/blob/6c5a07602aed248acc86598f30ab61923a54a83e/ipld/unixfs/io/directory.go#L491
+func createDirectoryForHAMT(dirPath string, cidLength int, unixfsNodeSizeTarget, seed string) error {
+ hamtThreshold, err := humanize.ParseBytes(unixfsNodeSizeTarget)
+ if err != nil {
+ return err
+ }
+
+ // Calculate how many files with long filenames are needed to hit UnixFSHAMTDirectorySizeThreshold
+ nameLen := 255 // max that works across windows/macos/linux
+ alphabetLen := len(testutils.AlphabetEasy)
+ numFiles := int(hamtThreshold) / (nameLen + cidLength)
+
+ // Deterministic pseudo-random bytes for static CID
+ drand, err := testutils.DeterministicRandomReader(unixfsNodeSizeTarget, seed)
+ if err != nil {
+ return err
+ }
+
+ // Create necessary files in a single, flat directory
+ for i := 0; i < numFiles; i++ {
+ buf := make([]byte, nameLen)
+ _, err := io.ReadFull(drand, buf)
+ if err != nil {
+ return err
+ }
+
+ // Convert deterministic pseudo-random bytes to ASCII
+ var sb strings.Builder
+
+ for _, b := range buf {
+ // Map byte to printable ASCII range (33-126)
+ char := testutils.AlphabetEasy[int(b)%alphabetLen]
+ sb.WriteRune(char)
+ }
+ filename := sb.String()[:nameLen]
+ filePath := filepath.Join(dirPath, filename)
+
+ // Create empty file
+ f, err := os.Create(filePath)
+ if err != nil {
+ return err
+ }
+ f.Close()
+ }
+ return nil
+}
diff --git a/test/cli/basic_commands_test.go b/test/cli/basic_commands_test.go
index b4bb2c182cf..62733d00b6f 100644
--- a/test/cli/basic_commands_test.go
+++ b/test/cli/basic_commands_test.go
@@ -62,7 +62,7 @@ func TestIPFSVersionDeps(t *testing.T) {
res = strings.TrimSpace(res)
lines := SplitLines(res)
- assert.Equal(t, "github.com/ipfs/kubo@(devel)", lines[0])
+ assert.True(t, strings.HasPrefix(lines[0], "github.com/ipfs/kubo@v"))
for _, depLine := range lines[1:] {
split := strings.Split(depLine, " => ")
@@ -112,7 +112,7 @@ func TestAllRootCommandsAreMentionedInHelpText(t *testing.T) {
// 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
+ // have to make a conscious decision to exclude them
notInHelp := map[string]bool{
"object": true,
"shutdown": true,
@@ -147,14 +147,12 @@ func TestCommandDocsWidth(t *testing.T) {
"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 pin update": true,
"ipfs pin rm": true,
@@ -165,9 +163,6 @@ func TestCommandDocsWidth(t *testing.T) {
"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,
diff --git a/test/cli/bitswap_config_test.go b/test/cli/bitswap_config_test.go
new file mode 100644
index 00000000000..9674d3cb6b3
--- /dev/null
+++ b/test/cli/bitswap_config_test.go
@@ -0,0 +1,176 @@
+package cli
+
+import (
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/ipfs/boxo/bitswap/network/bsnet"
+ "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 TestBitswapConfig(t *testing.T) {
+ t.Parallel()
+
+ // Create test data that will be shared between nodes
+ testData := testutils.RandomBytes(100)
+
+ t.Run("server enabled (default)", func(t *testing.T) {
+ t.Parallel()
+ h := harness.NewT(t)
+ provider := h.NewNode().Init().StartDaemon()
+ requester := h.NewNode().Init().StartDaemon()
+
+ hash := provider.IPFSAddStr(string(testData))
+ requester.Connect(provider)
+
+ res := requester.IPFS("cat", hash)
+ assert.Equal(t, testData, res.Stdout.Bytes(), "retrieved data should match original")
+ })
+
+ t.Run("server disabled", func(t *testing.T) {
+ t.Parallel()
+ h := harness.NewT(t)
+
+ provider := h.NewNode().Init()
+ provider.SetIPFSConfig("Bitswap.ServerEnabled", false)
+ provider = provider.StartDaemon()
+
+ requester := h.NewNode().Init().StartDaemon()
+
+ hash := provider.IPFSAddStr(string(testData))
+ requester.Connect(provider)
+
+ // If the data was available, it would be retrieved immediately.
+ // Therefore, after the timeout, we can assume the data is not available
+ // i.e. the server is disabled
+ timeout := time.After(3 * time.Second)
+ dataChan := make(chan []byte)
+
+ go func() {
+ res := requester.RunIPFS("cat", hash)
+ dataChan <- res.Stdout.Bytes()
+ }()
+
+ select {
+ case data := <-dataChan:
+ assert.NotEqual(t, testData, data, "retrieved data should not match original")
+ case <-timeout:
+ t.Log("Test passed: operation timed out after 3 seconds as expected")
+ }
+ })
+
+ t.Run("client still works when server disabled", func(t *testing.T) {
+ t.Parallel()
+ h := harness.NewT(t)
+
+ requester := h.NewNode().Init()
+ requester.SetIPFSConfig("Bitswap.ServerEnabled", false)
+ requester.StartDaemon()
+
+ provider := h.NewNode().Init().StartDaemon()
+ hash := provider.IPFSAddStr(string(testData))
+ requester.Connect(provider)
+
+ // Even when the server is disabled, the client should be able to retrieve data
+ res := requester.RunIPFS("cat", hash)
+ assert.Equal(t, testData, res.Stdout.Bytes(), "retrieved data should match original")
+ })
+
+ t.Run("bitswap over libp2p disabled", func(t *testing.T) {
+ t.Parallel()
+ h := harness.NewT(t)
+
+ requester := h.NewNode().Init()
+ requester.UpdateConfig(func(cfg *config.Config) {
+ cfg.Bitswap.Libp2pEnabled = config.False
+ cfg.Bitswap.ServerEnabled = config.False
+ cfg.HTTPRetrieval.Enabled = config.True
+ })
+ requester.StartDaemon()
+
+ provider := h.NewNode().Init().StartDaemon()
+ hash := provider.IPFSAddStr(string(testData))
+
+ requester.Connect(provider)
+ res := requester.RunIPFS("cat", hash)
+ assert.Equal(t, []byte{}, res.Stdout.Bytes(), "cat should not return any data")
+ assert.Contains(t, res.Stderr.String(), "Error: ipld: could not find")
+
+ // Verify that basic operations still work with bitswap disabled
+ res = requester.IPFS("id")
+ assert.Equal(t, 0, res.ExitCode(), "basic IPFS operations should work")
+ res = requester.IPFS("bitswap", "stat")
+ assert.Equal(t, 0, res.ExitCode(), "bitswap stat should work even with bitswap disabled")
+ res = requester.IPFS("bitswap", "wantlist")
+ assert.Equal(t, 0, res.ExitCode(), "bitswap wantlist should work even with bitswap disabled")
+
+ // Verify local operations still work
+ hashNew := requester.IPFSAddStr("random")
+ res = requester.IPFS("cat", hashNew)
+ assert.Equal(t, []byte("random"), res.Stdout.Bytes(), "cat should return the added data")
+ })
+
+ // Disabling Bitswap.Libp2pEnabled should remove /ipfs/bitswap* protocols from `ipfs id`
+ t.Run("disabling bitswap over libp2p removes it from identify protocol list", func(t *testing.T) {
+ t.Parallel()
+ h := harness.NewT(t)
+
+ provider := h.NewNode().Init()
+ provider.UpdateConfig(func(cfg *config.Config) {
+ cfg.Bitswap.Libp2pEnabled = config.False
+ cfg.Bitswap.ServerEnabled = config.False
+ cfg.HTTPRetrieval.Enabled = config.True
+ })
+ provider = provider.StartDaemon()
+ requester := h.NewNode().Init().StartDaemon()
+ requester.Connect(provider)
+
+ // read libp2p identify from remote peer, and print protocols
+ res := requester.IPFS("id", "-f", "", provider.PeerID().String())
+ protocols := strings.Split(strings.TrimSpace(res.Stdout.String()), "\n")
+
+ // No bitswap protocols should be present
+ for _, proto := range protocols {
+ assert.NotContains(t, proto, bsnet.ProtocolBitswap, "bitswap protocol %s should not be advertised when server is disabled", proto)
+ assert.NotContains(t, proto, bsnet.ProtocolBitswapNoVers, "bitswap protocol %s should not be advertised when server is disabled", proto)
+ assert.NotContains(t, proto, bsnet.ProtocolBitswapOneOne, "bitswap protocol %s should not be advertised when server is disabled", proto)
+ assert.NotContains(t, proto, bsnet.ProtocolBitswapOneZero, "bitswap protocol %s should not be advertised when server is disabled", proto)
+ }
+ })
+
+ // HTTPRetrieval uses bitswap engine, we need it
+ t.Run("errors when both HTTP and libp2p are disabled", func(t *testing.T) {
+ t.Parallel()
+
+ // init Kubo repo
+ node := harness.NewT(t).NewNode().Init()
+ node.UpdateConfig(func(cfg *config.Config) {
+ cfg.HTTPRetrieval.Enabled = config.False
+ cfg.Bitswap.Libp2pEnabled = config.False
+ cfg.Bitswap.ServerEnabled = config.Default
+ })
+ res := node.RunIPFS("daemon")
+ assert.Contains(t, res.Stderr.Trimmed(), "invalid configuration: Bitswap.Libp2pEnabled and HTTPRetrieval.Enabled are both disabled, unable to initialize Bitswap")
+ assert.Equal(t, 1, res.ExitCode())
+ })
+
+ // HTTPRetrieval uses bitswap engine, we need it
+ t.Run("errors when user set conflicting HTTP and libp2p flags", func(t *testing.T) {
+ t.Parallel()
+
+ // init Kubo repo
+ node := harness.NewT(t).NewNode().Init()
+ node.UpdateConfig(func(cfg *config.Config) {
+ cfg.HTTPRetrieval.Enabled = config.False
+ cfg.Bitswap.Libp2pEnabled = config.False
+ cfg.Bitswap.ServerEnabled = config.True // bad user config: can't enable server when libp2p is down
+ })
+ res := node.RunIPFS("daemon")
+ assert.Contains(t, res.Stderr.Trimmed(), "invalid configuration: Bitswap.Libp2pEnabled and HTTPRetrieval.Enabled are both disabled, unable to initialize Bitswap")
+ assert.Equal(t, 1, res.ExitCode())
+ })
+}
diff --git a/test/cli/cli_https_test.go b/test/cli/cli_https_test.go
new file mode 100644
index 00000000000..e128a191641
--- /dev/null
+++ b/test/cli/cli_https_test.go
@@ -0,0 +1,46 @@
+package cli
+
+import (
+ "fmt"
+ "net"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "testing"
+
+ "github.com/ipfs/kubo/test/cli/harness"
+ "github.com/stretchr/testify/require"
+)
+
+func TestCLIWithRemoteHTTPS(t *testing.T) {
+ tests := []struct{ addrSuffix string }{{"https"}, {"tls/http"}}
+ for _, tt := range tests {
+ t.Run("with "+tt.addrSuffix+" multiaddr", func(t *testing.T) {
+
+ // Create HTTPS test server
+ server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.TLS == nil {
+ t.Error("Mocked Kubo RPC received plain HTTP request instead of HTTPS TLS Handshake")
+ }
+ _, _ = w.Write([]byte("OK"))
+ }))
+ defer server.Close()
+
+ serverURL, _ := url.Parse(server.URL)
+ _, port, _ := net.SplitHostPort(serverURL.Host)
+
+ // Create Kubo repo
+ node := harness.NewT(t).NewNode().Init()
+
+ // Attempt to talk to remote Kubo RPC endpoint over HTTPS
+ resp := node.RunIPFS("id", "--api", fmt.Sprintf("/ip4/127.0.0.1/tcp/%s/%s", port, tt.addrSuffix))
+
+ // Expect HTTPS error (confirming TLS and https:// were used, and not Cleartext HTTP)
+ require.Error(t, resp.Err)
+ require.Contains(t, resp.Stderr.String(), "Error: tls: failed to verify certificate: x509: certificate signed by unknown authority")
+
+ node.StopDaemon()
+
+ })
+ }
+}
diff --git a/test/cli/content_blocking_test.go b/test/cli/content_blocking_test.go
index ddb7c951e88..6598354d16e 100644
--- a/test/cli/content_blocking_test.go
+++ b/test/cli/content_blocking_test.go
@@ -12,7 +12,9 @@ import (
"strings"
"testing"
+ "github.com/ipfs/go-cid"
"github.com/ipfs/kubo/test/cli/harness"
+ carstore "github.com/ipld/go-car/v2/blockstore"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/peer"
libp2phttp "github.com/libp2p/go-libp2p/p2p/http"
@@ -34,8 +36,10 @@ func TestContentBlocking(t *testing.T) {
node := h.NewNode().Init("--empty-repo", "--profile=test")
// Create CIDs we use in test
- h.WriteFile("blocked-dir/subdir/indirectly-blocked-file.txt", "indirectly blocked file content")
- parentDirCID := node.IPFS("add", "--raw-leaves", "-Q", "-r", filepath.Join(h.Dir, "blocked-dir")).Stdout.Trimmed()
+ h.WriteFile("parent-dir/blocked-subdir/indirectly-blocked-file.txt", "indirectly blocked file content")
+ allowedParentDirCID := node.IPFS("add", "--raw-leaves", "-Q", "-r", "--pin=false", filepath.Join(h.Dir, "parent-dir")).Stdout.Trimmed()
+ blockedSubDirCID := node.IPFS("add", "--raw-leaves", "-Q", "-r", "--pin=false", filepath.Join(h.Dir, "parent-dir", "blocked-subdir")).Stdout.Trimmed()
+ node.IPFS("block", "rm", blockedSubDirCID)
h.WriteFile("directly-blocked-file.txt", "directly blocked file content")
blockedCID := node.IPFS("add", "--raw-leaves", "-Q", filepath.Join(h.Dir, "directly-blocked-file.txt")).Stdout.Trimmed()
@@ -50,7 +54,7 @@ func TestContentBlocking(t *testing.T) {
"//8526ba05eec55e28f8db5974cc891d0d92c8af69d386fc6464f1e9f372caf549\n" + // Legacy CID double-hash block: sha256(bafkqahtcnrxwg23fmqqgi33vmjwgk2dbonuca3dfm5qwg6jamnuwicq/)
"//e5b7d2ce2594e2e09901596d8e1f29fa249b74c8c9e32ea01eda5111e4d33f07\n" + // Legacy Path double-hash block: sha256(bafyaagyscufaqalqaacauaqiaejao43vmjygc5didacauaqiae/subpath)
"/ipfs/" + blockedCID + "\n" + // block specific CID
- "/ipfs/" + parentDirCID + "/subdir*\n" + // block only specific subpath
+ "/ipfs/" + allowedParentDirCID + "/blocked-subdir*\n" + // block only specific subpath
"/ipns/blocked-cid.example.com\n" +
"/ipns/blocked-dnslink.example.com\n")
@@ -94,22 +98,63 @@ func TestContentBlocking(t *testing.T) {
// Confirm parent of blocked subpath is not blocked
t.Run("Gateway Allows parent Path that is not blocked", func(t *testing.T) {
t.Parallel()
- resp := client.Get("/ipfs/" + parentDirCID)
+ resp := client.Get("/ipfs/" + allowedParentDirCID)
assert.Equal(t, http.StatusOK, resp.StatusCode)
})
+ // Confirm CAR responses skip blocked subpaths
+ t.Run("Gateway returns CAR without blocked subpath", func(t *testing.T) {
+ resp := client.Get("/ipfs/" + allowedParentDirCID + "/subdir?format=car")
+ assert.Equal(t, http.StatusOK, resp.StatusCode)
+
+ bs, err := carstore.NewReadOnly(strings.NewReader(resp.Body), nil)
+ assert.NoError(t, err)
+
+ has, err := bs.Has(context.Background(), cid.MustParse(blockedSubDirCID))
+ assert.NoError(t, err)
+ assert.False(t, has)
+ })
+
+ /* TODO: this was already broken in 0.26, but we should fix it
+ t.Run("Gateway returns CAR without directly blocked CID", func(t *testing.T) {
+ allowedDirWithDirectlyBlockedCID := node.IPFS("add", "--raw-leaves", "-Q", "-rw", filepath.Join(h.Dir, "directly-blocked-file.txt")).Stdout.Trimmed()
+ resp := client.Get("/ipfs/" + allowedDirWithDirectlyBlockedCID + "?format=car")
+ assert.Equal(t, http.StatusOK, resp.StatusCode)
+
+ bs, err := carstore.NewReadOnly(strings.NewReader(resp.Body), nil)
+ assert.NoError(t, err)
+
+ has, err := bs.Has(context.Background(), cid.MustParse(blockedCID))
+ assert.NoError(t, err)
+ assert.False(t, has, "Returned CAR should not include blockedCID")
+ })
+ */
+
+ // Confirm CAR responses skip blocked subpaths
+ t.Run("Gateway returns CAR without blocked subpath", func(t *testing.T) {
+ resp := client.Get("/ipfs/" + allowedParentDirCID + "/subdir?format=car")
+ assert.Equal(t, http.StatusOK, resp.StatusCode)
+
+ bs, err := carstore.NewReadOnly(strings.NewReader(resp.Body), nil)
+ assert.NoError(t, err)
+
+ has, err := bs.Has(context.Background(), cid.MustParse(blockedSubDirCID))
+ assert.NoError(t, err)
+ assert.False(t, has, "Returned CAR should not include blockedSubDirCID")
+ })
+
// Ok, now the full list of test cases we want to cover in both CLI and Gateway
testCases := []struct {
name string
path string
}{
{
- name: "directly blocked CID",
+ name: "directly blocked file CID",
path: "/ipfs/" + blockedCID,
},
{
name: "indirectly blocked file (on a blocked subpath)",
- path: "/ipfs/" + parentDirCID + "/subdir/indirectly-blocked-file.txt",
+ path: "/ipfs/" + allowedParentDirCID + "/blocked-subdir/indirectly-blocked-file.txt",
},
{
name: "/ipns path that resolves to a blocked CID",
@@ -161,9 +206,14 @@ func TestContentBlocking(t *testing.T) {
t.Run(cliTestName, func(t *testing.T) {
t.Parallel()
args := append(cmd, testCase.path)
- errMsg := node.RunIPFS(args...).Stderr.Trimmed()
- if !strings.Contains(errMsg, expectedMsg) {
- t.Errorf("Expected STDERR error message %q, but got: %q", expectedMsg, errMsg)
+ cmd := node.RunIPFS(args...)
+ stdout := cmd.Stdout.Trimmed()
+ stderr := cmd.Stderr.Trimmed()
+ if !strings.Contains(stderr, expectedMsg) {
+ t.Errorf("Expected STDERR error message %q, but got: %q", expectedMsg, stderr)
+ if stdout != "" {
+ t.Errorf("Expected STDOUT to be empty, but got: %q", stdout)
+ }
}
})
}
@@ -299,5 +349,17 @@ func TestContentBlocking(t *testing.T) {
assert.NotEqual(t, string(body), "directly blocked file content")
assert.Contains(t, string(body), blockedMsg, bodyExpl)
})
+
+ t.Run("Denies Blocked CID as CAR", func(t *testing.T) {
+ t.Parallel()
+ resp, err := libp2pClient.Get(fmt.Sprintf("/ipfs/%s?format=car", blockedCID))
+ require.NoError(t, err)
+ defer resp.Body.Close()
+ assert.Equal(t, http.StatusGone, resp.StatusCode, statusExpl)
+ body, err := io.ReadAll(resp.Body)
+ require.NoError(t, err)
+ assert.NotContains(t, string(body), "directly blocked file content")
+ assert.Contains(t, string(body), blockedMsg, bodyExpl)
+ })
})
}
diff --git a/test/cli/content_routing_http_test.go b/test/cli/content_routing_http_test.go
index aea5c41caeb..4b210cfbaef 100644
--- a/test/cli/content_routing_http_test.go
+++ b/test/cli/content_routing_http_test.go
@@ -1,69 +1,20 @@
package cli
import (
- "context"
"net/http"
"net/http/httptest"
"os/exec"
- "sync"
"testing"
"time"
- "github.com/ipfs/boxo/ipns"
"github.com/ipfs/boxo/routing/http/server"
- "github.com/ipfs/boxo/routing/http/types"
- "github.com/ipfs/boxo/routing/http/types/iter"
- "github.com/ipfs/go-cid"
+ "github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/test/cli/harness"
"github.com/ipfs/kubo/test/cli/testutils"
- "github.com/libp2p/go-libp2p/core/peer"
- "github.com/libp2p/go-libp2p/core/routing"
+ "github.com/ipfs/kubo/test/cli/testutils/httprouting"
"github.com/stretchr/testify/assert"
)
-type fakeHTTPContentRouter struct {
- m sync.Mutex
- provideBitswapCalls int
- findProvidersCalls int
- findPeersCalls int
-}
-
-func (r *fakeHTTPContentRouter) FindProviders(ctx context.Context, key cid.Cid, limit int) (iter.ResultIter[types.Record], error) {
- r.m.Lock()
- defer r.m.Unlock()
- r.findProvidersCalls++
- return iter.FromSlice([]iter.Result[types.Record]{}), nil
-}
-
-// nolint deprecated
-func (r *fakeHTTPContentRouter) ProvideBitswap(ctx context.Context, req *server.BitswapWriteProvideRequest) (time.Duration, error) {
- r.m.Lock()
- defer r.m.Unlock()
- r.provideBitswapCalls++
- return 0, nil
-}
-
-func (r *fakeHTTPContentRouter) FindPeers(ctx context.Context, pid peer.ID, limit int) (iter.ResultIter[*types.PeerRecord], error) {
- r.m.Lock()
- defer r.m.Unlock()
- r.findPeersCalls++
- return iter.FromSlice([]iter.Result[*types.PeerRecord]{}), nil
-}
-
-func (r *fakeHTTPContentRouter) GetIPNS(ctx context.Context, name ipns.Name) (*ipns.Record, error) {
- return nil, routing.ErrNotSupported
-}
-
-func (r *fakeHTTPContentRouter) PutIPNS(ctx context.Context, name ipns.Name, rec *ipns.Record) error {
- return routing.ErrNotSupported
-}
-
-func (r *fakeHTTPContentRouter) numFindProvidersCalls() int {
- r.m.Lock()
- defer r.m.Unlock()
- return r.findProvidersCalls
-}
-
// userAgentRecorder records the user agent of every HTTP request
type userAgentRecorder struct {
delegate http.Handler
@@ -76,16 +27,19 @@ func (r *userAgentRecorder) ServeHTTP(w http.ResponseWriter, req *http.Request)
}
func TestContentRoutingHTTP(t *testing.T) {
- cr := &fakeHTTPContentRouter{}
+ mockRouter := &httprouting.MockHTTPContentRouter{}
// run the content routing HTTP server
- userAgentRecorder := &userAgentRecorder{delegate: server.Handler(cr)}
+ userAgentRecorder := &userAgentRecorder{delegate: server.Handler(mockRouter)}
server := httptest.NewServer(userAgentRecorder)
t.Cleanup(func() { server.Close() })
// setup the node
node := harness.NewT(t).NewNode().Init()
- node.Runner.Env["IPFS_HTTP_ROUTERS"] = server.URL
+ node.UpdateConfig(func(cfg *config.Config) {
+ // setup Kubo node to use mocked HTTP Router
+ cfg.Routing.DelegatedRouters = []string{server.URL}
+ })
node.StartDaemon()
// compute a random CID
@@ -107,7 +61,7 @@ func TestContentRoutingHTTP(t *testing.T) {
// verify the content router was called
assert.Eventually(t, func() bool {
- return cr.numFindProvidersCalls() > 0
+ return mockRouter.NumFindProvidersCalls() > 0
}, time.Minute, 10*time.Millisecond)
assert.NotEmpty(t, userAgentRecorder.userAgents)
diff --git a/test/cli/dag_test.go b/test/cli/dag_test.go
index d17b71cfb12..1a3defc3c00 100644
--- a/test/cli/dag_test.go
+++ b/test/cli/dag_test.go
@@ -36,7 +36,7 @@ type Data struct {
// The Fixture file represents a dag where 2 nodes of size = 46B each, have a common child of 7B
// when traversing the DAG from the root's children (node1 and node2) we count (46 + 7)x2 bytes (counting redundant bytes) = 106
// since both nodes share a common child of 7 bytes we actually had to read (46)x2 + 7 = 99 bytes
-// we should get a dedup ratio of 106/99 that results in approximatelly 1.0707071
+// we should get a dedup ratio of 106/99 that results in approximately 1.0707071
func TestDag(t *testing.T) {
t.Parallel()
diff --git a/test/cli/delegated_routing_v1_http_proxy_test.go b/test/cli/delegated_routing_v1_http_proxy_test.go
index 1d80ae50a5f..7f8ff8bcaa8 100644
--- a/test/cli/delegated_routing_v1_http_proxy_test.go
+++ b/test/cli/delegated_routing_v1_http_proxy_test.go
@@ -15,9 +15,11 @@ func TestRoutingV1Proxy(t *testing.T) {
t.Parallel()
setupNodes := func(t *testing.T) harness.Nodes {
- nodes := harness.NewT(t).NewNodes(2).Init()
+ nodes := harness.NewT(t).NewNodes(3).Init()
- // Node 0 uses DHT and exposes the Routing API.
+ // Node 0 uses DHT and exposes the Routing API. For the DHT
+ // to actually work there will need to be another DHT-enabled
+ // node.
nodes[0].UpdateConfig(func(cfg *config.Config) {
cfg.Gateway.ExposeRoutingAPI = config.True
cfg.Discovery.MDNS.Enabled = false
@@ -49,6 +51,15 @@ func TestRoutingV1Proxy(t *testing.T) {
})
nodes[1].StartDaemon()
+ // This is the second DHT node. Only used so that the DHT is
+ // operative.
+ nodes[2].UpdateConfig(func(cfg *config.Config) {
+ cfg.Gateway.ExposeRoutingAPI = config.True
+ cfg.Discovery.MDNS.Enabled = false
+ cfg.Routing.Type = config.NewOptionalString("dht")
+ })
+ nodes[2].StartDaemon()
+
// Connect them.
nodes.Connect()
@@ -60,8 +71,10 @@ func TestRoutingV1Proxy(t *testing.T) {
nodes := setupNodes(t)
cidStr := nodes[0].IPFSAddStr(testutils.RandomStr(1000))
-
- res := nodes[1].IPFS("routing", "findprovs", cidStr)
+ // Reprovide as initialProviderDelay still ongoing
+ res := nodes[0].IPFS("routing", "reprovide")
+ require.NoError(t, res.Err)
+ res = nodes[1].IPFS("routing", "findprovs", cidStr)
assert.Equal(t, nodes[0].PeerID().String(), res.Stdout.Trimmed())
})
diff --git a/test/cli/delegated_routing_v1_http_server_test.go b/test/cli/delegated_routing_v1_http_server_test.go
index f2bd98cb77b..8492e761c6c 100644
--- a/test/cli/delegated_routing_v1_http_server_test.go
+++ b/test/cli/delegated_routing_v1_http_server_test.go
@@ -14,6 +14,7 @@ import (
"github.com/ipfs/kubo/test/cli/harness"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func TestRoutingV1Server(t *testing.T) {
@@ -38,6 +39,9 @@ func TestRoutingV1Server(t *testing.T) {
text := "hello world " + uuid.New().String()
cidStr := nodes[2].IPFSAddStr(text)
_ = nodes[3].IPFSAddStr(text)
+ // Reprovide as initialProviderDelay still ongoing
+ res := nodes[3].IPFS("routing", "reprovide")
+ require.NoError(t, res.Err)
cid, err := cid.Decode(cidStr)
assert.NoError(t, err)
diff --git a/test/cli/dht_legacy_test.go b/test/cli/dht_legacy_test.go
deleted file mode 100644
index cfcb4f0cd09..00000000000
--- a/test/cli/dht_legacy_test.go
+++ /dev/null
@@ -1,137 +0,0 @@
-package cli
-
-import (
- "sort"
- "sync"
- "testing"
-
- "github.com/ipfs/kubo/test/cli/harness"
- "github.com/ipfs/kubo/test/cli/testutils"
- "github.com/libp2p/go-libp2p/core/peer"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-)
-
-func TestLegacyDHT(t *testing.T) {
- t.Parallel()
- nodes := harness.NewT(t).NewNodes(5).Init()
- nodes.ForEachPar(func(node *harness.Node) {
- node.IPFS("config", "Routing.Type", "dht")
- })
- nodes.StartDaemons().Connect()
-
- t.Run("ipfs dht findpeer", func(t *testing.T) {
- t.Parallel()
- res := nodes[1].RunIPFS("dht", "findpeer", nodes[0].PeerID().String())
- assert.Equal(t, 0, res.ExitCode())
-
- swarmAddr := nodes[0].SwarmAddrsWithoutPeerIDs()[0]
- require.Equal(t, swarmAddr.String(), res.Stdout.Trimmed())
- })
-
- t.Run("ipfs dht get ", func(t *testing.T) {
- t.Parallel()
- hash := nodes[2].IPFSAddStr("hello world")
- nodes[2].IPFS("name", "publish", "/ipfs/"+hash)
-
- res := nodes[1].IPFS("dht", "get", "/ipns/"+nodes[2].PeerID().String())
- assert.Contains(t, res.Stdout.String(), "/ipfs/"+hash)
-
- t.Run("put round trips (#3124)", func(t *testing.T) {
- t.Parallel()
- nodes[0].WriteBytes("get_result", res.Stdout.Bytes())
- res := nodes[0].IPFS("dht", "put", "/ipns/"+nodes[2].PeerID().String(), "get_result")
- assert.Greater(t, len(res.Stdout.Lines()), 0, "should put to at least one node")
- })
-
- t.Run("put with bad keys fails (issue #5113, #4611)", func(t *testing.T) {
- t.Parallel()
- keys := []string{"foo", "/pk/foo", "/ipns/foo"}
- for _, key := range keys {
- key := key
- t.Run(key, func(t *testing.T) {
- t.Parallel()
- res := nodes[0].RunIPFS("dht", "put", key)
- assert.Equal(t, 1, res.ExitCode())
- assert.Contains(t, res.Stderr.String(), "invalid")
- assert.Empty(t, res.Stdout.String())
- })
- }
- })
-
- t.Run("get with bad keys (issue #4611)", func(t *testing.T) {
- for _, key := range []string{"foo", "/pk/foo"} {
- key := key
- t.Run(key, func(t *testing.T) {
- t.Parallel()
- res := nodes[0].RunIPFS("dht", "get", key)
- assert.Equal(t, 1, res.ExitCode())
- assert.Contains(t, res.Stderr.String(), "invalid")
- assert.Empty(t, res.Stdout.String())
- })
- }
- })
- })
-
- t.Run("ipfs dht findprovs", func(t *testing.T) {
- t.Parallel()
- hash := nodes[3].IPFSAddStr("some stuff")
- res := nodes[4].IPFS("dht", "findprovs", hash)
- assert.Equal(t, nodes[3].PeerID().String(), res.Stdout.Trimmed())
- })
-
- t.Run("ipfs dht query ", func(t *testing.T) {
- t.Parallel()
- t.Run("normal DHT configuration", func(t *testing.T) {
- t.Parallel()
- hash := nodes[0].IPFSAddStr("some other stuff")
- peerCounts := map[string]int{}
- peerCountsMut := sync.Mutex{}
- harness.Nodes(nodes).ForEachPar(func(node *harness.Node) {
- res := node.IPFS("dht", "query", hash)
- closestPeer := res.Stdout.Lines()[0]
- // check that it's a valid peer ID
- _, err := peer.Decode(closestPeer)
- require.NoError(t, err)
-
- peerCountsMut.Lock()
- peerCounts[closestPeer]++
- peerCountsMut.Unlock()
- })
- // 4 nodes should see the same peer ID
- // 1 node (the closest) should see a different one
- var counts []int
- for _, count := range peerCounts {
- counts = append(counts, count)
- }
- sort.IntSlice(counts).Sort()
- assert.Equal(t, []int{1, 4}, counts)
- })
- })
-
- t.Run("dht commands fail when offline", func(t *testing.T) {
- t.Parallel()
- node := harness.NewT(t).NewNode().Init()
-
- // these cannot be run in parallel due to repo locking (seems like a bug)
-
- t.Run("dht findprovs", func(t *testing.T) {
- res := node.RunIPFS("dht", "findprovs", testutils.CIDEmptyDir)
- assert.Equal(t, 1, res.ExitCode())
- assert.Contains(t, res.Stderr.String(), "this command must be run in online mode")
- })
-
- t.Run("dht findpeer", func(t *testing.T) {
- res := node.RunIPFS("dht", "findpeer", testutils.CIDEmptyDir)
- assert.Equal(t, 1, res.ExitCode())
- assert.Contains(t, res.Stderr.String(), "this command must be run in online mode")
- })
-
- t.Run("dht put", func(t *testing.T) {
- node.WriteBytes("foo", []byte("foo"))
- res := node.RunIPFS("dht", "put", "/ipns/"+node.PeerID().String(), "foo")
- assert.Equal(t, 1, res.ExitCode())
- assert.Contains(t, res.Stderr.String(), "can't put while offline: pass `--allow-offline` to override")
- })
- })
-}
diff --git a/test/cli/dht_opt_prov_test.go b/test/cli/dht_opt_prov_test.go
index 5481315afaa..f7b492066af 100644
--- a/test/cli/dht_opt_prov_test.go
+++ b/test/cli/dht_opt_prov_test.go
@@ -22,7 +22,7 @@ func TestDHTOptimisticProvide(t *testing.T) {
nodes.StartDaemons().Connect()
hash := nodes[0].IPFSAddStr(testutils.RandomStr(100))
- nodes[0].IPFS("dht", "provide", hash)
+ nodes[0].IPFS("routing", "provide", hash)
res := nodes[1].IPFS("routing", "findprovs", "--num-providers=1", hash)
assert.Equal(t, nodes[0].PeerID().String(), res.Stdout.Trimmed())
diff --git a/test/cli/files_test.go b/test/cli/files_test.go
new file mode 100644
index 00000000000..27526189785
--- /dev/null
+++ b/test/cli/files_test.go
@@ -0,0 +1,120 @@
+package cli
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "testing"
+
+ "github.com/ipfs/kubo/test/cli/harness"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestFilesCp(t *testing.T) {
+ t.Parallel()
+
+ t.Run("files cp with valid UnixFS succeeds", func(t *testing.T) {
+ t.Parallel()
+
+ node := harness.NewT(t).NewNode().Init().StartDaemon()
+
+ // Create simple text file
+ data := "testing files cp command"
+ cid := node.IPFSAddStr(data)
+
+ // Copy form IPFS => MFS
+ res := node.IPFS("files", "cp", fmt.Sprintf("/ipfs/%s", cid), "/valid-file")
+ assert.NoError(t, res.Err)
+
+ // verification
+ catRes := node.IPFS("files", "read", "/valid-file")
+ assert.Equal(t, data, catRes.Stdout.Trimmed())
+ })
+
+ t.Run("files cp with unsupported DAG node type fails", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init().StartDaemon()
+
+ // MFS UnixFS is limited to dag-pb or raw, so we create a dag-cbor node to test this
+ jsonData := `{"data": "not a UnixFS node"}`
+ tempFile := filepath.Join(node.Dir, "test.json")
+ err := os.WriteFile(tempFile, []byte(jsonData), 0644)
+ require.NoError(t, err)
+ cid := node.IPFS("dag", "put", "--input-codec=json", "--store-codec=dag-cbor", tempFile).Stdout.Trimmed()
+
+ // copy without --force
+ res := node.RunIPFS("files", "cp", fmt.Sprintf("/ipfs/%s", cid), "/invalid-file")
+ assert.NotEqual(t, 0, res.ExitErr.ExitCode())
+ assert.Contains(t, res.Stderr.String(), "Error: cp: source must be a valid UnixFS (dag-pb or raw codec)")
+ })
+
+ t.Run("files cp with invalid UnixFS data structure fails", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init().StartDaemon()
+
+ // Create an invalid proto file
+ data := []byte{0xDE, 0xAD, 0xBE, 0xEF} // Invalid protobuf data
+ tempFile := filepath.Join(node.Dir, "invalid-proto.bin")
+ err := os.WriteFile(tempFile, data, 0644)
+ require.NoError(t, err)
+
+ res := node.IPFS("block", "put", "--format=raw", tempFile)
+ require.NoError(t, res.Err)
+
+ // we manually changed codec from raw to dag-pb to test "bad dag-pb" scenario
+ cid := "bafybeic7pdbte5heh6u54vszezob3el6exadoiw4wc4ne7ny2x7kvajzkm"
+
+ // should fail because node cannot be read as a valid dag-pb
+ cpResNoForce := node.RunIPFS("files", "cp", fmt.Sprintf("/ipfs/%s", cid), "/invalid-proto")
+ assert.NotEqual(t, 0, cpResNoForce.ExitErr.ExitCode())
+ assert.Contains(t, cpResNoForce.Stderr.String(), "Error")
+ })
+
+ t.Run("files cp with raw node succeeds", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init().StartDaemon()
+
+ // Create a raw node
+ data := "raw data"
+ tempFile := filepath.Join(node.Dir, "raw.bin")
+ err := os.WriteFile(tempFile, []byte(data), 0644)
+ require.NoError(t, err)
+
+ res := node.IPFS("block", "put", "--format=raw", tempFile)
+ require.NoError(t, res.Err)
+ cid := res.Stdout.Trimmed()
+
+ // Copy from IPFS to MFS (raw nodes should work without --force)
+ cpRes := node.IPFS("files", "cp", fmt.Sprintf("/ipfs/%s", cid), "/raw-file")
+ assert.NoError(t, cpRes.Err)
+
+ // Verify the file was copied correctly
+ catRes := node.IPFS("files", "read", "/raw-file")
+ assert.Equal(t, data, catRes.Stdout.Trimmed())
+ })
+
+ t.Run("files cp creates intermediate directories with -p", func(t *testing.T) {
+ t.Parallel()
+ node := harness.NewT(t).NewNode().Init().StartDaemon()
+
+ // Create a simple text file and add it to IPFS
+ data := "hello parent directories"
+ tempFile := filepath.Join(node.Dir, "parent-test.txt")
+ err := os.WriteFile(tempFile, []byte(data), 0644)
+ require.NoError(t, err)
+
+ cid := node.IPFS("add", "-Q", tempFile).Stdout.Trimmed()
+
+ // Copy from IPFS to MFS with parent flag
+ res := node.IPFS("files", "cp", "-p", fmt.Sprintf("/ipfs/%s", cid), "/parent/dir/file")
+ assert.NoError(t, res.Err)
+
+ // Verify the file and directories were created
+ lsRes := node.IPFS("files", "ls", "/parent/dir")
+ assert.Contains(t, lsRes.Stdout.String(), "file")
+
+ catRes := node.IPFS("files", "read", "/parent/dir/file")
+ assert.Equal(t, data, catRes.Stdout.Trimmed())
+ })
+}
diff --git a/test/cli/gateway_test.go b/test/cli/gateway_test.go
index c98c62c47eb..2d500c65594 100644
--- a/test/cli/gateway_test.go
+++ b/test/cli/gateway_test.go
@@ -1,6 +1,7 @@
package cli
import (
+ "bufio"
"context"
"encoding/json"
"fmt"
@@ -11,10 +12,10 @@ import (
"strconv"
"strings"
"testing"
+ "time"
"github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/test/cli/harness"
- . "github.com/ipfs/kubo/test/cli/testutils"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
@@ -158,14 +159,8 @@ func TestGateway(t *testing.T) {
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,
- ``,
- )
+ assert.Equal(t, 301, resp.StatusCode)
+ assert.Equal(t, "/ipfs/bafkqaaa?query=to-remember", resp.Resp.Header.Get("Location"))
})
})
@@ -200,15 +195,8 @@ func TestGateway(t *testing.T) {
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")
-
- assert.Contains(t,
- resp.Body,
- fmt.Sprintf(``, peerID),
- )
- assert.Contains(t,
- resp.Body,
- fmt.Sprintf(``, peerID),
- )
+ assert.Equal(t, 301, resp.StatusCode)
+ assert.Equal(t, fmt.Sprintf("/ipns/%s?query=to-remember", peerID), resp.Resp.Header.Get("Location"))
})
})
@@ -252,30 +240,6 @@ func TestGateway(t *testing.T) {
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)
@@ -357,76 +321,6 @@ func TestGateway(t *testing.T) {
})
})
- 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.Contains(t,
- res.Stderr.Trimmed(),
- `Error: invalid path "local":`,
- )
- })
-
t.Run("raw leaves node", func(t *testing.T) {
t.Parallel()
contents := "This is RAW!"
@@ -498,12 +392,12 @@ func TestGateway(t *testing.T) {
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.Run("not present CID from node 1", func(t *testing.T) {
t.Parallel()
- assert.Equal(t, 500, node1.GatewayClient().Get("/ipfs/"+cidFoo).StatusCode)
+ assert.Equal(t, 404, node1.GatewayClient().Get("/ipfs/"+cidFoo).StatusCode)
})
- t.Run("not present IPNS key from node 1", func(t *testing.T) {
+ t.Run("not present IPNS Record from node 1", func(t *testing.T) {
t.Parallel()
assert.Equal(t, 500, node1.GatewayClient().Get("/ipns/"+node2PeerID).StatusCode)
})
@@ -512,12 +406,12 @@ func TestGateway(t *testing.T) {
t.Run("present", func(t *testing.T) {
cidBar := node1.IPFSAddStr("bar")
- t.Run("present key from node 1", func(t *testing.T) {
+ t.Run("present CID 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.Run("present IPNS Record from node 1", func(t *testing.T) {
t.Parallel()
node2.IPFS("name", "publish", "/ipfs/"+cidBar)
assert.Equal(t, 200, node1.GatewayClient().Get("/ipns/"+node2PeerID).StatusCode)
@@ -642,3 +536,47 @@ func TestGateway(t *testing.T) {
})
})
}
+
+// TestLogs tests that GET /logs returns log messages. This test is separate
+// because it requires setting the server's log level to "info" which may
+// change the output expected by other tests.
+func TestLogs(t *testing.T) {
+ h := harness.NewT(t)
+
+ t.Setenv("GOLOG_LOG_LEVEL", "info")
+
+ node := h.NewNode().Init().StartDaemon("--offline")
+ cid := node.IPFSAddStr("Hello Worlds!")
+
+ peerID, err := peer.ToCid(node.PeerID()).StringOfBase(multibase.Base36)
+ assert.NoError(t, err)
+
+ client := node.GatewayClient()
+ client.TemplateData = map[string]string{
+ "CID": cid,
+ "PeerID": peerID,
+ }
+
+ apiClient := node.APIClient()
+ reqURL := apiClient.BuildURL("/logs")
+
+ ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
+ 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()
+
+ var found bool
+ scanner := bufio.NewScanner(resp.Body)
+ for scanner.Scan() {
+ if strings.Contains(scanner.Text(), "log API client connected") {
+ found = true
+ break
+ }
+ }
+ assert.True(t, found)
+}
diff --git a/test/cli/harness/ipfs.go b/test/cli/harness/ipfs.go
index 8537e2aa25d..0842d362727 100644
--- a/test/cli/harness/ipfs.go
+++ b/test/cli/harness/ipfs.go
@@ -76,6 +76,17 @@ func (n *Node) IPFSAddStr(content string, args ...string) string {
return n.IPFSAdd(strings.NewReader(content), args...)
}
+// IPFSAddDeterministic produces a CID of a file of a certain size, filled with deterministically generated bytes based on some seed.
+// This ensures deterministic CID on the other end, that can be used in tests.
+func (n *Node) IPFSAddDeterministic(size string, seed string, args ...string) string {
+ log.Debugf("node %d adding %s of deterministic pseudo-random data with seed %q and args: %v", n.ID, size, seed, args)
+ reader, err := DeterministicRandomReader(size, seed)
+ if err != nil {
+ panic(err)
+ }
+ return n.IPFSAdd(reader, 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"}
@@ -108,3 +119,15 @@ func (n *Node) IPFSDagImport(content io.Reader, cid string, args ...string) erro
})
return res.Err
}
+
+/*
+func (n *Node) IPFSDagExport(cid string, car *os.File) error {
+ log.Debugf("node %d dag export of %s to %q with args: %v", n.ID, cid, car.Name())
+ res := n.Runner.MustRun(RunRequest{
+ Path: n.IPFSBin,
+ Args: []string{"dag", "export", cid},
+ CmdOpts: []CmdOpt{RunWithStdout(car)},
+ })
+ return res.Err
+}
+*/
diff --git a/test/cli/harness/node.go b/test/cli/harness/node.go
index d030c7c9404..49a551535eb 100644
--- a/test/cli/harness/node.go
+++ b/test/cli/harness/node.go
@@ -208,6 +208,7 @@ func (n *Node) Init(ipfsArgs ...string) *Node {
cfg.Addresses.Gateway = []string{n.GatewayListenAddr.String()}
cfg.Swarm.DisableNatPortMap = true
cfg.Discovery.MDNS.Enabled = n.EnableMDNS
+ cfg.Routing.LoopbackAddressesOnLanDHT = config.True
})
return n
}
@@ -349,6 +350,17 @@ func (n *Node) checkAPI(authorization string) bool {
log.Debugf("node %d API addr not available yet: %s", n.ID, err.Error())
return false
}
+
+ if unixAddr, err := apiAddr.ValueForProtocol(multiaddr.P_UNIX); err == nil {
+ parts := strings.SplitN(unixAddr, "/", 2)
+ if len(parts) < 1 {
+ panic("malformed unix socket address")
+ }
+ fileName := "/" + parts[1]
+ _, err := os.Stat(fileName)
+ return !errors.Is(err, fs.ErrNotExist)
+ }
+
ip, err := apiAddr.ValueForProtocol(multiaddr.P_IP4)
if err != nil {
panic(err)
@@ -484,16 +496,18 @@ func (n *Node) SwarmAddrsWithPeerIDs() []multiaddr.Multiaddr {
func (n *Node) SwarmAddrsWithoutPeerIDs() []multiaddr.Multiaddr {
var addrs []multiaddr.Multiaddr
for _, ma := range n.SwarmAddrs() {
- var components []multiaddr.Multiaddr
- multiaddr.ForEach(ma, func(c multiaddr.Component) bool {
+ i := 0
+ for _, c := range ma {
if c.Protocol().Code == multiaddr.P_IPFS {
- return true
+ continue
}
- components = append(components, &c)
- return true
- })
- ma = multiaddr.Join(components...)
- addrs = append(addrs, ma)
+ ma[i] = c
+ i++
+ }
+ ma = ma[:i]
+ if len(ma) > 0 {
+ addrs = append(addrs, ma)
+ }
}
return addrs
}
diff --git a/test/cli/harness/pbinspect.go b/test/cli/harness/pbinspect.go
new file mode 100644
index 00000000000..6abddb61f10
--- /dev/null
+++ b/test/cli/harness/pbinspect.go
@@ -0,0 +1,54 @@
+package harness
+
+import (
+ "bytes"
+ "encoding/json"
+)
+
+// InspectPBNode uses dag-json output of 'ipfs dag get' to inspect
+// "Logical Format" of DAG-PB as defined in
+// https://web.archive.org/web/20250403194752/https://ipld.io/specs/codecs/dag-pb/spec/#logical-format
+// (mainly used for inspecting Links without depending on any libraries)
+func (n *Node) InspectPBNode(cid string) (PBNode, error) {
+ log.Debugf("node %d dag get %s as dag-json", n.ID, cid)
+
+ var root PBNode
+ var dagJsonOutput bytes.Buffer
+ res := n.Runner.MustRun(RunRequest{
+ Path: n.IPFSBin,
+ Args: []string{"dag", "get", "--output-codec=dag-json", cid},
+ CmdOpts: []CmdOpt{RunWithStdout(&dagJsonOutput)},
+ })
+ if res.Err != nil {
+ return root, res.Err
+ }
+
+ err := json.Unmarshal(dagJsonOutput.Bytes(), &root)
+ if err != nil {
+ return root, err
+ }
+ return root, nil
+
+}
+
+// Define structs to match the JSON for
+type PBHash struct {
+ Slash string `json:"/"`
+}
+
+type PBLink struct {
+ Hash PBHash `json:"Hash"`
+ Name string `json:"Name"`
+ Tsize int `json:"Tsize"`
+}
+
+type PBData struct {
+ Slash struct {
+ Bytes string `json:"bytes"`
+ } `json:"/"`
+}
+
+type PBNode struct {
+ Data PBData `json:"Data"`
+ Links []PBLink `json:"Links"`
+}
diff --git a/test/cli/harness/peering.go b/test/cli/harness/peering.go
index 7680eaf575f..8488c822d6f 100644
--- a/test/cli/harness/peering.go
+++ b/test/cli/harness/peering.go
@@ -3,6 +3,7 @@ package harness
import (
"fmt"
"math/rand"
+ "net"
"testing"
"github.com/ipfs/kubo/config"
@@ -14,6 +15,13 @@ type Peering struct {
}
func NewRandPort() int {
+ if a, err := net.ResolveTCPAddr("tcp", "localhost:0"); err == nil {
+ var l *net.TCPListener
+ if l, err = net.ListenTCP("tcp", a); err == nil {
+ defer l.Close()
+ return l.Addr().(*net.TCPAddr).Port
+ }
+ }
n := rand.Int()
return 3000 + (n % 1000)
}
diff --git a/test/cli/harness/run.go b/test/cli/harness/run.go
index 8ca85eb63b1..077af6ca574 100644
--- a/test/cli/harness/run.go
+++ b/test/cli/harness/run.go
@@ -3,6 +3,7 @@ package harness
import (
"fmt"
"io"
+ "os"
"os/exec"
"strings"
)
@@ -60,8 +61,27 @@ func environToMap(environ []string) map[string]string {
func (r *Runner) Run(req RunRequest) *RunResult {
cmd := exec.Command(req.Path, req.Args...)
- stdout := &Buffer{}
- stderr := &Buffer{}
+ var stdout io.Writer
+ var stderr io.Writer
+ outbuf := &Buffer{}
+ errbuf := &Buffer{}
+
+ if r.Verbose {
+ or, ow := io.Pipe()
+ errr, errw := io.Pipe()
+ stdout = io.MultiWriter(outbuf, ow)
+ stderr = io.MultiWriter(errbuf, errw)
+ go func() {
+ _, _ = io.Copy(os.Stdout, or)
+ }()
+ go func() {
+ _, _ = io.Copy(os.Stderr, errr)
+ }()
+ } else {
+ stdout = outbuf
+ stderr = errbuf
+ }
+
cmd.Stdout = stdout
cmd.Stderr = stderr
cmd.Dir = r.Dir
@@ -83,8 +103,8 @@ func (r *Runner) Run(req RunRequest) *RunResult {
err := req.RunFunc(cmd)
result := RunResult{
- Stdout: stdout,
- Stderr: stderr,
+ Stdout: outbuf,
+ Stderr: errbuf,
Cmd: cmd,
Err: err,
}
diff --git a/test/cli/http_gateway_over_libp2p_test.go b/test/cli/http_gateway_over_libp2p_test.go
index ee57175719d..f8cfe0071fd 100644
--- a/test/cli/http_gateway_over_libp2p_test.go
+++ b/test/cli/http_gateway_over_libp2p_test.go
@@ -71,7 +71,7 @@ func TestGatewayOverLibp2p(t *testing.T) {
t.Run("WillNotServeRemoteContent", func(t *testing.T) {
resp, err := http.Get(fmt.Sprintf("http://%s/ipfs/%s?format=raw", p2pProxyNodeHTTPListenAddr, cidDataNotOnGatewayNode))
require.NoError(t, err)
- require.Equal(t, 500, resp.StatusCode)
+ require.Equal(t, http.StatusNotFound, resp.StatusCode)
})
t.Run("WillNotServeDeserializedResponses", func(t *testing.T) {
diff --git a/test/cli/http_retrieval_client_test.go b/test/cli/http_retrieval_client_test.go
new file mode 100644
index 00000000000..f845c818ef5
--- /dev/null
+++ b/test/cli/http_retrieval_client_test.go
@@ -0,0 +1,145 @@
+package cli
+
+import (
+ "fmt"
+ "net"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "os"
+ "strings"
+ "testing"
+
+ "github.com/ipfs/boxo/routing/http/server"
+ "github.com/ipfs/boxo/routing/http/types"
+ "github.com/ipfs/go-cid"
+ "github.com/ipfs/kubo/config"
+ "github.com/ipfs/kubo/test/cli/harness"
+ "github.com/ipfs/kubo/test/cli/testutils"
+ "github.com/ipfs/kubo/test/cli/testutils/httprouting"
+ "github.com/libp2p/go-libp2p/core/peer"
+ "github.com/multiformats/go-multiaddr"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestHTTPRetrievalClient(t *testing.T) {
+ t.Parallel()
+
+ // many moving pieces here, show more when debug is needed
+ debug := os.Getenv("DEBUG") == "true"
+
+ // usee local /routing/v1/providers/{cid} and
+ // /ipfs/{cid} HTTP servers to confirm HTTP-only retrieval works end-to-end.
+ t.Run("works end-to-end with an HTTP-only provider", func(t *testing.T) {
+ // setup mocked HTTP Router to handle /routing/v1/providers/cid
+ mockRouter := &httprouting.MockHTTPContentRouter{Debug: debug}
+ delegatedRoutingServer := httptest.NewServer(server.Handler(mockRouter))
+ t.Cleanup(func() { delegatedRoutingServer.Close() })
+
+ // init Kubo repo
+ node := harness.NewT(t).NewNode().Init()
+
+ node.UpdateConfig(func(cfg *config.Config) {
+ // explicitly enable http client
+ cfg.HTTPRetrieval.Enabled = config.True
+ // allow NewMockHTTPProviderServer to use self-signed TLS cert
+ cfg.HTTPRetrieval.TLSInsecureSkipVerify = config.True
+ // setup client-only routing which asks both HTTP + DHT
+ // cfg.Routing.Type = config.NewOptionalString("autoclient")
+ // setup Kubo node to use mocked HTTP Router
+ cfg.Routing.DelegatedRouters = []string{delegatedRoutingServer.URL}
+ })
+
+ // compute a random CID
+ randStr := string(testutils.RandomBytes(100))
+ res := node.PipeStrToIPFS(randStr, "add", "-qn", "--cid-version", "1") // -n means dont add to local repo, just produce CID
+ wantCIDStr := res.Stdout.Trimmed()
+ testCid := cid.MustParse(wantCIDStr)
+
+ // setup mock HTTP provider
+ httpProviderServer := NewMockHTTPProviderServer(testCid, randStr, debug)
+ t.Cleanup(func() { httpProviderServer.Close() })
+ httpHost, httpPort, err := splitHostPort(httpProviderServer.URL)
+ assert.NoError(t, err)
+
+ // setup /routing/v1/providers/cid result that points at our mocked HTTP provider
+ mockHTTPProviderPeerID := "12D3KooWCjfPiojcCUmv78Wd1NJzi4Mraj1moxigp7AfQVQvGLwH" // static, it does not matter, we only care about multiaddr
+ mockHTTPMultiaddr, _ := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/%s/tcp/%s/tls/http", httpHost, httpPort))
+ mpid, _ := peer.Decode(mockHTTPProviderPeerID)
+ mockRouter.AddProvider(testCid, &types.PeerRecord{
+ Schema: types.SchemaPeer,
+ ID: &mpid,
+ Addrs: []types.Multiaddr{{Multiaddr: mockHTTPMultiaddr}},
+ // no explicit Protocols, ensure multiaddr alone is enough
+ })
+
+ // Start Kubo
+ node.StartDaemon()
+
+ if debug {
+ fmt.Printf("delegatedRoutingServer.URL: %s\n", delegatedRoutingServer.URL)
+ fmt.Printf("httpProviderServer.URL: %s\n", httpProviderServer.URL)
+ fmt.Printf("httpProviderServer.Multiaddr: %s\n", mockHTTPMultiaddr)
+ fmt.Printf("testCid: %s\n", testCid)
+ }
+
+ // Now, make Kubo to read testCid. it was not added to local blockstore, so it has only one provider -- a HTTP server.
+
+ // First, confirm delegatedRoutingServer returned HTTP provider
+ findprovsRes := node.IPFS("routing", "findprovs", testCid.String())
+ assert.Equal(t, mockHTTPProviderPeerID, findprovsRes.Stdout.Trimmed())
+
+ // Ok, now attempt retrieval.
+ // If there was no timeout and returned bytes match expected body, HTTP routing and retrieval worked end-to-end.
+ catRes := node.IPFS("cat", testCid.String())
+ assert.Equal(t, randStr, catRes.Stdout.Trimmed())
+ })
+}
+
+// NewMockHTTPProviderServer pretends to be http provider that supports
+// block response https://specs.ipfs.tech/http-gateways/trustless-gateway/#block-responses-application-vnd-ipld-raw
+func NewMockHTTPProviderServer(c cid.Cid, body string, debug bool) *httptest.Server {
+ expectedPathPrefix := "/ipfs/" + c.String()
+ handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ if debug {
+ fmt.Printf("NewMockHTTPProviderServer GET %s\n", req.URL.Path)
+ }
+ if strings.HasPrefix(req.URL.Path, expectedPathPrefix) {
+ w.Header().Set("Content-Type", "application/vnd.ipld.raw")
+ w.WriteHeader(http.StatusOK)
+ if req.Method == "GET" {
+ _, err := w.Write([]byte(body))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "NewMockHTTPProviderServer GET %s error: %v\n", req.URL.Path, err)
+ }
+ }
+ } else if strings.HasPrefix(req.URL.Path, "/ipfs/bafkqaaa") {
+ // This is probe from https://specs.ipfs.tech/http-gateways/trustless-gateway/#dedicated-probe-paths
+ w.Header().Set("Content-Type", "application/vnd.ipld.raw")
+ w.WriteHeader(http.StatusOK)
+ } else {
+ http.Error(w, "Not Found", http.StatusNotFound)
+ }
+ })
+
+ // Make it HTTP/2 with self-signed TLS cert
+ srv := httptest.NewUnstartedServer(handler)
+ srv.EnableHTTP2 = true
+ srv.StartTLS()
+ return srv
+}
+
+func splitHostPort(httpUrl string) (ipAddr string, port string, err error) {
+ u, err := url.Parse(httpUrl)
+ if err != nil {
+ return "", "", err
+ }
+ if u.Scheme == "" || u.Host == "" {
+ return "", "", fmt.Errorf("invalid URL format: missing scheme or host")
+ }
+ ipAddr, port, err = net.SplitHostPort(u.Host)
+ if err != nil {
+ return "", "", fmt.Errorf("failed to split host and port from %q: %w", u.Host, err)
+ }
+ return ipAddr, port, nil
+}
diff --git a/test/cli/pins_test.go b/test/cli/pins_test.go
index 415da8d3b6a..3e3325a019e 100644
--- a/test/cli/pins_test.go
+++ b/test/cli/pins_test.go
@@ -242,6 +242,44 @@ func TestPins(t *testing.T) {
require.NotContains(t, lsOut, outADetailed)
})
+ t.Run("test listing pins with names that contain specific string", func(t *testing.T) {
+ t.Parallel()
+
+ node := harness.NewT(t).NewNode().Init()
+ cidAStr := node.IPFSAddStr(RandomStr(1000), "--pin=false")
+ cidBStr := node.IPFSAddStr(RandomStr(1000), "--pin=false")
+ cidCStr := node.IPFSAddStr(RandomStr(1000), "--pin=false")
+
+ outA := cidAStr + " recursive testPin"
+ outB := cidBStr + " recursive testPin"
+ outC := cidCStr + " recursive randPin"
+
+ // make sure both -n and --name work
+ for _, nameParam := range []string{"--name", "-n"} {
+ _ = node.IPFS("pin", "add", "--name", "testPin", cidAStr)
+ lsOut := pinLs(node, "-t=recursive", nameParam+"=test")
+ require.Contains(t, lsOut, outA)
+ lsOut = pinLs(node, "-t=recursive", nameParam+"=randomLabel")
+ require.NotContains(t, lsOut, outA)
+
+ _ = node.IPFS("pin", "add", "--name", "testPin", cidBStr)
+ lsOut = pinLs(node, "-t=recursive", nameParam+"=test")
+ require.Contains(t, lsOut, outA)
+ require.Contains(t, lsOut, outB)
+
+ _ = node.IPFS("pin", "add", "--name", "randPin", cidCStr)
+ lsOut = pinLs(node, "-t=recursive", nameParam+"=rand")
+ require.NotContains(t, lsOut, outA)
+ require.NotContains(t, lsOut, outB)
+ require.Contains(t, lsOut, outC)
+
+ lsOut = pinLs(node, "-t=recursive", nameParam+"=testPin")
+ require.Contains(t, lsOut, outA)
+ require.Contains(t, lsOut, outB)
+ require.NotContains(t, lsOut, outC)
+ }
+ })
+
t.Run("test overwriting pin with name", func(t *testing.T) {
t.Parallel()
diff --git a/test/cli/provider_test.go b/test/cli/provider_test.go
new file mode 100644
index 00000000000..7e2bee411c0
--- /dev/null
+++ b/test/cli/provider_test.go
@@ -0,0 +1,222 @@
+package cli
+
+import (
+ "bytes"
+ "testing"
+ "time"
+
+ "github.com/ipfs/kubo/test/cli/harness"
+ "github.com/ipfs/kubo/test/cli/testutils"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestProvider(t *testing.T) {
+ t.Parallel()
+
+ initNodes := func(t *testing.T, n int, fn func(n *harness.Node)) harness.Nodes {
+ nodes := harness.NewT(t).NewNodes(n).Init()
+ nodes.ForEachPar(fn)
+ return nodes.StartDaemons().Connect()
+ }
+
+ expectNoProviders := func(t *testing.T, cid string, nodes ...*harness.Node) {
+ for _, node := range nodes {
+ res := node.IPFS("routing", "findprovs", "-n=1", cid)
+ require.Empty(t, res.Stdout.String())
+ }
+ }
+
+ expectProviders := func(t *testing.T, cid, expectedProvider string, nodes ...*harness.Node) {
+ for _, node := range nodes {
+ res := node.IPFS("routing", "findprovs", "-n=1", cid)
+ require.Equal(t, expectedProvider, res.Stdout.Trimmed())
+ }
+ }
+
+ t.Run("Provider.Enabled=true announces new CIDs created by ipfs add", func(t *testing.T) {
+ t.Parallel()
+
+ nodes := initNodes(t, 2, func(n *harness.Node) {
+ n.SetIPFSConfig("Provider.Enabled", true)
+ })
+ defer nodes.StopDaemons()
+
+ cid := nodes[0].IPFSAddStr(time.Now().String())
+ // Reprovide as initialProviderDelay still ongoing
+ res := nodes[0].IPFS("routing", "reprovide")
+ require.NoError(t, res.Err)
+ expectProviders(t, cid, nodes[0].PeerID().String(), nodes[1:]...)
+ })
+
+ t.Run("Provider.Enabled=false disables announcement of new CID from ipfs add", func(t *testing.T) {
+ t.Parallel()
+
+ nodes := initNodes(t, 2, func(n *harness.Node) {
+ n.SetIPFSConfig("Provider.Enabled", false)
+ })
+ defer nodes.StopDaemons()
+
+ cid := nodes[0].IPFSAddStr(time.Now().String())
+ expectNoProviders(t, cid, nodes[1:]...)
+ })
+
+ t.Run("Provider.Enabled=false disables manual announcement via RPC command", func(t *testing.T) {
+ t.Parallel()
+
+ nodes := initNodes(t, 2, func(n *harness.Node) {
+ n.SetIPFSConfig("Provider.Enabled", false)
+ })
+ defer nodes.StopDaemons()
+
+ cid := nodes[0].IPFSAddStr(time.Now().String())
+ res := nodes[0].RunIPFS("routing", "provide", cid)
+ assert.Contains(t, res.Stderr.Trimmed(), "invalid configuration: Provider.Enabled is set to 'false'")
+ assert.Equal(t, 1, res.ExitCode())
+
+ expectNoProviders(t, cid, nodes[1:]...)
+ })
+
+ // Right now Provide and Reprovide are tied together
+ t.Run("Reprovide.Interval=0 disables announcement of new CID too", func(t *testing.T) {
+ t.Parallel()
+
+ nodes := initNodes(t, 2, func(n *harness.Node) {
+ n.SetIPFSConfig("Reprovider.Interval", "0")
+ })
+ defer nodes.StopDaemons()
+
+ cid := nodes[0].IPFSAddStr(time.Now().String())
+ expectNoProviders(t, cid, nodes[1:]...)
+ })
+
+ // It is a lesser evil - forces users to fix their config and have some sort of interval
+ t.Run("Manual Reprovider trigger does not work when periodic Reprovider is disabled", func(t *testing.T) {
+ t.Parallel()
+
+ nodes := initNodes(t, 2, func(n *harness.Node) {
+ n.SetIPFSConfig("Reprovider.Interval", "0")
+ })
+ defer nodes.StopDaemons()
+
+ cid := nodes[0].IPFSAddStr(time.Now().String(), "--offline")
+
+ expectNoProviders(t, cid, nodes[1:]...)
+
+ res := nodes[0].RunIPFS("routing", "reprovide")
+ assert.Contains(t, res.Stderr.Trimmed(), "invalid configuration: Reprovider.Interval is set to '0'")
+ assert.Equal(t, 1, res.ExitCode())
+
+ expectNoProviders(t, cid, nodes[1:]...)
+ })
+
+ // It is a lesser evil - forces users to fix their config and have some sort of interval
+ t.Run("Manual Reprovider trigger does not work when Provider system is disabled", func(t *testing.T) {
+ t.Parallel()
+
+ nodes := initNodes(t, 2, func(n *harness.Node) {
+ n.SetIPFSConfig("Provider.Enabled", false)
+ })
+ defer nodes.StopDaemons()
+
+ cid := nodes[0].IPFSAddStr(time.Now().String(), "--offline")
+
+ expectNoProviders(t, cid, nodes[1:]...)
+
+ res := nodes[0].RunIPFS("routing", "reprovide")
+ assert.Contains(t, res.Stderr.Trimmed(), "invalid configuration: Provider.Enabled is set to 'false'")
+ assert.Equal(t, 1, res.ExitCode())
+
+ expectNoProviders(t, cid, nodes[1:]...)
+ })
+
+ t.Run("Reprovides with 'all' strategy", func(t *testing.T) {
+ t.Parallel()
+
+ nodes := initNodes(t, 2, func(n *harness.Node) {
+ n.SetIPFSConfig("Reprovider.Strategy", "all")
+ })
+ defer nodes.StopDaemons()
+
+ cid := nodes[0].IPFSAddStr(time.Now().String(), "--local")
+
+ expectNoProviders(t, cid, nodes[1:]...)
+
+ nodes[0].IPFS("routing", "reprovide")
+
+ expectProviders(t, cid, nodes[0].PeerID().String(), nodes[1:]...)
+ })
+
+ t.Run("Reprovides with 'flat' strategy", func(t *testing.T) {
+ t.Parallel()
+
+ nodes := initNodes(t, 2, func(n *harness.Node) {
+ n.SetIPFSConfig("Reprovider.Strategy", "flat")
+ })
+ defer nodes.StopDaemons()
+
+ cid := nodes[0].IPFSAddStr(time.Now().String(), "--local")
+
+ expectNoProviders(t, cid, nodes[1:]...)
+
+ nodes[0].IPFS("routing", "reprovide")
+
+ expectProviders(t, cid, nodes[0].PeerID().String(), nodes[1:]...)
+ })
+
+ t.Run("Reprovides with 'pinned' strategy", func(t *testing.T) {
+ t.Parallel()
+
+ foo := testutils.RandomBytes(1000)
+ bar := testutils.RandomBytes(1000)
+
+ nodes := initNodes(t, 2, func(n *harness.Node) {
+ n.SetIPFSConfig("Reprovider.Strategy", "pinned")
+ })
+ defer nodes.StopDaemons()
+
+ cidFoo := nodes[0].IPFSAdd(bytes.NewReader(foo), "--offline", "--pin=false")
+ cidBar := nodes[0].IPFSAdd(bytes.NewReader(bar), "--offline", "--pin=false")
+ cidBarDir := nodes[0].IPFSAdd(bytes.NewReader(bar), "-Q", "--offline", "-w")
+
+ expectNoProviders(t, cidFoo, nodes[1:]...)
+ expectNoProviders(t, cidBar, nodes[1:]...)
+ expectNoProviders(t, cidBarDir, nodes[1:]...)
+
+ nodes[0].IPFS("routing", "reprovide")
+
+ expectNoProviders(t, cidFoo, nodes[1:]...)
+ expectProviders(t, cidBar, nodes[0].PeerID().String(), nodes[1:]...)
+ expectProviders(t, cidBarDir, nodes[0].PeerID().String(), nodes[1:]...)
+ })
+
+ t.Run("Reprovides with 'roots' strategy", func(t *testing.T) {
+ t.Parallel()
+
+ foo := testutils.RandomBytes(1000)
+ bar := testutils.RandomBytes(1000)
+ baz := testutils.RandomBytes(1000)
+
+ nodes := initNodes(t, 2, func(n *harness.Node) {
+ n.SetIPFSConfig("Reprovider.Strategy", "roots")
+ })
+ defer nodes.StopDaemons()
+
+ cidFoo := nodes[0].IPFSAdd(bytes.NewReader(foo), "--offline", "--pin=false")
+ cidBar := nodes[0].IPFSAdd(bytes.NewReader(bar), "--offline", "--pin=false")
+ cidBaz := nodes[0].IPFSAdd(bytes.NewReader(baz), "--offline")
+ cidBarDir := nodes[0].IPFSAdd(bytes.NewReader(bar), "-Q", "--offline", "-w")
+
+ expectNoProviders(t, cidFoo, nodes[1:]...)
+ expectNoProviders(t, cidBar, nodes[1:]...)
+ expectNoProviders(t, cidBarDir, nodes[1:]...)
+
+ nodes[0].IPFS("routing", "reprovide")
+
+ expectNoProviders(t, cidFoo, nodes[1:]...)
+ expectNoProviders(t, cidBar, nodes[1:]...)
+ expectProviders(t, cidBaz, nodes[0].PeerID().String(), nodes[1:]...)
+ expectProviders(t, cidBarDir, nodes[0].PeerID().String(), nodes[1:]...)
+ })
+
+}
diff --git a/test/cli/routing_dht_test.go b/test/cli/routing_dht_test.go
index fb0d391951e..9322d8cc164 100644
--- a/test/cli/routing_dht_test.go
+++ b/test/cli/routing_dht_test.go
@@ -84,7 +84,10 @@ func testRoutingDHT(t *testing.T, enablePubsub bool) {
t.Run("ipfs routing findprovs", func(t *testing.T) {
t.Parallel()
hash := nodes[3].IPFSAddStr("some stuff")
- res := nodes[4].IPFS("routing", "findprovs", hash)
+ // Reprovide as initialProviderDelay still ongoing
+ res := nodes[3].IPFS("routing", "reprovide")
+ require.NoError(t, res.Err)
+ res = nodes[4].IPFS("routing", "findprovs", hash)
assert.Equal(t, nodes[3].PeerID().String(), res.Stdout.Trimmed())
})
diff --git a/test/cli/rpc_unixsocket_test.go b/test/cli/rpc_unixsocket_test.go
new file mode 100644
index 00000000000..8cead7388d5
--- /dev/null
+++ b/test/cli/rpc_unixsocket_test.go
@@ -0,0 +1,51 @@
+package cli
+
+import (
+ "context"
+ "path"
+ "testing"
+
+ rpcapi "github.com/ipfs/kubo/client/rpc"
+ "github.com/ipfs/kubo/config"
+ "github.com/ipfs/kubo/test/cli/harness"
+ "github.com/multiformats/go-multiaddr"
+ "github.com/stretchr/testify/require"
+)
+
+func TestRPCUnixSocket(t *testing.T) {
+ node := harness.NewT(t).NewNode().Init()
+
+ sockDir := node.Dir
+ sockAddr := path.Join("/unix", sockDir, "sock")
+
+ node.UpdateConfig(func(cfg *config.Config) {
+ //cfg.Addresses.API = append(cfg.Addresses.API, sockPath)
+ cfg.Addresses.API = []string{sockAddr}
+ })
+ t.Log("Starting daemon with unix socket:", sockAddr)
+ node.StartDaemon()
+
+ unixMaddr, err := multiaddr.NewMultiaddr(sockAddr)
+ require.NoError(t, err)
+
+ apiClient, err := rpcapi.NewApi(unixMaddr)
+ require.NoError(t, err)
+
+ var ver struct {
+ Version string
+ }
+ err = apiClient.Request("version").Exec(context.Background(), &ver)
+ require.NoError(t, err)
+ require.NotEmpty(t, ver)
+ t.Log("Got version:", ver.Version)
+
+ var res struct {
+ ID string
+ }
+ err = apiClient.Request("id").Exec(context.Background(), &res)
+ require.NoError(t, err)
+ require.NotEmpty(t, res)
+ t.Log("Got ID:", res.ID)
+
+ node.StopDaemon()
+}
diff --git a/test/cli/testutils/httprouting/mock_http_content_router.go b/test/cli/testutils/httprouting/mock_http_content_router.go
new file mode 100644
index 00000000000..8f6f3102387
--- /dev/null
+++ b/test/cli/testutils/httprouting/mock_http_content_router.go
@@ -0,0 +1,117 @@
+package httprouting
+
+import (
+ "context"
+ "fmt"
+ "sync"
+ "time"
+
+ "github.com/ipfs/boxo/ipns"
+ "github.com/ipfs/boxo/routing/http/server"
+ "github.com/ipfs/boxo/routing/http/types"
+ "github.com/ipfs/boxo/routing/http/types/iter"
+ "github.com/ipfs/go-cid"
+ "github.com/libp2p/go-libp2p/core/peer"
+ "github.com/libp2p/go-libp2p/core/routing"
+)
+
+// MockHTTPContentRouter provides /routing/v1
+// (https://specs.ipfs.tech/routing/http-routing-v1/) server implementation
+// based on github.com/ipfs/boxo/routing/http/server
+type MockHTTPContentRouter struct {
+ m sync.Mutex
+ provideBitswapCalls int
+ findProvidersCalls int
+ findPeersCalls int
+ providers map[cid.Cid][]types.Record
+ peers map[peer.ID][]*types.PeerRecord
+ Debug bool
+}
+
+func (r *MockHTTPContentRouter) FindProviders(ctx context.Context, key cid.Cid, limit int) (iter.ResultIter[types.Record], error) {
+ if r.Debug {
+ fmt.Printf("MockHTTPContentRouter.FindProviders(%s)\n", key.String())
+ }
+ r.m.Lock()
+ defer r.m.Unlock()
+ r.findProvidersCalls++
+ if r.providers == nil {
+ r.providers = make(map[cid.Cid][]types.Record)
+ }
+ records, found := r.providers[key]
+ if !found {
+ return iter.FromSlice([]iter.Result[types.Record]{}), nil
+ }
+ results := make([]iter.Result[types.Record], len(records))
+ for i, rec := range records {
+ results[i] = iter.Result[types.Record]{Val: rec}
+ if r.Debug {
+ fmt.Printf("MockHTTPContentRouter.FindProviders(%s) result: %+v\n", key.String(), rec)
+ }
+ }
+ return iter.FromSlice(results), nil
+}
+
+// nolint deprecated
+func (r *MockHTTPContentRouter) ProvideBitswap(ctx context.Context, req *server.BitswapWriteProvideRequest) (time.Duration, error) {
+ r.m.Lock()
+ defer r.m.Unlock()
+ r.provideBitswapCalls++
+ return 0, nil
+}
+
+func (r *MockHTTPContentRouter) FindPeers(ctx context.Context, pid peer.ID, limit int) (iter.ResultIter[*types.PeerRecord], error) {
+ r.m.Lock()
+ defer r.m.Unlock()
+ r.findPeersCalls++
+
+ if r.peers == nil {
+ r.peers = make(map[peer.ID][]*types.PeerRecord)
+ }
+ records, found := r.peers[pid]
+ if !found {
+ return iter.FromSlice([]iter.Result[*types.PeerRecord]{}), nil
+ }
+
+ results := make([]iter.Result[*types.PeerRecord], len(records))
+ for i, rec := range records {
+ results[i] = iter.Result[*types.PeerRecord]{Val: rec}
+ if r.Debug {
+ fmt.Printf("MockHTTPContentRouter.FindPeers(%s) result: %+v\n", pid.String(), rec)
+ }
+ }
+ return iter.FromSlice(results), nil
+}
+
+func (r *MockHTTPContentRouter) GetIPNS(ctx context.Context, name ipns.Name) (*ipns.Record, error) {
+ return nil, routing.ErrNotSupported
+}
+
+func (r *MockHTTPContentRouter) PutIPNS(ctx context.Context, name ipns.Name, rec *ipns.Record) error {
+ return routing.ErrNotSupported
+}
+
+func (r *MockHTTPContentRouter) NumFindProvidersCalls() int {
+ r.m.Lock()
+ defer r.m.Unlock()
+ return r.findProvidersCalls
+}
+
+// AddProvider adds a record for a given CID
+func (r *MockHTTPContentRouter) AddProvider(key cid.Cid, record types.Record) {
+ r.m.Lock()
+ defer r.m.Unlock()
+ if r.providers == nil {
+ r.providers = make(map[cid.Cid][]types.Record)
+ }
+ r.providers[key] = append(r.providers[key], record)
+
+ peerRecord, ok := record.(*types.PeerRecord)
+ if ok {
+ if r.peers == nil {
+ r.peers = make(map[peer.ID][]*types.PeerRecord)
+ }
+ pid := peerRecord.ID
+ r.peers[*pid] = append(r.peers[*pid], peerRecord)
+ }
+}
diff --git a/test/cli/testutils/random_deterministic.go b/test/cli/testutils/random_deterministic.go
new file mode 100644
index 00000000000..e55404168f6
--- /dev/null
+++ b/test/cli/testutils/random_deterministic.go
@@ -0,0 +1,46 @@
+package testutils
+
+import (
+ "crypto/sha256"
+ "io"
+
+ "github.com/dustin/go-humanize"
+ "golang.org/x/crypto/chacha20"
+)
+
+type randomReader struct {
+ cipher *chacha20.Cipher
+ remaining int64
+}
+
+func (r *randomReader) Read(p []byte) (int, error) {
+ if r.remaining <= 0 {
+ return 0, io.EOF
+ }
+ n := int64(len(p))
+ if n > r.remaining {
+ n = r.remaining
+ }
+ // Generate random bytes directly into the provided buffer
+ r.cipher.XORKeyStream(p[:n], make([]byte, n))
+ r.remaining -= n
+ return int(n), nil
+}
+
+// createRandomReader produces specified number of pseudo-random bytes
+// from a seed.
+func DeterministicRandomReader(sizeStr string, seed string) (io.Reader, error) {
+ size, err := humanize.ParseBytes(sizeStr)
+ if err != nil {
+ return nil, err
+ }
+ // Hash the seed string to a 32-byte key for ChaCha20
+ key := sha256.Sum256([]byte(seed))
+ // Use ChaCha20 for deterministic random bytes
+ var nonce [chacha20.NonceSize]byte // Zero nonce for simplicity
+ cipher, err := chacha20.NewUnauthenticatedCipher(key[:chacha20.KeySize], nonce[:])
+ if err != nil {
+ return nil, err
+ }
+ return &randomReader{cipher: cipher, remaining: int64(size)}, nil
+}
diff --git a/test/cli/testutils/random_files.go b/test/cli/testutils/random_files.go
index c7dca10d6de..7991cad8309 100644
--- a/test/cli/testutils/random_files.go
+++ b/test/cli/testutils/random_files.go
@@ -24,20 +24,22 @@ type RandFiles struct {
FanoutFiles int // how many files per dir
FanoutDirs int // how many dirs per dir
- RandomSize bool // randomize file sizes
- RandomFanout bool // randomize fanout numbers
+ RandomSize bool // randomize file sizes
+ RandomNameSize bool // randomize filename lengths
+ RandomFanout bool // randomize fanout numbers
}
func NewRandFiles() *RandFiles {
return &RandFiles{
- Rand: rand.New(rand.NewSource(time.Now().UnixNano())),
- FileSize: 4096,
- FilenameSize: 16,
- Alphabet: AlphabetEasy,
- FanoutDepth: 2,
- FanoutDirs: 5,
- FanoutFiles: 10,
- RandomSize: true,
+ Rand: rand.New(rand.NewSource(time.Now().UnixNano())),
+ FileSize: 4096,
+ FilenameSize: 16,
+ Alphabet: AlphabetEasy,
+ FanoutDepth: 2,
+ FanoutDirs: 5,
+ FanoutFiles: 10,
+ RandomSize: true,
+ RandomNameSize: true,
}
}
@@ -83,7 +85,10 @@ func (r *RandFiles) WriteRandomFile(root string) error {
filesize = r.Rand.Int63n(filesize) + 1
}
- n := rand.Intn(r.FilenameSize-4) + 4
+ n := r.FilenameSize
+ if r.RandomNameSize {
+ n = rand.Intn(r.FilenameSize-4) + 4
+ }
name := r.RandomFilename(n)
filepath := path.Join(root, name)
f, err := os.Create(filepath)
diff --git a/test/cli/transports_test.go b/test/cli/transports_test.go
index a523351816d..ec27e00baf8 100644
--- a/test/cli/transports_test.go
+++ b/test/cli/transports_test.go
@@ -90,8 +90,11 @@ func TestTransports(t *testing.T) {
nodes.ForEachPar(func(n *harness.Node) {
n.UpdateConfig(func(cfg *config.Config) {
cfg.Addresses.Swarm = []string{"/ip4/127.0.0.1/udp/0/quic-v1"}
- cfg.Swarm.Transports.Network.QUIC = config.True
cfg.Swarm.Transports.Network.TCP = config.False
+ cfg.Swarm.Transports.Network.QUIC = config.True
+ cfg.Swarm.Transports.Network.WebTransport = config.False
+ cfg.Swarm.Transports.Network.WebRTCDirect = config.False
+ cfg.Swarm.Transports.Network.Websocket = config.False
})
})
disableRouting(nodes)
@@ -99,14 +102,17 @@ func TestTransports(t *testing.T) {
runTests(nodes)
})
- t.Run("QUIC", func(t *testing.T) {
+ t.Run("QUIC+Webtransport", func(t *testing.T) {
t.Parallel()
nodes := harness.NewT(t).NewNodes(5).Init()
nodes.ForEachPar(func(n *harness.Node) {
n.UpdateConfig(func(cfg *config.Config) {
cfg.Addresses.Swarm = []string{"/ip4/127.0.0.1/udp/0/quic-v1/webtransport"}
+ cfg.Swarm.Transports.Network.TCP = config.False
cfg.Swarm.Transports.Network.QUIC = config.True
cfg.Swarm.Transports.Network.WebTransport = config.True
+ cfg.Swarm.Transports.Network.WebRTCDirect = config.False
+ cfg.Swarm.Transports.Network.Websocket = config.False
})
})
disableRouting(nodes)
@@ -146,6 +152,7 @@ func TestTransports(t *testing.T) {
cfg.Swarm.Transports.Network.QUIC = config.False
cfg.Swarm.Transports.Network.WebTransport = config.False
cfg.Swarm.Transports.Network.WebRTCDirect = config.True
+ cfg.Swarm.Transports.Network.Websocket = config.False
})
})
disableRouting(nodes)
diff --git a/test/dependencies/dependencies.go b/test/dependencies/dependencies.go
index 0d56cd5a7c5..88c8ed7fc29 100644
--- a/test/dependencies/dependencies.go
+++ b/test/dependencies/dependencies.go
@@ -7,9 +7,9 @@ import (
_ "github.com/Kubuxu/gocovmerge"
_ "github.com/golangci/golangci-lint/cmd/golangci-lint"
_ "github.com/ipfs/go-cidutil/cid-fmt"
+ _ "github.com/ipfs/go-test/cli/random-data"
+ _ "github.com/ipfs/go-test/cli/random-files"
_ "github.com/ipfs/hang-fds"
- _ "github.com/jbenet/go-random-files/random-files"
- _ "github.com/jbenet/go-random/random"
_ "github.com/multiformats/go-multihash/multihash"
_ "gotest.tools/gotestsum"
)
diff --git a/test/dependencies/go.mod b/test/dependencies/go.mod
index d12db0cbc33..d5a6e34fd48 100644
--- a/test/dependencies/go.mod
+++ b/test/dependencies/go.mod
@@ -1,262 +1,332 @@
module github.com/ipfs/kubo/test/dependencies
-go 1.20
+go 1.24
replace github.com/ipfs/kubo => ../../
require (
github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd
- github.com/golangci/golangci-lint v1.54.1
+ github.com/golangci/golangci-lint v1.60.2
github.com/ipfs/go-cidutil v0.1.0
- github.com/ipfs/go-log v1.0.5
+ github.com/ipfs/go-log/v2 v2.6.0
+ github.com/ipfs/go-test v0.2.2
github.com/ipfs/hang-fds v0.1.0
- github.com/ipfs/iptb v1.4.0
- github.com/ipfs/iptb-plugins v0.5.0
- github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c
- github.com/jbenet/go-random-files v0.0.0-20190219210431-31b3f20ebded
- github.com/multiformats/go-multiaddr v0.12.2
+ github.com/ipfs/iptb v1.4.1
+ github.com/ipfs/iptb-plugins v0.5.1
+ github.com/multiformats/go-multiaddr v0.15.0
github.com/multiformats/go-multihash v0.2.3
- gotest.tools/gotestsum v0.4.2
+ gotest.tools/gotestsum v1.12.0
)
require (
4d63.com/gocheckcompilerdirectives v1.2.1 // indirect
4d63.com/gochecknoglobals v0.2.1 // indirect
- github.com/4meepo/tagalign v1.3.2 // indirect
- github.com/Abirdcfly/dupword v0.0.12 // indirect
- github.com/Antonboom/errname v0.1.10 // indirect
- github.com/Antonboom/nilnil v0.1.5 // indirect
- github.com/BurntSushi/toml v1.3.2 // indirect
+ github.com/4meepo/tagalign v1.3.4 // indirect
+ github.com/Abirdcfly/dupword v0.0.14 // indirect
+ github.com/Antonboom/errname v0.1.13 // indirect
+ github.com/Antonboom/nilnil v0.1.9 // indirect
+ github.com/Antonboom/testifylint v1.4.3 // indirect
+ github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect
+ github.com/Crocmagnon/fatcontext v0.4.0 // indirect
+ github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e // indirect
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect
- github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0 // indirect
- github.com/Masterminds/semver v1.5.0 // indirect
- github.com/OpenPeeDeeP/depguard/v2 v2.1.0 // indirect
- github.com/alexkohler/nakedret/v2 v2.0.2 // indirect
+ github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 // indirect
+ github.com/Masterminds/semver/v3 v3.2.1 // indirect
+ github.com/OpenPeeDeeP/depguard/v2 v2.2.0 // indirect
+ github.com/alecthomas/go-check-sumtype v0.1.4 // indirect
+ github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
+ github.com/alexkohler/nakedret/v2 v2.0.4 // indirect
github.com/alexkohler/prealloc v1.0.0 // indirect
github.com/alingse/asasalint v0.0.11 // indirect
github.com/ashanbrown/forbidigo v1.6.0 // indirect
github.com/ashanbrown/makezero v1.1.1 // indirect
+ github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
+ github.com/bitfield/gotestdox v0.2.2 // indirect
github.com/bkielbasa/cyclop v1.2.1 // indirect
github.com/blizzy78/varnamelen v0.8.0 // indirect
- github.com/bombsimon/wsl/v3 v3.4.0 // indirect
- github.com/breml/bidichk v0.2.4 // indirect
- github.com/breml/errchkjson v0.3.1 // indirect
- github.com/butuzov/ireturn v0.2.0 // indirect
- github.com/butuzov/mirror v1.1.0 // indirect
- github.com/cespare/xxhash/v2 v2.2.0 // indirect
+ github.com/bombsimon/wsl/v4 v4.4.1 // indirect
+ github.com/breml/bidichk v0.2.7 // indirect
+ github.com/breml/errchkjson v0.3.6 // indirect
+ github.com/butuzov/ireturn v0.3.0 // indirect
+ github.com/butuzov/mirror v1.2.0 // indirect
+ github.com/caddyserver/certmagic v0.21.6 // indirect
+ github.com/caddyserver/zerossl v0.1.3 // indirect
+ github.com/catenacyber/perfsprint v0.7.1 // indirect
+ github.com/ccojocar/zxcvbn-go v1.0.2 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/charithe/durationcheck v0.0.10 // indirect
- github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 // indirect
- github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
+ github.com/chavacava/garif v0.1.0 // indirect
+ github.com/ckaznocha/intrange v0.1.2 // indirect
+ github.com/cockroachdb/crlib v0.0.0-20241015224233-894974b3ad94 // indirect
+ github.com/cockroachdb/errors v1.11.3 // indirect
+ github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect
+ github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
+ github.com/cockroachdb/pebble/v2 v2.0.3 // indirect
+ github.com/cockroachdb/redact v1.1.5 // indirect
+ github.com/cockroachdb/swiss v0.0.0-20250327203710-2932b022f6df // indirect
+ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
+ github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
+ github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf // indirect
github.com/curioswitch/go-reassign v0.2.0 // indirect
- github.com/daixiang0/gci v0.11.0 // indirect
- github.com/davecgh/go-spew v1.1.1 // indirect
- github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
- github.com/denis-tingaikin/go-header v0.4.3 // indirect
- github.com/dustin/go-humanize v1.0.1 // indirect
- github.com/esimonov/ifshort v1.0.4 // indirect
- github.com/ettle/strcase v0.1.1 // indirect
+ github.com/daixiang0/gci v0.13.4 // indirect
+ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
+ github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
+ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
+ github.com/denis-tingaikin/go-header v0.5.0 // indirect
+ github.com/dnephin/pflag v1.0.7 // indirect
+ github.com/ettle/strcase v0.2.0 // indirect
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect
- github.com/fatih/color v1.15.0 // indirect
+ github.com/fatih/color v1.17.0 // indirect
github.com/fatih/structtag v1.2.0 // indirect
- github.com/firefart/nonamedreturns v1.0.4 // indirect
- github.com/fsnotify/fsnotify v1.6.0 // indirect
+ github.com/firefart/nonamedreturns v1.0.5 // indirect
+ github.com/flynn/noise v1.1.0 // indirect
+ github.com/francoispqt/gojay v1.2.13 // indirect
+ github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fzipp/gocyclo v0.6.0 // indirect
- github.com/go-critic/go-critic v0.9.0 // indirect
- github.com/go-logr/logr v1.4.1 // indirect
+ github.com/gammazero/deque v1.0.0 // indirect
+ github.com/getsentry/sentry-go v0.27.0 // indirect
+ github.com/ghostiam/protogetter v0.3.6 // indirect
+ github.com/go-critic/go-critic v0.11.4 // indirect
+ github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
+ github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/go-toolsmith/astcast v1.1.0 // indirect
github.com/go-toolsmith/astcopy v1.1.0 // indirect
- github.com/go-toolsmith/astequal v1.1.0 // indirect
+ github.com/go-toolsmith/astequal v1.2.0 // indirect
github.com/go-toolsmith/astfmt v1.1.0 // indirect
github.com/go-toolsmith/astp v1.1.0 // indirect
github.com/go-toolsmith/strparse v1.1.0 // indirect
github.com/go-toolsmith/typep v1.1.0 // indirect
+ github.com/go-viper/mapstructure/v2 v2.0.0 // indirect
github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect
github.com/gobwas/glob v0.2.3 // indirect
- github.com/gofrs/flock v0.8.1 // indirect
+ github.com/gofrs/flock v0.12.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect
+ github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect
- github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect
- github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 // indirect
- github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect
- github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect
- github.com/golangci/misspell v0.4.1 // indirect
- github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 // indirect
- github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect
- github.com/google/go-cmp v0.6.0 // indirect
+ github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9 // indirect
+ github.com/golangci/misspell v0.6.0 // indirect
+ github.com/golangci/modinfo v0.3.4 // indirect
+ github.com/golangci/plugin-module-register v0.1.1 // indirect
+ github.com/golangci/revgrep v0.5.3 // indirect
+ github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect
+ github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
- github.com/google/uuid v1.5.0 // indirect
- github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601 // indirect
+ github.com/google/pprof v0.0.0-20250208200701-d0013a598941 // indirect
+ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
+ github.com/google/uuid v1.6.0 // indirect
+ github.com/gordonklaus/ineffassign v0.1.0 // indirect
github.com/gostaticanalysis/analysisutil v0.7.1 // indirect
github.com/gostaticanalysis/comment v1.4.2 // indirect
github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect
github.com/gostaticanalysis/nilerr v0.1.1 // indirect
- github.com/gxed/go-shellwords v1.0.3 // indirect
- github.com/hashicorp/errwrap v1.1.0 // indirect
- github.com/hashicorp/go-multierror v1.1.1 // indirect
- github.com/hashicorp/go-version v1.6.0 // indirect
+ github.com/hashicorp/go-version v1.7.0 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hexops/gotextdiff v1.0.3 // indirect
+ github.com/huin/goupnp v1.3.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/ipfs/bbloom v0.0.4 // indirect
- github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a // indirect
- github.com/ipfs/go-block-format v0.2.0 // indirect
- github.com/ipfs/go-cid v0.4.1 // indirect
- github.com/ipfs/go-datastore v0.6.0 // indirect
- github.com/ipfs/go-ipfs-util v0.0.3 // indirect
- github.com/ipfs/go-ipld-format v0.6.0 // indirect
+ github.com/ipfs/boxo v0.31.1-0.20250528182950-f87feb50c39c // indirect
+ github.com/ipfs/go-bitfield v1.1.0 // indirect
+ github.com/ipfs/go-block-format v0.2.1 // indirect
+ github.com/ipfs/go-cid v0.5.0 // indirect
+ github.com/ipfs/go-datastore v0.8.2 // indirect
+ github.com/ipfs/go-ipld-format v0.6.1 // indirect
github.com/ipfs/go-ipld-legacy v0.2.1 // indirect
- github.com/ipfs/go-log/v2 v2.5.1 // indirect
- github.com/ipfs/go-metrics-interface v0.0.1 // indirect
- github.com/ipfs/kubo v0.16.0 // indirect
- github.com/ipld/go-codec-dagpb v1.6.0 // indirect
+ github.com/ipfs/go-metrics-interface v0.3.0 // indirect
+ github.com/ipfs/kubo v0.31.0 // indirect
+ github.com/ipld/go-codec-dagpb v1.7.0 // indirect
github.com/ipld/go-ipld-prime v0.21.0 // indirect
- github.com/jbenet/goprocess v0.1.4 // indirect
- github.com/jgautheron/goconst v1.5.1 // indirect
+ github.com/ipshipyard/p2p-forge v0.5.1 // indirect
+ github.com/jackpal/go-nat-pmp v1.0.2 // indirect
+ github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
+ github.com/jgautheron/goconst v1.7.1 // indirect
github.com/jingyugao/rowserrcheck v1.1.1 // indirect
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect
- github.com/jonboulle/clockwork v0.2.0 // indirect
+ github.com/jjti/go-spancheck v0.6.2 // indirect
github.com/julz/importas v0.1.0 // indirect
- github.com/kisielk/errcheck v1.6.3 // indirect
- github.com/kisielk/gotool v1.0.0 // indirect
- github.com/kkHAIKE/contextcheck v1.1.4 // indirect
- github.com/klauspost/cpuid/v2 v2.2.6 // indirect
+ github.com/karamaru-alpha/copyloopvar v1.1.0 // indirect
+ github.com/kisielk/errcheck v1.7.0 // indirect
+ github.com/kkHAIKE/contextcheck v1.1.5 // indirect
+ github.com/klauspost/compress v1.18.0 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.10 // indirect
+ github.com/koron/go-ssdp v0.0.5 // indirect
+ github.com/kr/pretty v0.3.1 // indirect
+ github.com/kr/text v0.2.0 // indirect
github.com/kulti/thelper v0.6.3 // indirect
- github.com/kunwardeep/paralleltest v1.0.8 // indirect
+ github.com/kunwardeep/paralleltest v1.0.10 // indirect
github.com/kyoh86/exportloopref v0.1.11 // indirect
- github.com/ldez/gomoddirectives v0.2.3 // indirect
+ github.com/lasiar/canonicalheader v1.1.1 // indirect
+ github.com/ldez/gomoddirectives v0.2.4 // indirect
github.com/ldez/tagliatelle v0.5.0 // indirect
- github.com/leonklingele/grouper v1.1.1 // indirect
+ github.com/leonklingele/grouper v1.1.2 // indirect
+ github.com/libdns/libdns v0.2.2 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
- github.com/libp2p/go-libp2p v0.32.2 // indirect
+ github.com/libp2p/go-flow-metrics v0.2.0 // indirect
+ github.com/libp2p/go-libp2p v0.41.1 // indirect
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
- github.com/libp2p/go-libp2p-kad-dht v0.24.4 // indirect
- github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect
- github.com/libp2p/go-libp2p-record v0.2.0 // indirect
- github.com/libp2p/go-libp2p-routing-helpers v0.7.3 // indirect
+ github.com/libp2p/go-libp2p-kad-dht v0.33.1 // indirect
+ github.com/libp2p/go-libp2p-kbucket v0.7.0 // indirect
+ github.com/libp2p/go-libp2p-record v0.3.1 // indirect
+ github.com/libp2p/go-libp2p-routing-helpers v0.7.5 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
- github.com/libp2p/go-netroute v0.2.1 // indirect
+ github.com/libp2p/go-netroute v0.2.2 // indirect
+ github.com/libp2p/go-reuseport v0.4.0 // indirect
github.com/lufeee/execinquery v1.2.1 // indirect
- github.com/magiconair/properties v1.8.6 // indirect
+ github.com/macabu/inamedparam v0.1.3 // indirect
+ github.com/magiconair/properties v1.8.7 // indirect
github.com/maratori/testableexamples v1.0.0 // indirect
github.com/maratori/testpackage v1.1.1 // indirect
- github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 // indirect
+ github.com/matoous/godox v0.0.0-20240105082147-c5b5e0e7c0c0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
- github.com/mattn/go-runewidth v0.0.9 // indirect
- github.com/mbilski/exhaustivestruct v1.2.0 // indirect
- github.com/mgechev/revive v1.3.2 // indirect
- github.com/miekg/dns v1.1.58 // indirect
+ github.com/mattn/go-runewidth v0.0.15 // indirect
+ github.com/mattn/go-shellwords v1.0.12 // indirect
+ github.com/mgechev/revive v1.3.9 // indirect
+ github.com/mholt/acmez/v3 v3.0.0 // indirect
+ github.com/miekg/dns v1.1.66 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
- github.com/moricho/tparallel v0.3.1 // indirect
+ github.com/moricho/tparallel v0.3.2 // 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.2.0 // indirect
- github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect
+ github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect
+ github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
- github.com/multiformats/go-multistream v0.5.0 // indirect
+ github.com/multiformats/go-multistream v0.6.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
+ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nakabonne/nestif v0.3.1 // indirect
- github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect
- github.com/nishanths/exhaustive v0.11.0 // indirect
+ github.com/nishanths/exhaustive v0.12.0 // indirect
github.com/nishanths/predeclared v0.2.2 // indirect
- github.com/nunnatsa/ginkgolinter v0.13.3 // indirect
+ github.com/nunnatsa/ginkgolinter v0.16.2 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
- github.com/onsi/gomega v1.27.10 // indirect
- github.com/opentracing/opentracing-go v1.2.0 // indirect
- github.com/pelletier/go-toml v1.9.5 // indirect
- github.com/pelletier/go-toml/v2 v2.0.5 // indirect
+ github.com/onsi/ginkgo/v2 v2.22.2 // indirect
+ github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
+ github.com/pelletier/go-toml/v2 v2.2.2 // indirect
+ github.com/pion/datachannel v1.5.10 // indirect
+ github.com/pion/dtls/v2 v2.2.12 // indirect
+ github.com/pion/dtls/v3 v3.0.4 // indirect
+ github.com/pion/ice/v4 v4.0.8 // indirect
+ github.com/pion/interceptor v0.1.37 // indirect
+ github.com/pion/logging v0.2.3 // indirect
+ github.com/pion/mdns/v2 v2.0.7 // indirect
+ github.com/pion/randutil v0.1.0 // indirect
+ github.com/pion/rtcp v1.2.15 // indirect
+ github.com/pion/rtp v1.8.11 // indirect
+ github.com/pion/sctp v1.8.37 // indirect
+ github.com/pion/sdp/v3 v3.0.10 // indirect
+ github.com/pion/srtp/v3 v3.0.4 // indirect
+ github.com/pion/stun v0.6.1 // indirect
+ github.com/pion/stun/v3 v3.0.0 // indirect
+ github.com/pion/transport/v2 v2.2.10 // indirect
+ github.com/pion/transport/v3 v3.0.7 // indirect
+ github.com/pion/turn/v4 v4.0.0 // indirect
+ github.com/pion/webrtc/v4 v4.0.10 // indirect
github.com/pkg/errors v0.9.1 // indirect
- github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
- github.com/polyfloyd/go-errorlint v1.4.3 // indirect
- github.com/prometheus/client_golang v1.18.0 // indirect
- github.com/prometheus/client_model v0.5.0 // indirect
- github.com/prometheus/common v0.46.0 // indirect
- github.com/prometheus/procfs v0.12.0 // indirect
- github.com/quasilyte/go-ruleguard v0.4.0 // indirect
+ github.com/polyfloyd/go-errorlint v1.6.0 // indirect
+ github.com/prometheus/client_golang v1.22.0 // indirect
+ github.com/prometheus/client_model v0.6.2 // indirect
+ github.com/prometheus/common v0.63.0 // indirect
+ github.com/prometheus/procfs v0.16.1 // indirect
+ github.com/quasilyte/go-ruleguard v0.4.2 // indirect
+ github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect
github.com/quasilyte/gogrep v0.5.0 // indirect
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect
+ github.com/quic-go/qpack v0.5.1 // indirect
+ github.com/quic-go/quic-go v0.50.1 // indirect
+ github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect
+ github.com/rivo/uniseg v0.4.7 // indirect
+ github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
- github.com/ryancurrah/gomodguard v1.3.0 // indirect
- github.com/ryanrolds/sqlclosecheck v0.4.0 // indirect
- github.com/samber/lo v1.39.0 // indirect
+ github.com/ryancurrah/gomodguard v1.3.3 // indirect
+ github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect
+ github.com/sagikazarmark/locafero v0.6.0 // indirect
+ github.com/sagikazarmark/slog-shim v0.1.0 // indirect
+ github.com/samber/lo v1.47.0 // indirect
github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect
+ github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect
github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
- github.com/sashamelentyev/usestdlibvars v1.23.0 // indirect
- github.com/securego/gosec/v2 v2.16.0 // indirect
+ github.com/sashamelentyev/usestdlibvars v1.27.0 // indirect
+ github.com/securego/gosec/v2 v2.20.1-0.20240820084340-81cda2f91fbe // indirect
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sivchari/containedctx v1.0.3 // indirect
- github.com/sivchari/nosnakecase v1.7.0 // indirect
- github.com/sivchari/tenv v1.7.1 // indirect
+ github.com/sivchari/tenv v1.10.0 // indirect
github.com/sonatard/noctx v0.0.2 // indirect
+ github.com/sourcegraph/conc v0.3.0 // indirect
github.com/sourcegraph/go-diff v0.7.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
- github.com/spf13/afero v1.8.2 // indirect
- github.com/spf13/cast v1.5.0 // indirect
- github.com/spf13/cobra v1.7.0 // indirect
- github.com/spf13/jwalterweatherman v1.1.0 // indirect
+ github.com/spf13/afero v1.11.0 // indirect
+ github.com/spf13/cast v1.6.0 // indirect
+ github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
- github.com/spf13/viper v1.12.0 // indirect
+ github.com/spf13/viper v1.19.0 // indirect
github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect
- github.com/stretchr/objx v0.5.0 // indirect
- github.com/stretchr/testify v1.8.4 // indirect
- github.com/subosito/gotenv v1.4.1 // indirect
- github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect
+ github.com/stretchr/objx v0.5.2 // indirect
+ github.com/stretchr/testify v1.10.0 // indirect
+ github.com/subosito/gotenv v1.6.0 // indirect
github.com/tdakkota/asciicheck v0.2.0 // indirect
- github.com/tetafro/godot v1.4.11 // indirect
- github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 // indirect
+ github.com/tetafro/godot v1.4.16 // indirect
+ github.com/timakin/bodyclose v0.0.0-20240125160201-f835fa56326a // indirect
github.com/timonwong/loggercheck v0.9.4 // indirect
- github.com/tomarrell/wrapcheck/v2 v2.8.1 // indirect
+ github.com/tomarrell/wrapcheck/v2 v2.9.0 // indirect
github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect
github.com/ultraware/funlen v0.1.0 // indirect
- github.com/ultraware/whitespace v0.0.5 // indirect
- github.com/urfave/cli v1.22.10 // indirect
- github.com/uudashr/gocognit v1.0.7 // indirect
+ github.com/ultraware/whitespace v0.1.1 // indirect
+ github.com/urfave/cli v1.22.16 // indirect
+ github.com/uudashr/gocognit v1.1.3 // indirect
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect
+ github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
- github.com/xen0n/gosmopolitan v1.2.1 // indirect
+ github.com/wlynxg/anet v0.0.5 // indirect
+ github.com/xen0n/gosmopolitan v1.2.2 // indirect
github.com/yagipy/maintidx v1.0.0 // indirect
- github.com/yeya24/promlinter v0.2.0 // indirect
- github.com/ykadowak/zerologlint v0.1.3 // indirect
- gitlab.com/bosi/decorder v0.4.0 // indirect
- go.opencensus.io v0.24.0 // indirect
- go.opentelemetry.io/otel v1.22.0 // indirect
- go.opentelemetry.io/otel/metric v1.22.0 // indirect
- go.opentelemetry.io/otel/trace v1.22.0 // indirect
- go.tmz.dev/musttag v0.7.1 // indirect
+ github.com/yeya24/promlinter v0.3.0 // indirect
+ github.com/ykadowak/zerologlint v0.1.5 // indirect
+ github.com/zeebo/blake3 v0.2.4 // indirect
+ gitlab.com/bosi/decorder v0.4.2 // indirect
+ go-simpler.org/musttag v0.12.2 // indirect
+ go-simpler.org/sloglint v0.7.2 // indirect
+ go.opentelemetry.io/auto/sdk v1.1.0 // indirect
+ go.opentelemetry.io/otel v1.35.0 // indirect
+ go.opentelemetry.io/otel/metric v1.35.0 // indirect
+ go.opentelemetry.io/otel/trace v1.35.0 // indirect
+ go.uber.org/automaxprocs v1.5.3 // indirect
+ go.uber.org/dig v1.18.0 // indirect
+ go.uber.org/fx v1.23.0 // indirect
+ go.uber.org/mock v0.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.26.0 // indirect
- golang.org/x/crypto v0.18.0 // indirect
- golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
- golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 // indirect
- golang.org/x/mod v0.14.0 // indirect
- golang.org/x/net v0.20.0 // indirect
- golang.org/x/sync v0.6.0 // indirect
- golang.org/x/sys v0.16.0 // indirect
- golang.org/x/term v0.16.0 // indirect
- golang.org/x/text v0.14.0 // indirect
- golang.org/x/tools v0.17.0 // indirect
- gonum.org/v1/gonum v0.14.0 // indirect
- google.golang.org/protobuf v1.32.0 // indirect
+ go.uber.org/zap v1.27.0 // indirect
+ go.uber.org/zap/exp v0.3.0 // indirect
+ golang.org/x/crypto v0.38.0 // indirect
+ golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
+ golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f // indirect
+ golang.org/x/mod v0.24.0 // indirect
+ golang.org/x/net v0.40.0 // indirect
+ golang.org/x/sync v0.14.0 // indirect
+ golang.org/x/sys v0.33.0 // indirect
+ golang.org/x/term v0.32.0 // indirect
+ golang.org/x/text v0.25.0 // indirect
+ golang.org/x/tools v0.33.0 // indirect
+ gonum.org/v1/gonum v0.16.0 // indirect
+ google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- honnef.co/go/tools v0.4.3 // indirect
- lukechampine.com/blake3 v1.2.1 // indirect
- mvdan.cc/gofumpt v0.5.0 // indirect
- mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect
- mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect
- mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d // indirect
+ honnef.co/go/tools v0.5.1 // indirect
+ lukechampine.com/blake3 v1.4.1 // indirect
+ mvdan.cc/gofumpt v0.7.0 // indirect
+ mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect
)
diff --git a/test/dependencies/go.sum b/test/dependencies/go.sum
index 7fd77f18833..a2fa489a5f0 100644
--- a/test/dependencies/go.sum
+++ b/test/dependencies/go.sum
@@ -3,306 +3,302 @@
4d63.com/gochecknoglobals v0.2.1 h1:1eiorGsgHOFOuoOiJDy2psSrQbRdIHrlge0IJIkUgDc=
4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
-cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
-cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
-cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
-cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
-cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
-cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
-cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
-cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
-cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
-cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
-cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
-cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
-cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
-cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
-cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
-cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
-cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
-cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
-cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
-cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
-cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
-cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
-cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
-cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
-cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
-cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
-cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
-cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
-cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
-cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
-cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
-cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
-cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
-dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-github.com/4meepo/tagalign v1.3.2 h1:1idD3yxlRGV18VjqtDbqYvQ5pXqQS0wO2dn6M3XstvI=
-github.com/4meepo/tagalign v1.3.2/go.mod h1:Q9c1rYMZJc9dPRkbQPpcBNCLEmY2njbAsXhQOZFE2dE=
-github.com/Abirdcfly/dupword v0.0.12 h1:56NnOyrXzChj07BDFjeRA+IUzSz01jmzEq+G4kEgFhc=
-github.com/Abirdcfly/dupword v0.0.12/go.mod h1:+us/TGct/nI9Ndcbcp3rgNcQzctTj68pq7TcgNpLfdI=
-github.com/Antonboom/errname v0.1.10 h1:RZ7cYo/GuZqjr1nuJLNe8ZH+a+Jd9DaZzttWzak9Bls=
-github.com/Antonboom/errname v0.1.10/go.mod h1:xLeiCIrvVNpUtsN0wxAh05bNIZpqE22/qDMnTBTttiA=
-github.com/Antonboom/nilnil v0.1.5 h1:X2JAdEVcbPaOom2TUa1FxZ3uyuUlex0XMLGYMemu6l0=
-github.com/Antonboom/nilnil v0.1.5/go.mod h1:I24toVuBKhfP5teihGWctrRiPbRKHwZIFOvc6v3HZXk=
+cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
+dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
+dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
+dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
+dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
+git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
+github.com/4meepo/tagalign v1.3.4 h1:P51VcvBnf04YkHzjfclN6BbsopfJR5rxs1n+5zHt+w8=
+github.com/4meepo/tagalign v1.3.4/go.mod h1:M+pnkHH2vG8+qhE5bVc/zeP7HS/j910Fwa9TUSyZVI0=
+github.com/Abirdcfly/dupword v0.0.14 h1:3U4ulkc8EUo+CaT105/GJ1BQwtgyj6+VaBVbAX11Ba8=
+github.com/Abirdcfly/dupword v0.0.14/go.mod h1:VKDAbxdY8YbKUByLGg8EETzYSuC4crm9WwI6Y3S0cLI=
+github.com/Antonboom/errname v0.1.13 h1:JHICqsewj/fNckzrfVSe+T33svwQxmjC+1ntDsHOVvM=
+github.com/Antonboom/errname v0.1.13/go.mod h1:uWyefRYRN54lBg6HseYCFhs6Qjcy41Y3Jl/dVhA87Ns=
+github.com/Antonboom/nilnil v0.1.9 h1:eKFMejSxPSA9eLSensFmjW2XTgTwJMjZ8hUHtV4s/SQ=
+github.com/Antonboom/nilnil v0.1.9/go.mod h1:iGe2rYwCq5/Me1khrysB4nwI7swQvjclR8/YRPl5ihQ=
+github.com/Antonboom/testifylint v1.4.3 h1:ohMt6AHuHgttaQ1xb6SSnxCeK4/rnK7KKzbvs7DmEck=
+github.com/Antonboom/testifylint v1.4.3/go.mod h1:+8Q9+AOLsz5ZiQiiYujJKs9mNz398+M6UgslP4qgJLA=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
-github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
-github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
+github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=
+github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
+github.com/Crocmagnon/fatcontext v0.4.0 h1:4ykozu23YHA0JB6+thiuEv7iT6xq995qS1vcuWZq0tg=
+github.com/Crocmagnon/fatcontext v0.4.0/go.mod h1:ZtWrXkgyfsYPzS6K3O88va6t2GEglG93vnII/F94WC0=
+github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e h1:ZIWapoIRN1VqT8GR8jAwb1Ie9GyehWjVcGh32Y2MznE=
+github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM=
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs=
-github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0 h1:3ZBs7LAezy8gh0uECsA6CGU43FF3zsx5f4eah5FxTMA=
-github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0/go.mod h1:rZLTje5A9kFBe0pzhpe2TdhRniBF++PRHQuRpR8esVc=
+github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 h1:/fTUt5vmbkAcMBt4YQiuC23cV0kEsN1MVMNqeOW43cU=
+github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0/go.mod h1:ONJg5sxcbsdQQ4pOW8TGdTidT2TMAUy/2Xhr8mrYaao=
github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd h1:HNhzThEtZW714v8Eda8sWWRcu9WSzJC+oCyjRjvZgRA=
github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd/go.mod h1:bqoB8kInrTeEtYAwaIXoSRqdwnjQmFhsfusnzyui6yY=
-github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
-github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
-github.com/OpenPeeDeeP/depguard/v2 v2.1.0 h1:aQl70G173h/GZYhWf36aE5H0KaujXfVMnn/f1kSDVYY=
-github.com/OpenPeeDeeP/depguard/v2 v2.1.0/go.mod h1:PUBgk35fX4i7JDmwzlJwJ+GMe6NfO1723wmJMgPThNQ=
-github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
-github.com/alexkohler/nakedret/v2 v2.0.2 h1:qnXuZNvv3/AxkAb22q/sEsEpcA99YxLFACDtEw9TPxE=
-github.com/alexkohler/nakedret/v2 v2.0.2/go.mod h1:2b8Gkk0GsOrqQv/gPWjNLDSKwG8I5moSXG1K4VIBcTQ=
+github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
+github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
+github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJPdp74zmpA=
+github.com/OpenPeeDeeP/depguard/v2 v2.2.0/go.mod h1:CIzddKRvLBC4Au5aYP/i3nyaWQ+ClszLIuVocRiCYFQ=
+github.com/aclements/go-perfevent v0.0.0-20240301234650-f7843625020f h1:JjxwchlOepwsUWcQwD2mLUAGE9aCp0/ehy6yCHFBOvo=
+github.com/aclements/go-perfevent v0.0.0-20240301234650-f7843625020f/go.mod h1:tMDTce/yLLN/SK8gMOxQfnyeMeCg8KGzp0D1cbECEeo=
+github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk=
+github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
+github.com/alecthomas/go-check-sumtype v0.1.4 h1:WCvlB3l5Vq5dZQTFmodqL2g68uHiSwwlWcT5a2FGK0c=
+github.com/alecthomas/go-check-sumtype v0.1.4/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ=
+github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
+github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
+github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0=
+github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs=
+github.com/alexkohler/nakedret/v2 v2.0.4 h1:yZuKmjqGi0pSmjGpOC016LtPJysIL0WEUiaXW5SUnNg=
+github.com/alexkohler/nakedret/v2 v2.0.4/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU=
github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw=
github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE=
github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw=
github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY=
github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU=
github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s=
github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI=
-github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
+github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
-github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bitfield/gotestdox v0.2.2 h1:x6RcPAbBbErKLnapz1QeAlf3ospg8efBsedU93CDsnE=
+github.com/bitfield/gotestdox v0.2.2/go.mod h1:D+gwtS0urjBrzguAkTM2wodsTQYFHdpx8eqRJ3N+9pY=
github.com/bkielbasa/cyclop v1.2.1 h1:AeF71HZDob1P2/pRm1so9cd1alZnrpyc4q2uP2l0gJY=
github.com/bkielbasa/cyclop v1.2.1/go.mod h1:K/dT/M0FPAiYjBgQGau7tz+3TMh4FWAEqlMhzFWCrgM=
github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M=
github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k=
-github.com/bombsimon/wsl/v3 v3.4.0 h1:RkSxjT3tmlptwfgEgTgU+KYKLI35p/tviNXNXiL2aNU=
-github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo=
-github.com/breml/bidichk v0.2.4 h1:i3yedFWWQ7YzjdZJHnPo9d/xURinSq3OM+gyM43K4/8=
-github.com/breml/bidichk v0.2.4/go.mod h1:7Zk0kRFt1LIZxtQdl9W9JwGAcLTTkOs+tN7wuEYGJ3s=
-github.com/breml/errchkjson v0.3.1 h1:hlIeXuspTyt8Y/UmP5qy1JocGNR00KQHgfaNtRAjoxQ=
-github.com/breml/errchkjson v0.3.1/go.mod h1:XroxrzKjdiutFyW3nWhw34VGg7kiMsDQox73yWCGI2U=
-github.com/butuzov/ireturn v0.2.0 h1:kCHi+YzC150GE98WFuZQu9yrTn6GEydO2AuPLbTgnO4=
-github.com/butuzov/ireturn v0.2.0/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc=
-github.com/butuzov/mirror v1.1.0 h1:ZqX54gBVMXu78QLoiqdwpl2mgmoOJTk7s4p4o+0avZI=
-github.com/butuzov/mirror v1.1.0/go.mod h1:8Q0BdQU6rC6WILDiBM60DBfvV78OLJmMmixe7GF45AE=
-github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-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/bombsimon/wsl/v4 v4.4.1 h1:jfUaCkN+aUpobrMO24zwyAMwMAV5eSziCkOKEauOLdw=
+github.com/bombsimon/wsl/v4 v4.4.1/go.mod h1:Xu/kDxGZTofQcDGCtQe9KCzhHphIe0fDuyWTxER9Feo=
+github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
+github.com/breml/bidichk v0.2.7 h1:dAkKQPLl/Qrk7hnP6P+E0xOodrq8Us7+U0o4UBOAlQY=
+github.com/breml/bidichk v0.2.7/go.mod h1:YodjipAGI9fGcYM7II6wFvGhdMYsC5pHDlGzqvEW3tQ=
+github.com/breml/errchkjson v0.3.6 h1:VLhVkqSBH96AvXEyclMR37rZslRrY2kcyq+31HCsVrA=
+github.com/breml/errchkjson v0.3.6/go.mod h1:jhSDoFheAF2RSDOlCfhHO9KqhZgAYLyvHe7bRCX8f/U=
+github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
+github.com/butuzov/ireturn v0.3.0 h1:hTjMqWw3y5JC3kpnC5vXmFJAWI/m31jaCYQqzkS6PL0=
+github.com/butuzov/ireturn v0.3.0/go.mod h1:A09nIiwiqzN/IoVo9ogpa0Hzi9fex1kd9PSD6edP5ZA=
+github.com/butuzov/mirror v1.2.0 h1:9YVK1qIjNspaqWutSv8gsge2e/Xpq1eqEkslEUHy5cs=
+github.com/butuzov/mirror v1.2.0/go.mod h1:DqZZDtzm42wIAIyHXeN8W/qb1EPlb9Qn/if9icBOpdQ=
+github.com/caddyserver/certmagic v0.21.6 h1:1th6GfprVfsAtFNOu4StNMF5IxK5XiaI0yZhAHlZFPE=
+github.com/caddyserver/certmagic v0.21.6/go.mod h1:n1sCo7zV1Ez2j+89wrzDxo4N/T1Ws/Vx8u5NvuBFabw=
+github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
+github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
+github.com/catenacyber/perfsprint v0.7.1 h1:PGW5G/Kxn+YrN04cRAZKC+ZuvlVwolYMrIyyTJ/rMmc=
+github.com/catenacyber/perfsprint v0.7.1/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50=
+github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg=
+github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4=
github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ=
-github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 h1:W9o46d2kbNL06lq7UNDPV0zYLzkrde/bjIqO02eoll0=
-github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8/go.mod h1:gakxgyXaaPkxvLw1XQxNGK4I37ys9iBRzNUx/B7pUCo=
-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=
-github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc=
+github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww=
+github.com/ckaznocha/intrange v0.1.2 h1:3Y4JAxcMntgb/wABQ6e8Q8leMd26JbX2790lIss9MTI=
+github.com/ckaznocha/intrange v0.1.2/go.mod h1:RWffCw/vKBwHeOEwWdCikAtY0q4gGt8VhJZEEA5n+RE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cockroachdb/crlib v0.0.0-20241015224233-894974b3ad94 h1:bvJv505UUfjzbaIPdNS4AEkHreDqQk6yuNpsdRHpwFA=
+github.com/cockroachdb/crlib v0.0.0-20241015224233-894974b3ad94/go.mod h1:Gq51ZeKaFCXk6QwuGM0w1dnaOqc/F5zKT2zA9D6Xeac=
+github.com/cockroachdb/datadriven v1.0.3-0.20240530155848-7682d40af056 h1:slXychO2uDM6hYRu4c0pD0udNI8uObfeKN6UInWViS8=
+github.com/cockroachdb/datadriven v1.0.3-0.20240530155848-7682d40af056/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
+github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
+github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8=
+github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4=
+github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M=
+github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
+github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
+github.com/cockroachdb/metamorphic v0.0.0-20231108215700-4ba948b56895 h1:XANOgPYtvELQ/h4IrmPAohXqe2pWA8Bwhejr3VQoZsA=
+github.com/cockroachdb/metamorphic v0.0.0-20231108215700-4ba948b56895/go.mod h1:aPd7gM9ov9M8v32Yy5NJrDyOcD8z642dqs+F0CeNXfA=
+github.com/cockroachdb/pebble/v2 v2.0.3 h1:YJ3Sc9jRN/q6OOCNyRHPbcpenbxL1DdgdpUqPlPus6o=
+github.com/cockroachdb/pebble/v2 v2.0.3/go.mod h1:NgxgNcWwyG/uxkLUZGM2aelshaLIZvc0hCX7SCfaO8s=
+github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
+github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
+github.com/cockroachdb/swiss v0.0.0-20250327203710-2932b022f6df h1:GUJ4KuZtbOcIfRlprHJFFvIqQ4irtQUl+1fJr+yNmPI=
+github.com/cockroachdb/swiss v0.0.0-20250327203710-2932b022f6df/go.mod h1:yBRu/cnL4ks9bgy4vAASdjIW+/xMlFwuHKqtmh3GZQg=
+github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
+github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
+github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
+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.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
+github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
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.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
-github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
+github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf h1:dwGgBWn84wUS1pVikGiruW+x5XM4amhjaZO20vCjay4=
+github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf/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/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo=
github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc=
-github.com/daixiang0/gci v0.11.0 h1:XeQbFKkCRxvVyn06EOuNY6LPGBLVuB/W130c8FrnX6A=
-github.com/daixiang0/gci v0.11.0/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI=
+github.com/daixiang0/gci v0.13.4 h1:61UGkmpoAcxHM2hhNkZEf5SzwQtWJXTSws7jaPyqwlw=
+github.com/daixiang0/gci v0.13.4/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU=
-github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
-github.com/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU=
-github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c=
+github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U=
+github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
+github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
+github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8=
+github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY=
+github.com/dnephin/pflag v1.0.7 h1:oxONGlWxhmUct0YzKTgrpQv9AUA1wtPBn7zuSjJqptk=
+github.com/dnephin/pflag v1.0.7/go.mod h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
-github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
-github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
-github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4=
-github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
-github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA=
-github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0=
-github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw=
-github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY=
+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/elastic/gosigar v0.14.3 h1:xwkKwPia+hSfg9GqrCUKYdId102m9qTJIIr7egmK/uo=
+github.com/elastic/gosigar v0.14.3/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
+github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q=
+github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A=
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A=
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg=
-github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
+github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
+github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
-github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y=
-github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI=
-github.com/flynn/noise v1.0.1 h1:vPp/jdQLXC6ppsXSj/pM3W1BIJ5FEHE2TulSJBpb43Y=
+github.com/filecoin-project/go-clock v0.1.0 h1:SFbYIM75M8NnFm1yMHhN9Ahy3W5bEZV9gd6MPfXbKVU=
+github.com/filecoin-project/go-clock v0.1.0/go.mod h1:4uB/O4PvOjlx1VCMdZ9MyDZXRm//gkj1ELEbxfI1AZs=
+github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA=
+github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
+github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
+github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
+github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
-github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
-github.com/go-critic/go-critic v0.9.0 h1:Pmys9qvU3pSML/3GEQ2Xd9RZ/ip+aXHKILuxczKGV/U=
-github.com/go-critic/go-critic v0.9.0/go.mod h1:5P8tdXL7m/6qnyG6oRAlYLORvoXH0WDypYgAEmagT40=
-github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
-github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
-github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
-github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/gammazero/chanqueue v1.1.0 h1:yiwtloc1azhgGLFo2gMloJtQvkYD936Ai7tBfa+rYJw=
+github.com/gammazero/chanqueue v1.1.0/go.mod h1:fMwpwEiuUgpab0sH4VHiVcEoji1pSi+EIzeG4TPeKPc=
+github.com/gammazero/deque v1.0.0 h1:LTmimT8H7bXkkCy6gZX7zNLtkbz4NdS2z8LZuor3j34=
+github.com/gammazero/deque v1.0.0/go.mod h1:iflpYvtGfM3U8S8j+sZEKIak3SAKYpA5/SQewgfXDKo=
+github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
+github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
+github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9 h1:r5GgOLGbza2wVHRzK7aAj6lWZjfbAwiu/RDCVOKjRyM=
+github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/ghostiam/protogetter v0.3.6 h1:R7qEWaSgFCsy20yYHNIJsU9ZOb8TziSRRxuAOTVKeOk=
+github.com/ghostiam/protogetter v0.3.6/go.mod h1:7lpeDnEJ1ZjL/YtyoN99ljO4z0pd3H0d18/t2dPBxHw=
+github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
+github.com/go-critic/go-critic v0.11.4 h1:O7kGOCx0NDIni4czrkRIXTnit0mkyKOCePh3My6OyEU=
+github.com/go-critic/go-critic v0.11.4/go.mod h1:2QAdo4iuLik5S9YG0rT4wcZ8QxwHYkrr6/2MWAiv/vc=
+github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
+github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
+github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
-github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
-github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
-github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
+github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
+github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
+github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
+github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8=
github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU=
github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s=
github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw=
github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4=
-github.com/go-toolsmith/astequal v1.1.0 h1:kHKm1AWqClYn15R0K1KKE4RG614D46n+nqUQ06E1dTw=
github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ=
+github.com/go-toolsmith/astequal v1.2.0 h1:3Fs3CYZ1k9Vo4FzFhwwewC3CHISHDnVUPC4x0bI2+Cw=
+github.com/go-toolsmith/astequal v1.2.0/go.mod h1:c8NZ3+kSFtFY/8lPso4v8LuJjdJiUFVnSuU3s0qrrDY=
github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco=
github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4=
github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA=
github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA=
github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk=
+github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus=
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw=
github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ=
github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus=
github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig=
+github.com/go-viper/mapstructure/v2 v2.0.0 h1:dhn8MZ1gZ0mzeodTG3jt5Vj/o87xZKuNAprG2mQfMfc=
+github.com/go-viper/mapstructure/v2 v2.0.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U=
github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
-github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
-github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
+github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
+github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
+github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
-github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
-github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
-github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
-github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
-github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
-github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
-github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
-github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
-github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
-github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0=
-github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4=
+github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e h1:4bw4WeyTYPp0smaXiJZCNnLrvVBqirQVreixayXezGc=
+github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM=
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk=
-github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo=
-github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ=
-github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY=
-github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs=
-github.com/golangci/golangci-lint v1.54.1 h1:0qMrH1gkeIBqCZaaAm5Fwq4xys9rO/lJofHfZURIFFk=
-github.com/golangci/golangci-lint v1.54.1/go.mod h1:JK47+qksV/t2mAz9YvndwT0ZLW4A1rvDljOs3g9jblo=
-github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA=
-github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
-github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA=
-github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o=
-github.com/golangci/misspell v0.4.1 h1:+y73iSicVy2PqyX7kmUefHusENlrP9YwuHZHPLGQj/g=
-github.com/golangci/misspell v0.4.1/go.mod h1:9mAN1quEo3DlpbaIKKyEvRxK1pwqR9s/Sea1bJCtlNI=
-github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 h1:DIPQnGy2Gv2FSA4B/hh8Q7xx3B7AIDk3DAMeHclH1vQ=
-github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs=
-github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys=
-github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ=
+github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9 h1:/1322Qns6BtQxUZDTAT4SdcoxknUki7IAoK4SAXr8ME=
+github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9/go.mod h1:Oesb/0uFAyWoaw1U1qS5zyjCg5NP9C9iwjnI4tIsXEE=
+github.com/golangci/golangci-lint v1.60.2 h1:Y8aWnZCMOLY5T7Ga5hcoemyKsZZJCUmIIK3xTD3jIhc=
+github.com/golangci/golangci-lint v1.60.2/go.mod h1:4UvjLpOJoQSvmyWkmO1urDR3txhL9R9sn4oM/evJ95g=
+github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs=
+github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo=
+github.com/golangci/modinfo v0.3.4 h1:oU5huX3fbxqQXdfspamej74DFX0kyGLkw1ppvXoJ8GA=
+github.com/golangci/modinfo v0.3.4/go.mod h1:wytF1M5xl9u0ij8YSvhkEVPP3M5Mc7XLl1pxH3B2aUM=
+github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c=
+github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc=
+github.com/golangci/revgrep v0.5.3 h1:3tL7c1XBMtWHHqVpS5ChmiAAoe4PF/d5+ULzV9sLAzs=
+github.com/golangci/revgrep v0.5.3/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k=
+github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs=
+github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
-github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
+github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
-github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-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-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20231229205709-960ae82b1e42 h1:dHLYa5D8/Ta0aLR2XcPsrkpAgGeFs6thhMcQK0oQ0n8=
-github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
-github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
-github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
-github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
+github.com/google/pprof v0.0.0-20250208200701-d0013a598941 h1:43XjGa6toxLpeksjcxs1jIoIyr+vUfOqY2c6HB4bpoc=
+github.com/google/pprof v0.0.0-20250208200701-d0013a598941/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
+github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
-github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601 h1:mrEEilTAUmaAORhssPPkxj84TsHrPMLBGW2Z4SoTxm8=
-github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0=
-github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
+github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s=
+github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0=
+github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
+github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk=
github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc=
github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado=
@@ -314,18 +310,12 @@ github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3
github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A=
github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M=
github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY=
-github.com/gxed/go-shellwords v1.0.3 h1:2TP32H4TAklZUdz84oj95BJhVnIrRasyx2j1cqH5K38=
-github.com/gxed/go-shellwords v1.0.3/go.mod h1:N7paucT91ByIjmVJHhvoarjoQnmsi3Jd3vH7VqgtMxQ=
-github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
-github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
-github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU=
+github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
-github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
-github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
-github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
+github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
@@ -334,174 +324,182 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
-github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
-github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
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/boxo v0.17.1-0.20240126101119-fdfcfcc0708a h1:BMxa0aXrjyGh5gAkzxVsjDN71YhAWGfjbOoNvZt4/jg=
-github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a/go.mod h1:pIZgTWdm3k3pLF9Uq6MB8JEcW07UDwNJjlXW1HELW80=
-github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs=
-github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM=
-github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
-github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
+github.com/ipfs/boxo v0.31.1-0.20250528182950-f87feb50c39c h1:0jAFJxC74Gy0VwDG6WwYJq0yZdXOFIIeCwUXXln0w6A=
+github.com/ipfs/boxo v0.31.1-0.20250528182950-f87feb50c39c/go.mod h1:gEkUkBiZWtEjHd1AiUxaWEYaQApPtbeGF45fdfCwLX0=
+github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
+github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
+github.com/ipfs/go-block-format v0.2.1 h1:96kW71XGNNa+mZw/MTzJrCpMhBWCrd9kBLoKm9Iip/Q=
+github.com/ipfs/go-block-format v0.2.1/go.mod h1:frtvXHMQhM6zn7HvEQu+Qz5wSTj+04oEH/I+NjDgEjk=
+github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg=
+github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk=
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.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
-github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8=
+github.com/ipfs/go-datastore v0.8.2 h1:Jy3wjqQR6sg/LhyY0NIePZC3Vux19nLtg7dx0TVqr6U=
+github.com/ipfs/go-datastore v0.8.2/go.mod h1:W+pI1NsUsz3tcsAACMtfC+IZdnQTnC/7VfPoJBQuts0=
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-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ=
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-pq v0.0.3 h1:YpoHVJB+jzK15mr/xsWC574tyDLkezVrDNeaalQBsTE=
-github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0=
-github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs=
-github.com/ipfs/go-ipld-format v0.6.0 h1:VEJlA2kQ3LqFSIm5Vu6eIlSxD/Ze90xtc4Meten1F5U=
-github.com/ipfs/go-ipld-format v0.6.0/go.mod h1:g4QVMTn3marU3qXchwjpKPKgJv+zF+OlaKMyhJ4LHPg=
+github.com/ipfs/go-ipfs-pq v0.0.3/go.mod h1:btNw5hsHBpRcSSgZtiNm/SLj5gYIZ18AKtv3kERkRb4=
+github.com/ipfs/go-ipld-format v0.6.1 h1:lQLmBM/HHbrXvjIkrydRXkn+gc0DE5xO5fqelsCKYOQ=
+github.com/ipfs/go-ipld-format v0.6.1/go.mod h1:8TOH1Hj+LFyqM2PjSqI2/ZnyO0KlfhHbJLkbxFa61hs=
github.com/ipfs/go-ipld-legacy v0.2.1 h1:mDFtrBpmU7b//LzLSypVrXsD8QxkEWxu5qVxN99/+tk=
github.com/ipfs/go-ipld-legacy v0.2.1/go.mod h1:782MOUghNzMO2DER0FlBR94mllfdCJCkTtDtPM51otM=
-github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
-github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
-github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
-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.8.1 h1:YhxAs1+wxb5jk7RvS0LHdyiILpNmRIRnZVztekOF0pg=
+github.com/ipfs/go-log/v2 v2.6.0 h1:2Nu1KKQQ2ayonKp4MPo6pXCjqw1ULc9iohRqWV5EYqg=
+github.com/ipfs/go-log/v2 v2.6.0/go.mod h1:p+Efr3qaY5YXpx9TX7MoLCSEZX5boSWj9wh86P5HJa8=
+github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6q/JR9V40TU=
+github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY=
+github.com/ipfs/go-peertaskqueue v0.8.2 h1:PaHFRaVFdxQk1Qo3OKiHPYjmmusQy7gKQUaL8JDszAU=
+github.com/ipfs/go-peertaskqueue v0.8.2/go.mod h1:L6QPvou0346c2qPJNiJa6BvOibxDfaiPlqHInmzg0FA=
+github.com/ipfs/go-test v0.2.2 h1:1yjYyfbdt1w93lVzde6JZ2einh3DIV40at4rVoyEcE8=
+github.com/ipfs/go-test v0.2.2/go.mod h1:cmLisgVwkdRCnKu/CFZOk2DdhOcwghr5GsHeqwexoRA=
github.com/ipfs/hang-fds v0.1.0 h1:deBiFlWHsVGzJ0ZMaqscEqRM1r2O1rFZ59UiQXb1Xko=
github.com/ipfs/hang-fds v0.1.0/go.mod h1:29VLWOn3ftAgNNgXg/al7b11UzuQ+w7AwtCGcTaWkbM=
-github.com/ipfs/iptb v1.4.0 h1:YFYTrCkLMRwk/35IMyC6+yjoQSHTEcNcefBStLJzgvo=
-github.com/ipfs/iptb v1.4.0/go.mod h1:1rzHpCYtNp87/+hTxG5TfCVn/yMY3dKnLn8tBiMfdmg=
-github.com/ipfs/iptb-plugins v0.5.0 h1:zEMLlWAb531mLpD36KFy/yc0egT6FkBEHQtdERexNao=
-github.com/ipfs/iptb-plugins v0.5.0/go.mod h1:/6crDf3s58T70BhZ+m9SyyKpK7VvSDS2Ny4kafxXDp4=
-github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc=
-github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s=
+github.com/ipfs/iptb v1.4.1 h1:faXd3TKGPswbHyZecqqg6UfbES7RDjTKQb+6VFPKDUo=
+github.com/ipfs/iptb v1.4.1/go.mod h1:nTsBMtVYFEu0FjC5DgrErnABm3OG9ruXkFXGJoTV5OA=
+github.com/ipfs/iptb-plugins v0.5.1 h1:11PNTNEt2+SFxjUcO5qpyCTXqDj6T8Tx9pU/G4ytCIQ=
+github.com/ipfs/iptb-plugins v0.5.1/go.mod h1:mscJAjRnu4g16QK6oUBn9RGpcp8ueJmLfmPxIG/At78=
+github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0=
+github.com/ipld/go-codec-dagpb v1.7.0/go.mod h1:rD3Zg+zub9ZnxcLwfol/OTQRVjaLzXypgy4UqHQvilM=
github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E=
github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ=
+github.com/ipshipyard/p2p-forge v0.5.1 h1:9MCpAlk+wNhy7W/yOYKgi9KlXPnyb0abmDpsRPHUDxQ=
+github.com/ipshipyard/p2p-forge v0.5.1/go.mod h1:GNDXM2CR8KRS8mJGw7ARIRVlrG9NH8MdewgNVfIIByA=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
-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-random-files v0.0.0-20190219210431-31b3f20ebded h1:fHCa28iw+qaRWZK4IqrntHxXALD5kKr/ESrpOCRRdrg=
-github.com/jbenet/go-random-files v0.0.0-20190219210431-31b3f20ebded/go.mod h1:FKvZrl5nnaGnTAMewcq0i7wM5zHD75e0lwlnF8q46uo=
+github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
-github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o=
-github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
-github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM=
-github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4=
+github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk=
+github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
+github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk=
+github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4=
github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs=
github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c=
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48=
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0=
-github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
-github.com/jonboulle/clockwork v0.2.0 h1:J2SLSdy7HgElq8ekSl2Mxh6vrRNFxqbXGenYH2I02Vs=
-github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
-github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
+github.com/jjti/go-spancheck v0.6.2 h1:iYtoxqPMzHUPp7St+5yA8+cONdyXD3ug6KK15n7Pklk=
+github.com/jjti/go-spancheck v0.6.2/go.mod h1:+X7lvIrR5ZdUTkxFYqzJ0abr8Sb5LOo80uOhWNqIrYA=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
-github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
-github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
-github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY=
github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0=
+github.com/karamaru-alpha/copyloopvar v1.1.0 h1:x7gNyKcC2vRBO1H2Mks5u1VxQtYvFiym7fCjIP8RPos=
+github.com/karamaru-alpha/copyloopvar v1.1.0/go.mod h1:u7CIfztblY0jZLOQZgH3oYsJzpC2A7S6u/lfgSXHy0k=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
-github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8=
-github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw=
-github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
+github.com/kisielk/errcheck v1.7.0 h1:+SbscKmWJ5mOK/bO1zS60F5I9WwZDWOfRsC4RwfwRV0=
+github.com/kisielk/errcheck v1.7.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/kkHAIKE/contextcheck v1.1.4 h1:B6zAaLhOEEcjvUgIYEqystmnFk1Oemn8bvJhbt0GMb8=
-github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJGZVmr6QRBNJg=
-github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
-github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
-github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
-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.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
-github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
-github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kkHAIKE/contextcheck v1.1.5 h1:CdnJh63tcDe53vG+RebdpdXJTc9atMgGqdx8LXxiilg=
+github.com/kkHAIKE/contextcheck v1.1.5/go.mod h1:O930cpht4xb1YQpK+1+AgoM3mFsvxr7uyFptcnWTYUA=
+github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
+github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
+github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
+github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
+github.com/koron/go-ssdp v0.0.5 h1:E1iSMxIs4WqxTbIBLtmNBeOOC+1sCIXQeqTWVnpmwhk=
+github.com/koron/go-ssdp v0.0.5/go.mod h1:Qm59B7hpKpDqfyRNWRNr00jGwLdXjDyZh6y7rH6VS0w=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
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/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/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs=
github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I=
-github.com/kunwardeep/paralleltest v1.0.8 h1:Ul2KsqtzFxTlSU7IP0JusWlLiNqQaloB9vguyjbE558=
-github.com/kunwardeep/paralleltest v1.0.8/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY=
+github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs=
+github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY=
github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ=
github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA=
-github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA=
-github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0=
+github.com/lasiar/canonicalheader v1.1.1 h1:wC+dY9ZfiqiPwAexUApFush/csSPXeIi4QqyxXmng8I=
+github.com/lasiar/canonicalheader v1.1.1/go.mod h1:cXkb3Dlk6XXy+8MVQnF23CYKWlyA7kfQhSw2CcZtZb0=
+github.com/ldez/gomoddirectives v0.2.4 h1:j3YjBIjEBbqZ0NKtBNzr8rtMHTOrLPeiwTkfUJZ3alg=
+github.com/ldez/gomoddirectives v0.2.4/go.mod h1:oWu9i62VcQDYp9EQ0ONTfqLNh+mDLWWDO+SO0qSQw5g=
github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo=
github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4=
-github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU=
-github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY=
+github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY=
+github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA=
+github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
+github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
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-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
-github.com/libp2p/go-libp2p v0.32.2 h1:s8GYN4YJzgUoyeYNPdW7JZeZ5Ee31iNaIBfGYMAY4FQ=
-github.com/libp2p/go-libp2p v0.32.2/go.mod h1:E0LKe+diV/ZVJVnOJby8VC5xzHF0660osg71skcxJvk=
+github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw=
+github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc=
+github.com/libp2p/go-libp2p v0.41.1 h1:8ecNQVT5ev/jqALTvisSJeVNvXYJyK4NhQx1nNRXQZE=
+github.com/libp2p/go-libp2p v0.41.1/go.mod h1:DcGTovJzQl/I7HMrby5ZRjeD0kQkGiy+9w6aEkSZpRI=
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
-github.com/libp2p/go-libp2p-kad-dht v0.24.4 h1:ktNiJe7ffsJ1wX3ULpMCwXts99mPqGFSE/Qn1i8pErQ=
-github.com/libp2p/go-libp2p-kad-dht v0.24.4/go.mod h1:ybWBJ5Fbvz9sSLkNtXt+2+bK0JB8+tRPvhBbRGHegRU=
-github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0=
-github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEHetYSPXOaJnOiD8i0=
-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.7.3 h1:u1LGzAMVRK9Nqq5aYDVOiq/HaB93U9WWczBzGyAC5ZY=
-github.com/libp2p/go-libp2p-routing-helpers v0.7.3/go.mod h1:cN4mJAD/7zfPKXBcs9ze31JGYAZgzdABEm+q/hkswb8=
+github.com/libp2p/go-libp2p-kad-dht v0.33.1 h1:hKFhHMf7WH69LDjaxsJUWOU6qZm71uO47M/a5ijkiP0=
+github.com/libp2p/go-libp2p-kad-dht v0.33.1/go.mod h1:CdmNk4VeGJa9EXM9SLNyNVySEvduKvb+5rSC/H4pLAo=
+github.com/libp2p/go-libp2p-kbucket v0.7.0 h1:vYDvRjkyJPeWunQXqcW2Z6E93Ywx7fX0jgzb/dGOKCs=
+github.com/libp2p/go-libp2p-kbucket v0.7.0/go.mod h1:blOINGIj1yiPYlVEX0Rj9QwEkmVnz3EP8LK1dRKBC6g=
+github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg=
+github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.5 h1:HdwZj9NKovMx0vqq6YNPTh6aaNzey5zHD7HeLJtq6fI=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.5/go.mod h1:3YaxrwP0OBPDD7my3D0KxfR89FlcX/IEbxDEDfAmj98=
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-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
-github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk=
-github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU=
-github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
+github.com/libp2p/go-netroute v0.2.2 h1:Dejd8cQ47Qx2kRABg6lPwknU7+nBnFRpko45/fFPuZ8=
+github.com/libp2p/go-netroute v0.2.2/go.mod h1:Rntq6jUAH0l9Gg17w5bFGhcC9a+vk4KNXs6s7IljKYE=
github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
-github.com/libp2p/go-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ=
+github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
+github.com/libp2p/go-yamux/v5 v5.0.0 h1:2djUh96d3Jiac/JpGkKs4TO49YhsfLopAoryfPmf+Po=
+github.com/libp2p/go-yamux/v5 v5.0.0/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU=
github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM=
github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM=
-github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
-github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
+github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
+github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk=
+github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I=
+github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
+github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI=
github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE=
github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04=
github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc=
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
-github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 h1:gWg6ZQ4JhDfJPqlo2srm/LN17lpybq15AryXIRcWYLE=
-github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
+github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
+github.com/matoous/godox v0.0.0-20240105082147-c5b5e0e7c0c0 h1:Ny7cm4KSWceJLYyI1sm+aFIVDWSGXLcOJ0O0UaS5wdU=
+github.com/matoous/godox v0.0.0-20240105082147-c5b5e0e7c0c0/go.mod h1:jgE/3fUXiTurkdHOLT5WEkThTSuE7yxHv5iWPa80afs=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
-github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
-github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
+github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
+github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo=
-github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc=
-github.com/mgechev/revive v1.3.2 h1:Wb8NQKBaALBJ3xrrj4zpwJwqwNA6nDpyJSEQWcCka6U=
-github.com/mgechev/revive v1.3.2/go.mod h1:UCLtc7o5vg5aXCwdUTU1kEBQ1v+YXPAkYDIDXbrs5I0=
-github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
-github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
-github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
+github.com/mgechev/revive v1.3.9 h1:18Y3R4a2USSBF+QZKFQwVkBROUda7uoBlkEuBD+YD1A=
+github.com/mgechev/revive v1.3.9/go.mod h1:+uxEIr5UH0TjXWHTno3xh4u7eg6jDpXKzQccA9UGhHU=
+github.com/mholt/acmez/v3 v3.0.0 h1:r1NcjuWR0VaKP2BTjDK9LRFBw/WvURx3jlaEUl9Ht8E=
+github.com/mholt/acmez/v3 v3.0.0/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
+github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
+github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE=
+github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE=
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
+github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU=
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc=
+github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
@@ -510,13 +508,10 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
-github.com/moricho/tparallel v0.3.1 h1:fQKD4U1wRMAYNngDonW5XupoB/ZGJHdpzrWqgyg9krA=
-github.com/moricho/tparallel v0.3.1/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI=
+github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI=
+github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U=
github.com/mr-tron/base58 v1.1.2/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=
@@ -524,12 +519,13 @@ github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aG
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
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.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
-github.com/multiformats/go-multiaddr v0.12.2 h1:9G9sTY/wCYajKa9lyfWPmpZAwe6oV+Wb1zcmMS1HG24=
-github.com/multiformats/go-multiaddr v0.12.2/go.mod h1:GKyaTYjZRdcUhyOetrxTk9z0cW+jA/YrnqTOvKgi44M=
-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 v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
+github.com/multiformats/go-multiaddr v0.15.0 h1:zB/HeaI/apcZiTDwhY5YqMvNVl/oQYvs3XySU+qeAVo=
+github.com/multiformats/go-multiaddr v0.15.0/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0=
+github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M=
+github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
+github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg=
@@ -537,165 +533,225 @@ github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI1
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
-github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE=
-github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA=
-github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
+github.com/multiformats/go-multistream v0.6.0 h1:ZaHKbsL404720283o4c/IHQXiS6gb8qAN5EIJ4PN5EA=
+github.com/multiformats/go-multistream v0.6.0/go.mod h1:MOyoG5otO24cHIg8kf9QW2/NozURlkP/rvi2FQJyCPg=
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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U=
github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE=
-github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA=
-github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8=
-github.com/nishanths/exhaustive v0.11.0 h1:T3I8nUGhl/Cwu5Z2hfc92l0e04D2GEW6e0l8pzda2l0=
-github.com/nishanths/exhaustive v0.11.0/go.mod h1:RqwDsZ1xY0dNdqHho2z6X+bgzizwbLYOWnZbbl2wLB4=
+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/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhKRf3Swg=
+github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs=
github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk=
github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c=
-github.com/nunnatsa/ginkgolinter v0.13.3 h1:wEvjrzSMfDdnoWkctignX9QTf4rT9f4GkQ3uVoXBmiU=
-github.com/nunnatsa/ginkgolinter v0.13.3/go.mod h1:aTKXo8WddENYxNEFT+4ZxEgWXqlD9uMD3w9Bfw/ABEc=
+github.com/nunnatsa/ginkgolinter v0.16.2 h1:8iLqHIZvN4fTLDC0Ke9tbSZVcyVHoBs0HIbnVSxfHJk=
+github.com/nunnatsa/ginkgolinter v0.16.2/go.mod h1:4tWRinDN1FeJgU+iJANW/kz7xKN5nYRAOfJDQUS9dOQ=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
-github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
-github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs=
-github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
-github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
-github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
-github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
-github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
-github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
-github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k=
+github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
+github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
+github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
+github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
+github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
+github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw=
+github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
+github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
-github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
-github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
-github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
-github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
-github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
+github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
+github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
+github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
+github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
+github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o=
+github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
+github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
+github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk=
+github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE=
+github.com/pion/dtls/v3 v3.0.4 h1:44CZekewMzfrn9pmGrj5BNnTMDCFwr+6sLH+cCuLM7U=
+github.com/pion/dtls/v3 v3.0.4/go.mod h1:R373CsjxWqNPf6MEkfdy3aSe9niZvL/JaKlGeFphtMg=
+github.com/pion/ice/v4 v4.0.8 h1:ajNx0idNG+S+v9Phu4LSn2cs8JEfTsA1/tEjkkAVpFY=
+github.com/pion/ice/v4 v4.0.8/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
+github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
+github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
+github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
+github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
+github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90=
+github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM=
+github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
+github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
+github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
+github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
+github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
+github.com/pion/rtp v1.8.11 h1:17xjnY5WO5hgO6SD3/NTIUPvSFw/PbLsIJyz1r1yNIk=
+github.com/pion/rtp v1.8.11/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
+github.com/pion/sctp v1.8.37 h1:ZDmGPtRPX9mKCiVXtMbTWybFw3z/hVKAZgU81wcOrqs=
+github.com/pion/sctp v1.8.37/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
+github.com/pion/sdp/v3 v3.0.10 h1:6MChLE/1xYB+CjumMw+gZ9ufp2DPApuVSnDT8t5MIgA=
+github.com/pion/sdp/v3 v3.0.10/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
+github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
+github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ=
+github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
+github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
+github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
+github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
+github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
+github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
+github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
+github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
+github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
+github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
+github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
+github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
+github.com/pion/webrtc/v4 v4.0.10 h1:Hq/JLjhqLxi+NmCtE8lnRPDr8H4LcNvwg8OxVcdv56Q=
+github.com/pion/webrtc/v4 v4.0.10/go.mod h1:ViHLVaNpiuvaH8pdiuQxuA9awuE6KVzAXx3vVWilOck=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
-github.com/polyfloyd/go-errorlint v1.4.3 h1:P6NALOLV8BrWhm6PsqOraUK05E5h8IZnpXYJ+CIg+0U=
-github.com/polyfloyd/go-errorlint v1.4.3/go.mod h1:VPlWPh6hB/wruVG803SuNpLuTGNjLHYlvcdSy4RhdPA=
-github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-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/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
-github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
-github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
+github.com/polyfloyd/go-errorlint v1.6.0 h1:tftWV9DE7txiFzPpztTAwyoRLKNj9gpVm2cg8/OwcYY=
+github.com/polyfloyd/go-errorlint v1.6.0/go.mod h1:HR7u8wuP1kb1NeN1zqTd1ZMlqUKPPHF+Id4vIPvDqVw=
+github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
+github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
+github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
+github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
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=
-github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
-github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
-github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
-github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
-github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
-github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
-github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
-github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
-github.com/prometheus/procfs v0.1.3/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.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
-github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
-github.com/quasilyte/go-ruleguard v0.4.0 h1:DyM6r+TKL+xbKB4Nm7Afd1IQh9kEUKQs2pboWGKtvQo=
-github.com/quasilyte/go-ruleguard v0.4.0/go.mod h1:Eu76Z/R8IXtViWUIHkE3p8gdH3/PKk1eh3YGfaEof10=
+github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
+github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
+github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
+github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
+github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
+github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
+github.com/quasilyte/go-ruleguard v0.4.2 h1:htXcXDK6/rO12kiTHKfHuqR4kr3Y4M0J0rOL6CH/BYs=
+github.com/quasilyte/go-ruleguard v0.4.2/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI=
+github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE=
+github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo=
github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng=
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU=
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0=
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs=
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ=
-github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
-github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
-github.com/quic-go/quic-go v0.40.1 h1:X3AGzUNFs0jVuO3esAGnTfvdgvL4fq655WaOi1snv1Q=
-github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY=
+github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
+github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
+github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q=
+github.com/quic-go/quic-go v0.50.1/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E=
+github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 h1:4WFk6u3sOT6pLa1kQ50ZVdm8BQFgJNA117cepZxtLIg=
+github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66/go.mod h1:Vp72IJajgeOL6ddqrAhmp7IM9zbTcgkQxD/YdxrVwMw=
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
-github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
+github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
+github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
+github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
+github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
+github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
+github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw=
-github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50=
-github.com/ryanrolds/sqlclosecheck v0.4.0 h1:i8SX60Rppc1wRuyQjMciLqIzV3xnoHB7/tXbr6RGYNI=
-github.com/ryanrolds/sqlclosecheck v0.4.0/go.mod h1:TBRRjzL31JONc9i4XMinicuo+s+E8yKZ5FN8X3G6CKQ=
-github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
-github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
+github.com/ryancurrah/gomodguard v1.3.3 h1:eiSQdJVNr9KTNxY2Niij8UReSwR8Xrte3exBrAZfqpg=
+github.com/ryancurrah/gomodguard v1.3.3/go.mod h1:rsKQjj4l3LXe8N344Ow7agAy5p9yjsWOtRzUMYmA0QY=
+github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU=
+github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ=
+github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
+github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
+github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
+github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
+github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
+github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc=
github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI=
+github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
+github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw=
github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ=
-github.com/sashamelentyev/usestdlibvars v1.23.0 h1:01h+/2Kd+NblNItNeux0veSL5cBF1jbEOPrEhDzGYq0=
-github.com/sashamelentyev/usestdlibvars v1.23.0/go.mod h1:YPwr/Y1LATzHI93CqoPUN/2BzGQ/6N/cl/KwgR0B/aU=
-github.com/securego/gosec/v2 v2.16.0 h1:Pi0JKoasQQ3NnoRao/ww/N/XdynIB9NRYYZT5CyOs5U=
-github.com/securego/gosec/v2 v2.16.0/go.mod h1:xvLcVZqUfo4aAQu56TNv7/Ltz6emAOQAEsrZrt7uGlI=
+github.com/sashamelentyev/usestdlibvars v1.27.0 h1:t/3jZpSXtRPRf2xr0m63i32ZrusyurIGT9E5wAvXQnI=
+github.com/sashamelentyev/usestdlibvars v1.27.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8=
+github.com/securego/gosec/v2 v2.20.1-0.20240820084340-81cda2f91fbe h1:exdneYmXwZ4+VaIWv9mQ47uIHkTQSN50DYdCjXJ1cdQ=
+github.com/securego/gosec/v2 v2.20.1-0.20240820084340-81cda2f91fbe/go.mod h1:iyeMMRw8QEmueUSZ2VqmkQMiDyDcobfPnG00CV/NWdE=
+github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU=
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs=
+github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
+github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
+github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
+github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
+github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
+github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
+github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
+github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
+github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
+github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
+github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
+github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
+github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
+github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
+github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
+github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
+github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
+github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
-github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
-github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
+github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE=
github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4=
-github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8=
-github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY=
-github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak=
-github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg=
+github.com/sivchari/tenv v1.10.0 h1:g/hzMA+dBCKqGXgW8AV/1xIWhAvDrx0zFKNR48NFMg0=
+github.com/sivchari/tenv v1.10.0/go.mod h1:tdY24masnVoZFxYrHv/nD6Tc8FbkEtAQEEziXpyMgqY=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00=
github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo=
+github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
+github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
+github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0=
github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs=
+github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
-github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo=
-github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
-github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
-github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
-github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
-github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
-github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
-github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
-github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
+github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
+github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
+github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
+github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
+github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ=
-github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI=
+github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
+github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0=
github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I=
github.com/stbenjam/no-sprintf-host-port v0.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm07ysF0U6JQXczc=
github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I=
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.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
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=
@@ -703,54 +759,62 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
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/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
-github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
-github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8=
-github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
+github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
+github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/tdakkota/asciicheck v0.2.0 h1:o8jvnUANo0qXtnslk2d3nMKTFNlOnJjRrNcj0j9qkHM=
github.com/tdakkota/asciicheck v0.2.0/go.mod h1:Qb7Y9EgjCLJGup51gDHFzbI08/gbGhL/UVhYIPWG2rg=
github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA=
github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0=
github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag=
github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY=
-github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw=
-github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8=
-github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 h1:quvGphlmUVU+nhpFa4gg4yJyTRJ13reZMDHrKwYw53M=
-github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ=
+github.com/tetafro/godot v1.4.16 h1:4ChfhveiNLk4NveAZ9Pu2AN8QZ2nkUGFuadM9lrr5D0=
+github.com/tetafro/godot v1.4.16/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio=
+github.com/timakin/bodyclose v0.0.0-20240125160201-f835fa56326a h1:A6uKudFIfAEpoPdaal3aSqGxBzLyU8TqyXImLwo6dIo=
+github.com/timakin/bodyclose v0.0.0-20240125160201-f835fa56326a/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460=
github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4=
github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg=
-github.com/tomarrell/wrapcheck/v2 v2.8.1 h1:HxSqDSN0sAt0yJYsrcYVoEeyM4aI9yAm3KQpIXDJRhQ=
-github.com/tomarrell/wrapcheck/v2 v2.8.1/go.mod h1:/n2Q3NZ4XFT50ho6Hbxg+RV1uyo2Uow/Vdm9NQcl5SE=
+github.com/tomarrell/wrapcheck/v2 v2.9.0 h1:801U2YCAjLhdN8zhZ/7tdjB3EnAoRlJHt/s+9hijLQ4=
+github.com/tomarrell/wrapcheck/v2 v2.9.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo=
github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw=
github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw=
github.com/ultraware/funlen v0.1.0 h1:BuqclbkY6pO+cvxoq7OsktIXZpgBSkYTQtmwhAK81vI=
github.com/ultraware/funlen v0.1.0/go.mod h1:XJqmOQja6DpxarLj6Jj1U7JuoS8PvL4nEqDaQhy22p4=
-github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI=
-github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
-github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
-github.com/urfave/cli v1.22.10 h1:p8Fspmz3iTctJstry1PYS3HVdllxnEzTEsgIgtxTrCk=
+github.com/ultraware/whitespace v0.1.1 h1:bTPOGejYFulW3PkcrqkeQwOd6NKOOXvmGD9bo/Gk8VQ=
+github.com/ultraware/whitespace v0.1.1/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8=
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/uudashr/gocognit v1.0.7 h1:e9aFXgKgUJrQ5+bs61zBigmj7bFJ/5cC6HmMahVzuDo=
-github.com/uudashr/gocognit v1.0.7/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY=
+github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ=
+github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po=
+github.com/uudashr/gocognit v1.1.3 h1:l+a111VcDbKfynh+airAy/DJQKaXh2m9vkoysMPSZyM=
+github.com/uudashr/gocognit v1.1.3/go.mod h1:aKH8/e8xbTRBwjbCkwZ8qt4l2EpKXl31KMHgSS+lZ2U=
+github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
+github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s=
+github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
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/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E=
+github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
-github.com/xen0n/gosmopolitan v1.2.1 h1:3pttnTuFumELBRSh+KQs1zcz4fN6Zy7aB0xlnQSn1Iw=
-github.com/xen0n/gosmopolitan v1.2.1/go.mod h1:JsHq/Brs1o050OOdmzHeOr0N7OtlnKRAGAsElF8xBQA=
+github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
+github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
+github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
+github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU=
+github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg=
github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM=
github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk=
-github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o=
-github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA=
-github.com/ykadowak/zerologlint v0.1.3 h1:TLy1dTW3Nuc+YE3bYRPToG1Q9Ej78b5UUN6bjbGdxPE=
-github.com/ykadowak/zerologlint v0.1.3/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg=
+github.com/yeya24/promlinter v0.3.0 h1:JVDbMp08lVCP7Y6NP3qHroGAO6z2yGKQtS5JsjqtoFs=
+github.com/yeya24/promlinter v0.3.0/go.mod h1:cDfJQQYv9uYciW60QT0eeHlFodotkYZlL+YcPQN+mW4=
+github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw=
+github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -758,92 +822,81 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
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=
-gitlab.com/bosi/decorder v0.4.0 h1:HWuxAhSxIvsITcXeP+iIRg9d1cVfvVkmlF7M68GaoDY=
-gitlab.com/bosi/decorder v0.4.0/go.mod h1:xarnteyUoJiOTEldDysquWKTVDCKo2TOIOIibSuWqOg=
-go-simpler.org/assert v0.5.0 h1:+5L/lajuQtzmbtEfh69sr5cRf2/xZzyJhFjoOz/PPqs=
-go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
-go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
-go.opencensus.io v0.22.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.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
-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.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y=
-go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI=
-go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg=
-go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
-go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0=
-go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
-go.tmz.dev/musttag v0.7.1 h1:9lFmeSFnFfPuMq4IksHGomItE6NgKMNW2Nt2FPOhCfU=
-go.tmz.dev/musttag v0.7.1/go.mod h1:oJLkpR56EsIryktZJk/B0IroSMi37YWver47fibGh5U=
-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/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc=
-go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk=
-go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
-go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
-go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
-go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
-go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
+github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
+github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
+github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE=
+github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
+github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
+gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo=
+gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8=
+go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ=
+go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28=
+go-simpler.org/musttag v0.12.2 h1:J7lRc2ysXOq7eM8rwaTYnNrHd5JwjppzB6mScysB2Cs=
+go-simpler.org/musttag v0.12.2/go.mod h1:uN1DVIasMTQKk6XSik7yrJoEysGtR2GRqvWnI9S7TYM=
+go-simpler.org/sloglint v0.7.2 h1:Wc9Em/Zeuu7JYpl+oKoYOsQSy2X560aVueCW/m6IijY=
+go-simpler.org/sloglint v0.7.2/go.mod h1:US+9C80ppl7VsThQclkM7BkCHQAzuz8kHLsW3ppuluo=
+go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
+go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
+go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
+go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
+go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
+go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
+go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
+go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
+go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
+go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
+go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
+go.uber.org/dig v1.18.0 h1:imUL1UiY0Mg4bqbFfsRQO5G4CGRBec/ZujWTvSVp3pw=
+go.uber.org/dig v1.18.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
+go.uber.org/fx v1.23.0 h1:lIr/gYWQGfTwGcSXWXu4vP5Ws6iqnNEIY+F/aFzCKTg=
+go.uber.org/fx v1.23.0/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
+go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
-go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
-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.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
-go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
-golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
+go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
+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-20181030102418-4d3f4d9ffa16/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
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=
+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=
-golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
-golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
+golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
+golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
+golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
+golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
+golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
+golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
+golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
+golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
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-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
-golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
-golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
-golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
-golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
+golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
+golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
-golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 h1:jWGQJV4niP+CCmFW9ekjA9Zx8vYORzOUH2/Nl5WPuLQ=
-golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
-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/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f h1:phY1HzDcf18Aq9A8KkmRtY9WvOFIxN8wgfvy6Zm1DV8=
+golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
+golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
-golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
-golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/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/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.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.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/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=
@@ -852,227 +905,161 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
-golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
+golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
-golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-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-20200822124328-c89045814202/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-20201031054903-ff519b6c9102/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-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
+golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
+golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
+golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
+golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
+golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
+golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
+golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
+golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
+golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/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-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/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-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/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.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
+golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
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/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
+golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
+golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
+golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
-golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
+golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
+golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
+golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.4/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/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
+golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
+golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
+golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
-golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-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-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
-golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
-golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
-golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
-golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
@@ -1080,159 +1067,69 @@ 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.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
-golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
-golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
+golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
+golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
+golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
+golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
+golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
+golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
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=
-gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
-gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
-google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
-google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
-google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
-google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
-google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
-google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
-google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
-google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
-google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
+gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
+gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
+google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
+google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
+google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
-google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
-google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
-google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
-google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
-google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
+google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
+google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
+google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
-google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
-google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
-google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
-google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
-google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
-google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
-google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
-google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
-google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
-google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
-google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
-google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
-google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
-gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
-gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
+google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
-gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
-gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gotest.tools/gotestsum v0.4.2 h1:QOdtb6bnnPUuHKkR9+/QQa8e6qjpTTP7cDi7G9/10C4=
-gotest.tools/gotestsum v0.4.2/go.mod h1:a32lmn/7xfm0+QHj8K5NyQY1NNNNhZoAp+/OHkLs77Y=
-gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E=
-gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
+gotest.tools/gotestsum v1.12.0 h1:CmwtaGDkHxrZm4Ib0Vob89MTfpc3GrEFMJKovliPwGk=
+gotest.tools/gotestsum v1.12.0/go.mod h1:fAvqkSptospfSbQw26CTYzNwnsE/ztqLeyhP0h67ARY=
+gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
+gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
+grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
+honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
-honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-honnef.co/go/tools v0.4.3 h1:o/n5/K5gXqk8Gozvs2cnL0F2S1/g1vcGCAx2vETjITw=
-honnef.co/go/tools v0.4.3/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA=
-lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
-lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
-mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E=
-mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js=
-mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I=
-mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
-mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo=
-mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
-mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d h1:3rvTIIM22r9pvXk+q3swxUQAQOxksVMGK7sml4nG57w=
-mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is=
-rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
-rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
-rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I=
+honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs=
+lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
+lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=
+mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=
+mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo=
+mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U=
+mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ=
+sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
+sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
diff --git a/test/dependencies/pollEndpoint/main.go b/test/dependencies/pollEndpoint/main.go
index 0c548d8c9f2..fbea6fd77fc 100644
--- a/test/dependencies/pollEndpoint/main.go
+++ b/test/dependencies/pollEndpoint/main.go
@@ -10,7 +10,7 @@ import (
"os"
"time"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
)
diff --git a/test/integration/addcat_test.go b/test/integration/addcat_test.go
index 222326de21d..22d8be9be1c 100644
--- a/test/integration/addcat_test.go
+++ b/test/integration/addcat_test.go
@@ -13,12 +13,12 @@ import (
"github.com/ipfs/boxo/bootstrap"
"github.com/ipfs/boxo/files"
- logging "github.com/ipfs/go-log"
+ logging "github.com/ipfs/go-log/v2"
+ "github.com/ipfs/go-test/random"
"github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/core/coreapi"
mock "github.com/ipfs/kubo/core/mock"
"github.com/ipfs/kubo/thirdparty/unit"
- "github.com/jbenet/go-random"
testutil "github.com/libp2p/go-libp2p-testing/net"
"github.com/libp2p/go-libp2p/core/peer"
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
@@ -84,12 +84,8 @@ func AddCatPowers(conf testutil.LatencyConfig, megabytesMax int64) error {
}
func RandomBytes(n int64) []byte {
- var data bytes.Buffer
- err := random.WritePseudoRandomBytes(n, &data, kSeed)
- if err != nil {
- panic(err)
- }
- return data.Bytes()
+ random.SetSeed(kSeed)
+ return random.Bytes(int(n))
}
func DirectAddCat(data []byte, conf testutil.LatencyConfig) error {
diff --git a/test/sharness/README.md b/test/sharness/README.md
index 6ab8539da2c..239e46d1eb4 100644
--- a/test/sharness/README.md
+++ b/test/sharness/README.md
@@ -13,7 +13,7 @@ The usual ipfs env flags also apply:
```sh
# the output will make your eyes bleed
-IPFS_LOGGING=debug TEST_VERBOSE=1 make
+GOLOG_LOG_LEVEL=debug TEST_VERBOSE=1 make
```
To make the tests abort as soon as an error occurs, use the TEST_IMMEDIATE env variable:
diff --git a/test/sharness/Rules.mk b/test/sharness/Rules.mk
index c1e70eb0925..2f2e076ba7c 100644
--- a/test/sharness/Rules.mk
+++ b/test/sharness/Rules.mk
@@ -4,8 +4,8 @@ SHARNESS_$(d) = $(d)/lib/sharness/sharness.sh
T_$(d) = $(sort $(wildcard $(d)/t[0-9][0-9][0-9][0-9]-*.sh))
-DEPS_$(d) := test/bin/random test/bin/multihash test/bin/pollEndpoint \
- test/bin/iptb test/bin/go-sleep test/bin/random-files \
+DEPS_$(d) := test/bin/multihash test/bin/pollEndpoint test/bin/iptb \
+ test/bin/go-sleep test/bin/random-data test/bin/random-files \
test/bin/go-timeout test/bin/hang-fds test/bin/ma-pipe-unidir \
test/bin/cid-fmt
DEPS_$(d) += cmd/ipfs/ipfs
diff --git a/test/sharness/lib/install-sharness.sh b/test/sharness/lib/install-sharness.sh
index 41b27188c93..c695a3419bb 100755
--- a/test/sharness/lib/install-sharness.sh
+++ b/test/sharness/lib/install-sharness.sh
@@ -5,7 +5,7 @@
# MIT Licensed; see the LICENSE file in this repository.
#
-gitrepo=pl-strflt/sharness
+gitrepo=ipfs/sharness
githash=803df39d3cba16bb7d493dd6cd8bc5e29826da61
if test ! -n "$clonedir" ; then
diff --git a/test/sharness/lib/iptb-lib.sh b/test/sharness/lib/iptb-lib.sh
index 3d2e95a4916..8b2d956c2e9 100644
--- a/test/sharness/lib/iptb-lib.sh
+++ b/test/sharness/lib/iptb-lib.sh
@@ -34,6 +34,10 @@ startup_cluster() {
other_args="$@"
bound=$(expr "$num_nodes" - 1)
+ test_expect_success "set Routing.LoopbackAddressesOnLanDHT to true" '
+ iptb run [0-$bound] -- ipfs config --json "Routing.LoopbackAddressesOnLanDHT" true
+ '
+
if test -n "$other_args"; then
test_expect_success "start up nodes with additional args" "
iptb start -wait [0-$bound] -- ${other_args[@]}
diff --git a/test/sharness/lib/test-lib.sh b/test/sharness/lib/test-lib.sh
index bd8f7de9b90..f9292cb237c 100644
--- a/test/sharness/lib/test-lib.sh
+++ b/test/sharness/lib/test-lib.sh
@@ -158,8 +158,8 @@ test_wait_open_tcp_port_10_sec() {
for i in $(test_seq 1 100)
do
# this is not a perfect check, but it's portable.
- # cant count on ss. not installed everywhere.
- # cant count on netstat using : or . as port delim. differ across platforms.
+ # can't count on ss. not installed everywhere.
+ # can't count on netstat using : or . as port delim. differ across platforms.
echo $(netstat -aln | egrep "^tcp.*LISTEN" | egrep "[.:]$1" | wc -l) -gt 0
if [ $(netstat -aln | egrep "^tcp.*LISTEN" | egrep "[.:]$1" | wc -l) -gt 0 ]; then
return 0
@@ -205,6 +205,28 @@ test_init_ipfs() {
ipfs init "${args[@]}" --profile=test > /dev/null
'
+ test_expect_success "prepare config -- mounting" '
+ mkdir mountdir ipfs ipns mfs &&
+ test_config_set Mounts.IPFS "$(pwd)/ipfs" &&
+ test_config_set Mounts.IPNS "$(pwd)/ipns" &&
+ test_config_set Mounts.MFS "$(pwd)/mfs" ||
+ test_fsh cat "\"$IPFS_PATH/config\""
+ '
+
+}
+
+test_init_ipfs_measure() {
+ args=("$@")
+
+ # we set the Addresses.API config variable.
+ # the cli client knows to use it, so only need to set.
+ # todo: in the future, use env?
+
+ test_expect_success "ipfs init succeeds" '
+ export IPFS_PATH="$(pwd)/.ipfs" &&
+ ipfs init "${args[@]}" --profile=test,flatfs-measure > /dev/null
+ '
+
test_expect_success "prepare config -- mounting" '
mkdir mountdir ipfs ipns &&
test_config_set Mounts.IPFS "$(pwd)/ipfs" &&
@@ -300,12 +322,14 @@ test_mount_ipfs() {
test_expect_success FUSE "'ipfs mount' succeeds" '
do_umount "$(pwd)/ipfs" || true &&
do_umount "$(pwd)/ipns" || true &&
+ do_umount "$(pwd)/mfs" || true &&
ipfs mount >actual
'
test_expect_success FUSE "'ipfs mount' output looks good" '
echo "IPFS mounted at: $(pwd)/ipfs" >expected &&
echo "IPNS mounted at: $(pwd)/ipns" >>expected &&
+ echo "MFS mounted at: $(pwd)/mfs" >>expected &&
test_cmp expected actual
'
@@ -512,7 +536,7 @@ port_from_maddr() {
findprovs_empty() {
test_expect_success 'findprovs '$1' succeeds' '
- ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut
+ ipfsi 1 routing findprovs -n 1 '$1' > findprovsOut
'
test_expect_success "findprovs $1 output is empty" '
@@ -522,7 +546,7 @@ findprovs_empty() {
findprovs_expect() {
test_expect_success 'findprovs '$1' succeeds' '
- ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut &&
+ ipfsi 1 routing findprovs -n 1 '$1' > findprovsOut &&
echo '$2' > expected
'
diff --git a/test/sharness/t0002-docker-image.sh b/test/sharness/t0002-docker-image.sh
index 11ccf01b74e..81bb8d4493f 100755
--- a/test/sharness/t0002-docker-image.sh
+++ b/test/sharness/t0002-docker-image.sh
@@ -36,8 +36,8 @@ test_expect_success "docker image build succeeds" '
'
test_expect_success "write init scripts" '
- echo "ipfs config Foo Bar" > 001.sh &&
- echo "ipfs config Baz Qux" > 002.sh &&
+ echo "ipfs config Mounts.IPFS Bar" > 001.sh &&
+ echo "ipfs config Pubsub.Router Qux" > 002.sh &&
chmod +x 002.sh
'
@@ -50,7 +50,7 @@ test_expect_success "docker image runs" '
'
test_expect_success "docker container gateway is up" '
- pollEndpoint -host=/ip4/127.0.0.1/tcp/8080 -http-url http://localhost:8080/api/v0/version -v -tries 30 -tout 1s
+ pollEndpoint -host=/ip4/127.0.0.1/tcp/8080 -http-url http://localhost:8080/ipfs/bafkqaddimvwgy3zao5xxe3debi -v -tries 30 -tout 1s
'
test_expect_success "docker container API is up" '
@@ -65,10 +65,10 @@ test_expect_success "check that init scripts were run correctly and in the corre
test_expect_success "check that init script configs were applied" '
echo Bar > expected &&
- docker exec "$DOC_ID" ipfs config Foo > actual &&
+ docker exec "$DOC_ID" ipfs config Mounts.IPFS > actual &&
test_cmp actual expected &&
echo Qux > expected &&
- docker exec "$DOC_ID" ipfs config Baz > actual &&
+ docker exec "$DOC_ID" ipfs config Pubsub.Router > actual &&
test_cmp actual expected
'
diff --git a/test/sharness/t0003-docker-migrate.sh b/test/sharness/t0003-docker-migrate.sh
index ac3c7aee2bc..c2c7ce9697c 100755
--- a/test/sharness/t0003-docker-migrate.sh
+++ b/test/sharness/t0003-docker-migrate.sh
@@ -36,15 +36,20 @@ test_expect_success "configure migration sources" '
ipfs config --json Migration.DownloadSources "[\"http://127.0.0.1:17233\"]"
'
-test_expect_success "make repo be version 4" '
- echo 4 > "$IPFS_PATH/version"
-'
-
test_expect_success "setup http response" '
+ mkdir migration &&
+ echo "v1.1.1" > migration/versions &&
+ mkdir -p migration/fs-repo-6-to-7 &&
+ echo "v1.1.1" > migration/fs-repo-6-to-7/versions &&
+ CID=$(ipfs add -r -Q migration) &&
echo "HTTP/1.1 200 OK" > vers_resp &&
- echo "Content-Length: 7" >> vers_resp &&
+ echo "Content-Type: application/vnd.ipld.car" >> vers_resp &&
echo "" >> vers_resp &&
- echo "v1.1.1" >> vers_resp
+ ipfs dag export $CID >> vers_resp
+'
+
+test_expect_success "make repo be version 4" '
+ echo 4 > "$IPFS_PATH/version"
'
test_expect_success "startup fake dists server" '
@@ -53,7 +58,7 @@ test_expect_success "startup fake dists server" '
'
test_expect_success "docker image runs" '
- DOC_ID=$(docker run -d -v "$IPFS_PATH":/data/ipfs --net=host "$IMAGE_TAG")
+ DOC_ID=$(docker run -d -v "$IPFS_PATH":/data/ipfs -e IPFS_DIST_PATH=/ipfs/$CID --net=host "$IMAGE_TAG")
'
test_expect_success "docker container tries to pull migrations from netcat" '
diff --git a/test/sharness/t0021-config.sh b/test/sharness/t0021-config.sh
index 5264908c73f..3e688634863 100755
--- a/test/sharness/t0021-config.sh
+++ b/test/sharness/t0021-config.sh
@@ -13,41 +13,23 @@ test_config_cmd_set() {
cfg_key=$1
cfg_val=$2
- test_expect_success "ipfs config succeeds" '
- ipfs config $cfg_flags "$cfg_key" "$cfg_val"
- '
-
- test_expect_success "ipfs config output looks good" '
- echo "$cfg_val" >expected &&
- ipfs config "$cfg_key" >actual &&
- test_cmp expected actual
- '
-
- # also test our lib function. it should work too.
- cfg_key="Lib.$cfg_key"
- test_expect_success "test_config_set succeeds" '
- test_config_set $cfg_flags "$cfg_key" "$cfg_val"
- '
-
- test_expect_success "test_config_set value looks good" '
- echo "$cfg_val" >expected &&
- ipfs config "$cfg_key" >actual &&
- test_cmp expected actual
- '
+ test_expect_success "ipfs config succeeds" "
+ ipfs config $cfg_flags \"$cfg_key\" \"$cfg_val\"
+ "
+
+ test_expect_success "ipfs config output looks good" "
+ echo \"$cfg_val\" >expected &&
+ if [$cfg_flags != \"--json\"]; then
+ ipfs config \"$cfg_key\" >actual &&
+ test_cmp expected actual
+ else
+ ipfs config \"$cfg_key\" | tr -d \"\\n\\t \" >actual &&
+ echo >>actual &&
+ test_cmp expected actual
+ fi
+ "
}
-# this is a bit brittle. the problem is we need to test
-# with something that will be forced to unmarshal as a struct.
-# (i.e. just setting 'ipfs config --json foo "[1, 2, 3]"') may
-# set it as astring instead of proper json. We leverage the
-# unmarshalling that has to happen.
-CONFIG_SET_JSON_TEST='{
- "MDNS": {
- "Enabled": true,
- "Interval": 10
- }
-}'
-
test_profile_apply_revert() {
profile=$1
inverse_profile=$2
@@ -87,27 +69,32 @@ test_profile_apply_dry_run_not_alter() {
}
test_config_cmd() {
- test_config_cmd_set "beep" "boop"
- test_config_cmd_set "beep1" "boop2"
- test_config_cmd_set "beep1" "boop2"
- test_config_cmd_set "--bool" "beep2" "true"
- test_config_cmd_set "--bool" "beep2" "false"
- test_config_cmd_set "--json" "beep3" "true"
- test_config_cmd_set "--json" "beep3" "false"
- test_config_cmd_set "--json" "Discovery" "$CONFIG_SET_JSON_TEST"
- test_config_cmd_set "--json" "deep-not-defined.prop" "true"
- test_config_cmd_set "--json" "deep-null" "null"
- test_config_cmd_set "--json" "deep-null.prop" "true"
+ test_config_cmd_set "Addresses.API" "foo"
+ test_config_cmd_set "Addresses.Gateway" "bar"
+ test_config_cmd_set "Datastore.GCPeriod" "baz"
+ test_config_cmd_set "AutoNAT.ServiceMode" "enabled"
+ test_config_cmd_set "--bool" "Discovery.MDNS.Enabled" "true"
+ test_config_cmd_set "--bool" "Discovery.MDNS.Enabled" "false"
+ test_config_cmd_set "--json" "Datastore.HashOnRead" "true"
+ test_config_cmd_set "--json" "Datastore.HashOnRead" "false"
+ test_config_cmd_set "--json" "Experimental.FilestoreEnabled" "true"
+ test_config_cmd_set "--json" "Import.BatchMaxSize" "null"
+ test_config_cmd_set "--json" "Import.UnixFSRawLeaves" "true"
+ test_config_cmd_set "--json" "Routing.Routers.Test" "{\\\"Parameters\\\":\\\"Test\\\",\\\"Type\\\":\\\"Test\\\"}"
+ test_config_cmd_set "--json" "Experimental.OptimisticProvideJobsPoolSize" "1337"
+ test_config_cmd_set "--json" "Addresses.Swarm" "[\\\"test\\\",\\\"test\\\",\\\"test\\\"]"
+ test_config_cmd_set "--json" "Gateway.PublicGateways.Foo" "{\\\"DeserializedResponses\\\":true,\\\"InlineDNSLink\\\":false,\\\"NoDNSLink\\\":false,\\\"Paths\\\":[\\\"Bar\\\",\\\"Baz\\\"],\\\"UseSubdomains\\\":true}"
+ test_config_cmd_set "--bool" "Gateway.PublicGateways.Foo.UseSubdomains" "false"
test_expect_success "'ipfs config show' works" '
ipfs config show >actual
'
test_expect_success "'ipfs config show' output looks good" '
- grep "\"beep\": \"boop\"," actual &&
- grep "\"beep1\": \"boop2\"," actual &&
- grep "\"beep2\": false," actual &&
- grep "\"beep3\": false," actual
+ grep "\"API\": \"foo\"," actual &&
+ grep "\"Gateway\": \"bar\"" actual &&
+ grep "\"Enabled\": false" actual &&
+ grep "\"HashOnRead\": false" actual
'
test_expect_success "'ipfs config show --config-file' works" '
@@ -281,7 +268,7 @@ test_config_cmd() {
# won't work as it changes datastore definition, which makes ipfs not launch
# without converting first
- # test_profile_apply_revert badgerds
+ # test_profile_apply_revert pebbleds
test_expect_success "cleanup config backups" '
find "$IPFS_PATH" -name "config-*" -exec rm {} \;
diff --git a/test/sharness/t0025-datastores.sh b/test/sharness/t0025-datastores.sh
index f0ddd4e2e8f..6be9eb3ed48 100755
--- a/test/sharness/t0025-datastores.sh
+++ b/test/sharness/t0025-datastores.sh
@@ -4,13 +4,20 @@ test_description="Test non-standard datastores"
. lib/test-lib.sh
-test_expect_success "'ipfs init --empty-repo=false --profile=badgerds' succeeds" '
- BITS="2048" &&
- ipfs init --empty-repo=false --profile=badgerds
-'
+profiles=("flatfs" "pebbleds" "badgerds")
+proot="$(mktemp -d "${TMPDIR:-/tmp}/t0025.XXXXXX")"
-test_expect_success "'ipfs pin ls' works" '
- ipfs pin ls | wc -l | grep 9
-'
+for profile in "${profiles[@]}"; do
+ test_expect_success "'ipfs init --empty-repo=false --profile=$profile' succeeds" '
+ BITS="2048" &&
+ IPFS_PATH="$proot/$profile" &&
+ ipfs init --empty-repo=false --profile=$profile
+ '
+ test_expect_success "'ipfs pin add' and 'pin ls' works with $profile" '
+ export IPFS_PATH="$proot/$profile" &&
+ echo -n "hello_$profile" | ipfs block put --pin=true > hello_cid &&
+ ipfs pin ls -t recursive "$(cat hello_cid)"
+ '
+done
test_done
diff --git a/test/sharness/t0026-id.sh b/test/sharness/t0026-id.sh
index d4248c56295..992892a39a6 100755
--- a/test/sharness/t0026-id.sh
+++ b/test/sharness/t0026-id.sh
@@ -65,5 +65,16 @@ iptb stop
test_kill_ipfs_daemon
+# Version.AgentSuffix overrides --agent-version-suffix (local, offline)
+test_expect_success "setting Version.AgentSuffix in config" '
+ ipfs config Version.AgentSuffix json-config-suffix
+'
+test_launch_ipfs_daemon --agent-version-suffix=ignored-cli-suffix
+test_expect_success "checking AgentVersion with suffix set via JSON config" '
+ test_id_compute_agent json-config-suffix > expected-agent-version &&
+ ipfs id -f "\n" > actual-agent-version &&
+ test_cmp expected-agent-version actual-agent-version
+'
+test_kill_ipfs_daemon
test_done
diff --git a/test/sharness/t0030-mount.sh b/test/sharness/t0030-mount.sh
index 0c0983d0c41..6df7a26bbef 100755
--- a/test/sharness/t0030-mount.sh
+++ b/test/sharness/t0030-mount.sh
@@ -16,7 +16,8 @@ if ! test_have_prereq FUSE; then
fi
-export IPFS_NS_MAP="welcome.example.com:/ipfs/$HASH_WELCOME_DOCS"
+# echo -n "ipfs" > expected && ipfs add --cid-version 1 -Q -w expected
+export IPFS_NS_MAP="welcome.example.com:/ipfs/bafybeicq7bvn5lz42qlmghaoiwrve74pzi53auqetbantp5kajucsabike"
# start iptb + wait for peering
NUM_NODES=5
@@ -27,17 +28,17 @@ startup_cluster $NUM_NODES
# test mount failure before mounting properly.
test_expect_success "'ipfs mount' fails when there is no mount dir" '
- tmp_ipfs_mount() { ipfsi 0 mount -f=not_ipfs -n=not_ipns >output 2>output.err; } &&
+ tmp_ipfs_mount() { ipfsi 0 mount -f=not_ipfs -n=not_ipns -m=not_mfs >output 2>output.err; } &&
test_must_fail tmp_ipfs_mount
'
test_expect_success "'ipfs mount' output looks good" '
test_must_be_empty output &&
- test_should_contain "not_ipns\|not_ipfs" output.err
+ test_should_contain "not_ipns\|not_ipfs\|not_mfs" output.err
'
test_expect_success "setup and publish default IPNS value" '
- mkdir "$(pwd)/ipfs" "$(pwd)/ipns" &&
+ mkdir "$(pwd)/ipfs" "$(pwd)/ipns" "$(pwd)/mfs" &&
ipfsi 0 name publish QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn
'
@@ -46,12 +47,14 @@ test_expect_success "setup and publish default IPNS value" '
test_expect_success FUSE "'ipfs mount' succeeds" '
do_umount "$(pwd)/ipfs" || true &&
do_umount "$(pwd)/ipns" || true &&
- ipfsi 0 mount -f "$(pwd)/ipfs" -n "$(pwd)/ipns" >actual
+ do_umount "$(pwd)/mfs" || true &&
+ ipfsi 0 mount -f "$(pwd)/ipfs" -n "$(pwd)/ipns" -m "$(pwd)/mfs" >actual
'
test_expect_success FUSE "'ipfs mount' output looks good" '
echo "IPFS mounted at: $(pwd)/ipfs" >expected &&
echo "IPNS mounted at: $(pwd)/ipns" >>expected &&
+ echo "MFS mounted at: $(pwd)/mfs" >>expected &&
test_cmp expected actual
'
@@ -63,21 +66,64 @@ test_expect_success FUSE "local symlink works" '
test_expect_success FUSE "can resolve ipns names" '
echo -n "ipfs" > expected &&
- cat ipns/welcome.example.com/ping > actual &&
+ ipfsi 0 add --cid-version 1 -Q -w expected &&
+ cat ipns/welcome.example.com/expected > actual &&
test_cmp expected actual
'
+test_expect_success FUSE "create mfs file via fuse" '
+ touch mfs/testfile &&
+ ipfsi 0 files ls | grep testfile
+'
+
+test_expect_success FUSE "create mfs dir via fuse" '
+ mkdir mfs/testdir &&
+ ipfsi 0 files ls | grep testdir
+'
+
+test_expect_success FUSE "read mfs file from fuse" '
+ echo content > mfs/testfile &&
+ getfattr -n ipfs_cid mfs/testfile
+'
+test_expect_success FUSE "ipfs add file and read it back via fuse" '
+ echo content3 | ipfsi 0 files write -e /testfile3 &&
+ grep content3 mfs/testfile3
+'
+
+test_expect_success FUSE "ipfs add file and read it back via fuse" '
+ echo content > testfile2 &&
+ ipfsi 0 add --to-files /testfile2 testfile2 &&
+ grep content mfs/testfile2
+'
+
+test_expect_success FUSE "test file xattr" '
+ echo content > mfs/testfile &&
+ getfattr -n ipfs_cid mfs/testfile
+'
+
+test_expect_success FUSE "test file removal" '
+ touch mfs/testfile &&
+ rm mfs/testfile
+'
+
+test_expect_success FUSE "test nested dirs" '
+ mkdir -p mfs/foo/bar/baz/qux &&
+ echo content > mfs/foo/bar/baz/qux/quux &&
+ ipfsi 0 files stat /foo/bar/baz/qux/quux
+'
+
test_expect_success "mount directories cannot be removed while active" '
- test_must_fail rmdir ipfs ipns 2>/dev/null
+ test_must_fail rmdir ipfs ipns mfs 2>/dev/null
'
test_expect_success "unmount directories" '
do_umount "$(pwd)/ipfs" &&
- do_umount "$(pwd)/ipns"
+ do_umount "$(pwd)/ipns" &&
+ do_umount "$(pwd)/mfs"
'
test_expect_success "mount directories can be removed after shutdown" '
- rmdir ipfs ipns
+ rmdir ipfs ipns mfs
'
test_expect_success 'stop iptb' '
diff --git a/test/sharness/t0032-mount-sharded.sh b/test/sharness/t0032-mount-sharded.sh
index 10ba421a225..7a3e518585b 100755
--- a/test/sharness/t0032-mount-sharded.sh
+++ b/test/sharness/t0032-mount-sharded.sh
@@ -16,7 +16,7 @@ fi
test_init_ipfs
test_expect_success 'force sharding' '
- ipfs config --json Internal.UnixFSShardingSizeThreshold "\"1B\""
+ ipfs config --json Import.UnixFSHAMTDirectorySizeThreshold "\"1B\""
'
test_launch_ipfs_daemon
diff --git a/test/sharness/t0040-add-and-cat.sh b/test/sharness/t0040-add-and-cat.sh
index 142ab8ec18c..f0e5a1bb9e6 100755
--- a/test/sharness/t0040-add-and-cat.sh
+++ b/test/sharness/t0040-add-and-cat.sh
@@ -355,10 +355,10 @@ test_add_cat_file() {
test_cmp expected actual
'
- test_must_fail "ipfs add with multiple files of same name but different dirs fails" '
+ test_expect_success "ipfs add with multiple files of same name but different dirs fails" '
mkdir -p mountdir/same-file/ &&
cp mountdir/hello.txt mountdir/same-file/hello.txt &&
- ipfs add mountdir/hello.txt mountdir/same-file/hello.txt >actual &&
+ test_expect_code 1 ipfs add mountdir/hello.txt mountdir/same-file/hello.txt >actual &&
rm mountdir/same-file/hello.txt &&
rmdir mountdir/same-file
'
@@ -469,18 +469,27 @@ test_add_cat_file() {
ipfs files rm -r --force /mfs
'
+ # confirm -w and --to-files are exclusive
+ # context: https://github.com/ipfs/kubo/issues/10611
+ test_expect_success "ipfs add -r -w dir --to-files /mfs/subdir5/ errors (-w and --to-files are exclusive)" '
+ ipfs files mkdir -p /mfs/subdir5 &&
+ test_expect_code 1 ipfs add -r -w test --to-files /mfs/subdir5/ >actual 2>&1 &&
+ test_should_contain "Error" actual &&
+ ipfs files rm -r --force /mfs
+ '
+
}
test_add_cat_5MB() {
ADD_FLAGS="$1"
EXP_HASH="$2"
- test_expect_success "generate 5MB file using go-random" '
- random 5242880 41 >mountdir/bigfile
+ test_expect_success "generate 5MB file using random-data" '
+ random-data -size=5242880 -seed=41 >mountdir/bigfile
'
test_expect_success "sha1 of the file looks ok" '
- echo "11145620fb92eb5a49c9986b5c6844efda37e471660e" >sha1_expected &&
+ echo "11145b8c4bc8f87ea2fcfc3d55708b8cac2aadf12862" >sha1_expected &&
multihash -a=sha1 -e=hex mountdir/bigfile >sha1_actual &&
test_cmp sha1_expected sha1_actual
'
@@ -585,12 +594,12 @@ test_add_cat_expensive() {
ADD_FLAGS="$1"
HASH="$2"
- test_expect_success EXPENSIVE "generate 100MB file using go-random" '
- random 104857600 42 >mountdir/bigfile
+ test_expect_success EXPENSIVE "generate 100MB file using random-data" '
+ random-data -size=104857600 -seed=42 >mountdir/bigfile
'
test_expect_success EXPENSIVE "sha1 of the file looks ok" '
- echo "1114885b197b01e0f7ff584458dc236cb9477d2e736d" >sha1_expected &&
+ echo "11141e8c04d7cd019cc0acf0311a8ca6cf2c18413c96" >sha1_expected &&
multihash -a=sha1 -e=hex mountdir/bigfile >sha1_actual &&
test_cmp sha1_expected sha1_actual
'
@@ -614,7 +623,7 @@ test_add_cat_expensive() {
'
test_expect_success EXPENSIVE "ipfs cat output hashed looks good" '
- echo "1114885b197b01e0f7ff584458dc236cb9477d2e736d" >sha1_expected &&
+ echo "11141e8c04d7cd019cc0acf0311a8ca6cf2c18413c96" >sha1_expected &&
test_cmp sha1_expected sha1_actual
'
@@ -873,17 +882,17 @@ test_expect_success "'ipfs add -rn' succeeds" '
mkdir -p mountdir/moons/saturn &&
echo "Hello Europa!" >mountdir/moons/jupiter/europa.txt &&
echo "Hello Titan!" >mountdir/moons/saturn/titan.txt &&
- echo "hey youre no moon!" >mountdir/moons/mercury.txt &&
+ echo "hey you are no moon!" >mountdir/moons/mercury.txt &&
ipfs add -rn mountdir/moons >actual
'
test_expect_success "'ipfs add -rn' output looks good" '
- MOONS="QmVKvomp91nMih5j6hYBA8KjbiaYvEetU2Q7KvtZkLe9nQ" &&
+ MOONS="QmbGoaQZm8kjYfCiN1aBsgwhqfUBGDYTrDb91Mz7Dvq81B" &&
EUROPA="Qmbjg7zWdqdMaK2BucPncJQDxiALExph5k3NkQv5RHpccu" &&
JUPITER="QmS5mZddhFPLWFX3w6FzAy9QxyYkaxvUpsWCtZ3r7jub9J" &&
SATURN="QmaMagZT4rTE7Nonw8KGSK4oe1bh533yhZrCo1HihSG8FK" &&
TITAN="QmZzppb9WHn552rmRqpPfgU5FEiHH6gDwi3MrB9cTdPwdb" &&
- MERCURY="QmUJjVtnN8YEeYcS8VmUeWffTWhnMQAkk5DzZdKnPhqUdK" &&
+ MERCURY="QmRsTB5CpEUvDUpDgHCzb3VftZ139zrk9zs5ZcgYh9TMPJ" &&
echo "added $EUROPA moons/jupiter/europa.txt" >expected &&
echo "added $MERCURY moons/mercury.txt" >>expected &&
echo "added $TITAN moons/saturn/titan.txt" >>expected &&
@@ -893,42 +902,42 @@ test_expect_success "'ipfs add -rn' output looks good" '
test_cmp expected actual
'
-test_expect_success "go-random is installed" '
- type random
+test_expect_success "random-data is installed" '
+ type random-data
'
-test_add_cat_5MB "" "QmSr7FqYkxYWGoSfy8ZiaMWQ5vosb18DQGCzjwEQnVHkTb"
+test_add_cat_5MB "" "QmapAfmzmeWYTNztMQEhUXFcSGrsax22WRG7YN9xLdMeQq"
-test_add_cat_5MB --raw-leaves "QmbdLHCmdi48eM8T7D67oXjA1S2Puo8eMfngdHhdPukFd6"
+test_add_cat_5MB --raw-leaves "QmabWSFaPusmiZaaVZLhEUtHcj8CCvVeUfkBpKqAkKVMiS"
# note: the specified hash implies that internal nodes are stored
# using CidV1 and leaves are stored using raw blocks
-test_add_cat_5MB --cid-version=1 "bafybeigfnx3tka2rf5ovv2slb7ymrt4zbwa3ryeqibe6fipyt5vgsrli3u"
+test_add_cat_5MB --cid-version=1 "bafybeifwdkm32fmukqwh3jofm6ma76bcqvn6opxstsnzmya7utboi4cb2m"
# note: the specified hash implies that internal nodes are stored
# using CidV1 and leaves are stored using CidV1 but using the legacy
# format (i.e. not raw)
-test_add_cat_5MB '--cid-version=1 --raw-leaves=false' "bafybeieyifrgpjn3yengthr7qaj72ozm2aq3wm53srgeprc43w67qpvfqa"
+test_add_cat_5MB '--cid-version=1 --raw-leaves=false' "bafybeifq4unep5w4agr3nlynxidj2rymf6dzu6bf4ieqqildkboe5mdmne"
# note: --hash=blake2b-256 implies --cid-version=1 which implies --raw-leaves=true
# the specified hash represents the leaf nodes stored as raw leaves and
# encoded with the blake2b-256 hash function
-test_add_cat_5MB '--hash=blake2b-256' "bafykbzacebnmjcl4sn37b3ehtibvf263oun2w6idghenrvlpehq5w5jqyvhjo"
+test_add_cat_5MB '--hash=blake2b-256' "bafykbzacebxcnlql4oc3mtscqn32aumqkqxxv3wt7dkyrphgh6lc2gckiq6bw"
# the specified hash represents the leaf nodes stored as protoful nodes and
# encoded with the blake2b-256 hash function
-test_add_cat_5MB '--hash=blake2b-256 --raw-leaves=false' "bafykbzaceaxiiykzgpbhnzlecffqm3zbuvhujyvxe5scltksyafagkyw4rjn2"
+test_add_cat_5MB '--hash=blake2b-256 --raw-leaves=false' "bafykbzacearibnoamkfmcagpfgk2sbgx65qftnsrh4ttd3g7ghooasfnyavme"
-test_add_cat_expensive "" "QmU9SWAPPmNEKZB8umYMmjYvN7VyHqABNvdA6GUi4MMEz3"
+test_add_cat_expensive "" "Qma1WZKC3jad7e3F7GEDvkFdhPLyMEhKszBF4nBUCBGh6c"
# note: the specified hash implies that internal nodes are stored
# using CidV1 and leaves are stored using raw blocks
-test_add_cat_expensive "--cid-version=1" "bafybeidkj5ecbhrqmzrcee2rw7qwsx24z3364qya3fnp2ktkg2tnsrewhi"
+test_add_cat_expensive "--cid-version=1" "bafybeibdfw7nsmb3erhej2k6v4eopaswsf5yfv2ikweqa3qsc5no4jywqu"
# note: --hash=blake2b-256 implies --cid-version=1 which implies --raw-leaves=true
# the specified hash represents the leaf nodes stored as raw leaves and
# encoded with the blake2b-256 hash function
-test_add_cat_expensive '--hash=blake2b-256' "bafykbzaceb26fnq5hz5iopzamcb4yqykya5x6a4nvzdmcyuu4rj2akzs3z7r6"
+test_add_cat_expensive '--hash=blake2b-256' "bafykbzaceduy3thhmcf6ptfqzxberlvj7sgo4uokrvd6qwrhim6r3rgcb26qi"
test_add_named_pipe
diff --git a/test/sharness/t0043-add-w.sh b/test/sharness/t0043-add-w.sh
index 1f13cae3a65..a0bfc279703 100755
--- a/test/sharness/t0043-add-w.sh
+++ b/test/sharness/t0043-add-w.sh
@@ -6,58 +6,54 @@
test_description="Test add -w"
-add_w_m='QmazHkwx6mPmmCEi1jR5YzjjQd1g5XzKfYQLzRAg7x5uUk'
-
-add_w_1='added Qme987pqNBhZZXy4ckeXiR7zaRQwBabB7fTgHurW2yJfNu 4r93
-added Qmf82PSsMpUHcrqxa69KG6Qp5yeK7K9BTizXgG3nvzWcNG '
-
-add_w_12='added Qme987pqNBhZZXy4ckeXiR7zaRQwBabB7fTgHurW2yJfNu 4r93
-added QmVb4ntSZZnT2J2zvCmXKMJc52cmZYH6AB37MzeYewnkjs 4u6ead
-added QmZPASVB6EsADrLN8S2sak34zEHL8mx4TAVsPJU9cNnQQJ '
-
-add_w_21='added Qme987pqNBhZZXy4ckeXiR7zaRQwBabB7fTgHurW2yJfNu 4r93
-added QmVb4ntSZZnT2J2zvCmXKMJc52cmZYH6AB37MzeYewnkjs 4u6ead
-added QmZPASVB6EsADrLN8S2sak34zEHL8mx4TAVsPJU9cNnQQJ '
-
-add_w_d1='added QmPcaX84tDiTfzdTn8GQxexodgeWH6mHjSss5Zfr5ojssb _jo7/-s782qgs
-added QmaVBqquUuXKjkyWHXaXfsaQUxAnsCKS95VRDHU8PzGA4K _jo7/15totauzkak-
-added QmaAHFG8cmhW3WLjofx5siSp44VV25ETN6ThzrU8iAqpkR _jo7/galecuirrj4r
-added QmeuSfhJNKwBESp1W9H8cfoMdBfW3AeHQDWXbNXQJYWp53 _jo7/mzo50r-1xidf5zx
-added QmYC3u5jGWuyFwvTxtvLYm2K3SpWZ31tg3NjpVVvh9cJaJ _jo7/wzvsihy
-added QmQkib3f9XNX5sj6WEahLUPFpheTcwSRJwUCSvjcv8b9by _jo7
-added QmNQoesMj1qp8ApE51NbtTjFYksyzkezPD4cat7V2kzbKN '
-
-add_w_d1_v1='added bafkreif7rizm7yeem72okzlwr2ls73cyemfyv5mjghdew3kzhtfznzz4dq _jo7/-s782qgs
-added bafkreifkecyeevzcocvjliaz3ssiej5tkp32xyuogizonybihapdzovlsu _jo7/15totauzkak-
-added bafkreif5xhyhjhqp3muvj52wp37nutafsznckeuhikrl3h6w2sx3xdyeqm _jo7/galecuirrj4r
-added bafkreia6ooswgjtadq5n5zxkn2qyw3dpuyutvam7grtxn36ywykv52vkje _jo7/mzo50r-1xidf5zx
-added bafkreibhvbkg6zgra4bu56a36h25g52g6yxsb25qvgqv2trx4zbmhkmxku _jo7/wzvsihy
-added bafybeietuhja6ipwwnxefjecz6c5yls4j4q7r5gxiesyzfzkwsaimpa5mu _jo7
-added bafybeihxnrujsxdwyzuf3rq6wigzitrj6vjvxphttrtsx6tqabzpqfbd54 '
-
-add_w_d2='added Qme987pqNBhZZXy4ckeXiR7zaRQwBabB7fTgHurW2yJfNu 4r93
-added QmU9Jqks8TPu4vFr6t7EKkAKQrSJuEujNj1AkzoCeTEDFJ gnz66h/1k0xpx34
-added QmSLYZycXAufRw3ePMVH2brbtYWCcWsmksGLbHcT8ia9Ke gnz66h/9cwudvacx
-added QmfYmpCCAMU9nLe7xbrYsHf5z2R2GxeQnsm4zavUhX9vq2 gnz66h/9ximv51cbo8
-added QmWgEE4e2kfx3b8HZcBk5cLrfhoi8kTMQP2MipgPhykuV3 gnz66h/b54ygh6gs
-added QmcLbqEqhREGednc6mrVtanee4WHKp5JnUfiwTTHCJwuDf gnz66h/lbl5
-added QmPcaX84tDiTfzdTn8GQxexodgeWH6mHjSss5Zfr5ojssb _jo7/-s782qgs
-added QmaVBqquUuXKjkyWHXaXfsaQUxAnsCKS95VRDHU8PzGA4K _jo7/15totauzkak-
-added QmaAHFG8cmhW3WLjofx5siSp44VV25ETN6ThzrU8iAqpkR _jo7/galecuirrj4r
-added QmeuSfhJNKwBESp1W9H8cfoMdBfW3AeHQDWXbNXQJYWp53 _jo7/mzo50r-1xidf5zx
-added QmYC3u5jGWuyFwvTxtvLYm2K3SpWZ31tg3NjpVVvh9cJaJ _jo7/wzvsihy
-added QmVaKAt2eVftNKFfKhiBV7Mu5HjCugffuLqWqobSSFgiA7 h3qpecj0
-added QmQkib3f9XNX5sj6WEahLUPFpheTcwSRJwUCSvjcv8b9by _jo7
-added QmVPwNy8pZegpsNmsjjZvdTQn4uCeuZgtzhgWhRSQWjK9x gnz66h
-added QmTmc46fhKC8Liuh5soy1VotdnHcqLu3r6HpPGwDZCnqL1 '
-
-add_w_r='QmcCksBMDuuyuyfAMMNzEAx6Z7jTrdRy9a23WpufAhG9ji'
+add_w_m='QmbDfuW3tZ5PmAucyLBAMzVeETHCHM7Ho9CWdBvWxRGd3i'
+
+add_w_1='added QmP9WCV5SjQRoxoCkgywzw4q5X23rhHJJXzPQt4VbNa9M5 0h0r91
+added Qmave82G8vLbtx6JCokrrhLPpFNfWj5pbXobddiUASfpe3 '
+
+add_w_12='added QmP9WCV5SjQRoxoCkgywzw4q5X23rhHJJXzPQt4VbNa9M5 0h0r91
+added QmNUiT9caQy5zXvw942UYXkjLseQLWBkf7ZJD6RCfk8JgP 951op
+added QmWXoq9vUtdNxmM16kvJRgyQdi4S4gfYSjd2MsRprBXWmG '
+
+add_w_d1='added QmQKZCZKKL71zcMNpFFVcWzoh5dimX45mKgUu3LhvdaCRn 3s78oa/cb5v5v
+added QmPng2maSno8o659Lu2QtKg2d2L53RMahoyK6wNkifYaxY 3s78oa/cnd062l-rh
+added QmX3s7jJjFQhKRuGpDA3W4BYHdCWAyL3oB6U3iSoaYxVxs 3s78oa/es3gm9ck7b
+added QmSUZXb48DoNjUPpX9Jue1mUpyCghEDZY62iif1JhdofoG 3s78oa/kfo77-6i_hp0ttz
+added QmdC215Wp2sH47aw6R9CLBVa5uxJB4zEag1gtsKqjYGDb5 3s78oa/p91vs5t
+added QmSEGJRYb5wrJRBxNsse91YJSpmgf5ikKRtCwvGZ1V1Nc2 3s78oa
+added QmS2ML7DPVisc4gQtSrwMi3qwS9eyzGR7zVdwqwRPU9rGz '
+
+add_w_d1_v1='added bafkreibpfapmbmf55elpipnoofmda7xbs5spthba2srrovnchttzplmrnm fvmq97/0vz12t0yf
+added bafkreihc5hdzpjwbqy6b5r2h2oxbm6mp4sx4eqll253k6f5yijsismvoxy fvmq97/2hpfk8slf0
+added bafkreihlmwk6pkk7klsmypmk2wfkgijbk7wavhtrcvgrfxvug7x5ndawge fvmq97/nda000755cd76
+added bafkreigpntro6bt4m6c5pcnmvk24qyiq3lwffhwry7k2hqtretqhfsfvqa fvmq97/nsz0wsonz
+added bafkreieeznfvzr6742npktcn4ajzxujst6j2uztwfninhvic4bbvm356u4 fvmq97/pq3f6t0
+added bafybeiatm3oos62mm5hu4cmq234wipw2fjaqflq2cdqgc6i6dcgzamxwrm fvmq97
+added bafybeifp4ioszjk2377psexdhk7thcxnpaj2wls4yifsntbgxzti7ds4uy '
+
+add_w_d2='added QmP9WCV5SjQRoxoCkgywzw4q5X23rhHJJXzPQt4VbNa9M5 0h0r91
+added QmPpv7rFgkBqMYKJok6kVixqJgAGkyPiX3Jrr7n9rU1gcv 1o8ef-25onywi
+added QmW7zDxGpaJTRpte7uCvMA9eXJ5L274FfsFPK9pE5RShq9 2ju9tn-b09/-qw1d8j9
+added QmNNm9D3pn8NXbuYSde614qbb9xE67g9TNV6zXePgSZvHj 2ju9tn-b09/03rfc61t4qq_m
+added QmUYefaFAWka9LWarDeetQFe8CCSHaAtj4JR7YToYPSJyi 2ju9tn-b09/57dl-1lbjvu
+added QmcMLvVinwJsHtYxTUXEoPd8XkbuyvJNffZ85PT11cWDc2 2ju9tn-b09/t8h1_w
+added QmUTZE57VoF7xqWmrrcDNtDXrEs6znTQaRwmwkawGDs1GA 2ju9tn-b09/ugqi0nmv-1
+added QmfX5q9CMquL4JnAuG4H13RXjTb9DncMfu9pvpEsWkECJk fvmq97/0vz12t0yf
+added Qmdr3jR1UATLFeuoieBTHLNNwhCUJbgN5oat7U9X8TtfdZ fvmq97/2hpfk8slf0
+added QmfUKgXSiE1wCQuX3Pws9FftthJuAMXrDWhG5EhhnmA6gQ fvmq97/nda000755cd76
+added QmYM35pgHvLdKH8ssw9kJeiUY5kcjhb5h3BTiDhAgbsYYh fvmq97/nsz0wsonz
+added QmNarBSVwzYjLeEjGMJqTNtRCYGCLGo6TJqd21hPi7WXFT fvmq97/pq3f6t0
+added QmUNhQpFBZvfH4JyNxiE8QY31bZDpQHMmjSRRnbRZYZ3be 2ju9tn-b09
+added QmWtZu8dv4XRK8zPmwbNjS6biqe4bGEF9J5zb51sBJCMro fvmq97
+added QmYp7QoL8wRacLn9pJftJSkiiSmNGdWb7qT5ENDW2HXBcu '
+
+add_w_r='QmUerh2irM8cngqJHLGKCn4AGBSyHYAUi8i8zyVzXKNYyb'
. lib/test-lib.sh
test_add_w() {
- test_expect_success "go-random-files is installed" '
+ test_expect_success "random-files is installed" '
type random-files
'
@@ -70,7 +66,7 @@ test_add_w() {
# test single file
test_expect_success "ipfs add -w (single file) succeeds" '
- ipfs add -w m/4r93 >actual
+ ipfs add -w m/0h0r91 >actual
'
test_expect_success "ipfs add -w (single file) is correct" '
@@ -80,7 +76,7 @@ test_add_w() {
# test two files together
test_expect_success "ipfs add -w (multiple) succeeds" '
- ipfs add -w m/4r93 m/4u6ead >actual
+ ipfs add -w m/0h0r91 m/951op >actual
'
test_expect_success "ipfs add -w (multiple) is correct" '
@@ -89,17 +85,17 @@ test_add_w() {
'
test_expect_success "ipfs add -w (multiple) succeeds" '
- ipfs add -w m/4u6ead m/4r93 >actual
+ ipfs add -w m/951op m/0h0r91 >actual
'
test_expect_success "ipfs add -w (multiple) orders" '
- echo "$add_w_21" >expected &&
+ echo "$add_w_12" >expected &&
test_sort_cmp expected actual
'
# test a directory
test_expect_success "ipfs add -w -r (dir) succeeds" '
- ipfs add -r -w m/t_1wp-8a2/_jo7 >actual
+ ipfs add -r -w m/9m7mh3u51z3b/3s78oa >actual
'
test_expect_success "ipfs add -w -r (dir) is correct" '
@@ -109,8 +105,8 @@ test_add_w() {
# test files and directory
test_expect_success "ipfs add -w -r succeeds" '
- ipfs add -w -r m/t_1wp-8a2/h3qpecj0 \
- m/ha6f0x7su6/gnz66h m/t_1wp-8a2/_jo7 m/4r93 >actual
+ ipfs add -w -r m/9m7mh3u51z3b/1o8ef-25onywi \
+ m/vck_-2/2ju9tn-b09 m/9m7mh3u51z3b/fvmq97 m/0h0r91 >actual
'
test_expect_success "ipfs add -w -r is correct" '
@@ -130,10 +126,10 @@ test_add_w() {
# test repeats together
test_expect_success "ipfs add -w (repeats) succeeds" '
- ipfs add -Q -w -r m/t_1wp-8a2/h3qpecj0 m/ha6f0x7su6/gnz66h \
- m/t_1wp-8a2/_jo7 m/4r93 m/t_1wp-8a2 m/t_1wp-8a2 m/4r93 \
- m/4r93 m/ha6f0x7su6/_rwujlf3qh_g08 \
- m/ha6f0x7su6/gnz66h/9cwudvacx >actual
+ ipfs add -Q -w -r m/9m7mh3u51z3b/1o8ef-25onywi m/vck_-2/2ju9tn-b09 \
+ m/9m7mh3u51z3b/fvmq97 m/0h0r91 m/9m7mh3u51z3b m/9m7mh3u51z3b m/0h0r91 \
+ m/0h0r91 m/vck_-2/0dl083je2 \
+ m/vck_-2/2ju9tn-b09/-qw1d8j9 >actual
'
test_expect_success "ipfs add -w (repeats) is correct" '
@@ -142,7 +138,7 @@ test_add_w() {
'
test_expect_success "ipfs add -w -r (dir) --cid-version=1 succeeds" '
- ipfs add -r -w --cid-version=1 m/t_1wp-8a2/_jo7 >actual
+ ipfs add -r -w --cid-version=1 m/9m7mh3u51z3b/fvmq97 >actual
'
test_expect_success "ipfs add -w -r (dir) --cid-version=1 is correct" '
@@ -151,7 +147,7 @@ test_add_w() {
'
test_expect_success "ipfs add -w -r -n (dir) --cid-version=1 succeeds" '
- ipfs add -r -w -n --cid-version=1 m/t_1wp-8a2/_jo7 >actual
+ ipfs add -r -w -n --cid-version=1 m/9m7mh3u51z3b/fvmq97 >actual
'
test_expect_success "ipfs add -w -r -n (dir) --cid-version=1 is correct" '
diff --git a/test/sharness/t0045-ls.sh b/test/sharness/t0045-ls.sh
index 5e02ad167cd..ebb391d6562 100755
--- a/test/sharness/t0045-ls.sh
+++ b/test/sharness/t0045-ls.sh
@@ -16,106 +16,106 @@ test_ls_cmd() {
echo "test" >testData/f1 &&
echo "data" >testData/f2 &&
echo "hello" >testData/d1/a &&
- random 128 42 >testData/d1/128 &&
+ random-data -size=128 -seed=42 >testData/d1/128 &&
echo "world" >testData/d2/a &&
- random 1024 42 >testData/d2/1024 &&
+ random-data -size=1024 -seed=42 >testData/d2/1024 &&
echo "badname" >testData/d2/`echo -e "bad\x7fname.txt"` &&
ipfs add -r testData >actual_add
'
test_expect_success "'ipfs add' output looks good" '
cat <<-\EOF >expected_add &&
-added QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe testData/d1/128
+added QmWUixdcx1VJtpuAgXAy4e3JPAbEoHE6VEDut5KcYcpuGN testData/d1/128
added QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN testData/d1/a
-added QmbQBUSRL9raZtNXfpTDeaxQapibJEG6qEY8WqAN22aUzd testData/d2/1024
+added QmZHVTX2epinyx5baTFV2L2ap9VtgbmfeFdhgntAypT5N3 testData/d2/1024
added QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL testData/d2/a
added QmQSLRRd1Lxn6NMsWmmj2g9W3LtSRfmVAVqU3ShneLUrbn testData/d2/bad\x7fname.txt
added QmeomffUNfmQy76CQGy9NdmqEnnHU9soCexBnGU3ezPHVH testData/f1
added QmNtocSs7MoDkJMc1RkyisCSKvLadujPsfJfSdJ3e1eA1M testData/f2
-added QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss testData/d1
-added Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy testData/d2
-added QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21 testData
+added QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j testData/d1
+added Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW testData/d2
+added QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc testData
EOF
test_cmp expected_add actual_add
'
-
+
test_expect_success "'ipfs ls ' succeeds" '
- ipfs ls QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21 Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss >actual_ls
+ ipfs ls QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j >actual_ls
'
test_expect_success "'ipfs ls ' output looks good" '
cat <<-\EOF >expected_ls &&
-QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21:
-QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss - d1/
-Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy - d2/
+QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc:
+QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j - d1/
+Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW - d2/
QmeomffUNfmQy76CQGy9NdmqEnnHU9soCexBnGU3ezPHVH 5 f1
QmNtocSs7MoDkJMc1RkyisCSKvLadujPsfJfSdJ3e1eA1M 5 f2
-Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy:
-QmbQBUSRL9raZtNXfpTDeaxQapibJEG6qEY8WqAN22aUzd 1024 1024
+Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW:
+QmZHVTX2epinyx5baTFV2L2ap9VtgbmfeFdhgntAypT5N3 1024 1024
QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL 6 a
QmQSLRRd1Lxn6NMsWmmj2g9W3LtSRfmVAVqU3ShneLUrbn 8 bad\x7fname.txt
-QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss:
-QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 128 128
+QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j:
+QmWUixdcx1VJtpuAgXAy4e3JPAbEoHE6VEDut5KcYcpuGN 128 128
QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN 6 a
EOF
test_cmp expected_ls actual_ls
'
test_expect_success "'ipfs ls --size=false ' succeeds" '
- ipfs ls --size=false QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21 Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss >actual_ls
+ ipfs ls --size=false QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j >actual_ls
'
test_expect_success "'ipfs ls ' output looks good" '
cat <<-\EOF >expected_ls &&
-QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21:
-QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss d1/
-Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy d2/
+QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc:
+QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j d1/
+Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW d2/
QmeomffUNfmQy76CQGy9NdmqEnnHU9soCexBnGU3ezPHVH f1
QmNtocSs7MoDkJMc1RkyisCSKvLadujPsfJfSdJ3e1eA1M f2
-Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy:
-QmbQBUSRL9raZtNXfpTDeaxQapibJEG6qEY8WqAN22aUzd 1024
+Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW:
+QmZHVTX2epinyx5baTFV2L2ap9VtgbmfeFdhgntAypT5N3 1024
QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL a
QmQSLRRd1Lxn6NMsWmmj2g9W3LtSRfmVAVqU3ShneLUrbn bad\x7fname.txt
-QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss:
-QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 128
+QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j:
+QmWUixdcx1VJtpuAgXAy4e3JPAbEoHE6VEDut5KcYcpuGN 128
QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN a
EOF
test_cmp expected_ls actual_ls
'
test_expect_success "'ipfs ls --headers ' succeeds" '
- ipfs ls --headers QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21 Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss >actual_ls_headers
+ ipfs ls --headers QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j >actual_ls_headers
'
test_expect_success "'ipfs ls --headers ' output looks good" '
cat <<-\EOF >expected_ls_headers &&
-QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21:
+QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc:
Hash Size Name
-QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss - d1/
-Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy - d2/
+QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j - d1/
+Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW - d2/
QmeomffUNfmQy76CQGy9NdmqEnnHU9soCexBnGU3ezPHVH 5 f1
QmNtocSs7MoDkJMc1RkyisCSKvLadujPsfJfSdJ3e1eA1M 5 f2
-Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy:
+Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW:
Hash Size Name
-QmbQBUSRL9raZtNXfpTDeaxQapibJEG6qEY8WqAN22aUzd 1024 1024
+QmZHVTX2epinyx5baTFV2L2ap9VtgbmfeFdhgntAypT5N3 1024 1024
QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL 6 a
QmQSLRRd1Lxn6NMsWmmj2g9W3LtSRfmVAVqU3ShneLUrbn 8 bad\x7fname.txt
-QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss:
+QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j:
Hash Size Name
-QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 128 128
+QmWUixdcx1VJtpuAgXAy4e3JPAbEoHE6VEDut5KcYcpuGN 128 128
QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN 6 a
EOF
test_cmp expected_ls_headers actual_ls_headers
'
test_expect_success "'ipfs ls --size=false --cid-base=base32 ' succeeds" '
- ipfs ls --size=false --cid-base=base32 $(cid-fmt -v 1 -b base32 %s QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21 Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss) >actual_ls_base32
+ ipfs ls --size=false --cid-base=base32 $(cid-fmt -v 1 -b base32 %s QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j) >actual_ls_base32
'
test_expect_success "'ipfs ls --size=false --cid-base=base32 ' output looks good" '
@@ -132,99 +132,99 @@ test_ls_cmd_streaming() {
echo "test" >testData/f1 &&
echo "data" >testData/f2 &&
echo "hello" >testData/d1/a &&
- random 128 42 >testData/d1/128 &&
+ random-data -size=128 -seed=42 >testData/d1/128 &&
echo "world" >testData/d2/a &&
- random 1024 42 >testData/d2/1024 &&
+ random-data -size=1024 -seed=42 >testData/d2/1024 &&
echo "badname" >testData/d2/`echo -e "bad\x7fname.txt"` &&
ipfs add -r testData >actual_add
'
test_expect_success "'ipfs add' output looks good" '
cat <<-\EOF >expected_add &&
-added QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe testData/d1/128
+added QmWUixdcx1VJtpuAgXAy4e3JPAbEoHE6VEDut5KcYcpuGN testData/d1/128
added QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN testData/d1/a
-added QmbQBUSRL9raZtNXfpTDeaxQapibJEG6qEY8WqAN22aUzd testData/d2/1024
+added QmZHVTX2epinyx5baTFV2L2ap9VtgbmfeFdhgntAypT5N3 testData/d2/1024
added QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL testData/d2/a
added QmQSLRRd1Lxn6NMsWmmj2g9W3LtSRfmVAVqU3ShneLUrbn testData/d2/bad\x7fname.txt
added QmeomffUNfmQy76CQGy9NdmqEnnHU9soCexBnGU3ezPHVH testData/f1
added QmNtocSs7MoDkJMc1RkyisCSKvLadujPsfJfSdJ3e1eA1M testData/f2
-added QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss testData/d1
-added Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy testData/d2
-added QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21 testData
+added QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j testData/d1
+added Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW testData/d2
+added QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc testData
EOF
test_cmp expected_add actual_add
'
test_expect_success "'ipfs ls --stream ' succeeds" '
- ipfs ls --stream QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21 Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss >actual_ls_stream
+ ipfs ls --stream QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j >actual_ls_stream
'
test_expect_success "'ipfs ls --stream ' output looks good" '
cat <<-\EOF >expected_ls_stream &&
-QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21:
-QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss - d1/
-Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy - d2/
+QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc:
+QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j - d1/
+Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW - d2/
QmeomffUNfmQy76CQGy9NdmqEnnHU9soCexBnGU3ezPHVH 5 f1
QmNtocSs7MoDkJMc1RkyisCSKvLadujPsfJfSdJ3e1eA1M 5 f2
-Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy:
-QmbQBUSRL9raZtNXfpTDeaxQapibJEG6qEY8WqAN22aUzd 1024 1024
+Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW:
+QmZHVTX2epinyx5baTFV2L2ap9VtgbmfeFdhgntAypT5N3 1024 1024
QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL 6 a
QmQSLRRd1Lxn6NMsWmmj2g9W3LtSRfmVAVqU3ShneLUrbn 8 bad\x7fname.txt
-QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss:
-QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 128 128
+QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j:
+QmWUixdcx1VJtpuAgXAy4e3JPAbEoHE6VEDut5KcYcpuGN 128 128
QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN 6 a
EOF
test_cmp expected_ls_stream actual_ls_stream
'
test_expect_success "'ipfs ls --size=false --stream ' succeeds" '
- ipfs ls --size=false --stream QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21 Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss >actual_ls_stream
+ ipfs ls --size=false --stream QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j >actual_ls_stream
'
test_expect_success "'ipfs ls --size=false --stream ' output looks good" '
cat <<-\EOF >expected_ls_stream &&
-QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21:
-QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss d1/
-Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy d2/
+QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc:
+QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j d1/
+Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW d2/
QmeomffUNfmQy76CQGy9NdmqEnnHU9soCexBnGU3ezPHVH f1
QmNtocSs7MoDkJMc1RkyisCSKvLadujPsfJfSdJ3e1eA1M f2
-Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy:
-QmbQBUSRL9raZtNXfpTDeaxQapibJEG6qEY8WqAN22aUzd 1024
+Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW:
+QmZHVTX2epinyx5baTFV2L2ap9VtgbmfeFdhgntAypT5N3 1024
QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL a
QmQSLRRd1Lxn6NMsWmmj2g9W3LtSRfmVAVqU3ShneLUrbn bad\x7fname.txt
-QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss:
-QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 128
+QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j:
+QmWUixdcx1VJtpuAgXAy4e3JPAbEoHE6VEDut5KcYcpuGN 128
QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN a
EOF
test_cmp expected_ls_stream actual_ls_stream
'
test_expect_success "'ipfs ls --stream --headers ' succeeds" '
- ipfs ls --stream --headers QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21 Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss >actual_ls_stream_headers
+ ipfs ls --stream --headers QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j >actual_ls_stream_headers
'
test_expect_success "'ipfs ls --stream --headers ' output looks good" '
cat <<-\EOF >expected_ls_stream_headers &&
-QmRPX2PWaPGqzoVzqNcQkueijHVzPicjupnD7eLck6Rs21:
+QmR5UuxvF2ALd2GRGMCNg1GDiuuvcAyEkQaCV9fNkevWuc:
Hash Size Name
-QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss - d1/
-Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy - d2/
+QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j - d1/
+Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW - d2/
QmeomffUNfmQy76CQGy9NdmqEnnHU9soCexBnGU3ezPHVH 5 f1
QmNtocSs7MoDkJMc1RkyisCSKvLadujPsfJfSdJ3e1eA1M 5 f2
-Qmf9nCpkCfa8Gtz5m1NJMeHBWcBozKRcbdom338LukPAjy:
+Qmapxr4zxxUjoUFzyggydRZDkcJknjbtahYFKokbBAVghW:
Hash Size Name
-QmbQBUSRL9raZtNXfpTDeaxQapibJEG6qEY8WqAN22aUzd 1024 1024
+QmZHVTX2epinyx5baTFV2L2ap9VtgbmfeFdhgntAypT5N3 1024 1024
QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL 6 a
QmQSLRRd1Lxn6NMsWmmj2g9W3LtSRfmVAVqU3ShneLUrbn 8 bad\x7fname.txt
-QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss:
+QmWWEQhcLufF3qPmmbUjqH7WVWBT9JrGJwPiVTryCoBs2j:
Hash Size Name
-QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 128 128
+QmWUixdcx1VJtpuAgXAy4e3JPAbEoHE6VEDut5KcYcpuGN 128 128
QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN 6 a
EOF
test_cmp expected_ls_stream_headers actual_ls_stream_headers
@@ -244,19 +244,19 @@ test_ls_cmd_raw_leaves() {
test_ls_object() {
test_expect_success "ipfs add medium size file then 'ipfs ls --size=false' works as expected" '
- random 500000 2 > somefile &&
+ random-data -size=500000 -seed=2 > somefile &&
HASH=$(ipfs add somefile -q) &&
- echo "QmPrM8S5T7Q3M8DQvQMS7m41m3Aq4jBjzAzvky5fH3xfr4 " > ls-expect &&
- echo "QmdaAntAzQqqVMo4B8V69nkQd5d918YjHXUe2oF6hr72ri " >> ls-expect &&
+ echo "QmWJuiG6dhfwo3KXxCc9gkdizoMoXbLMCDiTTZgEhSmyyo " > ls-expect &&
+ echo "QmNPxtpjhoXMRVKm4oSwcJaS4fck5FR4LufPd5KJr4jYhm " >> ls-expect &&
ipfs ls --size=false $HASH > ls-actual &&
test_cmp ls-actual ls-expect
'
test_expect_success "ipfs add medium size file then 'ipfs ls' works as expected" '
- random 500000 2 > somefile &&
+ random-data -size=500000 -seed=2 > somefile &&
HASH=$(ipfs add somefile -q) &&
- echo "QmPrM8S5T7Q3M8DQvQMS7m41m3Aq4jBjzAzvky5fH3xfr4 262144 " > ls-expect &&
- echo "QmdaAntAzQqqVMo4B8V69nkQd5d918YjHXUe2oF6hr72ri 237856 " >> ls-expect &&
+ echo "QmWJuiG6dhfwo3KXxCc9gkdizoMoXbLMCDiTTZgEhSmyyo 262144 " > ls-expect &&
+ echo "QmNPxtpjhoXMRVKm4oSwcJaS4fck5FR4LufPd5KJr4jYhm 237856 " >> ls-expect &&
ipfs ls $HASH > ls-actual &&
test_cmp ls-actual ls-expect
'
@@ -285,8 +285,8 @@ test_ls_object
test_expect_success "'ipfs add -r' succeeds" '
mkdir adir &&
# note: not using a seed as the files need to have truly random content
- random 1000 > adir/file1 &&
- random 1000 > adir/file2 &&
+ random-data -size=1000 > adir/file1 &&
+ random-data -size=1000 > adir/file2 &&
ipfs add --pin=false -q -r adir > adir-hashes
'
diff --git a/test/sharness/t0046-id-hash.sh b/test/sharness/t0046-id-hash.sh
index d4c28f21507..7dfc73d09e5 100755
--- a/test/sharness/t0046-id-hash.sh
+++ b/test/sharness/t0046-id-hash.sh
@@ -65,7 +65,7 @@ test_expect_success "ipfs add --inline --raw-leaves outputs the correct hash" '
'
test_expect_success "create 1000 bytes file and get its hash" '
- random 1000 2 > 1000bytes &&
+ random-data -size=1000 -seed=2 > 1000bytes &&
HASH0=$(ipfs add -q --raw-leaves --only-hash 1000bytes)
'
diff --git a/test/sharness/t0047-add-mode-mtime.sh b/test/sharness/t0047-add-mode-mtime.sh
new file mode 100755
index 00000000000..520c692f3bc
--- /dev/null
+++ b/test/sharness/t0047-add-mode-mtime.sh
@@ -0,0 +1,513 @@
+#!/usr/bin/env bash
+
+test_description="Test storing and retrieving mode and mtime"
+
+. lib/test-lib.sh
+
+test_init_ipfs
+
+test_expect_success "set Import defaults to ensure deterministic cids for mod and mtime tests" '
+ ipfs config --json Import.CidVersion 0 &&
+ ipfs config Import.HashFunction sha2-256 &&
+ ipfs config Import.UnixFSChunker size-262144
+'
+
+HASH_NO_PRESERVE=QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH
+
+PRESERVE_MTIME=1604320482
+PRESERVE_MODE="0640"
+HASH_PRESERVE_MODE=QmQLgxypSNGNFTuUPGCecq6dDEjb6hNB5xSyVmP3cEuNtq
+HASH_PRESERVE_MTIME=QmQ6kErEW8kztQFV8vbwNU8E4dmtGsYpRiboiLxUEwibvj
+HASH_PRESERVE_LINK_MTIME=QmbJwotgtr84JxcnjpwJ86uZiyMoxbZuNH4YrdJMypkYaB
+HASH_PRESERVE_MODE_AND_MTIME=QmYkvboLsvLFcSYmqVJRxvBdYRQLroLv9kELf3LRiCqBri
+
+CUSTOM_MTIME=1603539720
+CUSTOM_MTIME_NSECS=54321
+CUSTOM_MODE="0764"
+HASH_CUSTOM_MODE=QmchD3BN8TQ3RW6jPLxSaNkqvfuj7syKhzTRmL4EpyY1Nz
+HASH_CUSTOM_MTIME=QmT3aY4avDcYXCWpU8CJzqUkW7YEuEsx36S8cTNoLcuK1B
+HASH_CUSTOM_MTIME_NSECS=QmaKH8H5rXBUBCX4vdxi7ktGQEL7wejV7L9rX2qpZjwncz
+HASH_CUSTOM_MODE_AND_MTIME=QmUkxrtBA8tPjwCYz1HrsoRfDz6NgKut3asVeHVQNH4C8L
+HASH_CUSTOM_LINK_MTIME=QmV1Uot2gy4bhY9yvYiZxhhchhyYC6MKKoGV1XtWNmpCLe
+HASH_CUSTOM_LINK_MTIME_NSECS=QmPHYCxYvvHj6VxiPNJ3kXxcPsnJLDYUJqsDJWjvytmrmY
+
+mk_name() {
+ tr -dc '[:alnum:]'" /ipfs/$HASH) &&
+ test "$ACTUAL" = "lrwxrwxrwx"
+ '
+
+
+ test_expect_success "can set symlink modification time nanoseconds [$1]" '
+ touch -h -m -t 202011021234.42 "$TESTLINK" &&
+ HASH=$(ipfs add -q --mtime=$CUSTOM_MTIME --mtime-nsecs=$CUSTOM_MTIME_NSECS "$TESTLINK") &&
+ test "$HASH_CUSTOM_LINK_MTIME_NSECS" = "$HASH"
+ '
+
+ test_expect_success "can get preserved mode and modification time [$1]" '
+ OUTFILE="$(mk_file $HASH_PRESERVE_MODE_AND_MTIME)" &&
+ ipfs get -o "$OUTFILE" $HASH_PRESERVE_MODE_AND_MTIME &&
+ test "$PRESERVE_MODE:$PRESERVE_MTIME" = "$(stat -c "0%a:%Y" "$OUTFILE")"
+ '
+
+ test_expect_success "can get custom mode and modification time [$1]" '
+ OUTFILE="$(mk_file $HASH_CUSTOM_MODE_AND_MTIME)" &&
+ ipfs get -o "$OUTFILE" $HASH_CUSTOM_MODE_AND_MTIME &&
+ TIMESTAMP=$(date +%s%N --date="$(stat -c "%y" "$OUTFILE")") &&
+ MODETIME=$(stat -c "0%a:$TIMESTAMP" "$OUTFILE") &&
+ printf -v EXPECTED "$CUSTOM_MODE:$CUSTOM_MTIME%09d" $CUSTOM_MTIME_NSECS &&
+ test "$EXPECTED" = "$MODETIME"
+ '
+
+ test_expect_success "can get custom symlink modification time [$1]" '
+ OUTFILE="$(mk_file $HASH_CUSTOM_LINK_MTIME_NSECS)" &&
+ ipfs get -o "$OUTFILE" $HASH_CUSTOM_LINK_MTIME_NSECS &&
+ TIMESTAMP=$(date +%s%N --date="$(stat -c "%y" "$OUTFILE")") &&
+ printf -v EXPECTED "$CUSTOM_MTIME%09d" $CUSTOM_MTIME_NSECS &&
+ test "$EXPECTED" = "$TIMESTAMP"
+ '
+
+ test_expect_success "can change file mode [$1]" '
+ NAME=$(mk_name) &&
+ HASH=$(echo testfile | ipfs add -q --mode=0600) &&
+ OUTFILE=$(mk_file "${NAME}") &&
+ ipfs files cp "/ipfs/$HASH" /$NAME &&
+ ipfs files chmod 444 /$NAME &&
+ HASH2=$(ipfs files stat /$NAME|head -1) &&
+ ipfs get -o "$OUTFILE" $HASH2 &&
+ test $(stat -c "%a" "$OUTFILE") = 444
+ '
+
+ # special case, because storing mode requires dag-pb envelope
+ # and when dealing with CIDv1 we can have 'raw' block instead of 'dag-pb'
+ # so it needs to be converted before adding attribute
+ test_expect_success "can add file mode to cidv1 raw block [$1]" '
+ NAME=$(mk_name) &&
+ HASH=$(date | ipfs add -q --cid-version 1 --raw-leaves=true) &&
+ OUTFILE=$(mk_file "${NAME}") &&
+ ipfs files cp "/ipfs/$HASH" /$NAME &&
+ ipfs files chmod 445 /$NAME &&
+ HASH2=$(ipfs files stat /$NAME|head -1) &&
+ ipfs get -o "$OUTFILE" $HASH2 &&
+ test $(stat -c "%a" "$OUTFILE") = 445
+ '
+
+ test_expect_success "can change file modification time [$1]" '
+ NAME=$(mk_name) &&
+ OUTFILE="$(mk_file "$NAME")" &&
+ NOW=$(date +%s) &&
+ HASH=$(echo testfile | ipfs add -q --mtime=$NOW) &&
+ ipfs files cp "/ipfs/$HASH" /$NAME &&
+ sleep 1 &&
+ ipfs files touch /$NAME &&
+ HASH=$(ipfs files stat /$NAME|head -1) &&
+ ipfs get -o "$OUTFILE" "$HASH" &&
+ test $(stat -c "%Y" "$OUTFILE") -gt $NOW
+ '
+
+ # special case, because storing mtime requires dag-pb envelope
+ # and when dealing with CIDv1 we can have 'raw' block instead of 'dag-pb'
+ # so it needs to be converted to dag-pb before adding attribute
+ test_expect_success "can add file modification time to cidv1 raw block [$1]" '
+ NAME=$(mk_name) &&
+ OUTFILE="$(mk_file "$NAME")" &&
+ EXPECTED="$CUSTOM_MTIME" &&
+ HASH=$(date | ipfs add -q --cid-version 1 --raw-leaves=true) &&
+ ipfs files cp "/ipfs/$HASH" /$NAME &&
+ ipfs files touch --mtime=$EXPECTED /$NAME &&
+ test $(ipfs files stat --format="" "/$NAME") -eq $EXPECTED &&
+ HASH=$(ipfs files stat /$NAME|head -1) &&
+ ipfs get -o "$OUTFILE" "$HASH" &&
+ test $(stat -c "%Y" "$OUTFILE") -eq $EXPECTED
+ '
+
+ test_expect_success "can change file modification time nanoseconds [$1]" '
+ NAME=$(mk_name) &&
+ echo test|ipfs files write --create /$NAME &&
+ EXPECTED=$(date --date="yesterday" +%s) &&
+ ipfs files touch --mtime=$EXPECTED --mtime-nsecs=55567 /$NAME &&
+ test $(ipfs files stat --format="" /$NAME) -eq $EXPECTED &&
+ test $(ipfs files stat --format="" /$NAME) -eq 55567
+ '
+
+ ## TODO: update these tests if/when symbolic links are fully supported in go-mfs
+ test_expect_success "can change symlink modification time [$1]" '
+ NAME=$(mk_name) &&
+ EXPECTED=$(date +%s) &&
+ ipfs files cp "/ipfs/$HASH_PRESERVE_LINK_MTIME" "/$NAME" ||
+ ipfs files touch --mtime=$EXPECTED "/$NAME" &&
+ test $(ipfs files stat --format="" "/$NAME") -eq $EXPECTED
+ '
+
+ test_expect_success "can change symlink modification time nanoseconds [$1]" '
+ NAME=$(mk_name) &&
+ EXPECTED=$(date +%s) &&
+ ipfs files cp "/ipfs/$HASH_PRESERVE_LINK_MTIME" "/$NAME" ||
+ ipfs files touch --mtime=$EXPECTED --mtime-nsecs=938475 "/$NAME" &&
+ test $(ipfs files stat --format="" "/$NAME") -eq $EXPECTED &&
+ test $(ipfs files stat --format="" "/$NAME") -eq 938475
+ '
+}
+
+DIR_TIME=1655158632
+
+setup_directory() {
+
+ local TESTDIR="$(mktemp -d -p "$FIXTURESDIR" "${1}XXXXXX")"
+ mkdir -p "$TESTDIR"/{dir1,dir2/sub1/sub2,dir3}
+ chmod 0755 "$TESTDIR/dir1"
+
+ touch -md @$(($DIR_TIME+10)) "$TESTDIR/dir2/sub1/sub2/file3"
+ ln -s ../sub2/file3 "$TESTDIR/dir2/sub1/link1"
+ touch -h -md @$(($DIR_TIME+20)) "$TESTDIR/dir2/sub1/link1"
+
+ touch -md @$(($DIR_TIME+30)) "$TESTDIR/dir2/sub1/sub2"
+ touch -md @$(($DIR_TIME+40)) "$TESTDIR/dir2/sub1"
+ touch -md @$(($DIR_TIME+50)) "$TESTDIR/dir2"
+
+ touch -md @$(($DIR_TIME+60)) "$TESTDIR/dir3/file2"
+ touch -md @$(($DIR_TIME+70)) "$TESTDIR/dir3"
+
+ touch -md @$(($DIR_TIME+80)) "$TESTDIR/file1"
+ touch -md @$(($DIR_TIME+90)) "$TESTDIR/dir1"
+ touch -md @$DIR_TIME "$TESTDIR"
+
+ echo "$TESTDIR"
+}
+
+test_directory() {
+ CUSTOM_DIR_MODE=0713
+ TESTDIR=$(setup_directory $1)
+ TESTDIR1="$TESTDIR/dir1"
+ OUTDIR="$(mk_dir "${1}")"
+ HASH_DIR_ROOT=QmSioyvQuXetxg7uo8FswGn9XKKEsisDq1HTMzGyWbw2R6
+ HASH_DIR1_NO_PRESERVE=QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn
+ HASH_DIR1_PRESERVE_MODE=QmRviohgafvCsbkiTgfQFipbuXJ6k1YtoiaQW4quttJPKu
+ HASH_DIR1_PRESERVE_MTIME=QmYMy7CZGb498QFSQBF5ZFwv1FYbrAtYZMe4VxhDXxAcvf
+ HASH_DIR1_CUSTOM_MODE=QmQ1ABnw2iip7sj23EzzBZ9T77KyyfESP6SUboiXPyzNQe
+ HASH_DIR1_CUSTOM_MTIME=QmfWitW6F13WHFXLbJzXRYmwrS1p4gaAJAfucUSMytRPn3
+ HASH_DIR1_CUSTOM_MTIME_NSECS=QmZFdCLJay31hT3Tx1LygJ7XfiLEs3qLCXtbeBfhf38aZg
+ HASH_DIR_SUB1=QmeQwX5qAX18fcPDxDdkfM6ttuFCZetF5hgeUa6ov8D5oc
+
+ HASH_DIR_MODE_AND_MTIME=(
+ QmRCG3Pprg4jbhfYBzVzfJVyneFHnBquPGXwvXU3jSuf5j
+ QmReHCn4BSJJdtd6Le8Hd8Puai6TmgpPCYb13wyM7FD9AD
+ QmSioyvQuXetxg7uo8FswGn9XKKEsisDq1HTMzGyWbw2R6
+ QmTMoVgJKhPrz9DfkvT132mxyBXNae5azXQ42WbM9abdSE
+ QmVzXqpuQGCAgRwEbGuE9xe8Fidi1HEXaPKsQEFEbPJW9j
+ QmW6Nqy2nziduAp3UGx2a52gtSUsYzhVcZMuPdxBRnwCyP
+ QmeQwX5qAX18fcPDxDdkfM6ttuFCZetF5hgeUa6ov8D5oc
+ QmefofUNwC2U3Xp87rB1x8Aws6AdsDuoXR7B9u2RkEZ4dQ
+ Qmeu24TFarJwLzJgMTDYDJTr4BMGnzafoSnfxov1513abW
+ Qmf82bbFg2e8HmcqiewutVVw5NoMpiXZD57LpLdC1poBuH)
+ HASH_DIR_CUSTOM_MODE=(
+ QmNZ5cyx3f6maXkczwhh3ufjDCh9f3k9zrDhX218ZZGvoV
+ QmRqtFVLkXfWJuqWtYiCPthgomo3gouno8uvMeGAyCVaWS
+ QmSkrWNcyDA7s1qiT6Ps7ey4zcB7uBH3sqGcKRfW4UMKhM
+ QmSkrWNcyDA7s1qiT6Ps7ey4zcB7uBH3sqGcKRfW4UMKhM
+ QmSkrWNcyDA7s1qiT6Ps7ey4zcB7uBH3sqGcKRfW4UMKhM
+ QmZNAZXB6JyJ1cK9h1uJEK4XDo1CKsSuHMPGUUMrzDXCQz
+ QmbSz6GyS8MNR4M9xtCteuGVJQRYkCXLbW174Fdy8jtaoZ
+ QmccnAQQeJGtmtgZoi3hpEmgdxbuX1ao2hQmrKmmwQnCn9
+ QmeTZoiAiduFY2hXaNQP4ehiE71BrQFEnrqduBZ5ZjHuFy
+ Qmf13KNurvAHUfMBhMWvZuftmUikhhGY7ohWVaBDDndFMz)
+ HASH_DIR_CUSTOM_MTIME=(
+ QmPCGFZ8ZFowAwfWdCeGsr9wSbGXwZiHW3bZ7XSYcc1Zby
+ QmT3aY4avDcYXCWpU8CJzqUkW7YEuEsx36S8cTNoLcuK1B
+ QmT3aY4avDcYXCWpU8CJzqUkW7YEuEsx36S8cTNoLcuK1B
+ QmT3aY4avDcYXCWpU8CJzqUkW7YEuEsx36S8cTNoLcuK1B
+ QmUGMu9epCEz5HMsuJFgpJxxt3HoahsTQcC65Jje6LNqYF
+ QmXhzoPKuqmkqbyr4kJFznFRXtGwriCXKGFPr4vviyK3aV
+ QmZ5wKCcL11TckypuDTKLLNFP6JMCBJRCn385XKQQ6PCLt
+ Qmdw3hiAxn6R5MRkkdzLdFvZUa2WJeLCTXXCyB8byFsHSA
+ QmedF4m2Y8341azfkpvaHSkxbSrZa4fo6FT25h6sRUVkpq
+ QmfWitW6F13WHFXLbJzXRYmwrS1p4gaAJAfucUSMytRPn3)
+
+ test_expect_success "feature on directory has no effect when not used [$1]" '
+ HASH=$(ipfs add -qr "$TESTDIR1") &&
+ test "$HASH_DIR1_NO_PRESERVE" = "$HASH"
+ '
+
+ test_expect_success "can preserve directory mode [$1]" '
+ HASH=$(ipfs add -qr --preserve-mode "$TESTDIR1") &&
+ test "$HASH_DIR1_PRESERVE_MODE" = "$HASH"
+ '
+
+ test_expect_success "can preserve directory modification time [$1]" '
+ HASH=$(ipfs add -qr --preserve-mtime "$TESTDIR1") &&
+ test "$HASH_DIR1_PRESERVE_MTIME" = "$HASH"
+ '
+
+ test_expect_success "can set directory mode [$1]" '
+ HASH=$(ipfs add -qr --mode=$CUSTOM_DIR_MODE "$TESTDIR1") &&
+ test "$HASH_DIR1_CUSTOM_MODE" = "$HASH"
+ '
+
+ test_expect_success "can set directory modification time [$1]" '
+ HASH=$(ipfs add -qr --mtime=$CUSTOM_MTIME "$TESTDIR1") &&
+ test "$HASH_DIR1_CUSTOM_MTIME" = "$HASH"
+ '
+
+ test_expect_success "can set directory modification time nanoseconds [$1]" '
+ HASH=$(ipfs add -qr --mtime=$CUSTOM_MTIME --mtime-nsecs=$CUSTOM_MTIME_NSECS "$TESTDIR1") &&
+ test "$HASH_DIR1_CUSTOM_MTIME_NSECS" = "$HASH"
+ '
+
+ test_expect_success "can recursively preserve mode and modification time [$1]" '
+ test "700:$DIR_TIME" = "$(stat -c "%a:%Y" "$TESTDIR")" &&
+ test "644:$((DIR_TIME+10))" = "$(stat -c "%a:%Y" "$TESTDIR/dir2/sub1/sub2/file3")" &&
+ test "777:$((DIR_TIME+20))" = "$(stat -c "%a:%Y" "$TESTDIR/dir2/sub1/link1")" &&
+ test "755:$((DIR_TIME+30))" = "$(stat -c "%a:%Y" "$TESTDIR/dir2/sub1/sub2")" &&
+ test "755:$((DIR_TIME+40))" = "$(stat -c "%a:%Y" "$TESTDIR/dir2/sub1")" &&
+ test "755:$((DIR_TIME+50))" = "$(stat -c "%a:%Y" "$TESTDIR/dir2")" &&
+ test "644:$((DIR_TIME+60))" = "$(stat -c "%a:%Y" "$TESTDIR/dir3/file2")" &&
+ test "755:$((DIR_TIME+70))" = "$(stat -c "%a:%Y" "$TESTDIR/dir3")" &&
+ test "644:$((DIR_TIME+80))" = "$(stat -c "%a:%Y" "$TESTDIR/file1")" &&
+ test "755:$((DIR_TIME+90))" = "$(stat -c "%a:%Y" "$TESTDIR/dir1")" &&
+ HASHES=($(ipfs add -qr --preserve-mode --preserve-mtime "$TESTDIR"|sort)) &&
+ test "${HASHES[*]}" = "${HASH_DIR_MODE_AND_MTIME[*]}"
+ '
+
+ test_expect_success "can recursively set directory mode [$1]" '
+ HASHES=($(ipfs add -qr --mode=0753 "$TESTDIR"|sort)) &&
+ test "${HASHES[*]}" = "${HASH_DIR_CUSTOM_MODE[*]}"
+ '
+
+ test_expect_success "can recursively set directory mtime [$1]" '
+ HASHES=($(ipfs add -qr --mtime=$CUSTOM_MTIME "$TESTDIR"|sort)) &&
+ test "${HASHES[*]}" = "${HASH_DIR_CUSTOM_MTIME[*]}"
+ '
+
+ test_expect_success "can recursively restore mode and mtime [$1]" '
+ ipfs get -o "$OUTDIR" $HASH_DIR_ROOT &&
+ test "700:$DIR_TIME" = "$(stat -c "%a:%Y" "$OUTDIR")" &&
+ test "644:$((DIR_TIME+10))" = "$(stat -c "%a:%Y" "$OUTDIR/dir2/sub1/sub2/file3")" &&
+ test "777:$((DIR_TIME+20))" = "$(stat -c "%a:%Y" "$OUTDIR/dir2/sub1/link1")" &&
+ test "755:$((DIR_TIME+30))" = "$(stat -c "%a:%Y" "$OUTDIR/dir2/sub1/sub2")" &&
+ test "755:$((DIR_TIME+40))" = "$(stat -c "%a:%Y" "$OUTDIR/dir2/sub1")" &&
+ test "755:$((DIR_TIME+50))" = "$(stat -c "%a:%Y" "$OUTDIR/dir2")" &&
+ test "644:$((DIR_TIME+60))" = "$(stat -c "%a:%Y" "$OUTDIR/dir3/file2")" &&
+ test "755:$((DIR_TIME+70))" = "$(stat -c "%a:%Y" "$OUTDIR/dir3")" &&
+ test "644:$((DIR_TIME+80))" = "$(stat -c "%a:%Y" "$OUTDIR/file1")" &&
+ test "755:$((DIR_TIME+90))" = "$(stat -c "%a:%Y" "$OUTDIR/dir1")"
+ '
+
+ # basic smoke-test for cidv1 (we dont care about CID, just care about
+ # mode/mtime surviving ipfs import and export if --cid-version 1 is at play)
+ test_expect_success "can recursively preserve and restore mode and mtime with CIDv1 [$1]" '
+ test "700:$DIR_TIME" = "$(stat -c "%a:%Y" "$TESTDIR")" &&
+ test "644:$((DIR_TIME+10))" = "$(stat -c "%a:%Y" "$TESTDIR/dir2/sub1/sub2/file3")" &&
+ test "777:$((DIR_TIME+20))" = "$(stat -c "%a:%Y" "$TESTDIR/dir2/sub1/link1")" &&
+ test "755:$((DIR_TIME+30))" = "$(stat -c "%a:%Y" "$TESTDIR/dir2/sub1/sub2")" &&
+ test "755:$((DIR_TIME+40))" = "$(stat -c "%a:%Y" "$TESTDIR/dir2/sub1")" &&
+ test "755:$((DIR_TIME+50))" = "$(stat -c "%a:%Y" "$TESTDIR/dir2")" &&
+ test "644:$((DIR_TIME+60))" = "$(stat -c "%a:%Y" "$TESTDIR/dir3/file2")" &&
+ test "755:$((DIR_TIME+70))" = "$(stat -c "%a:%Y" "$TESTDIR/dir3")" &&
+ test "644:$((DIR_TIME+80))" = "$(stat -c "%a:%Y" "$TESTDIR/file1")" &&
+ test "755:$((DIR_TIME+90))" = "$(stat -c "%a:%Y" "$TESTDIR/dir1")" &&
+ CIDV1DIR=$(ipfs add -Qr --preserve-mode --preserve-mtime --cid-version 1 "$TESTDIR") &&
+ OUTDIRV1=$(mk_dir cidv1roundtrip$1) &&
+ ipfs get -o "$OUTDIRV1" $CIDV1DIR &&
+ test "700:$DIR_TIME" = "$(stat -c "%a:%Y" "$OUTDIRV1")" &&
+ test "644:$((DIR_TIME+10))" = "$(stat -c "%a:%Y" "$OUTDIRV1/dir2/sub1/sub2/file3")" &&
+ test "777:$((DIR_TIME+20))" = "$(stat -c "%a:%Y" "$OUTDIRV1/dir2/sub1/link1")" &&
+ test "755:$((DIR_TIME+30))" = "$(stat -c "%a:%Y" "$OUTDIRV1/dir2/sub1/sub2")" &&
+ test "755:$((DIR_TIME+40))" = "$(stat -c "%a:%Y" "$OUTDIRV1/dir2/sub1")" &&
+ test "755:$((DIR_TIME+50))" = "$(stat -c "%a:%Y" "$OUTDIRV1/dir2")" &&
+ test "644:$((DIR_TIME+60))" = "$(stat -c "%a:%Y" "$OUTDIRV1/dir3/file2")" &&
+ test "755:$((DIR_TIME+70))" = "$(stat -c "%a:%Y" "$OUTDIRV1/dir3")" &&
+ test "644:$((DIR_TIME+80))" = "$(stat -c "%a:%Y" "$OUTDIRV1/file1")" &&
+ test "755:$((DIR_TIME+90))" = "$(stat -c "%a:%Y" "$OUTDIRV1/dir1")"
+ '
+
+ test_expect_success "can change directory mode [$1]" '
+ NAME=$(mk_name) &&
+ ipfs files cp "/ipfs/$HASH_DIR_SUB1" /$NAME &&
+ ipfs files chmod 0710 /$NAME &&
+ test $(ipfs files stat --format="" /$NAME) = "drwx--x---"
+ '
+
+ test_expect_success "can change directory modification time [$1]" '
+ NAME=$(mk_name) &&
+ ipfs files cp "/ipfs/$HASH_DIR_SUB1" /$NAME &&
+ ipfs files touch --mtime=$CUSTOM_MTIME /$NAME &&
+ test $(ipfs files stat --format="" /$NAME) -eq $CUSTOM_MTIME
+ '
+
+ test_expect_success "can change directory modification time nanoseconds [$1]" '
+ NAME=$(mk_name) &&
+ MTIME=$(date --date="yesterday" +%s) &&
+ ipfs files cp "/ipfs/$HASH_DIR_SUB1" /$NAME &&
+ ipfs files touch --mtime=$MTIME --mtime-nsecs=94783 /$NAME &&
+ test $(ipfs files stat --format="" /$NAME) -eq $MTIME &&
+ test $(ipfs files stat --format="" /$NAME) -eq 94783
+ '
+}
+
+test_stat_template() {
+ test_expect_success "can stat $2 string mode [$1]" '
+ touch "$STAT_TARGET" &&
+ HASH=$(ipfs add -qr --mode="$STAT_MODE_OCTAL" "$STAT_TARGET") &&
+ ACTUAL=$(ipfs files stat --format="" /ipfs/$HASH) &&
+ test "$ACTUAL" = "$STAT_MODE_STRING"
+ '
+ test_expect_success "can stat $2 octal mode [$1]" '
+ touch "$STAT_TARGET" &&
+ HASH=$(ipfs add -qr --mode="$STAT_MODE_OCTAL" "$STAT_TARGET") &&
+ ACTUAL=$(ipfs files stat --format="" /ipfs/$HASH) &&
+ test "$ACTUAL" = "$STAT_MODE_OCTAL"
+ '
+
+ test_expect_success "can stat $2 modification time string [$1]" '
+ touch "$STAT_TARGET" &&
+ HASH=$(ipfs add -qr --mtime=$CUSTOM_MTIME "$STAT_TARGET") &&
+ ACTUAL=$(ipfs files stat --format="" /ipfs/$HASH) &&
+ test "$ACTUAL" = "24 Oct 2020, 11:42:00 UTC"
+ '
+
+ test_expect_success "can stat $2 modification time seconds [$1]" '
+ touch "$STAT_TARGET" &&
+ HASH=$(ipfs add -qr --mtime=$CUSTOM_MTIME "$STAT_TARGET") &&
+ ACTUAL=$(ipfs files stat --format="" /ipfs/$HASH) &&
+ test $ACTUAL -eq $CUSTOM_MTIME
+ '
+
+ test_expect_success "can stat $2 modification time nanoseconds [$1]" '
+ touch "$STAT_TARGET" &&
+ HASH=$(ipfs add -qr --mtime=$CUSTOM_MTIME --mtime-nsecs=$CUSTOM_MTIME_NSECS "$STAT_TARGET") &&
+ ACTUAL=$(ipfs files stat --format="" /ipfs/$HASH) &&
+ test $ACTUAL -eq $CUSTOM_MTIME_NSECS
+ '
+}
+
+test_stat() {
+ STAT_TARGET="$FIXTURESDIR/statfile$1"
+ STAT_MODE_OCTAL="$CUSTOM_MODE"
+ STAT_MODE_STRING="-rwxrw-r--"
+ test_stat_template "$1" "file"
+
+ STAT_TARGET="$FIXTURESDIR/statdir$1"
+ STAT_MODE_OCTAL="0731"
+ STAT_MODE_STRING="drwx-wx--x"
+ mkdir "$STAT_TARGET"
+ test_stat_template "$1" "directory"
+
+ STAT_TARGET="$FIXTURESDIR/statlink$1"
+ STAT_MODE_OCTAL="0777"
+ STAT_MODE_STRING="lrwxrwxrwx"
+ ln -s nothing "$STAT_TARGET"
+ test_stat_template "$1" "link"
+
+
+ STAT_TARGET="$FIXTURESDIR/statfile$1"
+ test_expect_success "can chain stat template [$1]" '
+ HASH=$(ipfs add -q --mode=0644 --mtime=$CUSTOM_MTIME --mtime-nsecs=$CUSTOM_MTIME_NSECS "$STAT_TARGET") &&
+ ACTUAL=$(ipfs files stat --format=" " /ipfs/$HASH) &&
+ test "$ACTUAL" = "24 Oct 2020, 11:42:00 UTC 1603539720 54321 -rw-r--r-- 0644"
+ '
+}
+
+test_all() {
+test_stat "$1"
+test_file "$1"
+test_directory "$1"
+}
+
+# test direct
+test_all "direct"
+
+# test daemon
+test_launch_ipfs_daemon_without_network
+test_all "daemon"
+test_kill_ipfs_daemon
+
+test_done
diff --git a/test/sharness/t0051-object-data/testPut.pb b/test/sharness/t0050-block-data/testPut.pb
similarity index 100%
rename from test/sharness/t0051-object-data/testPut.pb
rename to test/sharness/t0050-block-data/testPut.pb
diff --git a/test/sharness/t0050-block.sh b/test/sharness/t0050-block.sh
index 9ecf2087596..05502adaf5e 100755
--- a/test/sharness/t0050-block.sh
+++ b/test/sharness/t0050-block.sh
@@ -42,12 +42,12 @@ test_expect_success "'ipfs block put' output looks good" '
'
test_expect_success "can set cid codec on block put" '
- CODEC_HASH=$(ipfs block put --cid-codec=dag-pb ../t0051-object-data/testPut.pb)
+ CODEC_HASH=$(ipfs block put --cid-codec=dag-pb ../t0050-block-data/testPut.pb)
'
test_expect_success "block get output looks right" '
ipfs block get $CODEC_HASH > pb_block_out &&
- test_cmp pb_block_out ../t0051-object-data/testPut.pb
+ test_cmp pb_block_out ../t0050-block-data/testPut.pb
'
#
@@ -210,33 +210,33 @@ test_expect_success "multi-block 'ipfs block rm -q' produces no output" '
# --format used 'protobuf' for 'dag-pb' which was invalid, but we keep
# for backward-compatibility
test_expect_success "can set deprecated --format=protobuf on block put" '
- HASH=$(ipfs block put --format=protobuf ../t0051-object-data/testPut.pb)
+ HASH=$(ipfs block put --format=protobuf ../t0050-block-data/testPut.pb)
'
test_expect_success "created an object correctly!" '
- ipfs object get $HASH > obj_out &&
- echo "{\"Links\":[],\"Data\":\"test json for sharness test\"}" > obj_exp &&
+ ipfs dag get $HASH > obj_out &&
+ echo -n "{\"Data\":{\"/\":{\"bytes\":\"dGVzdCBqc29uIGZvciBzaGFybmVzcyB0ZXN0\"}},\"Links\":[]}" > obj_exp &&
test_cmp obj_out obj_exp
'
test_expect_success "block get output looks right" '
ipfs block get $HASH > pb_block_out &&
- test_cmp pb_block_out ../t0051-object-data/testPut.pb
+ test_cmp pb_block_out ../t0050-block-data/testPut.pb
'
test_expect_success "can set --cid-codec=dag-pb on block put" '
- HASH=$(ipfs block put --cid-codec=dag-pb ../t0051-object-data/testPut.pb)
+ HASH=$(ipfs block put --cid-codec=dag-pb ../t0050-block-data/testPut.pb)
'
test_expect_success "created an object correctly!" '
- ipfs object get $HASH > obj_out &&
- echo "{\"Links\":[],\"Data\":\"test json for sharness test\"}" > obj_exp &&
+ ipfs dag get $HASH > obj_out &&
+ echo -n "{\"Data\":{\"/\":{\"bytes\":\"dGVzdCBqc29uIGZvciBzaGFybmVzcyB0ZXN0\"}},\"Links\":[]}" > obj_exp &&
test_cmp obj_out obj_exp
'
test_expect_success "block get output looks right" '
ipfs block get $HASH > pb_block_out &&
- test_cmp pb_block_out ../t0051-object-data/testPut.pb
+ test_cmp pb_block_out ../t0050-block-data/testPut.pb
'
test_expect_success "can set multihash type and length on block put with --format=raw (deprecated)" '
@@ -248,7 +248,7 @@ test_expect_success "output looks good" '
'
test_expect_success "can't use both legacy format and custom cid-codec at the same time" '
- test_expect_code 1 ipfs block put --format=dag-cbor --cid-codec=dag-json < ../t0051-object-data/testPut.pb 2> output &&
+ test_expect_code 1 ipfs block put --format=dag-cbor --cid-codec=dag-json < ../t0050-block-data/testPut.pb 2> output &&
test_should_contain "unable to use \"format\" (deprecated) and a custom \"cid-codec\" at the same time" output
'
diff --git a/test/sharness/t0051-object-data/UTF-8-test.txt b/test/sharness/t0051-object-data/UTF-8-test.txt
deleted file mode 100644
index 56213a84a98..00000000000
Binary files a/test/sharness/t0051-object-data/UTF-8-test.txt and /dev/null differ
diff --git a/test/sharness/t0051-object-data/brokenPut.json b/test/sharness/t0051-object-data/brokenPut.json
deleted file mode 100644
index 6ba2d6f3b62..00000000000
--- a/test/sharness/t0051-object-data/brokenPut.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "this": "should",
- "return": "an",
- "error":"not valid dag object"
-}
\ No newline at end of file
diff --git a/test/sharness/t0051-object-data/brokenPut.xml b/test/sharness/t0051-object-data/brokenPut.xml
deleted file mode 100644
index 331bbac9901..00000000000
--- a/test/sharness/t0051-object-data/brokenPut.xml
+++ /dev/null
@@ -1 +0,0 @@
-This is not a valid dag object fail
diff --git a/test/sharness/t0051-object-data/expected_getOut b/test/sharness/t0051-object-data/expected_getOut
deleted file mode 100644
index dc12f63ba14..00000000000
--- a/test/sharness/t0051-object-data/expected_getOut
+++ /dev/null
@@ -1 +0,0 @@
-{"Links":[],"Data":"\u0008\u0002\u0012\nHello Mars\u0018\n"}
diff --git a/test/sharness/t0051-object-data/mixed.json b/test/sharness/t0051-object-data/mixed.json
deleted file mode 100644
index b8de2b8d886..00000000000
--- a/test/sharness/t0051-object-data/mixed.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{"Data": "another",
- "Links": [
- {"Name": "some link", "Hash": "QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V", "Size": 8},
- {"Name": "inlined", "Hash": "z4CrgyEyhm4tAw1pgzQtNNuP7", "Size": 14}
-]}
diff --git a/test/sharness/t0051-object-data/testPut.json b/test/sharness/t0051-object-data/testPut.json
deleted file mode 100644
index c97f4ec0bf9..00000000000
--- a/test/sharness/t0051-object-data/testPut.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Data": "test json for sharness test"
-}
diff --git a/test/sharness/t0051-object-data/testPut.xml b/test/sharness/t0051-object-data/testPut.xml
deleted file mode 100644
index 5cc290b2709..00000000000
--- a/test/sharness/t0051-object-data/testPut.xml
+++ /dev/null
@@ -1 +0,0 @@
-Test xml for sharness test
diff --git a/test/sharness/t0051-object.sh b/test/sharness/t0051-object.sh
index 316c220abd5..4bac6137488 100755
--- a/test/sharness/t0051-object.sh
+++ b/test/sharness/t0051-object.sh
@@ -27,204 +27,21 @@ test_patch_create_path() {
}
test_object_cmd() {
-
- test_expect_success "'ipfs add testData' succeeds" '
- printf "Hello Mars" >expected_in &&
- ipfs add expected_in >actual_Addout
- '
-
- test_expect_success "'ipfs add testData' output looks good" '
- HASH="QmWkHFpYBZ9mpPRreRbMhhYWXfUhBAue3JkbbpFqwowSRb" &&
- echo "added $HASH expected_in" >expected_Addout &&
- test_cmp expected_Addout actual_Addout
- '
-
- test_expect_success "'ipfs object get' succeeds" '
- ipfs object get $HASH >actual_getOut
- '
-
- test_expect_success "'ipfs object get' output looks good" '
- test_cmp ../t0051-object-data/expected_getOut actual_getOut
- '
-
- test_expect_success "'ipfs object get' can specify data encoding as base64" '
- ipfs object get --data-encoding base64 $HASH > obj_out &&
- echo "{\"Links\":[],\"Data\":\"CAISCkhlbGxvIE1hcnMYCg==\"}" > obj_exp &&
- test_cmp obj_out obj_exp
- '
-
- test_expect_success "'ipfs object get' can specify data encoding as text" '
- echo "{\"Links\":[],\"Data\":\"Hello Mars\"}" | ipfs object put &&
- ipfs object get --data-encoding text QmS3hVY6eYrMQ6L22agwrx3YHBEsc3LJxVXCtyQHqRBukH > obj_out &&
- echo "{\"Links\":[],\"Data\":\"Hello Mars\"}" > obj_exp &&
- test_cmp obj_out obj_exp
- '
-
- test_expect_failure "'ipfs object get' requires known data encoding" '
- ipfs object get --data-encoding nonsensical-encoding $HASH
- '
-
- test_expect_success "'ipfs object stat' succeeds" '
- ipfs object stat $HASH >actual_stat
- '
-
- test_expect_success "'ipfs object get' output looks good" '
- echo "NumLinks: 0" > expected_stat &&
- echo "BlockSize: 18" >> expected_stat &&
- echo "LinksSize: 2" >> expected_stat &&
- echo "DataSize: 16" >> expected_stat &&
- echo "CumulativeSize: 18" >> expected_stat &&
- test_cmp expected_stat actual_stat
- '
-
- test_expect_success "'ipfs object put file.json' succeeds" '
- ipfs object put ../t0051-object-data/testPut.json > actual_putOut
- '
-
- test_expect_success "'ipfs object put file.json' output looks good" '
- HASH="QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD" &&
- printf "added $HASH\n" > expected_putOut &&
- test_cmp expected_putOut actual_putOut
- '
-
- test_expect_success "'ipfs object put --quiet file.json' succeeds" '
- ipfs object put --quiet ../t0051-object-data/testPut.json > actual_putOut
- '
-
- test_expect_success "'ipfs object put --quiet file.json' output looks good" '
- HASH="QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD" &&
- printf "$HASH\n" > expected_putOut &&
- test_cmp expected_putOut actual_putOut
- '
-
- test_expect_success "'ipfs object put file.xml' succeeds" '
- ipfs object put ../t0051-object-data/testPut.xml --inputenc=xml > actual_putOut
- '
-
- test_expect_success "'ipfs object put file.xml' output looks good" '
- HASH="QmQzNKUHy4HyEUGkqKe3q3t796ffPLQXYCkHCcXUNT5JNK" &&
- printf "added $HASH\n" > expected_putOut &&
- test_cmp expected_putOut actual_putOut
- '
-
- test_expect_success "'ipfs object put' from stdin succeeds" '
- cat ../t0051-object-data/testPut.xml | ipfs object put --inputenc=xml > actual_putStdinOut
- '
-
- test_expect_failure "'ipfs object put broken.xml' should fail" '
- test_expect_code 1 ipfs object put ../t0051-object-data/brokenPut.xml --inputenc=xml 2>actual_putBrokenErr >actual_putBroken
- '
-
- test_expect_failure "'ipfs object put broken.hxml' output looks good" '
- touch expected_putBroken &&
- printf "Error: no data or links in this node\n" > expected_putBrokenErr &&
- test_cmp expected_putBroken actual_putBroken &&
- test_cmp expected_putBrokenErr actual_putBrokenErr
- '
- test_expect_success "'ipfs object get --enc=xml' succeeds" '
- ipfs object get --enc=xml $HASH >utf8_xml
- '
-
- test_expect_success "'ipfs object put --inputenc=xml' succeeds" '
- ipfs object put --inputenc=xml actual
- '
-
- test_expect_failure "'ipfs object put --inputenc=xml' output looks good" '
- echo "added $HASH\n" >expected &&
- test_cmp expected actual
- '
-
- test_expect_success "'ipfs object put file.pb' succeeds" '
- ipfs object put --inputenc=protobuf ../t0051-object-data/testPut.pb > actual_putOut
- '
-
- test_expect_success "'ipfs object put file.pb' output looks good" '
- HASH="QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD" &&
- printf "added $HASH\n" > expected_putOut &&
- test_cmp expected_putOut actual_putOut
- '
-
- test_expect_success "'ipfs object put' from stdin succeeds" '
- cat ../t0051-object-data/testPut.json | ipfs object put > actual_putStdinOut
- '
-
- test_expect_success "'ipfs object put' from stdin output looks good" '
- HASH="QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD" &&
- printf "added $HASH\n" > expected_putStdinOut &&
- test_cmp expected_putStdinOut actual_putStdinOut
- '
-
- test_expect_success "'ipfs object put' from stdin (pb) succeeds" '
- cat ../t0051-object-data/testPut.pb | ipfs object put --inputenc=protobuf > actual_putPbStdinOut
- '
-
- test_expect_success "'ipfs object put' from stdin (pb) output looks good" '
- HASH="QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD" &&
- printf "added $HASH\n" > expected_putStdinOut &&
- test_cmp expected_putStdinOut actual_putPbStdinOut
- '
-
- test_expect_success "'ipfs object put broken.json' should fail" '
- test_expect_code 1 ipfs object put ../t0051-object-data/brokenPut.json 2>actual_putBrokenErr >actual_putBroken
- '
-
- test_expect_success "'ipfs object put broken.hjson' output looks good" '
- touch expected_putBroken &&
- printf "Error: json: unknown field \"this\"\n" > expected_putBrokenErr &&
- test_cmp expected_putBroken actual_putBroken &&
- test_cmp expected_putBrokenErr actual_putBrokenErr
- '
-
- test_expect_success "setup: add UTF-8 test file" '
- HASH="QmNY5sQeH9ttVCg24sizH71dNbcZTpGd7Yb3YwsKZ4jiFP" &&
- ipfs add ../t0051-object-data/UTF-8-test.txt >actual &&
- echo "added $HASH UTF-8-test.txt" >expected &&
- test_cmp expected actual
- '
-
- test_expect_success "'ipfs object get --enc=json' succeeds" '
- ipfs object get --enc=json $HASH >utf8_json
- '
-
- test_expect_success "'ipfs object put --inputenc=json' succeeds" '
- ipfs object put --inputenc=json actual
- '
-
- test_expect_failure "'ipfs object put --inputenc=json' output looks good" '
- echo "added $HASH" >expected &&
- test_cmp expected actual
- '
-
- test_expect_success "'ipfs object put --pin' succeeds" '
- HASH="QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V" &&
- echo "added $HASH" >expected &&
- echo "{ \"Data\": \"abc\" }" | ipfs object put --pin >actual
- '
-
- test_expect_success "'ipfs object put --pin' output looks good" '
- echo "added $HASH" >expected &&
- test_cmp expected actual
- '
-
- test_expect_success "after gc, objects still accessible" '
- ipfs repo gc > /dev/null &&
- ipfs refs -r --timeout=2s $HASH > /dev/null
- '
+ EMPTY_DIR=$(echo '{"Links":[]}' | ipfs dag put --store-codec dag-pb)
+ EMPTY_UNIXFS_DIR=$(echo '{"Data":{"/":{"bytes":"CAE"}},"Links":[]}' | ipfs dag put --store-codec dag-pb)
test_expect_success "'ipfs object patch' should work (no unixfs-dir)" '
- EMPTY_DIR=$(ipfs object new) &&
OUTPUT=$(ipfs object patch $EMPTY_DIR add-link foo $EMPTY_DIR) &&
- ipfs object stat $OUTPUT
+ ipfs dag stat $OUTPUT
'
test_expect_success "'ipfs object patch' should work" '
- EMPTY_DIR=$(ipfs object new unixfs-dir) &&
- OUTPUT=$(ipfs object patch $EMPTY_DIR add-link foo $EMPTY_DIR) &&
- ipfs object stat $OUTPUT
+ OUTPUT=$(ipfs object patch $EMPTY_UNIXFS_DIR add-link foo $EMPTY_UNIXFS_DIR) &&
+ ipfs dag stat $OUTPUT
'
test_expect_success "'ipfs object patch' check output block size" '
- DIR=$(ipfs object new unixfs-dir)
+ DIR=$EMPTY_UNIXFS_DIR
for i in {1..13}
do
DIR=$(ipfs object patch "$DIR" add-link "$DIR.jpg" "$DIR")
@@ -241,32 +58,20 @@ test_object_cmd() {
test_expect_code 0 ipfs object patch --allow-big-block=true "$DIR" add-link "$DIR.jpg" "$DIR"
'
- test_expect_success "'ipfs object new foo' shouldn't crash" '
- test_expect_code 1 ipfs object new foo
- '
-
- test_expect_success "'ipfs object links' gives the correct results" '
- echo "$EMPTY_DIR" 4 foo > expected &&
- ipfs object links "$OUTPUT" > actual &&
- test_cmp expected actual
- '
-
test_expect_success "'ipfs object patch add-link' should work with paths" '
- EMPTY_DIR=$(ipfs object new unixfs-dir) &&
- N1=$(ipfs object patch $EMPTY_DIR add-link baz $EMPTY_DIR) &&
- N2=$(ipfs object patch $EMPTY_DIR add-link bar $N1) &&
- N3=$(ipfs object patch $EMPTY_DIR add-link foo /ipfs/$N2/bar) &&
- ipfs object stat /ipfs/$N3 > /dev/null &&
- ipfs object stat $N3/foo > /dev/null &&
- ipfs object stat /ipfs/$N3/foo/baz > /dev/null
+ N1=$(ipfs object patch $EMPTY_UNIXFS_DIR add-link baz $EMPTY_UNIXFS_DIR) &&
+ N2=$(ipfs object patch $EMPTY_UNIXFS_DIR add-link bar $N1) &&
+ N3=$(ipfs object patch $EMPTY_UNIXFS_DIR add-link foo /ipfs/$N2/bar) &&
+ ipfs dag stat /ipfs/$N3 > /dev/null &&
+ ipfs dag stat $N3/foo > /dev/null &&
+ ipfs dag stat /ipfs/$N3/foo/baz > /dev/null
'
test_expect_success "'ipfs object patch add-link' allow linking IPLD objects" '
- EMPTY_DIR=$(ipfs object new unixfs-dir) &&
OBJ=$(echo "123" | ipfs dag put) &&
- N1=$(ipfs object patch $EMPTY_DIR add-link foo $OBJ) &&
+ N1=$(ipfs object patch $EMPTY_UNIXFS_DIR add-link foo $OBJ) &&
- ipfs object stat /ipfs/$N1 > /dev/null &&
+ ipfs dag stat /ipfs/$N1 > /dev/null &&
ipfs resolve /ipfs/$N1/foo > actual &&
echo /ipfs/$OBJ > expected &&
@@ -274,7 +79,7 @@ test_object_cmd() {
'
test_expect_success "object patch creation looks right" '
- echo "QmPc73aWK9dgFBXe86P4PvQizHo9e5Qt7n7DAMXWuigFuG" > hash_exp &&
+ echo "bafybeiakusqwohnt7bs75kx6jhmt4oi47l634bmudxfv4qxhpco6xuvgna" > hash_exp &&
echo $N3 > hash_actual &&
test_cmp hash_exp hash_actual
'
@@ -282,7 +87,7 @@ test_object_cmd() {
test_expect_success "multilayer ipfs patch works" '
echo "hello world" > hwfile &&
FILE=$(ipfs add -q hwfile) &&
- EMPTY=$(ipfs object new unixfs-dir) &&
+ EMPTY=$EMPTY_UNIXFS_DIR &&
ONE=$(ipfs object patch $EMPTY add-link b $EMPTY) &&
TWO=$(ipfs object patch $EMPTY add-link a $ONE) &&
ipfs object patch $TWO add-link a/b/c $FILE > multi_patch
@@ -293,49 +98,12 @@ test_object_cmd() {
test_cmp hwfile hwfile_out
'
- test_expect_success "ipfs object stat path succeeds" '
- ipfs object stat $(cat multi_patch)/a > obj_stat_out
- '
-
- test_expect_success "ipfs object stat output looks good" '
- echo "NumLinks: 1" > obj_stat_exp &&
- echo "BlockSize: 47" >> obj_stat_exp &&
- echo "LinksSize: 45" >> obj_stat_exp &&
- echo "DataSize: 2" >> obj_stat_exp &&
- echo "CumulativeSize: 114" >> obj_stat_exp &&
-
- test_cmp obj_stat_exp obj_stat_out
- '
-
- test_expect_success "'ipfs object stat --human' succeeds" '
- ipfs object stat $(cat multi_patch)/a --human > obj_stat_human_out
- '
-
- test_expect_success "ipfs object stat --human output looks good" '
- echo "NumLinks: 1" > obj_stat_human_exp &&
- echo "BlockSize: 47" >> obj_stat_human_exp &&
- echo "LinksSize: 45" >> obj_stat_human_exp &&
- echo "DataSize: 2" >> obj_stat_human_exp &&
- echo "CumulativeSize: 114 B" >> obj_stat_human_exp &&
-
- test_cmp obj_stat_human_exp obj_stat_human_out
- '
-
- test_expect_success "should have created dir within a dir" '
- ipfs ls $OUTPUT > patched_output
- '
-
- test_expect_success "output looks good" '
- echo "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn - foo/" > patched_exp &&
- test_cmp patched_exp patched_output
- '
-
test_expect_success "can remove the directory" '
ipfs object patch $OUTPUT rm-link foo > rmlink_output
'
test_expect_success "output should be empty" '
- echo QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn > rmlink_exp &&
+ echo bafybeiczsscdsbs7ffqz55asqdf3smv6klcw3gofszvwlyarci47bgf354 > rmlink_exp &&
test_cmp rmlink_exp rmlink_output
'
@@ -344,7 +112,7 @@ test_object_cmd() {
'
test_expect_success "output looks good" '
- echo "QmZD3r9cZjzU8huNY2JS9TC6n8daDfT8TmE8zBSqG31Wvq" > multi_link_rm_exp &&
+ echo "bafybeicourxysmtbe5hacxqico4d5hyvh7gqkrwlmqa4ew7zufn3pj3juu" > multi_link_rm_exp &&
test_cmp multi_link_rm_exp multi_link_rm_out
'
@@ -355,7 +123,7 @@ test_object_cmd() {
test_patch_create_path $EMPTY a/b/b/b/b $FILE
test_expect_success "can create blank object" '
- BLANK=$(ipfs object new)
+ BLANK=$EMPTY_DIR
'
test_patch_create_path $BLANK a $FILE
@@ -363,98 +131,6 @@ test_object_cmd() {
test_expect_success "create bad path fails" '
test_must_fail ipfs object patch $EMPTY add-link --create / $FILE
'
-
- test_expect_success "patch set-data works" '
- EMPTY=$(ipfs object new) &&
- HASH=$(printf "foo" | ipfs object patch $EMPTY set-data)
- '
-
- test_expect_success "output looks good" '
- echo "{\"Links\":[],\"Data\":\"foo\"}" > exp_data_set &&
- ipfs object get $HASH > actual_data_set &&
- test_cmp exp_data_set actual_data_set
- '
-
- test_expect_success "patch append-data works" '
- HASH=$(printf "bar" | ipfs object patch $HASH append-data)
- '
-
- test_expect_success "output looks good" '
- echo "{\"Links\":[],\"Data\":\"foobar\"}" > exp_data_append &&
- ipfs object get $HASH > actual_data_append &&
- test_cmp exp_data_append actual_data_append
- '
-
- #
- # CidBase Tests
- #
-
- test_expect_success "'ipfs object put file.json --cid-base=base32' succeeds" '
- ipfs object put --cid-base=base32 ../t0051-object-data/testPut.json > actual_putOut
- '
-
- test_expect_success "'ipfs object put file.json --cid-base=base32' output looks good" '
- HASH="QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD" &&
- printf "added $HASH\n" > expected_putOut &&
- test_cmp expected_putOut actual_putOut
- '
-
- test_expect_success "'ipfs object put file.json --cid-base=base32 --upgrade-cidv0-in-output=true' succeeds" '
- ipfs object put --cid-base=base32 --upgrade-cidv0-in-output=true ../t0051-object-data/testPut.json > actual_putOut
- '
-
- test_expect_success "'ipfs object put file.json --cid-base=base32 --upgrade-cidv0-in-output=true' output looks good" '
- HASH=$(ipfs cid base32 "QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD") &&
- printf "added $HASH\n" > expected_putOut &&
- test_cmp expected_putOut actual_putOut
- '
-
- test_expect_success "'insert json dag with both CidV0 and CidV1 links'" '
- MIXED=$(ipfs object put ../t0051-object-data/mixed.json -q) &&
- echo $MIXED
- '
-
- test_expect_success "ipfs object get then put creates identical object with --cid-base=base32" '
- ipfs object get --cid-base=base32 $MIXED > mixedv2.json &&
- MIXED2=$(ipfs object put -q mixedv2.json) &&
- echo "$MIXED =? $MIXED2" &&
- test "$MIXED" = "$MIXED2"
- '
-
- HASHv0=QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V
- HASHv1=bafkqadsimvwgy3zajb2w2yloeefau
-
- test_expect_success "ipfs object get with --cid-base=base32 uses base32 for CidV1 link only" '
- ipfs object get --cid-base=base32 $MIXED > mixed.actual &&
- grep -q $HASHv0 mixed.actual &&
- grep -q $(ipfs cid base32 $HASHv1) mixed.actual
- '
-
- test_expect_success "ipfs object links --cid-base=base32 --upgrade-cidv0-in-output=true converts both links" '
- ipfs object links --cid-base=base32 --upgrade-cidv0-in-output=true $MIXED | awk "{print \$1}" | sort > links.actual &&
- echo $(ipfs cid base32 $HASHv1) > links.expected
- echo $(ipfs cid base32 $HASHv0) >> links.expected
- test_cmp links.actual links.expected
- '
-}
-
-test_object_content_type() {
-
- test_expect_success "'ipfs object get --encoding=protobuf' returns the correct content type" '
- curl -X POST -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=protobuf" | grep -q "^Content-Type: application/protobuf"
- '
-
- test_expect_success "'ipfs object get --encoding=json' returns the correct content type" '
- curl -X POST -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=json" | grep -q "^Content-Type: application/json"
- '
-
- test_expect_success "'ipfs object get --encoding=text' returns the correct content type" '
- curl -X POST -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=text" | grep -q "^Content-Type: text/plain"
- '
-
- test_expect_success "'ipfs object get --encoding=xml' returns the correct content type" '
- curl -X POST -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=xml" | grep -q "^Content-Type: application/xml"
- '
}
# should work offline
@@ -463,7 +139,6 @@ test_object_cmd
# should work online
test_launch_ipfs_daemon
test_object_cmd
-test_object_content_type
test_kill_ipfs_daemon
test_done
diff --git a/test/sharness/t0060-daemon.sh b/test/sharness/t0060-daemon.sh
index 29474c7ffd0..5dbbd852feb 100755
--- a/test/sharness/t0060-daemon.sh
+++ b/test/sharness/t0060-daemon.sh
@@ -8,8 +8,8 @@ test_description="Test daemon command"
. lib/test-lib.sh
-test_expect_success "create badger config" '
- ipfs init --profile=badgerds,test > /dev/null &&
+test_expect_success "create pebble config" '
+ ipfs init --profile=pebbleds,test > /dev/null &&
cp "$IPFS_PATH/config" init-config
'
@@ -21,8 +21,8 @@ test_launch_ipfs_daemon --init --init-config="$(pwd)/init-config" --init-profile
test_kill_ipfs_daemon
test_expect_success "daemon initialization with existing config works" '
- ipfs config "Datastore.Spec.child.path" >actual &&
- test $(cat actual) = "badgerds" &&
+ ipfs config "Datastore.Spec.path" >actual &&
+ test $(cat actual) = "pebbleds" &&
ipfs config Addresses > orig_addrs
'
@@ -76,17 +76,16 @@ test_expect_success "ipfs gateway works with the correct allowed origin port" '
curl -s -X POST -H "Origin:http://localhost:$GWAY_PORT" -I "http://$GWAY_ADDR/api/v0/version"
'
-test_expect_success "ipfs daemon output looks good" '
- STARTFILE="ipfs cat /ipfs/$HASH_WELCOME_DOCS/readme" &&
- echo "Initializing daemon..." >expected_daemon &&
- ipfs version --all >> expected_daemon &&
- sed "s/^/Swarm listening on /" listen_addrs >>expected_daemon &&
- sed "s/^/Swarm announcing /" local_addrs >>expected_daemon &&
- echo "RPC API server listening on '$API_MADDR'" >>expected_daemon &&
- echo "WebUI: http://'$API_ADDR'/webui" >>expected_daemon &&
- echo "Gateway server listening on '$GWAY_MADDR'" >>expected_daemon &&
- echo "Daemon is ready" >>expected_daemon &&
- test_cmp expected_daemon actual_daemon
+test_expect_success "ipfs daemon output includes looks good" '
+ test_should_contain "Initializing daemon..." actual_daemon &&
+ test_should_contain "$(ipfs version --all)" actual_daemon &&
+ test_should_contain "PeerID: $(ipfs config Identity.PeerID)" actual_daemon &&
+ test_should_contain "Swarm listening on 127.0.0.1:" actual_daemon &&
+ test_should_contain "RPC API server listening on '$API_MADDR'" actual_daemon &&
+ test_should_contain "WebUI: http://'$API_ADDR'/webui" actual_daemon &&
+ test_should_contain "Gateway server listening on '$GWAY_MADDR'" actual_daemon &&
+ test_should_contain "Daemon is ready" actual_daemon &&
+ cat actual_daemon
'
test_expect_success ".ipfs/ has been created" '
@@ -132,21 +131,21 @@ test_expect_success "ipfs help output looks good" '
# check transport is encrypted by default and no plaintext is allowed
test_expect_success SOCAT "default transport should support encryption (TLS, needs socat )" '
- socat - tcp:localhost:$SWARM_PORT,connect-timeout=1 > swarmnc < ../t0060-data/mss-tls &&
+ socat -s - tcp:localhost:$SWARM_PORT,connect-timeout=1 > swarmnc < ../t0060-data/mss-tls &&
grep -q "/tls" swarmnc &&
test_must_fail grep -q "na" swarmnc ||
test_fsh cat swarmnc
'
test_expect_success SOCAT "default transport should support encryption (Noise, needs socat )" '
- socat - tcp:localhost:$SWARM_PORT,connect-timeout=1 > swarmnc < ../t0060-data/mss-noise &&
+ socat -s - tcp:localhost:$SWARM_PORT,connect-timeout=1 > swarmnc < ../t0060-data/mss-noise &&
grep -q "/noise" swarmnc &&
test_must_fail grep -q "na" swarmnc ||
test_fsh cat swarmnc
'
test_expect_success SOCAT "default transport should not support plaintext (needs socat )" '
- socat - tcp:localhost:$SWARM_PORT,connect-timeout=1 > swarmnc < ../t0060-data/mss-plaintext &&
+ socat -s - tcp:localhost:$SWARM_PORT,connect-timeout=1 > swarmnc < ../t0060-data/mss-plaintext &&
grep -q "na" swarmnc &&
test_must_fail grep -q "/plaintext" swarmnc ||
test_fsh cat swarmnc
diff --git a/test/sharness/t0061-daemon-opts.sh b/test/sharness/t0061-daemon-opts.sh
index 531d2d247a5..a168ae4b068 100755
--- a/test/sharness/t0061-daemon-opts.sh
+++ b/test/sharness/t0061-daemon-opts.sh
@@ -18,7 +18,7 @@ apiaddr=$API_ADDR
# Odd. this fails here, but the inverse works on t0060-daemon.
test_expect_success SOCAT 'transport should be unencrypted ( needs socat )' '
- socat - tcp:localhost:$SWARM_PORT,connect-timeout=1 > swarmnc < ../t0060-data/mss-plaintext &&
+ socat -s - tcp:localhost:$SWARM_PORT,connect-timeout=1 > swarmnc < ../t0060-data/mss-plaintext &&
grep -q "/plaintext" swarmnc &&
test_must_fail grep -q "na" swarmnc ||
test_fsh cat swarmnc
diff --git a/test/sharness/t0070-user-config.sh b/test/sharness/t0070-user-config.sh
index 63c26ea3afb..5a8180c7317 100755
--- a/test/sharness/t0070-user-config.sh
+++ b/test/sharness/t0070-user-config.sh
@@ -11,10 +11,12 @@ test_description="Test user-provided config values"
test_init_ipfs
test_expect_success "bootstrap doesn't overwrite user-provided config keys (top-level)" '
- ipfs config Foo.Bar baz &&
+ ipfs config Identity.PeerID >previous &&
+ ipfs config Identity.PeerID foo &&
ipfs bootstrap rm --all &&
- echo "baz" >expected &&
- ipfs config Foo.Bar >actual &&
+ echo "foo" >expected &&
+ ipfs config Identity.PeerID >actual &&
+ ipfs config Identity.PeerID $(cat previous) &&
test_cmp expected actual
'
diff --git a/test/sharness/t0080-repo.sh b/test/sharness/t0080-repo.sh
index 3f33a5f440b..5031af830d4 100755
--- a/test/sharness/t0080-repo.sh
+++ b/test/sharness/t0080-repo.sh
@@ -49,7 +49,7 @@ test_expect_success "'ipfs pin rm' output looks good" '
test_expect_success "ipfs repo gc fully reverse ipfs add (part 1)" '
ipfs repo gc &&
- random 100000 41 >gcfile &&
+ random-data -size=100000 -seed=41 >gcfile &&
find "$IPFS_PATH/blocks" -type f -name "*.data" | sort -u > expected_blocks &&
hash=$(ipfs add -q gcfile) &&
ipfs pin rm -r $hash &&
@@ -142,7 +142,7 @@ test_expect_success "'ipfs refs local' no longer shows file" '
'
test_expect_success "adding multiblock random file succeeds" '
- random 1000000 >multiblock &&
+ random-data -size=1000000 >multiblock &&
MBLOCKHASH=`ipfs add -q multiblock`
'
diff --git a/test/sharness/t0081-repo-pinning.sh b/test/sharness/t0081-repo-pinning.sh
index 030f3fa3d06..92cb71c3858 100755
--- a/test/sharness/t0081-repo-pinning.sh
+++ b/test/sharness/t0081-repo-pinning.sh
@@ -114,8 +114,8 @@ test_expect_success "objects are there" '
'
# saving this output for later
-test_expect_success "ipfs object links $HASH_DIR1 works" '
- ipfs object links $HASH_DIR1 > DIR1_objlink
+test_expect_success "ipfs dag get $HASH_DIR1 works" '
+ ipfs dag get $HASH_DIR1 | jq -r ".Links[] | .Hash | .[\"/\"]" > DIR1_objlink
'
@@ -224,7 +224,7 @@ test_expect_success "some objects are still there" '
ipfs cat "$HASH_FILE1" >>actual8 &&
ipfs ls "$HASH_DIR4" >>actual8 &&
ipfs ls "$HASH_DIR2" >>actual8 &&
- ipfs object links "$HASH_DIR1" >>actual8 &&
+ ipfs dag get "$HASH_DIR1" | jq -r ".Links[] | .Hash | .[\"/\"]" >>actual8 &&
test_cmp expected8 actual8
'
diff --git a/test/sharness/t0082-repo-gc-auto.sh b/test/sharness/t0082-repo-gc-auto.sh
index 50a4e6fae7f..4d45595342c 100755
--- a/test/sharness/t0082-repo-gc-auto.sh
+++ b/test/sharness/t0082-repo-gc-auto.sh
@@ -17,10 +17,10 @@ check_ipfs_storage() {
test_init_ipfs
-test_expect_success "generate 2 600 kB files and 2 MB file using go-random" '
- random 600k 41 >600k1 &&
- random 600k 42 >600k2 &&
- random 2M 43 >2M
+test_expect_success "generate 2 600 kB files and 2 MB file using random-data" '
+ random-data -size=614400 -seed=41 >600k1 &&
+ random-data -size=614400 -seed=42 >600k2 &&
+ random-data -size=2097152 -seed=43 >2M
'
test_expect_success "set ipfs gc watermark, storage max, and gc timeout" '
diff --git a/test/sharness/t0087-repo-robust-gc.sh b/test/sharness/t0087-repo-robust-gc.sh
index 884de5774e0..453e6a6cce1 100755
--- a/test/sharness/t0087-repo-robust-gc.sh
+++ b/test/sharness/t0087-repo-robust-gc.sh
@@ -16,7 +16,7 @@ to_raw_cid() {
test_gc_robust_part1() {
test_expect_success "add a 1MB file with --raw-leaves" '
- random 1048576 56 > afile &&
+ random-data -size=1048576 -seed=56 > afile &&
HASH1=`ipfs add --raw-leaves -q --cid-version 1 afile` &&
REFS=`ipfs refs -r $HASH1` &&
read LEAF1 LEAF2 LEAF3 LEAF4 < <(echo $REFS)
@@ -96,20 +96,20 @@ test_gc_robust_part1() {
test_gc_robust_part2() {
test_expect_success "add 1MB file normally (i.e., without raw leaves)" '
- random 1048576 56 > afile &&
+ random-data -size=1048576 -seed=56 > afile &&
HASH2=`ipfs add -q afile`
'
- LEAF1=QmSijovevteoY63Uj1uC5b8pkpDU5Jgyk2dYBqz3sMJUPc
- LEAF1FILE=.ipfs/blocks/ME/CIQECF2K344QITW5S6E6H6T4DOXDDB2XA2V7BBOCIMN2VVF4Q77SMEY.data
+ LEAF1=QmcNNR6JSCUhJ9nyoVQgBhABPgcgdsuYJgdSB1f2g6BF5c
+ LEAF1FILE=.ipfs/blocks/RA/CIQNA5C3BLRUX3LZ7X6UTOV3KSHLARNXVDK3W5KUO6GVHNRP4SGLRAY.data
- LEAF2=QmTbPEyrA1JyGUHFvmtx1FNZVzdBreMv8Hc8jV9sBRWhNA
- LEAF2FILE=.ipfs/blocks/WM/CIQE4EFIJN2SUTQYSKMKNG7VM75W3SXT6LWJCHJJ73UAWN73WCX3WMY.data
+ LEAF2=QmPvtiBLgwuwF2wyf9VL8PaYgSt1XwGJ2Yu4AscRGEQvqR
+ LEAF2FILE=.ipfs/blocks/RN/CIQBPIKEATBI7TIHVYRQJZAKEWF2H22PXW3A7LCEPB6MFFL7IA2CRNA.data
test_expect_success "add some additional unpinned content" '
- random 1000 3 > junk1 &&
- random 1000 4 > junk2 &&
+ random-data -size=1000 -seed=3 > junk1 &&
+ random-data -size=1000 -seed=4 > junk2 &&
JUNK1=`ipfs add --pin=false -q junk1` &&
JUNK2=`ipfs add --pin=false -q junk2`
'
diff --git a/test/sharness/t0090-get.sh b/test/sharness/t0090-get.sh
index 67fee89093a..6a803080e85 100755
--- a/test/sharness/t0090-get.sh
+++ b/test/sharness/t0090-get.sh
@@ -157,13 +157,13 @@ test_get_cmd() {
test_get_fail() {
test_expect_success "create an object that has unresolvable links" '
cat <<-\EOF >bad_object &&
-{ "Links": [ { "Name": "foo", "Hash": "QmZzaC6ydNXiR65W8VjGA73ET9MZ6VFAqUT1ngYMXcpihn", "Size": 1897 }, { "Name": "bar", "Hash": "Qmd4mG6pDFDmDTn6p3hX1srP8qTbkyXKj5yjpEsiHDX3u8", "Size": 56 }, { "Name": "baz", "Hash": "QmUTjwRnG28dSrFFVTYgbr6LiDLsBmRr2SaUSTGheK2YqG", "Size": 24266 } ], "Data": "\b\u0001" }
+{"Data":{"/":{"bytes":"CAE"}},"Links":[{"Hash":{"/":"Qmd4mG6pDFDmDTn6p3hX1srP8qTbkyXKj5yjpEsiHDX3u8"},"Name":"bar","Tsize":56},{"Hash":{"/":"QmUTjwRnG28dSrFFVTYgbr6LiDLsBmRr2SaUSTGheK2YqG"},"Name":"baz","Tsize":24266},{"Hash":{"/":"QmZzaC6ydNXiR65W8VjGA73ET9MZ6VFAqUT1ngYMXcpihn"},"Name":"foo","Tsize":1897}]}
EOF
- cat bad_object | ipfs object put > put_out
+ cat bad_object | ipfs dag put --store-codec dag-pb > put_out
'
test_expect_success "output looks good" '
- echo "added QmaGidyrnX8FMbWJoxp8HVwZ1uRKwCyxBJzABnR1S2FVUr" > put_exp &&
+ echo "bafybeifrjjol3gixedca6etdwccnvwfvhurc4wb3i5mnk2rvwvyfcgwxd4" > put_exp &&
test_cmp put_exp put_out
'
diff --git a/test/sharness/t0112-gateway-cors.sh b/test/sharness/t0112-gateway-cors.sh
index 37027c188a4..90813ad6a21 100755
--- a/test/sharness/t0112-gateway-cors.sh
+++ b/test/sharness/t0112-gateway-cors.sh
@@ -127,70 +127,6 @@ test_expect_success "Access-Control-Allow-Origin replaces the implicit list" '
test_should_contain "< Access-Control-Allow-Origin: localhost" curl_output
'
-# Read-Only /api/v0 RPC API (legacy subset, exposed on the Gateway Port)
-# TODO: we want to remove it, but for now this guards the legacy behavior to not go any further
-
-# also check this, as due to legacy reasons Kubo exposes small subset of /api/v0 on GW port
-test_expect_success "Assert the default API.HTTPHeaders config is empty" '
- echo "{}" > expected &&
- ipfs config --json API.HTTPHeaders > actual &&
- test_cmp expected actual
-'
-
-# HTTP GET Request
-test_expect_success "Default CORS GET to {gw}/api/v0" '
- curl -svX GET -H "Origin: https://example.com" "http://127.0.0.1:$GWAY_PORT/api/v0/cat?arg=$thash" >/dev/null 2>curl_output
-'
-# HTTP 403 is returned because Kubo has additional protections on top of regular CORS,
-# namely it only allows browser requests with localhost Origin header.
-test_expect_success "Default CORS GET response from {gw}/api/v0 is 403 Forbidden and has regular CORS headers" '
- test_should_contain "HTTP/1.1 403 Forbidden" curl_output &&
- test_should_contain "< Access-Control-" curl_output
-'
-
-# HTTP OPTIONS Request
-test_expect_success "Default OPTIONS to {gw}/api/v0" '
- curl -svX OPTIONS -H "Origin: https://example.com" "http://127.0.0.1:$GWAY_PORT/api/v0/cat?arg=$thash" 2>curl_output
-'
-# OPTIONS Response from the API should NOT contain CORS headers
-test_expect_success "OPTIONS response from {gw}/api/v0 has CORS headers" '
- test_should_contain "< Access-Control-" curl_output
-'
-
-test_kill_ipfs_daemon
-
-# TODO: /api/v0 with CORS headers set in API.HTTPHeaders does not really work,
-# as not all headers are correctly set. Below is only a basic regression test that documents
-# current state. Fixing CORS on /api/v0 (RPC and Gateway port) is tracked in https://github.com/ipfs/kubo/issues/7667
-
-test_expect_success "Manually set API.HTTPHeaders config to be as relaxed as Gateway.HTTPHeaders" "
- ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '[\"https://example.com\"]'
-"
-# TODO: ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '[\"GET\",\"POST\"]' &&
-# TODO: ipfs config --json API.HTTPHeaders.Access-Control-Allow-Headers '[\"X-Requested-With\", \"Range\", \"User-Agent\"]'
-
-test_launch_ipfs_daemon
-
-# HTTP GET Request
-test_expect_success "Manually relaxed CORS GET to {gw}/api/v0" '
- curl -svX GET -H "Origin: https://example.com" "http://127.0.0.1:$GWAY_PORT/api/v0/cat?arg=$thash" >/dev/null 2>curl_output
-'
-test_expect_success "Manually relaxed CORS GET response from {gw}/api/v0 is the same as Gateway" '
- test_should_contain "HTTP/1.1 200 OK" curl_output &&
- test_should_contain "< Access-Control-Allow-Origin: https://example.com" curl_output
-'
-# TODO: test_should_contain "< Access-Control-Allow-Methods: GET" curl_output
-
-# HTTP OPTIONS Request
-test_expect_success "Manually relaxed OPTIONS to {gw}/api/v0" '
- curl -svX OPTIONS -H "Origin: https://example.com" "http://127.0.0.1:$GWAY_PORT/api/v0/cat?arg=$thash" 2>curl_output
-'
-# OPTIONS Response from the API should NOT contain CORS headers
-test_expect_success "Manually relaxed OPTIONS response from {gw}/api/v0 is the same as Gateway" '
- test_should_contain "< Access-Control-Allow-Origin: https://example.com" curl_output
-'
-# TODO: test_should_contain "< Access-Control-Allow-Methods: GET" curl_output
-
test_kill_ipfs_daemon
test_done
diff --git a/test/sharness/t0114-gateway-subdomains.sh b/test/sharness/t0114-gateway-subdomains.sh
index 2596bb49254..7d18ab26564 100755
--- a/test/sharness/t0114-gateway-subdomains.sh
+++ b/test/sharness/t0114-gateway-subdomains.sh
@@ -163,7 +163,7 @@ test_localhost_gateway_response_should_contain \
"Location: http://$DIR_CID.ipfs.localhost:$GWAY_PORT/"
# Kubo specific end-to-end test
-# (independend of gateway-conformance)
+# (independent of gateway-conformance)
# We return human-readable body with HTTP 301 so existing cli scripts that use path-based
# gateway are informed to enable following HTTP redirects
@@ -194,7 +194,7 @@ test_localhost_gateway_response_should_contain \
# /ipns/
# Kubo specific end-to-end test
-# (independend of gateway-conformance)
+# (independent of gateway-conformance)
test_localhost_gateway_response_should_contain \
"request for localhost/ipns/{fqdn} redirects to DNSLink in subdomain" \
@@ -203,25 +203,6 @@ test_localhost_gateway_response_should_contain \
# end Kubo specific end-to-end test
-# API on localhost subdomain gateway
-
-# /api/v0 present on the root hostname
-test_localhost_gateway_response_should_contain \
- "request for localhost/api" \
- "http://localhost:$GWAY_PORT/api/v0/refs?arg=${DIR_CID}&r=true" \
- "Ref"
-
-# /api/v0 not mounted on content root subdomains
-test_localhost_gateway_response_should_contain \
- "request for {cid}.ipfs.localhost/api returns data if present on the content root" \
- "http://${DIR_CID}.ipfs.localhost:$GWAY_PORT/api/file.txt" \
- "I am a txt file"
-
-test_localhost_gateway_response_should_contain \
- "request for {cid}.ipfs.localhost/api/v0/refs returns 404" \
- "http://${DIR_CID}.ipfs.localhost:$GWAY_PORT/api/v0/refs?arg=${DIR_CID}&r=true" \
- "404 Not Found"
-
## ============================================================================
## Test subdomain-based requests to a local gateway with default config
## (origin per content root at http://*.localhost)
@@ -247,7 +228,7 @@ test_localhost_gateway_response_should_contain \
"I am a txt file"
# Kubo specific end-to-end test
-# (independend of gateway-conformance)
+# (independent of gateway-conformance)
# This tests link to parent specific to boxo + relative pathing end-to-end tests specific to Kubo.
# {CID}.ipfs.localhost/sub/dir (Directory Listing)
@@ -308,14 +289,6 @@ test_localhost_gateway_response_should_contain \
"http://$DNSLINK_FQDN.ipns.localhost:$GWAY_PORT" \
"$CID_VAL"
-# api.localhost/api
-
-# Note: we use DIR_CID so refs -r returns some CIDs for child nodes
-test_localhost_gateway_response_should_contain \
- "request for api.localhost returns API response" \
- "http://api.localhost:$GWAY_PORT/api/v0/refs?arg=$DIR_CID&r=true" \
- "Ref"
-
## ============================================================================
## Test DNSLink inlining on HTTP gateways
## ============================================================================
@@ -456,7 +429,7 @@ test_hostname_gateway_response_should_contain \
"404 Not Found"
# Kubo specific end-to-end test
-# (independend of gateway-conformance)
+# (independent of gateway-conformance)
# HTML specific to Boxo/Kubo, and relative pathing specific to code in Kubo
# {CID}.ipfs.example.com/sub/dir (Directory Listing)
@@ -518,54 +491,6 @@ test_hostname_gateway_response_should_contain \
"http://127.0.0.1:$GWAY_PORT" \
"Location: http://${ED25519_IPNS_IDv1}.ipns.example.com/"
-# API on subdomain gateway example.com
-# ============================================================================
-
-# present at the root domain
-test_hostname_gateway_response_should_contain \
- "request for example.com/api/v0/refs returns expected payload when /api is on Paths whitelist" \
- "example.com" \
- "http://127.0.0.1:$GWAY_PORT/api/v0/refs?arg=${DIR_CID}&r=true" \
- "Ref"
-
-# not mounted on content root subdomains
-test_hostname_gateway_response_should_contain \
- "request for {cid}.ipfs.example.com/api returns data if present on the content root" \
- "$DIR_CID.ipfs.example.com" \
- "http://127.0.0.1:$GWAY_PORT/api/file.txt" \
- "I am a txt file"
-
-test_hostname_gateway_response_should_contain \
- "request for {cid}.ipfs.example.com/api/v0/refs returns 404" \
- "$CIDv1.ipfs.example.com" \
- "http://127.0.0.1:$GWAY_PORT/api/v0/refs?arg=${DIR_CID}&r=true" \
- "404 Not Found"
-
-# disable /api on example.com
-ipfs config --json Gateway.PublicGateways '{
- "example.com": {
- "UseSubdomains": true,
- "Paths": ["/ipfs", "/ipns"]
- }
-}' || exit 1
-# restart daemon to apply config changes
-test_kill_ipfs_daemon
-test_launch_ipfs_daemon_without_network
-
-# not mounted at the root domain
-test_hostname_gateway_response_should_contain \
- "request for example.com/api/v0/refs returns 404 if /api not on Paths whitelist" \
- "example.com" \
- "http://127.0.0.1:$GWAY_PORT/api/v0/refs?arg=${DIR_CID}&r=true" \
- "404 Not Found"
-
-# not mounted on content root subdomains
-test_hostname_gateway_response_should_contain \
- "request for {cid}.ipfs.example.com/api returns data if present on the content root" \
- "$DIR_CID.ipfs.example.com" \
- "http://127.0.0.1:$GWAY_PORT/api/file.txt" \
- "I am a txt file"
-
# DNSLink: .ipns.example.com
# (not really useful outside of localhost, as setting TLS for more than one
# level of wildcard is a pain, but we support it if someone really wants it)
@@ -876,8 +801,8 @@ test_expect_success "request for http://fake.domain.com/ipfs/{CID} with X-Forwar
"
# Kubo specific end-to-end test
-# (independend of gateway-conformance)
-# test cofiguration beign wired up correctly end-to-end
+# (independent of gateway-conformance)
+# test configuration beign wired up correctly end-to-end
## ============================================================================
## Test support for wildcards in gateway config
@@ -991,4 +916,4 @@ test_expect_success "clean up ipfs dir" '
test_done
-# end Kubo specific end-to-end test
\ No newline at end of file
+# end Kubo specific end-to-end test
diff --git a/test/sharness/t0115-gateway-dir-listing.sh b/test/sharness/t0115-gateway-dir-listing.sh
index 1ce0861b2eb..d4e08e5be2e 100755
--- a/test/sharness/t0115-gateway-dir-listing.sh
+++ b/test/sharness/t0115-gateway-dir-listing.sh
@@ -40,7 +40,7 @@ test_expect_success "path gw: backlink on root CID should be hidden" '
test_expect_success "path gw: redirect dir listing to URL with trailing slash" '
curl -sD - http://127.0.0.1:$GWAY_PORT/ipfs/${DIR_CID}/ą/ę > list_response &&
test_should_contain "HTTP/1.1 301 Moved Permanently" list_response &&
- test_should_contain "Location: /ipfs/${DIR_CID}/%c4%85/%c4%99/" list_response
+ test_should_contain "Location: /ipfs/${DIR_CID}/%C4%85/%C4%99/" list_response
'
test_expect_success "path gw: Etag should be present" '
@@ -81,7 +81,7 @@ test_expect_success "subdomain gw: backlink on root CID should be hidden" '
test_expect_success "subdomain gw: redirect dir listing to URL with trailing slash" '
curl -sD - --resolve $DIR_HOSTNAME:$GWAY_PORT:127.0.0.1 http://$DIR_HOSTNAME:$GWAY_PORT/ą/ę > list_response &&
test_should_contain "HTTP/1.1 301 Moved Permanently" list_response &&
- test_should_contain "Location: /%c4%85/%c4%99/" list_response
+ test_should_contain "Location: /%C4%85/%C4%99/" list_response
'
test_expect_success "subdomain gw: Etag should be present" '
@@ -130,7 +130,7 @@ test_expect_success "dnslink gw: backlink on root CID should be hidden" '
test_expect_success "dnslink gw: redirect dir listing to URL with trailing slash" '
curl -sD - --resolve $DNSLINK_HOSTNAME:$GWAY_PORT:127.0.0.1 http://$DNSLINK_HOSTNAME:$GWAY_PORT/ą/ę > list_response &&
test_should_contain "HTTP/1.1 301 Moved Permanently" list_response &&
- test_should_contain "Location: /%c4%85/%c4%99/" list_response
+ test_should_contain "Location: /%C4%85/%C4%99/" list_response
'
test_expect_success "dnslink gw: Etag should be present" '
diff --git a/test/sharness/t0119-prometheus-data/prometheus_metrics b/test/sharness/t0119-prometheus-data/prometheus_metrics
index f3ba65c9746..d0900322b28 100644
--- a/test/sharness/t0119-prometheus-data/prometheus_metrics
+++ b/test/sharness/t0119-prometheus-data/prometheus_metrics
@@ -1,85 +1,17 @@
-flatfs_datastore_batchcommit_errors_total
-flatfs_datastore_batchcommit_latency_seconds_bucket
-flatfs_datastore_batchcommit_latency_seconds_count
-flatfs_datastore_batchcommit_latency_seconds_sum
-flatfs_datastore_batchcommit_total
-flatfs_datastore_batchdelete_errors_total
-flatfs_datastore_batchdelete_latency_seconds_bucket
-flatfs_datastore_batchdelete_latency_seconds_count
-flatfs_datastore_batchdelete_latency_seconds_sum
-flatfs_datastore_batchdelete_total
-flatfs_datastore_batchput_errors_total
-flatfs_datastore_batchput_latency_seconds_bucket
-flatfs_datastore_batchput_latency_seconds_count
-flatfs_datastore_batchput_latency_seconds_sum
-flatfs_datastore_batchput_size_bytes_bucket
-flatfs_datastore_batchput_size_bytes_count
-flatfs_datastore_batchput_size_bytes_sum
-flatfs_datastore_batchput_total
-flatfs_datastore_check_errors_total
-flatfs_datastore_check_latency_seconds_bucket
-flatfs_datastore_check_latency_seconds_count
-flatfs_datastore_check_latency_seconds_sum
-flatfs_datastore_check_total
-flatfs_datastore_delete_errors_total
-flatfs_datastore_delete_latency_seconds_bucket
-flatfs_datastore_delete_latency_seconds_count
-flatfs_datastore_delete_latency_seconds_sum
-flatfs_datastore_delete_total
-flatfs_datastore_du_errors_total
-flatfs_datastore_du_latency_seconds_bucket
-flatfs_datastore_du_latency_seconds_count
-flatfs_datastore_du_latency_seconds_sum
-flatfs_datastore_du_total
-flatfs_datastore_gc_errors_total
-flatfs_datastore_gc_latency_seconds_bucket
-flatfs_datastore_gc_latency_seconds_count
-flatfs_datastore_gc_latency_seconds_sum
-flatfs_datastore_gc_total
-flatfs_datastore_get_errors_total
-flatfs_datastore_get_latency_seconds_bucket
-flatfs_datastore_get_latency_seconds_count
-flatfs_datastore_get_latency_seconds_sum
-flatfs_datastore_get_size_bytes_bucket
-flatfs_datastore_get_size_bytes_count
-flatfs_datastore_get_size_bytes_sum
-flatfs_datastore_get_total
-flatfs_datastore_getsize_errors_total
-flatfs_datastore_getsize_latency_seconds_bucket
-flatfs_datastore_getsize_latency_seconds_count
-flatfs_datastore_getsize_latency_seconds_sum
-flatfs_datastore_getsize_total
-flatfs_datastore_has_errors_total
-flatfs_datastore_has_latency_seconds_bucket
-flatfs_datastore_has_latency_seconds_count
-flatfs_datastore_has_latency_seconds_sum
-flatfs_datastore_has_total
-flatfs_datastore_put_errors_total
-flatfs_datastore_put_latency_seconds_bucket
-flatfs_datastore_put_latency_seconds_count
-flatfs_datastore_put_latency_seconds_sum
-flatfs_datastore_put_size_bytes_bucket
-flatfs_datastore_put_size_bytes_count
-flatfs_datastore_put_size_bytes_sum
-flatfs_datastore_put_total
-flatfs_datastore_query_errors_total
-flatfs_datastore_query_latency_seconds_bucket
-flatfs_datastore_query_latency_seconds_count
-flatfs_datastore_query_latency_seconds_sum
-flatfs_datastore_query_total
-flatfs_datastore_scrub_errors_total
-flatfs_datastore_scrub_latency_seconds_bucket
-flatfs_datastore_scrub_latency_seconds_count
-flatfs_datastore_scrub_latency_seconds_sum
-flatfs_datastore_scrub_total
-flatfs_datastore_sync_errors_total
-flatfs_datastore_sync_latency_seconds_bucket
-flatfs_datastore_sync_latency_seconds_count
-flatfs_datastore_sync_latency_seconds_sum
-flatfs_datastore_sync_total
+exchange_bitswap_requests_in_flight
+exchange_bitswap_response_bytes_bucket
+exchange_bitswap_response_bytes_count
+exchange_bitswap_response_bytes_sum
+exchange_bitswap_wantlists_items_total
+exchange_bitswap_wantlists_seconds_bucket
+exchange_bitswap_wantlists_seconds_count
+exchange_bitswap_wantlists_seconds_sum
+exchange_bitswap_wantlists_total
go_gc_duration_seconds
go_gc_duration_seconds_count
go_gc_duration_seconds_sum
+go_gc_gogc_percent
+go_gc_gomemlimit_bytes
go_goroutines
go_info
go_memstats_alloc_bytes
@@ -94,7 +26,6 @@ go_memstats_heap_objects
go_memstats_heap_released_bytes
go_memstats_heap_sys_bytes
go_memstats_last_gc_time_seconds
-go_memstats_lookups_total
go_memstats_mallocs_total
go_memstats_mcache_inuse_bytes
go_memstats_mcache_sys_bytes
@@ -105,6 +36,7 @@ go_memstats_other_sys_bytes
go_memstats_stack_inuse_bytes
go_memstats_stack_sys_bytes
go_memstats_sys_bytes
+go_sched_gomaxprocs_threads
go_threads
ipfs_bitswap_active_block_tasks
ipfs_bitswap_active_tasks
@@ -216,85 +148,6 @@ ipfs_http_response_size_bytes
ipfs_http_response_size_bytes_count
ipfs_http_response_size_bytes_sum
ipfs_info
-leveldb_datastore_batchcommit_errors_total
-leveldb_datastore_batchcommit_latency_seconds_bucket
-leveldb_datastore_batchcommit_latency_seconds_count
-leveldb_datastore_batchcommit_latency_seconds_sum
-leveldb_datastore_batchcommit_total
-leveldb_datastore_batchdelete_errors_total
-leveldb_datastore_batchdelete_latency_seconds_bucket
-leveldb_datastore_batchdelete_latency_seconds_count
-leveldb_datastore_batchdelete_latency_seconds_sum
-leveldb_datastore_batchdelete_total
-leveldb_datastore_batchput_errors_total
-leveldb_datastore_batchput_latency_seconds_bucket
-leveldb_datastore_batchput_latency_seconds_count
-leveldb_datastore_batchput_latency_seconds_sum
-leveldb_datastore_batchput_size_bytes_bucket
-leveldb_datastore_batchput_size_bytes_count
-leveldb_datastore_batchput_size_bytes_sum
-leveldb_datastore_batchput_total
-leveldb_datastore_check_errors_total
-leveldb_datastore_check_latency_seconds_bucket
-leveldb_datastore_check_latency_seconds_count
-leveldb_datastore_check_latency_seconds_sum
-leveldb_datastore_check_total
-leveldb_datastore_delete_errors_total
-leveldb_datastore_delete_latency_seconds_bucket
-leveldb_datastore_delete_latency_seconds_count
-leveldb_datastore_delete_latency_seconds_sum
-leveldb_datastore_delete_total
-leveldb_datastore_du_errors_total
-leveldb_datastore_du_latency_seconds_bucket
-leveldb_datastore_du_latency_seconds_count
-leveldb_datastore_du_latency_seconds_sum
-leveldb_datastore_du_total
-leveldb_datastore_gc_errors_total
-leveldb_datastore_gc_latency_seconds_bucket
-leveldb_datastore_gc_latency_seconds_count
-leveldb_datastore_gc_latency_seconds_sum
-leveldb_datastore_gc_total
-leveldb_datastore_get_errors_total
-leveldb_datastore_get_latency_seconds_bucket
-leveldb_datastore_get_latency_seconds_count
-leveldb_datastore_get_latency_seconds_sum
-leveldb_datastore_get_size_bytes_bucket
-leveldb_datastore_get_size_bytes_count
-leveldb_datastore_get_size_bytes_sum
-leveldb_datastore_get_total
-leveldb_datastore_getsize_errors_total
-leveldb_datastore_getsize_latency_seconds_bucket
-leveldb_datastore_getsize_latency_seconds_count
-leveldb_datastore_getsize_latency_seconds_sum
-leveldb_datastore_getsize_total
-leveldb_datastore_has_errors_total
-leveldb_datastore_has_latency_seconds_bucket
-leveldb_datastore_has_latency_seconds_count
-leveldb_datastore_has_latency_seconds_sum
-leveldb_datastore_has_total
-leveldb_datastore_put_errors_total
-leveldb_datastore_put_latency_seconds_bucket
-leveldb_datastore_put_latency_seconds_count
-leveldb_datastore_put_latency_seconds_sum
-leveldb_datastore_put_size_bytes_bucket
-leveldb_datastore_put_size_bytes_count
-leveldb_datastore_put_size_bytes_sum
-leveldb_datastore_put_total
-leveldb_datastore_query_errors_total
-leveldb_datastore_query_latency_seconds_bucket
-leveldb_datastore_query_latency_seconds_count
-leveldb_datastore_query_latency_seconds_sum
-leveldb_datastore_query_total
-leveldb_datastore_scrub_errors_total
-leveldb_datastore_scrub_latency_seconds_bucket
-leveldb_datastore_scrub_latency_seconds_count
-leveldb_datastore_scrub_latency_seconds_sum
-leveldb_datastore_scrub_total
-leveldb_datastore_sync_errors_total
-leveldb_datastore_sync_latency_seconds_bucket
-leveldb_datastore_sync_latency_seconds_count
-leveldb_datastore_sync_latency_seconds_sum
-leveldb_datastore_sync_total
libp2p_autonat_next_probe_timestamp
libp2p_autonat_reachability_status
libp2p_autonat_reachability_status_confidence
@@ -359,6 +212,8 @@ libp2p_swarm_dial_ranking_delay_seconds_count
libp2p_swarm_dial_ranking_delay_seconds_sum
process_cpu_seconds_total
process_max_fds
+process_network_receive_bytes_total
+process_network_transmit_bytes_total
process_open_fds
process_resident_memory_bytes
process_start_time_seconds
diff --git a/test/sharness/t0119-prometheus-data/prometheus_metrics_added_by_enabling_rcmgr b/test/sharness/t0119-prometheus-data/prometheus_metrics_added_by_enabling_rcmgr
index 382ab125602..e69de29bb2d 100644
--- a/test/sharness/t0119-prometheus-data/prometheus_metrics_added_by_enabling_rcmgr
+++ b/test/sharness/t0119-prometheus-data/prometheus_metrics_added_by_enabling_rcmgr
@@ -1,4 +0,0 @@
-libp2p_rcmgr_memory_allocations_allowed_total
-libp2p_rcmgr_memory_allocations_blocked_total
-libp2p_rcmgr_peer_blocked_total
-libp2p_rcmgr_peers_allowed_total
diff --git a/test/sharness/t0119-prometheus-data/prometheus_metrics_added_by_measure_profile b/test/sharness/t0119-prometheus-data/prometheus_metrics_added_by_measure_profile
new file mode 100644
index 00000000000..03f132701f6
--- /dev/null
+++ b/test/sharness/t0119-prometheus-data/prometheus_metrics_added_by_measure_profile
@@ -0,0 +1,158 @@
+flatfs_datastore_batchcommit_errors_total
+flatfs_datastore_batchcommit_latency_seconds_bucket
+flatfs_datastore_batchcommit_latency_seconds_count
+flatfs_datastore_batchcommit_latency_seconds_sum
+flatfs_datastore_batchcommit_total
+flatfs_datastore_batchdelete_errors_total
+flatfs_datastore_batchdelete_latency_seconds_bucket
+flatfs_datastore_batchdelete_latency_seconds_count
+flatfs_datastore_batchdelete_latency_seconds_sum
+flatfs_datastore_batchdelete_total
+flatfs_datastore_batchput_errors_total
+flatfs_datastore_batchput_latency_seconds_bucket
+flatfs_datastore_batchput_latency_seconds_count
+flatfs_datastore_batchput_latency_seconds_sum
+flatfs_datastore_batchput_size_bytes_bucket
+flatfs_datastore_batchput_size_bytes_count
+flatfs_datastore_batchput_size_bytes_sum
+flatfs_datastore_batchput_total
+flatfs_datastore_check_errors_total
+flatfs_datastore_check_latency_seconds_bucket
+flatfs_datastore_check_latency_seconds_count
+flatfs_datastore_check_latency_seconds_sum
+flatfs_datastore_check_total
+flatfs_datastore_delete_errors_total
+flatfs_datastore_delete_latency_seconds_bucket
+flatfs_datastore_delete_latency_seconds_count
+flatfs_datastore_delete_latency_seconds_sum
+flatfs_datastore_delete_total
+flatfs_datastore_du_errors_total
+flatfs_datastore_du_latency_seconds_bucket
+flatfs_datastore_du_latency_seconds_count
+flatfs_datastore_du_latency_seconds_sum
+flatfs_datastore_du_total
+flatfs_datastore_gc_errors_total
+flatfs_datastore_gc_latency_seconds_bucket
+flatfs_datastore_gc_latency_seconds_count
+flatfs_datastore_gc_latency_seconds_sum
+flatfs_datastore_gc_total
+flatfs_datastore_get_errors_total
+flatfs_datastore_get_latency_seconds_bucket
+flatfs_datastore_get_latency_seconds_count
+flatfs_datastore_get_latency_seconds_sum
+flatfs_datastore_get_size_bytes_bucket
+flatfs_datastore_get_size_bytes_count
+flatfs_datastore_get_size_bytes_sum
+flatfs_datastore_get_total
+flatfs_datastore_getsize_errors_total
+flatfs_datastore_getsize_latency_seconds_bucket
+flatfs_datastore_getsize_latency_seconds_count
+flatfs_datastore_getsize_latency_seconds_sum
+flatfs_datastore_getsize_total
+flatfs_datastore_has_errors_total
+flatfs_datastore_has_latency_seconds_bucket
+flatfs_datastore_has_latency_seconds_count
+flatfs_datastore_has_latency_seconds_sum
+flatfs_datastore_has_total
+flatfs_datastore_put_errors_total
+flatfs_datastore_put_latency_seconds_bucket
+flatfs_datastore_put_latency_seconds_count
+flatfs_datastore_put_latency_seconds_sum
+flatfs_datastore_put_size_bytes_bucket
+flatfs_datastore_put_size_bytes_count
+flatfs_datastore_put_size_bytes_sum
+flatfs_datastore_put_total
+flatfs_datastore_query_errors_total
+flatfs_datastore_query_latency_seconds_bucket
+flatfs_datastore_query_latency_seconds_count
+flatfs_datastore_query_latency_seconds_sum
+flatfs_datastore_query_total
+flatfs_datastore_scrub_errors_total
+flatfs_datastore_scrub_latency_seconds_bucket
+flatfs_datastore_scrub_latency_seconds_count
+flatfs_datastore_scrub_latency_seconds_sum
+flatfs_datastore_scrub_total
+flatfs_datastore_sync_errors_total
+flatfs_datastore_sync_latency_seconds_bucket
+flatfs_datastore_sync_latency_seconds_count
+flatfs_datastore_sync_latency_seconds_sum
+flatfs_datastore_sync_total
+leveldb_datastore_batchcommit_errors_total
+leveldb_datastore_batchcommit_latency_seconds_bucket
+leveldb_datastore_batchcommit_latency_seconds_count
+leveldb_datastore_batchcommit_latency_seconds_sum
+leveldb_datastore_batchcommit_total
+leveldb_datastore_batchdelete_errors_total
+leveldb_datastore_batchdelete_latency_seconds_bucket
+leveldb_datastore_batchdelete_latency_seconds_count
+leveldb_datastore_batchdelete_latency_seconds_sum
+leveldb_datastore_batchdelete_total
+leveldb_datastore_batchput_errors_total
+leveldb_datastore_batchput_latency_seconds_bucket
+leveldb_datastore_batchput_latency_seconds_count
+leveldb_datastore_batchput_latency_seconds_sum
+leveldb_datastore_batchput_size_bytes_bucket
+leveldb_datastore_batchput_size_bytes_count
+leveldb_datastore_batchput_size_bytes_sum
+leveldb_datastore_batchput_total
+leveldb_datastore_check_errors_total
+leveldb_datastore_check_latency_seconds_bucket
+leveldb_datastore_check_latency_seconds_count
+leveldb_datastore_check_latency_seconds_sum
+leveldb_datastore_check_total
+leveldb_datastore_delete_errors_total
+leveldb_datastore_delete_latency_seconds_bucket
+leveldb_datastore_delete_latency_seconds_count
+leveldb_datastore_delete_latency_seconds_sum
+leveldb_datastore_delete_total
+leveldb_datastore_du_errors_total
+leveldb_datastore_du_latency_seconds_bucket
+leveldb_datastore_du_latency_seconds_count
+leveldb_datastore_du_latency_seconds_sum
+leveldb_datastore_du_total
+leveldb_datastore_gc_errors_total
+leveldb_datastore_gc_latency_seconds_bucket
+leveldb_datastore_gc_latency_seconds_count
+leveldb_datastore_gc_latency_seconds_sum
+leveldb_datastore_gc_total
+leveldb_datastore_get_errors_total
+leveldb_datastore_get_latency_seconds_bucket
+leveldb_datastore_get_latency_seconds_count
+leveldb_datastore_get_latency_seconds_sum
+leveldb_datastore_get_size_bytes_bucket
+leveldb_datastore_get_size_bytes_count
+leveldb_datastore_get_size_bytes_sum
+leveldb_datastore_get_total
+leveldb_datastore_getsize_errors_total
+leveldb_datastore_getsize_latency_seconds_bucket
+leveldb_datastore_getsize_latency_seconds_count
+leveldb_datastore_getsize_latency_seconds_sum
+leveldb_datastore_getsize_total
+leveldb_datastore_has_errors_total
+leveldb_datastore_has_latency_seconds_bucket
+leveldb_datastore_has_latency_seconds_count
+leveldb_datastore_has_latency_seconds_sum
+leveldb_datastore_has_total
+leveldb_datastore_put_errors_total
+leveldb_datastore_put_latency_seconds_bucket
+leveldb_datastore_put_latency_seconds_count
+leveldb_datastore_put_latency_seconds_sum
+leveldb_datastore_put_size_bytes_bucket
+leveldb_datastore_put_size_bytes_count
+leveldb_datastore_put_size_bytes_sum
+leveldb_datastore_put_total
+leveldb_datastore_query_errors_total
+leveldb_datastore_query_latency_seconds_bucket
+leveldb_datastore_query_latency_seconds_count
+leveldb_datastore_query_latency_seconds_sum
+leveldb_datastore_query_total
+leveldb_datastore_scrub_errors_total
+leveldb_datastore_scrub_latency_seconds_bucket
+leveldb_datastore_scrub_latency_seconds_count
+leveldb_datastore_scrub_latency_seconds_sum
+leveldb_datastore_scrub_total
+leveldb_datastore_sync_errors_total
+leveldb_datastore_sync_latency_seconds_bucket
+leveldb_datastore_sync_latency_seconds_count
+leveldb_datastore_sync_latency_seconds_sum
+leveldb_datastore_sync_total
diff --git a/test/sharness/t0119-prometheus.sh b/test/sharness/t0119-prometheus.sh
index 0e00f088ac2..4daf8281b7c 100755
--- a/test/sharness/t0119-prometheus.sh
+++ b/test/sharness/t0119-prometheus.sh
@@ -33,7 +33,7 @@ test_expect_success "make sure metrics haven't changed" '
# Check what was added by enabling ResourceMgr.Enabled
#
# NOTE: we won't see all the dynamic ones, but that is ok: the point of the
-# test here is to detect regression when rcmgr metrics dissapear due to
+# test here is to detect regression when rcmgr metrics disappear due to
# refactor/human error.
test_expect_success "enable ResourceMgr in the config" '
@@ -57,4 +57,28 @@ test_expect_success "make sure initial metrics added by setting ResourceMgr.Enab
diff -u ../t0119-prometheus-data/prometheus_metrics_added_by_enabling_rcmgr rcmgr_metrics
'
+# Reinitialize ipfs with --profile=flatfs-measure and check metrics.
+
+test_expect_success "remove ipfs directory" '
+ rm -rf .ipfs mountdir ipfs ipns
+'
+
+test_init_ipfs_measure
+
+test_launch_ipfs_daemon
+
+test_expect_success "collect metrics" '
+ curl "$API_ADDR/debug/metrics/prometheus" > raw_metrics
+'
+test_kill_ipfs_daemon
+
+test_expect_success "filter metrics and find ones added by enabling flatfs-measure profile" '
+ sed -ne "s/^\([a-z0-9_]\+\).*/\1/p" raw_metrics | LC_ALL=C sort > filtered_metrics &&
+ grep -v -x -f ../t0119-prometheus-data/prometheus_metrics filtered_metrics | LC_ALL=C sort | uniq > measure_metrics
+'
+
+test_expect_success "make sure initial metrics added by initializing with flatfs-measure profile haven't changed" '
+ diff -u ../t0119-prometheus-data/prometheus_metrics_added_by_measure_profile measure_metrics
+'
+
test_done
diff --git a/test/sharness/t0120-bootstrap.sh b/test/sharness/t0120-bootstrap.sh
index 2922533c628..00141da1f06 100755
--- a/test/sharness/t0120-bootstrap.sh
+++ b/test/sharness/t0120-bootstrap.sh
@@ -9,8 +9,9 @@ BP1="/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTez
BP2="/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"
BP3="/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb"
BP4="/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt"
-BP5="/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ"
-BP6="/ip4/104.131.131.82/udp/4001/quic-v1/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ"
+BP5="/dnsaddr/va1.bootstrap.libp2p.io/p2p/12D3KooWKnDdG3iXw9eTFijk3EWSunZcFi54Zka4wmtqtt6rPxc8"
+BP6="/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ"
+BP7="/ip4/104.131.131.82/udp/4001/quic-v1/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ"
test_description="Test ipfs repo operations"
@@ -93,10 +94,11 @@ test_bootstrap_cmd() {
echo "added $BP4" >>add2_expected &&
echo "added $BP5" >>add2_expected &&
echo "added $BP6" >>add2_expected &&
+ echo "added $BP7" >>add2_expected &&
test_cmp add2_expected add2_actual
'
- test_bootstrap_list_cmd $BP1 $BP2 $BP3 $BP4 $BP5 $BP6
+ test_bootstrap_list_cmd $BP1 $BP2 $BP3 $BP4 $BP5 $BP6 $BP7
test_expect_success "'ipfs bootstrap rm --all' succeeds" '
ipfs bootstrap rm --all >rm2_actual
@@ -109,6 +111,7 @@ test_bootstrap_cmd() {
echo "removed $BP4" >>rm2_expected &&
echo "removed $BP5" >>rm2_expected &&
echo "removed $BP6" >>rm2_expected &&
+ echo "removed $BP7" >>rm2_expected &&
test_cmp rm2_expected rm2_actual
'
diff --git a/test/sharness/t0121-bootstrap-iptb.sh b/test/sharness/t0121-bootstrap-iptb.sh
index 16dcbdb2f09..04919186598 100755
--- a/test/sharness/t0121-bootstrap-iptb.sh
+++ b/test/sharness/t0121-bootstrap-iptb.sh
@@ -52,7 +52,7 @@ test_expect_success "bring down iptb nodes" '
'
test_expect_success "reset iptb nodes" '
- # the api doesnt seem to get cleaned up in sharness tests for some reason
+ # the api does not seem to get cleaned up in sharness tests for some reason
iptb testbed create -type localipfs -count 5 -force -init
'
diff --git a/test/sharness/t0131-multinode-client-routing.sh b/test/sharness/t0131-multinode-client-routing.sh
index b62c9790b9c..13b9c97d515 100755
--- a/test/sharness/t0131-multinode-client-routing.sh
+++ b/test/sharness/t0131-multinode-client-routing.sh
@@ -24,7 +24,7 @@ check_file_fetch() {
run_single_file_test() {
test_expect_success "add a file on node1" '
- random 1000000 > filea &&
+ random-data -size=1000000 > filea &&
FILEA_HASH=$(ipfsi 1 add -q filea)
'
@@ -43,7 +43,8 @@ run_single_file_test() {
NNODES=10
test_expect_success "set up testbed" '
- iptb testbed create -type localipfs -count $NNODES -force -init
+ iptb testbed create -type localipfs -count $NNODES -force -init &&
+ iptb run -- ipfs config --json "Routing.LoopbackAddressesOnLanDHT" true
'
test_expect_success "start up nodes" '
@@ -56,7 +57,7 @@ test_expect_success "connect up nodes" '
'
test_expect_success "add a file on a node in client mode" '
- random 1000000 > filea &&
+ random-data -size=1000000 > filea &&
FILE_HASH=$(ipfsi 8 add -q filea)
'
diff --git a/test/sharness/t0142-testfilter.sh b/test/sharness/t0142-testfilter.sh
index 971aa68397a..bdd7e4f76b1 100755
--- a/test/sharness/t0142-testfilter.sh
+++ b/test/sharness/t0142-testfilter.sh
@@ -13,7 +13,8 @@ AF="/ip4/127.0.0.0/ipcidr/24"
NUM_NODES=3
test_expect_success "set up testbed" '
- iptb testbed create -type localipfs -count $NUM_NODES -force -init
+ iptb testbed create -type localipfs -count $NUM_NODES -force -init &&
+ iptb run -- ipfs config --json "Routing.LoopbackAddressesOnLanDHT" true
'
test_expect_success 'filter 127.0.0.0/24 on node 1' '
diff --git a/test/sharness/t0150-clisuggest.sh b/test/sharness/t0150-clisuggest.sh
index a504b38dd39..30ae6acd2ea 100755
--- a/test/sharness/t0150-clisuggest.sh
+++ b/test/sharness/t0150-clisuggest.sh
@@ -18,13 +18,13 @@ test_suggest() {
'
test_expect_success "test command fails" '
- test_must_fail ipfs lis 2>actual
+ test_must_fail ipfs li 2>actual
'
test_expect_success "test multiple commands are suggested" '
grep "Did you mean any of these?" actual &&
grep "ls" actual &&
- grep "id" actual ||
+ grep "log" actual ||
test_fsh cat actual
'
diff --git a/test/sharness/t0165-keystore-data/README.md b/test/sharness/t0165-keystore-data/README.md
index 4c0a68b5169..298b7708e95 100644
--- a/test/sharness/t0165-keystore-data/README.md
+++ b/test/sharness/t0165-keystore-data/README.md
@@ -8,7 +8,7 @@ openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 > openssl_rsa.pem
```
secp key used in the 'restrict import key' test.
-From: https://www.openssl.org/docs/man1.1.1/man1/openssl-genpkey.html
+From: https://docs.openssl.org/1.1.1/man1/genpkey/
```bash
openssl genpkey -genparam -algorithm EC -out ecp.pem \
-pkeyopt ec_paramgen_curve:secp384r1 \
diff --git a/test/sharness/t0175-provider.sh b/test/sharness/t0175-provider.sh
deleted file mode 100755
index cca110fe101..00000000000
--- a/test/sharness/t0175-provider.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env bash
-
-test_description="Test reprovider"
-
-. lib/test-lib.sh
-
-NUM_NODES=2
-
-test_expect_success 'init iptb' '
- iptb testbed create -type localipfs -force -count $NUM_NODES -init
-'
-
-test_expect_success 'peer ids' '
- PEERID_0=$(iptb attr get 0 id) &&
- PEERID_1=$(iptb attr get 1 id)
-'
-
-test_expect_success 'use strategic providing' '
- iptb run -- ipfs config --json Experimental.StrategicProviding false
-'
-
-startup_cluster ${NUM_NODES}
-
-test_expect_success 'add test object' '
- HASH_0=$(date +"%FT%T.%N%z" | ipfsi 0 add -q)
-'
-
-findprovs_expect '$HASH_0' '$PEERID_0'
-
-test_expect_success 'stop node 1' '
- iptb stop
-'
-
-test_done
diff --git a/test/sharness/t0175-reprovider.sh b/test/sharness/t0175-reprovider.sh
deleted file mode 100755
index 09535ecc4f5..00000000000
--- a/test/sharness/t0175-reprovider.sh
+++ /dev/null
@@ -1,140 +0,0 @@
-#!/usr/bin/env bash
-
-test_description="Test reprovider"
-
-. lib/test-lib.sh
-
-NUM_NODES=6
-
-init_strategy() {
- test_expect_success 'init iptb' '
- iptb testbed create -type localipfs -force -count $NUM_NODES -init
- '
-
- test_expect_success 'peer ids' '
- PEERID_0=$(iptb attr get 0 id) &&
- PEERID_1=$(iptb attr get 1 id)
- '
-
- test_expect_success 'use pinning strategy for reprovider' '
- ipfsi 0 config Reprovider.Strategy '$1'
- '
-
- startup_cluster ${NUM_NODES}
-}
-
-reprovide() {
- test_expect_success 'reprovide' '
- # TODO: this hangs, though only after reprovision was done
- ipfsi 0 bitswap reprovide
- '
-}
-
-# Test 'all' strategy
-init_strategy 'all'
-
-test_expect_success 'add test object' '
- HASH_0=$(date +"%FT%T.%N%z" | ipfsi 0 add -q --local)
-'
-
-findprovs_empty '$HASH_0'
-reprovide
-findprovs_expect '$HASH_0' '$PEERID_0'
-
-test_expect_success 'Stop iptb' '
- iptb stop
-'
-
-# Test 'pinned' strategy
-init_strategy 'pinned'
-
-test_expect_success 'prepare test files' '
- date +"%FT%T.%N%z" > f1 &&
- date +"%FT%T.%N%z" > f2
-'
-
-test_expect_success 'add test objects' '
- HASH_FOO=$(ipfsi 0 add -q --offline --pin=false f1) &&
- HASH_BAR=$(ipfsi 0 add -q --offline --pin=false f2) &&
- HASH_BAR_DIR=$(ipfsi 0 add -q --offline -w f2)
-'
-
-findprovs_empty '$HASH_FOO'
-findprovs_empty '$HASH_BAR'
-findprovs_empty '$HASH_BAR_DIR'
-
-reprovide
-
-findprovs_empty '$HASH_FOO'
-findprovs_expect '$HASH_BAR' '$PEERID_0'
-findprovs_expect '$HASH_BAR_DIR' '$PEERID_0'
-
-test_expect_success 'Stop iptb' '
- iptb stop
-'
-
-# Test 'roots' strategy
-init_strategy 'roots'
-
-test_expect_success 'prepare test files' '
- date +"%FT%T.%N%z" > f1 &&
- date +"%FT%T.%N%z" > f2 &&
- date +"%FT%T.%N%z" > f3
-'
-
-test_expect_success 'add test objects' '
- HASH_FOO=$(ipfsi 0 add -q --offline --pin=false f1) &&
- HASH_BAR=$(ipfsi 0 add -q --offline --pin=false f2) &&
- HASH_BAZ=$(ipfsi 0 add -q --offline f3) &&
- HASH_BAR_DIR=$(ipfsi 0 add -Q --offline -w f2)
-'
-
-findprovs_empty '$HASH_FOO'
-findprovs_empty '$HASH_BAR'
-findprovs_empty '$HASH_BAR_DIR'
-
-reprovide
-
-findprovs_empty '$HASH_FOO'
-findprovs_empty '$HASH_BAR'
-findprovs_expect '$HASH_BAZ' '$PEERID_0'
-findprovs_expect '$HASH_BAR_DIR' '$PEERID_0'
-
-test_expect_success 'Stop iptb' '
- iptb stop
-'
-
-# Test reprovider working with ticking disabled
-test_expect_success 'init iptb' '
- iptb testbed create -type localipfs -force -count $NUM_NODES -init
-'
-
-test_expect_success 'peer ids' '
- PEERID_0=$(iptb attr get 0 id) &&
- PEERID_1=$(iptb attr get 1 id)
-'
-
-test_expect_success 'Disable reprovider ticking' '
- ipfsi 0 config Reprovider.Interval 0
-'
-
-startup_cluster ${NUM_NODES}
-
-test_expect_success 'add test object' '
- HASH_0=$(date +"%FT%T.%N%z" | ipfsi 0 add -q --offline)
-'
-
-findprovs_empty '$HASH_0'
-reprovide
-findprovs_expect '$HASH_0' '$PEERID_0'
-
-test_expect_success 'resolve object $HASH_0' '
- HASH_WITH_PREFIX=$(ipfsi 1 resolve $HASH_0)
-'
-findprovs_expect '$HASH_WITH_PREFIX' '$PEERID_0'
-
-test_expect_success 'Stop iptb' '
- iptb stop
-'
-
-test_done
diff --git a/test/sharness/t0175-strategic-provider.sh b/test/sharness/t0175-strategic-provider.sh
deleted file mode 100755
index fafd6e5388c..00000000000
--- a/test/sharness/t0175-strategic-provider.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env bash
-
-test_description="Test reprovider"
-
-. lib/test-lib.sh
-
-NUM_NODES=2
-
-test_expect_success 'init iptb' '
- iptb testbed create -type localipfs -force -count $NUM_NODES -init
-'
-
-test_expect_success 'peer ids' '
- PEERID_0=$(iptb attr get 0 id) &&
- PEERID_1=$(iptb attr get 1 id)
-'
-
-test_expect_success 'use strategic providing' '
- iptb run -- ipfs config --json Experimental.StrategicProviding true
-'
-
-startup_cluster ${NUM_NODES}
-
-test_expect_success 'add test object' '
- HASH_0=$(date +"%FT%T.%N%z" | ipfsi 0 add -q)
-'
-
-findprovs_empty '$HASH_0'
-
-test_expect_success 'stop node 1' '
- iptb stop
-'
-
-test_done
diff --git a/test/sharness/t0181-private-network.sh b/test/sharness/t0181-private-network.sh
index 86c6151d3e4..5e566d317ff 100755
--- a/test/sharness/t0181-private-network.sh
+++ b/test/sharness/t0181-private-network.sh
@@ -26,7 +26,7 @@ test_expect_success "daemon output includes info about the reason" '
pnet_key() {
echo '/key/swarm/psk/1.0.0/'
echo '/bin/'
- random 32
+ random-data -size=32
}
pnet_key > "${IPFS_PATH}/swarm.key"
@@ -35,6 +35,8 @@ LIBP2P_FORCE_PNET=1 test_launch_ipfs_daemon
test_expect_success "set up iptb testbed" '
iptb testbed create -type localipfs -count 5 -force -init &&
+ iptb run -- ipfs config --json "Routing.LoopbackAddressesOnLanDHT" true &&
+ iptb run -- ipfs config --json "Swarm.Transports.Network.Websocket" false &&
iptb run -- ipfs config --json Addresses.Swarm '"'"'["/ip4/127.0.0.1/tcp/0"]'"'"'
'
@@ -99,7 +101,7 @@ run_single_file_test() {
node2=$2
test_expect_success "add a file on node$node1" '
- random 1000000 > filea &&
+ random-data -size=1000000 > filea &&
FILEA_HASH=$(ipfsi $node1 add -q filea)
'
diff --git a/test/sharness/t0182-circuit-relay.sh b/test/sharness/t0182-circuit-relay.sh
index d6e439ae318..d7d11214860 100755
--- a/test/sharness/t0182-circuit-relay.sh
+++ b/test/sharness/t0182-circuit-relay.sh
@@ -7,10 +7,11 @@ test_description="Test circuit relay"
# start iptb + wait for peering
NUM_NODES=3
test_expect_success 'init iptb' '
- iptb testbed create -type localipfs -count $NUM_NODES -init
+ iptb testbed create -type localipfs -count $NUM_NODES -init &&
+ iptb run -- ipfs config --json "Routing.LoopbackAddressesOnLanDHT" true
'
-# Network toplogy: A <-> Relay <-> B
+# Network topology: A <-> Relay <-> B
test_expect_success 'start up nodes for configuration' '
iptb start -wait -- --routing=none
'
diff --git a/test/sharness/t0184-http-proxy-over-p2p.sh b/test/sharness/t0184-http-proxy-over-p2p.sh
index 9c5308277c2..98e2f3ab20c 100755
--- a/test/sharness/t0184-http-proxy-over-p2p.sh
+++ b/test/sharness/t0184-http-proxy-over-p2p.sh
@@ -142,6 +142,7 @@ function curl_send_multipart_form_request() {
test_expect_success 'configure nodes' '
iptb testbed create -type localipfs -count 2 -force -init &&
+ iptb run -- ipfs config --json "Routing.LoopbackAddressesOnLanDHT" true &&
ipfsi 0 config --json Experimental.Libp2pStreamMounting true &&
ipfsi 1 config --json Experimental.Libp2pStreamMounting true &&
ipfsi 0 config --json Experimental.P2pHttpProxy true &&
diff --git a/test/sharness/t0220-bitswap.sh b/test/sharness/t0220-bitswap.sh
index 3575f0d33e2..412437651be 100755
--- a/test/sharness/t0220-bitswap.sh
+++ b/test/sharness/t0220-bitswap.sh
@@ -18,7 +18,6 @@ test_expect_success "'ipfs bitswap stat' succeeds" '
test_expect_success "'ipfs bitswap stat' output looks good" '
cat <expected &&
bitswap status
- provides buffer: 0 / 256
blocks received: 0
blocks sent: 0
data received: 0
@@ -56,7 +55,6 @@ test_expect_success "'ipfs bitswap stat' succeeds" '
test_expect_success "'ipfs bitswap stat' output looks good" '
cat <expected &&
bitswap status
- provides buffer: 0 / 256
blocks received: 0
blocks sent: 0
data received: 0
@@ -85,7 +83,6 @@ test_expect_success "'ipfs bitswap stat --human' succeeds" '
test_expect_success "'ipfs bitswap stat --human' output looks good" '
cat <expected &&
bitswap status
- provides buffer: 0 / 256
blocks received: 0
blocks sent: 0
data received: 0 B
diff --git a/test/sharness/t0231-channel-streaming.sh b/test/sharness/t0231-channel-streaming.sh
index 36e855fb7c2..147a13b5598 100755
--- a/test/sharness/t0231-channel-streaming.sh
+++ b/test/sharness/t0231-channel-streaming.sh
@@ -16,7 +16,7 @@ get_api_port() {
test_ls_cmd() {
test_expect_success "make a file with multiple refs" '
- HASH=$(random 1000000 | ipfs add -q)
+ HASH=$(random-data -size=1000000 | ipfs add -q)
'
test_expect_success "can get refs through curl" '
diff --git a/test/sharness/t0235-cli-request.sh b/test/sharness/t0235-cli-request.sh
index 3b2281894ad..02ef514dedf 100755
--- a/test/sharness/t0235-cli-request.sh
+++ b/test/sharness/t0235-cli-request.sh
@@ -28,7 +28,7 @@ test_expect_success "start nc" '
'
test_expect_success "can make http request against nc server" '
- ipfs cat /ipfs/Qmabcdef --api /ip4/127.0.0.1/tcp/5005 &
+ ipfs cat /ipfs/Qmabcdef --api /dns4/localhost/tcp/5005 &
IPFSPID=$!
# handle request for /api/v0/version
@@ -80,4 +80,8 @@ test_expect_success "api flag does not appear in request" '
test_expect_code 1 grep "api=/ip4" nc_out
'
+test_expect_success "host has dns name not ip address" '
+ grep "Host: localhost:5005" nc_out
+'
+
test_done
diff --git a/test/sharness/t0250-files-api.sh b/test/sharness/t0250-files-api.sh
index 382758a0551..63dacf7d407 100755
--- a/test/sharness/t0250-files-api.sh
+++ b/test/sharness/t0250-files-api.sh
@@ -230,6 +230,8 @@ test_files_api() {
echo "Size: 4" >> file1stat_expect &&
echo "ChildBlocks: 0" >> file1stat_expect &&
echo "Type: file" >> file1stat_expect &&
+ echo "Mode: not set (not set)" >> file1stat_expect &&
+ echo "Mtime: not set" >> file1stat_expect &&
test_cmp file1stat_expect file1stat_actual
'
@@ -243,6 +245,8 @@ test_files_api() {
echo "Size: 4" >> file1stat_expect &&
echo "ChildBlocks: 0" >> file1stat_expect &&
echo "Type: file" >> file1stat_expect &&
+ echo "Mode: not set (not set)" >> file1stat_expect &&
+ echo "Mtime: not set" >> file1stat_expect &&
test_cmp file1stat_expect file1stat_actual
'
@@ -845,7 +849,7 @@ tests_for_files_api "with-daemon"
test_kill_ipfs_daemon
test_expect_success "enable sharding in config" '
- ipfs config --json Internal.UnixFSShardingSizeThreshold "\"1B\""
+ ipfs config --json Import.UnixFSHAMTDirectorySizeThreshold "\"1B\""
'
test_launch_ipfs_daemon_without_network
@@ -876,7 +880,7 @@ test_expect_success "set up automatic sharding/unsharding data" '
'
test_expect_success "reset automatic sharding" '
- ipfs config --json Internal.UnixFSShardingSizeThreshold null
+ ipfs config --json Import.UnixFSHAMTDirectorySizeThreshold null
'
test_launch_ipfs_daemon_without_network
diff --git a/test/sharness/t0252-files-gc.sh b/test/sharness/t0252-files-gc.sh
index 7267985d49a..f2eb25b4fcc 100755
--- a/test/sharness/t0252-files-gc.sh
+++ b/test/sharness/t0252-files-gc.sh
@@ -38,9 +38,9 @@ test_expect_success "gc okay after adding incomplete node -- prep" '
'
test_expect_success "gc okay after adding incomplete node" '
- ipfs object stat $ADIR_HASH &&
+ ipfs dag get $ADIR_HASH &&
ipfs repo gc &&
- ipfs object stat $ADIR_HASH
+ ipfs dag get $ADIR_HASH
'
test_expect_success "add directory with direct pin" '
diff --git a/test/sharness/t0260-sharding.sh b/test/sharness/t0260-sharding.sh
index 85e4a7ca708..7b0094fd4ea 100755
--- a/test/sharness/t0260-sharding.sh
+++ b/test/sharness/t0260-sharding.sh
@@ -34,7 +34,7 @@ test_init_ipfs
UNSHARDED="QmavrTrQG4VhoJmantURAYuw3bowq3E2WcvP36NRQDAC1N"
test_expect_success "force sharding off" '
-ipfs config --json Internal.UnixFSShardingSizeThreshold "\"1G\""
+ipfs config --json Import.UnixFSHAMTDirectorySizeThreshold "\"1G\""
'
test_add_dir "$UNSHARDED"
@@ -46,7 +46,7 @@ test_add_dir "$UNSHARDED"
test_kill_ipfs_daemon
test_expect_success "force sharding on" '
- ipfs config --json Internal.UnixFSShardingSizeThreshold "\"1B\""
+ ipfs config --json Import.UnixFSHAMTDirectorySizeThreshold "\"1B\""
'
SHARDED="QmSCJD1KYLhVVHqBK3YyXuoEqHt7vggyJhzoFYbT8v1XYL"
diff --git a/test/sharness/t0270-filestore.sh b/test/sharness/t0270-filestore.sh
index 82b7ae49241..fc377c2d264 100755
--- a/test/sharness/t0270-filestore.sh
+++ b/test/sharness/t0270-filestore.sh
@@ -13,7 +13,7 @@ test_expect_success "create a dataset" '
random-files -seed=483 -depth=3 -dirs=4 -files=6 -filesize=1000000 somedir > /dev/null
'
-EXPHASH="QmW4JLyeTxEWGwa4mkE9mHzdtAkyhMX2ToGFEKZNjCiJud"
+EXPHASH="QmXKtATsEt42CF5JoSsmzJstrvwEB5P89YQtdX4mdf9E3M"
get_repo_size() {
disk_usage "$IPFS_PATH"
@@ -63,7 +63,7 @@ test_filestore_adds() {
init_ipfs_filestore() {
test_expect_success "clean up old node" '
- rm -rf "$IPFS_PATH" mountdir ipfs ipns
+ rm -rf "$IPFS_PATH" mountdir ipfs ipns mfs
'
test_init_ipfs
diff --git a/test/sharness/t0271-filestore-utils.sh b/test/sharness/t0271-filestore-utils.sh
index c7e814b9d0a..5fd33565932 100755
--- a/test/sharness/t0271-filestore-utils.sh
+++ b/test/sharness/t0271-filestore-utils.sh
@@ -10,7 +10,7 @@ test_description="Test out the filestore nocopy functionality"
test_init_filestore() {
test_expect_success "clean up old node" '
- rm -rf "$IPFS_PATH" mountdir ipfs ipns
+ rm -rf "$IPFS_PATH" mountdir ipfs ipns mfs
'
test_init_ipfs
@@ -24,9 +24,9 @@ test_init_dataset() {
test_expect_success "create a dataset" '
rm -r somedir
mkdir somedir &&
- random 1000 1 > somedir/file1 &&
- random 10000 2 > somedir/file2 &&
- random 1000000 3 > somedir/file3
+ random-data -size=1000 -seed=1 > somedir/file1 &&
+ random-data -size=10000 -seed=2 > somedir/file2 &&
+ random-data -size=1000000 -seed=3 > somedir/file3
'
}
@@ -35,30 +35,30 @@ test_init() {
test_init_dataset
}
-EXPHASH="QmRueCuPMYYvdxWz1vWncF7wzCScEx4qasZXo5aVBb1R4V"
+EXPHASH="QmXqfraAT3U8ct14PPPXcFkWyvmqUZazLdo29GXTKSHkP4"
cat < ls_expect_file_order
-bafkreicj3ezgtrh3euw2gyub6w3jydhnouqobxt7stbgtns3mv3iwv6bqq 1000 somedir/file1 0
-bafkreibxwxisv4cld6x76ybqbvf2uwbkoswjqt4hut46af6rps2twme7ey 10000 somedir/file2 0
-bafkreidntk6ciin24oez6yjz4b25fgwecncvi4ua4uhr2tdyenogpzpid4 262144 somedir/file3 0
-bafkreidwie26yauqbhpd2nhhhmod55irq3z372mh6gw4ikl2ifo34c5jra 262144 somedir/file3 262144
-bafkreib7piyesy3dr22sawmycdftrmpyt3z4tmhxrdig2zt5zdp7qwbuay 262144 somedir/file3 524288
-bafkreigxp5k3k6b3i5sldu4r3im74nfxmoptuuubcvq6rg632nfznskglu 213568 somedir/file3 786432
+bafkreidx7ivgllulfkzyoo4oa7dfrg4mjmudg2qgdivoooj4s7lh3m5nqu 1000 somedir/file1 0
+bafkreic2wqrsyr3y3qgzbvufen2w25r3p3zljckqyxkpcagsxz3zdcosd4 10000 somedir/file2 0
+bafkreiemzfmzws23c2po4m6deiueknqfty7r3voes3e3zujmobrooc2ngm 262144 somedir/file3 0
+bafkreihgm53yhxn427lnfdwhqgpawc62qejog7gega5kqb6uwbyhjm47hu 262144 somedir/file3 262144
+bafkreigl2pjptgxz6cexcnua56zc5dwsyrc4ph2eulmcb634oes6gzvmuy 262144 somedir/file3 524288
+bafkreifjcthslybjizk36xffcsb32fsbguxz3ptkl7723wz4u3qikttmam 213568 somedir/file3 786432
EOF
sort < ls_expect_file_order > ls_expect_key_order
-FILE1_HASH=bafkreicj3ezgtrh3euw2gyub6w3jydhnouqobxt7stbgtns3mv3iwv6bqq
-FILE2_HASH=bafkreibxwxisv4cld6x76ybqbvf2uwbkoswjqt4hut46af6rps2twme7ey
-FILE3_HASH=QmfE4SDQazxTD7u8VTYs9AJqQL8rrJPUAorLeJXKSZrVf9
+FILE1_HASH=bafkreidx7ivgllulfkzyoo4oa7dfrg4mjmudg2qgdivoooj4s7lh3m5nqu
+FILE2_HASH=bafkreic2wqrsyr3y3qgzbvufen2w25r3p3zljckqyxkpcagsxz3zdcosd4
+FILE3_HASH=QmYEZtRGGk8rgM8MetegLLRHMKskPCg7zWpmQQAo3cQiN5
cat < verify_expect_file_order
-ok bafkreicj3ezgtrh3euw2gyub6w3jydhnouqobxt7stbgtns3mv3iwv6bqq 1000 somedir/file1 0
-ok bafkreibxwxisv4cld6x76ybqbvf2uwbkoswjqt4hut46af6rps2twme7ey 10000 somedir/file2 0
-ok bafkreidntk6ciin24oez6yjz4b25fgwecncvi4ua4uhr2tdyenogpzpid4 262144 somedir/file3 0
-ok bafkreidwie26yauqbhpd2nhhhmod55irq3z372mh6gw4ikl2ifo34c5jra 262144 somedir/file3 262144
-ok bafkreib7piyesy3dr22sawmycdftrmpyt3z4tmhxrdig2zt5zdp7qwbuay 262144 somedir/file3 524288
-ok bafkreigxp5k3k6b3i5sldu4r3im74nfxmoptuuubcvq6rg632nfznskglu 213568 somedir/file3 786432
+ok bafkreidx7ivgllulfkzyoo4oa7dfrg4mjmudg2qgdivoooj4s7lh3m5nqu 1000 somedir/file1 0
+ok bafkreic2wqrsyr3y3qgzbvufen2w25r3p3zljckqyxkpcagsxz3zdcosd4 10000 somedir/file2 0
+ok bafkreiemzfmzws23c2po4m6deiueknqfty7r3voes3e3zujmobrooc2ngm 262144 somedir/file3 0
+ok bafkreihgm53yhxn427lnfdwhqgpawc62qejog7gega5kqb6uwbyhjm47hu 262144 somedir/file3 262144
+ok bafkreigl2pjptgxz6cexcnua56zc5dwsyrc4ph2eulmcb634oes6gzvmuy 262144 somedir/file3 524288
+ok bafkreifjcthslybjizk36xffcsb32fsbguxz3ptkl7723wz4u3qikttmam 213568 somedir/file3 786432
EOF
sort < verify_expect_file_order > verify_expect_key_order
@@ -201,30 +201,30 @@ test_kill_ipfs_daemon
## base32
##
-EXPHASH="bafybeibva2uh4qpwjo2yr5g7m7nd5kfq64atydq77qdlrikh5uejwqdcbi"
+EXPHASH="bafybeienfbjfbywu5y44i5qm4wxajblgy5a6xuc4eepjaw5fq223wwsy3m"
cat < ls_expect_file_order
-bafkreicj3ezgtrh3euw2gyub6w3jydhnouqobxt7stbgtns3mv3iwv6bqq 1000 somedir/file1 0
-bafkreibxwxisv4cld6x76ybqbvf2uwbkoswjqt4hut46af6rps2twme7ey 10000 somedir/file2 0
-bafkreidntk6ciin24oez6yjz4b25fgwecncvi4ua4uhr2tdyenogpzpid4 262144 somedir/file3 0
-bafkreidwie26yauqbhpd2nhhhmod55irq3z372mh6gw4ikl2ifo34c5jra 262144 somedir/file3 262144
-bafkreib7piyesy3dr22sawmycdftrmpyt3z4tmhxrdig2zt5zdp7qwbuay 262144 somedir/file3 524288
-bafkreigxp5k3k6b3i5sldu4r3im74nfxmoptuuubcvq6rg632nfznskglu 213568 somedir/file3 786432
+bafkreidx7ivgllulfkzyoo4oa7dfrg4mjmudg2qgdivoooj4s7lh3m5nqu 1000 somedir/file1 0
+bafkreic2wqrsyr3y3qgzbvufen2w25r3p3zljckqyxkpcagsxz3zdcosd4 10000 somedir/file2 0
+bafkreiemzfmzws23c2po4m6deiueknqfty7r3voes3e3zujmobrooc2ngm 262144 somedir/file3 0
+bafkreihgm53yhxn427lnfdwhqgpawc62qejog7gega5kqb6uwbyhjm47hu 262144 somedir/file3 262144
+bafkreigl2pjptgxz6cexcnua56zc5dwsyrc4ph2eulmcb634oes6gzvmuy 262144 somedir/file3 524288
+bafkreifjcthslybjizk36xffcsb32fsbguxz3ptkl7723wz4u3qikttmam 213568 somedir/file3 786432
EOF
sort < ls_expect_file_order > ls_expect_key_order
-FILE1_HASH=bafkreicj3ezgtrh3euw2gyub6w3jydhnouqobxt7stbgtns3mv3iwv6bqq
-FILE2_HASH=bafkreibxwxisv4cld6x76ybqbvf2uwbkoswjqt4hut46af6rps2twme7ey
-FILE3_HASH=bafybeih24zygzr2orr5q62mjnbgmjwgj6rx3tp74pwcqsqth44rloncllq
+FILE1_HASH=bafkreidx7ivgllulfkzyoo4oa7dfrg4mjmudg2qgdivoooj4s7lh3m5nqu
+FILE2_HASH=bafkreic2wqrsyr3y3qgzbvufen2w25r3p3zljckqyxkpcagsxz3zdcosd4
+FILE3_HASH=bafybeietaxxjghilcjhc2m4zcmicm7yjvkjdfkamc3ct2hq4gmsb3shqsi
cat < verify_expect_file_order
-ok bafkreicj3ezgtrh3euw2gyub6w3jydhnouqobxt7stbgtns3mv3iwv6bqq 1000 somedir/file1 0
-ok bafkreibxwxisv4cld6x76ybqbvf2uwbkoswjqt4hut46af6rps2twme7ey 10000 somedir/file2 0
-ok bafkreidntk6ciin24oez6yjz4b25fgwecncvi4ua4uhr2tdyenogpzpid4 262144 somedir/file3 0
-ok bafkreidwie26yauqbhpd2nhhhmod55irq3z372mh6gw4ikl2ifo34c5jra 262144 somedir/file3 262144
-ok bafkreib7piyesy3dr22sawmycdftrmpyt3z4tmhxrdig2zt5zdp7qwbuay 262144 somedir/file3 524288
-ok bafkreigxp5k3k6b3i5sldu4r3im74nfxmoptuuubcvq6rg632nfznskglu 213568 somedir/file3 786432
+ok bafkreidx7ivgllulfkzyoo4oa7dfrg4mjmudg2qgdivoooj4s7lh3m5nqu 1000 somedir/file1 0
+ok bafkreic2wqrsyr3y3qgzbvufen2w25r3p3zljckqyxkpcagsxz3zdcosd4 10000 somedir/file2 0
+ok bafkreiemzfmzws23c2po4m6deiueknqfty7r3voes3e3zujmobrooc2ngm 262144 somedir/file3 0
+ok bafkreihgm53yhxn427lnfdwhqgpawc62qejog7gega5kqb6uwbyhjm47hu 262144 somedir/file3 262144
+ok bafkreigl2pjptgxz6cexcnua56zc5dwsyrc4ph2eulmcb634oes6gzvmuy 262144 somedir/file3 524288
+ok bafkreifjcthslybjizk36xffcsb32fsbguxz3ptkl7723wz4u3qikttmam 213568 somedir/file3 786432
EOF
sort < verify_expect_file_order > verify_expect_key_order
diff --git a/test/sharness/t0272-urlstore.sh b/test/sharness/t0272-urlstore.sh
index 8fa7ff3b81f..47e95a8ca32 100755
--- a/test/sharness/t0272-urlstore.sh
+++ b/test/sharness/t0272-urlstore.sh
@@ -10,9 +10,9 @@ test_description="Test out the urlstore functionality"
test_expect_success "create some random files" '
- random 2222 7 > file1 &&
- random 500000 7 > file2 &&
- random 50000000 7 > file3
+ random-data -size=2222 -seed=7 > file1 &&
+ random-data -size=500000 -seed=7 > file2 &&
+ random-data -size=50000000 -seed=7 > file3
'
test_urlstore() {
@@ -69,9 +69,9 @@ test_urlstore() {
'
cat < ls_expect
-bafkreiafqvawjpukk4achpu7edu4d6x5dbzwgigl6nxunjif3ser6bnfpu 262144 http://127.0.0.1:$GWAY_PORT/ipfs/QmUow2T4P69nEsqTQDZCt8yg9CPS8GFmpuDAr5YtsPhTdM 0
-bafkreia46t3jwchosehfcq7kponx26shcjkatxek4m2tzzd67i6o3frpou 237856 http://127.0.0.1:$GWAY_PORT/ipfs/QmUow2T4P69nEsqTQDZCt8yg9CPS8GFmpuDAr5YtsPhTdM 262144
-bafkreiga7ukbxrxs26fiseijjd7zdd6gmlrmnxhalwfbagxwjv7ck4o34a 2222 http://127.0.0.1:$GWAY_PORT/ipfs/QmcHm3BL2cXuQ6rJdKQgPrmT9suqGkfy2KzH3MkXPEBXU6 0
+bafkreiconmdoujderxi757nf4wjpo4ukbhlo6mmxs6pg3yl53ln3ykldvi 2222 http://127.0.0.1:$GWAY_PORT/ipfs/QmUNEBSK2uPLSZU3Dj6XbSHjdGze4huWxESx2R4Ef1cKRW 0
+bafkreifybqsfcheqkxzlhuuvoi3u6wz42kic4yqohvkia2i5fg3mpkqt3i 262144 http://127.0.0.1:$GWAY_PORT/ipfs/QmTgZc5bhTHUcqGN8rRP9oTJBv1UeJVWufPMPiUfbP9Ghs 0
+bafkreigxuuyoickqhwxu4kjckmgfqb7ygd426qiakryvvstixy523imym4 237856 http://127.0.0.1:$GWAY_PORT/ipfs/QmTgZc5bhTHUcqGN8rRP9oTJBv1UeJVWufPMPiUfbP9Ghs 262144
EOF
test_expect_success "ipfs filestore ls works with urls" '
@@ -80,9 +80,9 @@ EOF
'
cat < verify_expect
-ok bafkreiafqvawjpukk4achpu7edu4d6x5dbzwgigl6nxunjif3ser6bnfpu 262144 http://127.0.0.1:$GWAY_PORT/ipfs/QmUow2T4P69nEsqTQDZCt8yg9CPS8GFmpuDAr5YtsPhTdM 0
-ok bafkreia46t3jwchosehfcq7kponx26shcjkatxek4m2tzzd67i6o3frpou 237856 http://127.0.0.1:$GWAY_PORT/ipfs/QmUow2T4P69nEsqTQDZCt8yg9CPS8GFmpuDAr5YtsPhTdM 262144
-ok bafkreiga7ukbxrxs26fiseijjd7zdd6gmlrmnxhalwfbagxwjv7ck4o34a 2222 http://127.0.0.1:$GWAY_PORT/ipfs/QmcHm3BL2cXuQ6rJdKQgPrmT9suqGkfy2KzH3MkXPEBXU6 0
+ok bafkreifybqsfcheqkxzlhuuvoi3u6wz42kic4yqohvkia2i5fg3mpkqt3i 262144 http://127.0.0.1:$GWAY_PORT/ipfs/QmTgZc5bhTHUcqGN8rRP9oTJBv1UeJVWufPMPiUfbP9Ghs 0
+ok bafkreigxuuyoickqhwxu4kjckmgfqb7ygd426qiakryvvstixy523imym4 237856 http://127.0.0.1:$GWAY_PORT/ipfs/QmTgZc5bhTHUcqGN8rRP9oTJBv1UeJVWufPMPiUfbP9Ghs 262144
+ok bafkreiconmdoujderxi757nf4wjpo4ukbhlo6mmxs6pg3yl53ln3ykldvi 2222 http://127.0.0.1:$GWAY_PORT/ipfs/QmUNEBSK2uPLSZU3Dj6XbSHjdGze4huWxESx2R4Ef1cKRW 0
EOF
test_expect_success "ipfs filestore verify works with urls" '
@@ -116,8 +116,8 @@ EOF
'
cat < verify_expect_2
-error bafkreiafqvawjpukk4achpu7edu4d6x5dbzwgigl6nxunjif3ser6bnfpu 262144 http://127.0.0.1:$GWAY_PORT/ipfs/QmUow2T4P69nEsqTQDZCt8yg9CPS8GFmpuDAr5YtsPhTdM 0
-error bafkreia46t3jwchosehfcq7kponx26shcjkatxek4m2tzzd67i6o3frpou 237856 http://127.0.0.1:$GWAY_PORT/ipfs/QmUow2T4P69nEsqTQDZCt8yg9CPS8GFmpuDAr5YtsPhTdM 262144
+error bafkreifybqsfcheqkxzlhuuvoi3u6wz42kic4yqohvkia2i5fg3mpkqt3i 262144 http://127.0.0.1:$GWAY_PORT/ipfs/QmTgZc5bhTHUcqGN8rRP9oTJBv1UeJVWufPMPiUfbP9Ghs 0
+error bafkreigxuuyoickqhwxu4kjckmgfqb7ygd426qiakryvvstixy523imym4 237856 http://127.0.0.1:$GWAY_PORT/ipfs/QmTgZc5bhTHUcqGN8rRP9oTJBv1UeJVWufPMPiUfbP9Ghs 262144
EOF
test_expect_success "ipfs filestore verify is correct" '
diff --git a/test/sharness/t0276-cidv0v1.sh b/test/sharness/t0276-cidv0v1.sh
index 2058a9d5497..04a3456929a 100755
--- a/test/sharness/t0276-cidv0v1.sh
+++ b/test/sharness/t0276-cidv0v1.sh
@@ -15,8 +15,8 @@ test_init_ipfs
#
test_expect_success "create two small files" '
- random 1000 7 > afile
- random 1000 9 > bfile
+ random-data -size=1000 -seed=7 > afile
+ random-data -size=1000 -seed=9 > bfile
'
test_expect_success "add file using CIDv1 but don't pin" '
@@ -95,7 +95,8 @@ test_expect_success "check that we can access the file when converted to CIDv1"
#
test_expect_success "set up iptb testbed" '
- iptb testbed create -type localipfs -count 2 -init
+ iptb testbed create -type localipfs -count 2 -init &&
+ iptb run -- ipfs config --json "Routing.LoopbackAddressesOnLanDHT" true
'
test_expect_success "start nodes" '
diff --git a/test/sharness/t0500-issues-and-regressions-offline.sh b/test/sharness/t0500-issues-and-regressions-offline.sh
index 5a361aae9dc..d185e7bec33 100755
--- a/test/sharness/t0500-issues-and-regressions-offline.sh
+++ b/test/sharness/t0500-issues-and-regressions-offline.sh
@@ -22,7 +22,7 @@ test_expect_success "ipfs pin ls --help succeeds when input remains open" '
'
test_expect_success "ipfs add on 1MB from stdin woks" '
- random 1048576 42 | ipfs add -q > 1MB.hash
+ random-data -size=1048576 -seed=42 | ipfs add -q > 1MB.hash
'
test_expect_success "'ipfs refs -r -e \$(cat 1MB.hash)' succeeds" '
diff --git a/test/sharness/t0701-delegated-routing-reframe.sh b/test/sharness/t0701-delegated-routing-reframe.sh
deleted file mode 100755
index 5070b4fff16..00000000000
--- a/test/sharness/t0701-delegated-routing-reframe.sh
+++ /dev/null
@@ -1,171 +0,0 @@
-#!/usr/bin/env bash
-
-test_description="Test delegated routing via reframe endpoint"
-
-. lib/test-lib.sh
-
-if ! test_have_prereq SOCAT; then
- skip_all="skipping '$test_description': socat is not available"
- test_done
-fi
-
-# simple reframe server mock
-# local endpoint responds with deterministic application/vnd.ipfs.rpc+dag-json; version=1
-REFRAME_PORT=5098
-function start_reframe_mock_endpoint() {
- REMOTE_SERVER_LOG="reframe-server.log"
- rm -f $REMOTE_SERVER_LOG
-
- touch response
- socat tcp-listen:$REFRAME_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:$REFRAME_PORT,retry=10
- return $?
-}
-function serve_reframe_response() {
- local body=$1
- local status_code=${2:-"200 OK"}
- local length=$((1 + ${#body}))
- echo -e "HTTP/1.1 $status_code\nContent-Type: application/vnd.ipfs.rpc+dag-json; version=1\nContent-Length: $length\n\n$body" > response
-}
-function stop_reframe_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 reframe messages:
-# t0701-delegated-routing-reframe/FindProvidersRequest
-# t0701-delegated-routing-reframe/FindProvidersResponse
-FINDPROV_CID="bafybeigvgzoolc3drupxhlevdp2ugqcrbcsqfmcek2zxiw5wctk3xjpjwy"
-EXPECTED_PROV="QmQzqxhK82kAmKvARFZSkUVS6fo9sySaiogAnx5EnZ6ZmC"
-
-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 reframe endpoint
-
-ipfs config Routing.Type --json '"custom"' || exit 1
-ipfs config Routing.Routers.TestDelegatedRouter --json '{
- "Type": "reframe",
- "Parameters": {
- "Endpoint": "http://127.0.0.1:5098/reframe"
- }
-}' || 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 reframe endpoint to Routing.Routers config works" '
- echo "http://127.0.0.1:5098/reframe" > expected &&
- ipfs config Routing.Routers.TestDelegatedRouter.Parameters.Endpoint > actual &&
- test_cmp expected actual
-'
-
-test_launch_ipfs_daemon
-
-test_expect_success "start_reframe_mock_endpoint" '
- start_reframe_mock_endpoint
-'
-
-test_expect_success "'ipfs routing findprovs' returns result from delegated reframe router" '
- serve_reframe_response "$(<../t0701-delegated-routing-reframe/FindProvidersResponse)" &&
- echo "$EXPECTED_PROV" > expected &&
- ipfs routing findprovs "$FINDPROV_CID" > actual &&
- test_cmp expected actual
-'
-
-test_expect_success "stop_reframe_mock_endpoint" '
- stop_reframe_mock_endpoint
-'
-
-
-test_kill_ipfs_daemon
-test_done
-# vim: ts=2 sw=2 sts=2 et:
diff --git a/tracing/doc.go b/tracing/doc.go
index d442ea2db50..2c9711a63a1 100644
--- a/tracing/doc.go
+++ b/tracing/doc.go
@@ -6,7 +6,7 @@
//
// Tracing is configured through environment variables, as consistent with the OpenTelemetry spec as possible:
//
-// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md
+// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md
//
// OTEL_TRACES_EXPORTER: a comma-separated list of exporters:
// - otlp
diff --git a/version.go b/version.go
index d5b0642f87a..85e0ebd8d5c 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.27.0-dev"
+const CurrentVersionNumber = "0.36.0-dev"
const ApiVersion = "/kubo/" + CurrentVersionNumber + "/" //nolint