├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ └── open_an_issue.md ├── config.yml └── workflows │ ├── automerge.yml │ ├── go-check.yml │ ├── go-test.yml │ ├── release-check.yml │ ├── releaser.yml │ ├── stale.yml │ └── tagpush.yml ├── .gx └── lastpubver ├── LICENSE ├── Makefile ├── README.md ├── go.mod ├── go.sum ├── mock ├── centralized_client.go ├── centralized_server.go ├── centralized_test.go └── interface.go ├── none └── none_client.go ├── offline ├── offline.go └── offline_test.go └── version.json /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Getting Help on IPFS 4 | url: https://ipfs.io/help 5 | about: All information about how and where to get help on IPFS. 6 | - name: IPFS Official Forum 7 | url: https://discuss.ipfs.io 8 | about: Please post general questions, support requests, and discussions here. 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/open_an_issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Open an issue 3 | about: Only for actionable issues relevant to this repository. 4 | title: '' 5 | labels: need/triage 6 | assignees: '' 7 | 8 | --- 9 | 20 | -------------------------------------------------------------------------------- /.github/config.yml: -------------------------------------------------------------------------------- 1 | # Configuration for welcome - https://github.com/behaviorbot/welcome 2 | 3 | # Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome 4 | # Comment to be posted to on first time issues 5 | newIssueWelcomeComment: > 6 | Thank you for submitting your first issue to this repository! A maintainer 7 | will be here shortly to triage and review. 8 | 9 | In the meantime, please double-check that you have provided all the 10 | necessary information to make this process easy! Any information that can 11 | help save additional round trips is useful! We currently aim to give 12 | initial feedback within **two business days**. If this does not happen, feel 13 | free to leave a comment. 14 | 15 | Please keep an eye on how this issue will be labeled, as labels give an 16 | overview of priorities, assignments and additional actions requested by the 17 | maintainers: 18 | 19 | - "Priority" labels will show how urgent this is for the team. 20 | - "Status" labels will show if this is ready to be worked on, blocked, or in progress. 21 | - "Need" labels will indicate if additional input or analysis is required. 22 | 23 | Finally, remember to use https://discuss.ipfs.io if you just need general 24 | support. 25 | 26 | # Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome 27 | # Comment to be posted to on PRs from first time contributors in your repository 28 | newPRWelcomeComment: > 29 | Thank you for submitting this PR! 30 | 31 | A maintainer will be here shortly to review it. 32 | 33 | We are super grateful, but we are also overloaded! Help us by making sure 34 | that: 35 | 36 | * The context for this PR is clear, with relevant discussion, decisions 37 | and stakeholders linked/mentioned. 38 | 39 | * Your contribution itself is clear (code comments, self-review for the 40 | rest) and in its best form. Follow the [code contribution 41 | guidelines](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md#code-contribution-guidelines) 42 | if they apply. 43 | 44 | Getting other community members to do a review would be great help too on 45 | complex PRs (you can ask in the chats/forums). If you are unsure about 46 | something, just leave us a comment. 47 | 48 | Next steps: 49 | 50 | * A maintainer will triage and assign priority to this PR, commenting on 51 | any missing things and potentially assigning a reviewer for high 52 | priority items. 53 | 54 | * The PR gets reviews, discussed and approvals as needed. 55 | 56 | * The PR is merged by maintainers when it has been approved and comments addressed. 57 | 58 | We currently aim to provide initial feedback/triaging within **two business 59 | days**. Please keep an eye on any labelling actions, as these will indicate 60 | priorities and status of your contribution. 61 | 62 | We are very grateful for your contribution! 63 | 64 | 65 | # Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge 66 | # Comment to be posted to on pull requests merged by a first time user 67 | # Currently disabled 68 | #firstPRMergeComment: "" 69 | -------------------------------------------------------------------------------- /.github/workflows/automerge.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | name: Automerge 5 | on: [ pull_request ] 6 | 7 | jobs: 8 | automerge: 9 | uses: protocol/.github/.github/workflows/automerge.yml@master 10 | with: 11 | job: 'automerge' 12 | -------------------------------------------------------------------------------- /.github/workflows/go-check.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | on: [push, pull_request] 5 | name: Go Checks 6 | 7 | jobs: 8 | unit: 9 | runs-on: ubuntu-latest 10 | name: All 11 | steps: 12 | - uses: actions/checkout@v3 13 | with: 14 | submodules: recursive 15 | - id: config 16 | uses: protocol/.github/.github/actions/read-config@master 17 | - uses: actions/setup-go@v3 18 | with: 19 | go-version: 1.20.x 20 | - name: Run repo-specific setup 21 | uses: ./.github/actions/go-check-setup 22 | if: hashFiles('./.github/actions/go-check-setup') != '' 23 | - name: Install staticcheck 24 | run: go install honnef.co/go/tools/cmd/staticcheck@4970552d932f48b71485287748246cf3237cebdf # 2023.1 (v0.4.0) 25 | - name: Check that go.mod is tidy 26 | uses: protocol/multiple-go-modules@v1.2 27 | with: 28 | run: | 29 | go mod tidy 30 | if [[ -n $(git ls-files --other --exclude-standard --directory -- go.sum) ]]; then 31 | echo "go.sum was added by go mod tidy" 32 | exit 1 33 | fi 34 | git diff --exit-code -- go.sum go.mod 35 | - name: gofmt 36 | if: success() || failure() # run this step even if the previous one failed 37 | run: | 38 | out=$(gofmt -s -l .) 39 | if [[ -n "$out" ]]; then 40 | echo $out | awk '{print "::error file=" $0 ",line=0,col=0::File is not gofmt-ed."}' 41 | exit 1 42 | fi 43 | - name: go vet 44 | if: success() || failure() # run this step even if the previous one failed 45 | uses: protocol/multiple-go-modules@v1.2 46 | with: 47 | run: go vet ./... 48 | - name: staticcheck 49 | if: success() || failure() # run this step even if the previous one failed 50 | uses: protocol/multiple-go-modules@v1.2 51 | with: 52 | run: | 53 | set -o pipefail 54 | staticcheck ./... | sed -e 's@\(.*\)\.go@./\1.go@g' 55 | - name: go generate 56 | uses: protocol/multiple-go-modules@v1.2 57 | if: (success() || failure()) && fromJSON(steps.config.outputs.json).gogenerate == true 58 | with: 59 | run: | 60 | git clean -fd # make sure there aren't untracked files / directories 61 | go generate -x ./... 62 | # check if go generate modified or added any files 63 | if ! $(git add . && git diff-index HEAD --exit-code --quiet); then 64 | echo "go generated caused changes to the repository:" 65 | git status --short 66 | exit 1 67 | fi 68 | -------------------------------------------------------------------------------- /.github/workflows/go-test.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | on: [push, pull_request] 5 | name: Go Test 6 | 7 | jobs: 8 | unit: 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | os: [ "ubuntu", "windows", "macos" ] 13 | go: ["1.19.x","1.20.x"] 14 | env: 15 | COVERAGES: "" 16 | runs-on: ${{ fromJSON(vars[format('UCI_GO_TEST_RUNNER_{0}', matrix.os)] || format('"{0}-latest"', matrix.os)) }} 17 | name: ${{ matrix.os }} (go ${{ matrix.go }}) 18 | steps: 19 | - uses: actions/checkout@v3 20 | with: 21 | submodules: recursive 22 | - id: config 23 | uses: protocol/.github/.github/actions/read-config@master 24 | - uses: actions/setup-go@v3 25 | with: 26 | go-version: ${{ matrix.go }} 27 | - name: Go information 28 | run: | 29 | go version 30 | go env 31 | - name: Use msys2 on windows 32 | if: matrix.os == 'windows' 33 | shell: bash 34 | # The executable for msys2 is also called bash.cmd 35 | # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#shells 36 | # If we prepend its location to the PATH 37 | # subsequent 'shell: bash' steps will use msys2 instead of gitbash 38 | run: echo "C:/msys64/usr/bin" >> $GITHUB_PATH 39 | - name: Run repo-specific setup 40 | uses: ./.github/actions/go-test-setup 41 | if: hashFiles('./.github/actions/go-test-setup') != '' 42 | - name: Run tests 43 | if: contains(fromJSON(steps.config.outputs.json).skipOSes, matrix.os) == false 44 | uses: protocol/multiple-go-modules@v1.2 45 | with: 46 | # Use -coverpkg=./..., so that we include cross-package coverage. 47 | # If package ./A imports ./B, and ./A's tests also cover ./B, 48 | # this means ./B's coverage will be significantly higher than 0%. 49 | run: go test -v -shuffle=on -coverprofile=module-coverage.txt -coverpkg=./... ./... 50 | - name: Run tests (32 bit) 51 | # can't run 32 bit tests on OSX. 52 | if: matrix.os != 'macos' && 53 | fromJSON(steps.config.outputs.json).skip32bit != true && 54 | contains(fromJSON(steps.config.outputs.json).skipOSes, matrix.os) == false 55 | uses: protocol/multiple-go-modules@v1.2 56 | env: 57 | GOARCH: 386 58 | with: 59 | run: | 60 | export "PATH=$PATH_386:$PATH" 61 | go test -v -shuffle=on ./... 62 | - name: Run tests with race detector 63 | # speed things up. Windows and OSX VMs are slow 64 | if: matrix.os == 'ubuntu' && 65 | contains(fromJSON(steps.config.outputs.json).skipOSes, matrix.os) == false 66 | uses: protocol/multiple-go-modules@v1.2 67 | with: 68 | run: go test -v -race ./... 69 | - name: Collect coverage files 70 | shell: bash 71 | run: echo "COVERAGES=$(find . -type f -name 'module-coverage.txt' | tr -s '\n' ',' | sed 's/,$//')" >> $GITHUB_ENV 72 | - name: Upload coverage to Codecov 73 | uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 74 | with: 75 | files: '${{ env.COVERAGES }}' 76 | env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }} 77 | -------------------------------------------------------------------------------- /.github/workflows/release-check.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | name: Release Checker 5 | on: 6 | pull_request_target: 7 | paths: [ 'version.json' ] 8 | 9 | jobs: 10 | release-check: 11 | uses: protocol/.github/.github/workflows/release-check.yml@master 12 | with: 13 | go-version: 1.20.x 14 | -------------------------------------------------------------------------------- /.github/workflows/releaser.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | name: Releaser 5 | on: 6 | push: 7 | paths: [ 'version.json' ] 8 | 9 | jobs: 10 | releaser: 11 | uses: protocol/.github/.github/workflows/releaser.yml@master 12 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Close and mark stale issue 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | 7 | jobs: 8 | stale: 9 | uses: pl-strflt/.github/.github/workflows/reusable-stale-issue.yml@v0.3 10 | -------------------------------------------------------------------------------- /.github/workflows/tagpush.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | name: Tag Push Checker 5 | on: 6 | push: 7 | tags: 8 | - v* 9 | 10 | jobs: 11 | releaser: 12 | uses: protocol/.github/.github/workflows/tagpush.yml@master 13 | -------------------------------------------------------------------------------- /.gx/lastpubver: -------------------------------------------------------------------------------- 1 | 0.1.18: QmZ22s3UgNi5vvYNH79jWJ63NPyQGiv4mdNaWCz4WKqMTZ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 IPFS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: deps 2 | gx: 3 | go get github.com/whyrusleeping/gx 4 | go get github.com/whyrusleeping/gx-go 5 | deps: gx 6 | gx --verbose install --global 7 | gx-go rewrite 8 | test: deps 9 | gx test -v -race ./... 10 | rw: 11 | gx-go rewrite 12 | rwundo: 13 | gx-go rewrite --undo 14 | publish: rwundo 15 | gx publish 16 | .PHONY: all gx deps test rw rwundo publish 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-ipfs-routing 2 | 3 | [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) 4 | [![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/) 5 | [![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) 6 | [![Build Status](https://travis-ci.org/ipfs/go-ipfs-routing.svg?branch=master)](https://travis-ci.org/ipfs/go-ipfs-routing) 7 | 8 | > go-ipfs-routing provides go-libp2p-routing implementations used in go-ipfs. 9 | 10 | ## ❗ This repo is no longer maintained. 11 | 👉 We highly recommend switching to the maintained version at https://github.com/ipfs/boxo/tree/main/routing. 12 | 🏎️ Good news! There is [tooling and documentation](https://github.com/ipfs/boxo#migrating-to-boxo) to expedite a switch in your repo. 13 | 14 | ⚠️ If you continue using this repo, please note that security fixes will not be provided (unless someone steps in to maintain it). 15 | 16 | 📚 Learn more, including how to take the maintainership mantle or ask questions, [here](https://github.com/ipfs/boxo/wiki/Copied-or-Migrated-Repos-FAQ). 17 | 18 | 19 | ## Table of Contents 20 | 21 | - [Install](#install) 22 | - [Usage](#usage) 23 | - [License](#license) 24 | 25 | ## Install 26 | 27 | `go-ipfs-routing` works like a set of regular Go packages: 28 | 29 | ``` 30 | > go get github.com/ipfs/go-ipfs-routing/... 31 | ``` 32 | 33 | This module uses [Gx](https://github.com/whyrusleeping/gx) to manage 34 | dependencies. You can use `make all` to build it with the `gx` dependencies. 35 | 36 | ## Usage 37 | 38 | This repo contains 3 different packages. 39 | 40 | ### Mock 41 | 42 | [![GoDoc](https://godoc.org/github.com/ipfs/go-ipfs-routing/mock?status.svg)](https://godoc.org/github.com/ipfs/go-ipfs-routing/mock) 43 | 44 | ``` 45 | import "github.com/ipfs/go-ipfs-routing/mock" 46 | ``` 47 | 48 | Mock is a fake router useful for tests. It provides a mock client that 49 | implements the `IpfsRouting` interface and a mock server from which the client 50 | retrieves routing records. 51 | 52 | 53 | ### Offline 54 | 55 | [![GoDoc](https://godoc.org/github.com/ipfs/go-ipfs-routing/offline?status.svg)](https://godoc.org/github.com/ipfs/go-ipfs-routing/offline) 56 | 57 | ``` 58 | import "github.com/ipfs/go-ipfs-routing/offline" 59 | ``` 60 | 61 | Offline is an offline router that can put and get records to and from a local 62 | `Datastore` but can't retrieve them from the network. 63 | 64 | ### None 65 | 66 | [![GoDoc](https://godoc.org/github.com/ipfs/go-ipfs-routing/none?status.svg)](https://godoc.org/github.com/ipfs/go-ipfs-routing/none) 67 | 68 | ``` 69 | import "github.com/ipfs/go-ipfs-routing/none" 70 | ``` 71 | 72 | None is a router no-op router that doesn't do anything. Puts always succeed and 73 | lookups always fail. 74 | 75 | ## License 76 | 77 | MIT © Protocol Labs, Inc. 78 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ipfs/go-ipfs-routing 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/gogo/protobuf v1.3.2 7 | github.com/ipfs/go-cid v0.3.2 8 | github.com/ipfs/go-datastore v0.6.0 9 | github.com/ipfs/go-ipfs-delay v0.0.1 10 | github.com/ipfs/go-ipfs-ds-help v1.1.0 11 | github.com/ipfs/go-ipfs-util v0.0.2 12 | github.com/ipfs/go-log v0.0.1 13 | github.com/libp2p/go-libp2p v0.22.0 14 | github.com/libp2p/go-libp2p-record v0.2.0 15 | github.com/libp2p/go-libp2p-testing v0.12.0 16 | github.com/multiformats/go-multiaddr v0.7.0 17 | github.com/multiformats/go-multihash v0.2.1 18 | ) 19 | 20 | require ( 21 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect 22 | github.com/google/uuid v1.3.0 // indirect 23 | github.com/jbenet/goprocess v0.1.4 // indirect 24 | github.com/klauspost/cpuid/v2 v2.1.0 // indirect 25 | github.com/libp2p/go-buffer-pool v0.1.0 // indirect 26 | github.com/libp2p/go-openssl v0.1.0 // indirect 27 | github.com/mattn/go-colorable v0.1.1 // indirect 28 | github.com/mattn/go-isatty v0.0.16 // indirect 29 | github.com/mattn/go-pointer v0.0.1 // indirect 30 | github.com/minio/sha256-simd v1.0.0 // indirect 31 | github.com/mr-tron/base58 v1.2.0 // indirect 32 | github.com/multiformats/go-base32 v0.0.4 // indirect 33 | github.com/multiformats/go-base36 v0.1.0 // indirect 34 | github.com/multiformats/go-multibase v0.1.1 // indirect 35 | github.com/multiformats/go-multicodec v0.5.0 // indirect 36 | github.com/multiformats/go-varint v0.0.6 // indirect 37 | github.com/opentracing/opentracing-go v1.0.2 // indirect 38 | github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect 39 | github.com/spaolacci/murmur3 v1.1.0 // indirect 40 | github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc // indirect 41 | golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect 42 | golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect 43 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect 44 | lukechampine.com/blake3 v1.1.7 // indirect 45 | ) 46 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 4 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= 6 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= 7 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= 8 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 9 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 10 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 11 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 12 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 13 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 14 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 15 | github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= 16 | github.com/ipfs/go-cid v0.3.2 h1:OGgOd+JCFM+y1DjWPmVH+2/4POtpDzwcr7VgnB7mZXc= 17 | github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svoupw= 18 | github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= 19 | github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk= 20 | github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8= 21 | github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= 22 | github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= 23 | github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= 24 | github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= 25 | github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= 26 | github.com/ipfs/go-ipfs-ds-help v1.1.0 h1:yLE2w9RAsl31LtfMt91tRZcrx+e61O5mDxFRR994w4Q= 27 | github.com/ipfs/go-ipfs-ds-help v1.1.0/go.mod h1:YR5+6EaebOhfcqVCyqemItCLthrpVNot+rsOU/5IatU= 28 | github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= 29 | github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= 30 | github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= 31 | github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= 32 | github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= 33 | github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= 34 | github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= 35 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 36 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 37 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 38 | github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 39 | github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 40 | github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0= 41 | github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= 42 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 43 | github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= 44 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 45 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 46 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 47 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 48 | github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= 49 | github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= 50 | github.com/libp2p/go-libp2p v0.22.0 h1:2Tce0kHOp5zASFKJbNzRElvh0iZwdtG5uZheNW8chIw= 51 | github.com/libp2p/go-libp2p v0.22.0/go.mod h1:UDolmweypBSjQb2f7xutPnwZ/fxioLbMBxSjRksxxU4= 52 | github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0= 53 | github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk= 54 | github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= 55 | github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= 56 | github.com/libp2p/go-openssl v0.1.0 h1:LBkKEcUv6vtZIQLVTegAil8jbNpJErQ9AnT+bWV+Ooo= 57 | github.com/libp2p/go-openssl v0.1.0/go.mod h1:OiOxwPpL3n4xlenjx2h7AwSGaFSC/KZvf6gNdOBQMtc= 58 | github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= 59 | github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= 60 | github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 61 | github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= 62 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 63 | github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= 64 | github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= 65 | github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= 66 | github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= 67 | github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= 68 | github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= 69 | github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= 70 | github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 71 | github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= 72 | github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 73 | github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= 74 | github.com/multiformats/go-base32 v0.0.4 h1:+qMh4a2f37b4xTNs6mqitDinryCI+tfO2dRVMN9mjSE= 75 | github.com/multiformats/go-base32 v0.0.4/go.mod h1:jNLFzjPZtp3aIARHbJRZIaPuspdH0J6q39uUM5pnABM= 76 | github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= 77 | github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= 78 | github.com/multiformats/go-multiaddr v0.7.0 h1:gskHcdaCyPtp9XskVwtvEeQOG465sCohbQIirSyqxrc= 79 | github.com/multiformats/go-multiaddr v0.7.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs= 80 | github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= 81 | github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI= 82 | github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8= 83 | github.com/multiformats/go-multicodec v0.5.0 h1:EgU6cBe/D7WRwQb1KmnBvU7lrcFGMggZVTPtOW9dDHs= 84 | github.com/multiformats/go-multicodec v0.5.0/go.mod h1:DiY2HFaEp5EhEXb/iYzVAunmyX/aSFMxq2KMKfWEues= 85 | github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= 86 | github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= 87 | github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= 88 | github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 89 | github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= 90 | github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 91 | github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= 92 | github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 93 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 94 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 95 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 96 | github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= 97 | github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= 98 | github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= 99 | github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 100 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 101 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 102 | github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= 103 | github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= 104 | github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= 105 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 106 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 107 | go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 108 | go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 109 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 110 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 111 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 112 | golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 113 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 114 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 115 | golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= 116 | golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 117 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 118 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 119 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 120 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 121 | golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 122 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 123 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 124 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 125 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 126 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 127 | golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E= 128 | golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= 129 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 130 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 131 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 132 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 133 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 134 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 135 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 136 | golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 137 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= 138 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 139 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 140 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 141 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 142 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 143 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 144 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 145 | golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 146 | golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 147 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 148 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 149 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 150 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 151 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 152 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 153 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 154 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 155 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 156 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 157 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 158 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 159 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 160 | lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= 161 | lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= 162 | -------------------------------------------------------------------------------- /mock/centralized_client.go: -------------------------------------------------------------------------------- 1 | package mockrouting 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/ipfs/go-cid" 8 | logging "github.com/ipfs/go-log" 9 | tnet "github.com/libp2p/go-libp2p-testing/net" 10 | "github.com/libp2p/go-libp2p/core/peer" 11 | "github.com/libp2p/go-libp2p/core/routing" 12 | ma "github.com/multiformats/go-multiaddr" 13 | ) 14 | 15 | var log = logging.Logger("mockrouter") 16 | 17 | type client struct { 18 | vs routing.ValueStore 19 | server server 20 | peer tnet.Identity 21 | } 22 | 23 | // PutValue FIXME(brian): is this method meant to simulate putting a value into the network? 24 | func (c *client) PutValue(ctx context.Context, key string, val []byte, opts ...routing.Option) error { 25 | log.Debugf("PutValue: %s", key) 26 | return c.vs.PutValue(ctx, key, val, opts...) 27 | } 28 | 29 | // GetValue FIXME(brian): is this method meant to simulate getting a value from the network? 30 | func (c *client) GetValue(ctx context.Context, key string, opts ...routing.Option) ([]byte, error) { 31 | log.Debugf("GetValue: %s", key) 32 | return c.vs.GetValue(ctx, key, opts...) 33 | } 34 | 35 | func (c *client) SearchValue(ctx context.Context, key string, opts ...routing.Option) (<-chan []byte, error) { 36 | log.Debugf("SearchValue: %s", key) 37 | return c.vs.SearchValue(ctx, key, opts...) 38 | } 39 | 40 | func (c *client) FindProviders(ctx context.Context, key cid.Cid) ([]peer.AddrInfo, error) { 41 | return c.server.Providers(key), nil 42 | } 43 | 44 | func (c *client) FindPeer(ctx context.Context, pid peer.ID) (peer.AddrInfo, error) { 45 | log.Debugf("FindPeer: %s", pid) 46 | return peer.AddrInfo{}, nil 47 | } 48 | 49 | func (c *client) FindProvidersAsync(ctx context.Context, k cid.Cid, max int) <-chan peer.AddrInfo { 50 | out := make(chan peer.AddrInfo) 51 | go func() { 52 | defer close(out) 53 | for i, p := range c.server.Providers(k) { 54 | if max <= i { 55 | return 56 | } 57 | select { 58 | case out <- p: 59 | case <-ctx.Done(): 60 | return 61 | } 62 | } 63 | }() 64 | return out 65 | } 66 | 67 | // Provide returns once the message is on the network. Value is not necessarily 68 | // visible yet. 69 | func (c *client) Provide(_ context.Context, key cid.Cid, brd bool) error { 70 | if !brd { 71 | return nil 72 | } 73 | info := peer.AddrInfo{ 74 | ID: c.peer.ID(), 75 | Addrs: []ma.Multiaddr{c.peer.Address()}, 76 | } 77 | return c.server.Announce(info, key) 78 | } 79 | 80 | func (c *client) Ping(ctx context.Context, p peer.ID) (time.Duration, error) { 81 | return 0, nil 82 | } 83 | 84 | func (c *client) Bootstrap(context.Context) error { 85 | return nil 86 | } 87 | 88 | var _ routing.Routing = &client{} 89 | -------------------------------------------------------------------------------- /mock/centralized_server.go: -------------------------------------------------------------------------------- 1 | package mockrouting 2 | 3 | import ( 4 | "context" 5 | "math/rand" 6 | "sync" 7 | "time" 8 | 9 | "github.com/ipfs/go-cid" 10 | ds "github.com/ipfs/go-datastore" 11 | dssync "github.com/ipfs/go-datastore/sync" 12 | "github.com/ipfs/go-ipfs-routing/offline" 13 | tnet "github.com/libp2p/go-libp2p-testing/net" 14 | "github.com/libp2p/go-libp2p/core/peer" 15 | ) 16 | 17 | // server is the mockrouting.Client's private interface to the routing server 18 | type server interface { 19 | Announce(peer.AddrInfo, cid.Cid) error 20 | Providers(cid.Cid) []peer.AddrInfo 21 | 22 | Server 23 | } 24 | 25 | // s is an implementation of the private server interface 26 | type s struct { 27 | delayConf DelayConfig 28 | 29 | lock sync.RWMutex 30 | providers map[string]map[peer.ID]providerRecord 31 | } 32 | 33 | type providerRecord struct { 34 | Peer peer.AddrInfo 35 | Created time.Time 36 | } 37 | 38 | func (rs *s) Announce(p peer.AddrInfo, c cid.Cid) error { 39 | rs.lock.Lock() 40 | defer rs.lock.Unlock() 41 | 42 | k := c.KeyString() 43 | 44 | _, ok := rs.providers[k] 45 | if !ok { 46 | rs.providers[k] = make(map[peer.ID]providerRecord) 47 | } 48 | rs.providers[k][p.ID] = providerRecord{ 49 | Created: time.Now(), 50 | Peer: p, 51 | } 52 | return nil 53 | } 54 | 55 | func (rs *s) Providers(c cid.Cid) []peer.AddrInfo { 56 | rs.delayConf.Query.Wait() // before locking 57 | 58 | rs.lock.RLock() 59 | defer rs.lock.RUnlock() 60 | k := c.KeyString() 61 | 62 | var ret []peer.AddrInfo 63 | records, ok := rs.providers[k] 64 | if !ok { 65 | return ret 66 | } 67 | for _, r := range records { 68 | if time.Since(r.Created) > rs.delayConf.ValueVisibility.Get() { 69 | ret = append(ret, r.Peer) 70 | } 71 | } 72 | 73 | for i := range ret { 74 | j := rand.Intn(i + 1) 75 | ret[i], ret[j] = ret[j], ret[i] 76 | } 77 | 78 | return ret 79 | } 80 | 81 | func (rs *s) Client(p tnet.Identity) Client { 82 | return rs.ClientWithDatastore(context.Background(), p, dssync.MutexWrap(ds.NewMapDatastore())) 83 | } 84 | 85 | func (rs *s) ClientWithDatastore(_ context.Context, p tnet.Identity, datastore ds.Datastore) Client { 86 | return &client{ 87 | peer: p, 88 | vs: offline.NewOfflineRouter(datastore, MockValidator{}), 89 | server: rs, 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /mock/centralized_test.go: -------------------------------------------------------------------------------- 1 | package mockrouting 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | "time" 7 | 8 | "github.com/ipfs/go-cid" 9 | delay "github.com/ipfs/go-ipfs-delay" 10 | u "github.com/ipfs/go-ipfs-util" 11 | tnet "github.com/libp2p/go-libp2p-testing/net" 12 | "github.com/libp2p/go-libp2p/core/peer" 13 | ) 14 | 15 | func TestKeyNotFound(t *testing.T) { 16 | 17 | var pi = tnet.RandIdentityOrFatal(t) 18 | var key = cid.NewCidV0(u.Hash([]byte("mock key"))) 19 | var ctx = context.Background() 20 | 21 | rs := NewServer() 22 | providers := rs.Client(pi).FindProvidersAsync(ctx, key, 10) 23 | _, ok := <-providers 24 | if ok { 25 | t.Fatal("should be closed") 26 | } 27 | } 28 | 29 | func TestClientFindProviders(t *testing.T) { 30 | pi := tnet.RandIdentityOrFatal(t) 31 | rs := NewServer() 32 | client := rs.Client(pi) 33 | 34 | k := cid.NewCidV0(u.Hash([]byte("hello"))) 35 | err := client.Provide(context.Background(), k, true) 36 | if err != nil { 37 | t.Fatal(err) 38 | } 39 | 40 | // This is bad... but simulating networks is hard 41 | time.Sleep(time.Millisecond * 300) 42 | max := 100 43 | 44 | providersFromClient := client.FindProvidersAsync(context.Background(), k, max) 45 | isInClient := false 46 | for p := range providersFromClient { 47 | if p.ID == pi.ID() { 48 | isInClient = true 49 | } 50 | } 51 | if !isInClient { 52 | t.Fatal("Despite client providing key, client didn't receive peer when finding providers") 53 | } 54 | } 55 | 56 | func TestClientOverMax(t *testing.T) { 57 | rs := NewServer() 58 | k := cid.NewCidV0(u.Hash([]byte("hello"))) 59 | numProvidersForHelloKey := 100 60 | for i := 0; i < numProvidersForHelloKey; i++ { 61 | pi := tnet.RandIdentityOrFatal(t) 62 | err := rs.Client(pi).Provide(context.Background(), k, true) 63 | if err != nil { 64 | t.Fatal(err) 65 | } 66 | } 67 | 68 | max := 10 69 | pi := tnet.RandIdentityOrFatal(t) 70 | client := rs.Client(pi) 71 | 72 | providersFromClient := client.FindProvidersAsync(context.Background(), k, max) 73 | i := 0 74 | for range providersFromClient { 75 | i++ 76 | } 77 | if i != max { 78 | t.Fatal("Too many providers returned") 79 | } 80 | } 81 | 82 | // TODO does dht ensure won't receive self as a provider? probably not. 83 | func TestCanceledContext(t *testing.T) { 84 | rs := NewServer() 85 | k := cid.NewCidV0(u.Hash([]byte("hello"))) 86 | 87 | // avoid leaking goroutine, without using the context to signal 88 | // (we want the goroutine to keep trying to publish on a 89 | // cancelled context until we've tested it doesnt do anything.) 90 | done := make(chan struct{}) 91 | defer func() { done <- struct{}{} }() 92 | 93 | t.Log("async'ly announce infinite stream of providers for key") 94 | i := 0 95 | go func() { // infinite stream 96 | for { 97 | select { 98 | case <-done: 99 | t.Log("exiting async worker") 100 | return 101 | default: 102 | } 103 | 104 | pi, err := tnet.RandIdentity() 105 | if err != nil { 106 | t.Error(err) 107 | } 108 | err = rs.Client(pi).Provide(context.Background(), k, true) 109 | if err != nil { 110 | t.Error(err) 111 | } 112 | i++ 113 | } 114 | }() 115 | 116 | local := tnet.RandIdentityOrFatal(t) 117 | client := rs.Client(local) 118 | 119 | t.Log("warning: max is finite so this test is non-deterministic") 120 | t.Log("context cancellation could simply take lower priority") 121 | t.Log("and result in receiving the max number of results") 122 | max := 1000 123 | 124 | t.Log("cancel the context before consuming") 125 | ctx, cancelFunc := context.WithCancel(context.Background()) 126 | cancelFunc() 127 | providers := client.FindProvidersAsync(ctx, k, max) 128 | 129 | numProvidersReturned := 0 130 | for range providers { 131 | numProvidersReturned++ 132 | } 133 | t.Log(numProvidersReturned) 134 | 135 | if numProvidersReturned == max { 136 | t.Fatal("Context cancel had no effect") 137 | } 138 | } 139 | 140 | func TestValidAfter(t *testing.T) { 141 | ctx, cancel := context.WithCancel(context.Background()) 142 | defer cancel() 143 | 144 | pi := tnet.RandIdentityOrFatal(t) 145 | key := cid.NewCidV0(u.Hash([]byte("mock key"))) 146 | conf := DelayConfig{ 147 | ValueVisibility: delay.Fixed(1 * time.Hour), 148 | Query: delay.Fixed(0), 149 | } 150 | 151 | rs := NewServerWithDelay(conf) 152 | 153 | rs.Client(pi).Provide(ctx, key, true) 154 | 155 | var providers []peer.AddrInfo 156 | max := 100 157 | providersChan := rs.Client(pi).FindProvidersAsync(ctx, key, max) 158 | for p := range providersChan { 159 | providers = append(providers, p) 160 | } 161 | if len(providers) > 0 { 162 | t.Fail() 163 | } 164 | 165 | conf.ValueVisibility.Set(0) 166 | time.Sleep(100 * time.Millisecond) 167 | 168 | providersChan = rs.Client(pi).FindProvidersAsync(ctx, key, max) 169 | t.Log("providers", providers) 170 | for p := range providersChan { 171 | providers = append(providers, p) 172 | } 173 | if len(providers) != 1 { 174 | t.Fail() 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /mock/interface.go: -------------------------------------------------------------------------------- 1 | // Package mockrouting provides a virtual routing server. To use it, 2 | // create a virtual routing server and use the Client() method to get a 3 | // routing client (Routing). The server quacks like a DHT but is 4 | // really a local in-memory hash table. 5 | package mockrouting 6 | 7 | import ( 8 | "context" 9 | 10 | ds "github.com/ipfs/go-datastore" 11 | delay "github.com/ipfs/go-ipfs-delay" 12 | tnet "github.com/libp2p/go-libp2p-testing/net" 13 | "github.com/libp2p/go-libp2p/core/peer" 14 | "github.com/libp2p/go-libp2p/core/routing" 15 | ) 16 | 17 | // MockValidator is a record validator that always returns success. 18 | // 19 | // Deprecated: use github.com/ipfs/boxo/routing/mock.MockValidator 20 | type MockValidator struct{} 21 | 22 | func (MockValidator) Validate(_ string, _ []byte) error { return nil } 23 | func (MockValidator) Select(_ string, _ [][]byte) (int, error) { return 0, nil } 24 | 25 | // Server provides mockrouting Clients 26 | // 27 | // Deprecated: use github.com/ipfs/boxo/routing/mock.Server 28 | type Server interface { 29 | Client(p tnet.Identity) Client 30 | ClientWithDatastore(context.Context, tnet.Identity, ds.Datastore) Client 31 | } 32 | 33 | // Client implements Routing 34 | // 35 | // Deprecated: use github.com/ipfs/boxo/routing/mock.Client 36 | type Client interface { 37 | routing.Routing 38 | } 39 | 40 | // NewServer returns a mockrouting Server 41 | // 42 | // Deprecated: use github.com/ipfs/boxo/routing/mock.NewServer 43 | func NewServer() Server { 44 | return NewServerWithDelay(DelayConfig{ 45 | ValueVisibility: delay.Fixed(0), 46 | Query: delay.Fixed(0), 47 | }) 48 | } 49 | 50 | // NewServerWithDelay returns a mockrouting Server with a delay! 51 | // 52 | // Deprecated: use github.com/ipfs/boxo/routing/mock.NewServerWithDelay 53 | func NewServerWithDelay(conf DelayConfig) Server { 54 | return &s{ 55 | providers: make(map[string]map[peer.ID]providerRecord), 56 | delayConf: conf, 57 | } 58 | } 59 | 60 | // DelayConfig can be used to configured the fake delays of a mock server. 61 | // Use with NewServerWithDelay(). 62 | // 63 | // Deprecated: use github.com/ipfs/boxo/routing/mock.DelayConfig 64 | type DelayConfig struct { 65 | // ValueVisibility is the time it takes for a value to be visible in the network 66 | // FIXME there _must_ be a better term for this 67 | ValueVisibility delay.D 68 | 69 | // Query is the time it takes to receive a response from a routing query 70 | Query delay.D 71 | } 72 | -------------------------------------------------------------------------------- /none/none_client.go: -------------------------------------------------------------------------------- 1 | // Package nilrouting implements a routing client that does nothing. 2 | package nilrouting 3 | 4 | import ( 5 | "context" 6 | "errors" 7 | 8 | "github.com/ipfs/go-cid" 9 | ds "github.com/ipfs/go-datastore" 10 | record "github.com/libp2p/go-libp2p-record" 11 | "github.com/libp2p/go-libp2p/core/host" 12 | "github.com/libp2p/go-libp2p/core/peer" 13 | "github.com/libp2p/go-libp2p/core/routing" 14 | ) 15 | 16 | type nilclient struct { 17 | } 18 | 19 | func (c *nilclient) PutValue(_ context.Context, _ string, _ []byte, _ ...routing.Option) error { 20 | return nil 21 | } 22 | 23 | func (c *nilclient) GetValue(_ context.Context, _ string, _ ...routing.Option) ([]byte, error) { 24 | return nil, errors.New("tried GetValue from nil routing") 25 | } 26 | 27 | func (c *nilclient) SearchValue(_ context.Context, _ string, _ ...routing.Option) (<-chan []byte, error) { 28 | return nil, errors.New("tried SearchValue from nil routing") 29 | } 30 | 31 | func (c *nilclient) FindPeer(_ context.Context, _ peer.ID) (peer.AddrInfo, error) { 32 | return peer.AddrInfo{}, nil 33 | } 34 | 35 | func (c *nilclient) FindProvidersAsync(_ context.Context, _ cid.Cid, _ int) <-chan peer.AddrInfo { 36 | out := make(chan peer.AddrInfo) 37 | defer close(out) 38 | return out 39 | } 40 | 41 | func (c *nilclient) Provide(_ context.Context, _ cid.Cid, _ bool) error { 42 | return nil 43 | } 44 | 45 | func (c *nilclient) Bootstrap(_ context.Context) error { 46 | return nil 47 | } 48 | 49 | // ConstructNilRouting creates an Routing client which does nothing. 50 | // 51 | // Deprecated: use github.com/ipfs/boxo/routing/none.ConstructNilRouting 52 | func ConstructNilRouting(_ context.Context, _ host.Host, _ ds.Batching, _ record.Validator) (routing.Routing, error) { 53 | return &nilclient{}, nil 54 | } 55 | 56 | // ensure nilclient satisfies interface 57 | var _ routing.Routing = &nilclient{} 58 | -------------------------------------------------------------------------------- /offline/offline.go: -------------------------------------------------------------------------------- 1 | // Package offline implements Routing with a client which 2 | // is only able to perform offline operations. 3 | package offline 4 | 5 | import ( 6 | "bytes" 7 | "context" 8 | "errors" 9 | "time" 10 | 11 | "github.com/gogo/protobuf/proto" 12 | "github.com/ipfs/go-cid" 13 | ds "github.com/ipfs/go-datastore" 14 | dshelp "github.com/ipfs/go-ipfs-ds-help" 15 | record "github.com/libp2p/go-libp2p-record" 16 | pb "github.com/libp2p/go-libp2p-record/pb" 17 | "github.com/libp2p/go-libp2p/core/peer" 18 | "github.com/libp2p/go-libp2p/core/routing" 19 | ) 20 | 21 | // ErrOffline is returned when trying to perform operations that 22 | // require connectivity. 23 | // 24 | // Deprecated: use github.com/ipfs/boxo/routing/offline.ErrOffline 25 | var ErrOffline = errors.New("routing system in offline mode") 26 | 27 | // NewOfflineRouter returns an Routing implementation which only performs 28 | // offline operations. It allows to Put and Get signed dht 29 | // records to and from the local datastore. 30 | // 31 | // Deprecated: use github.com/ipfs/boxo/routing/offline.NewOfflineRouter 32 | func NewOfflineRouter(dstore ds.Datastore, validator record.Validator) routing.Routing { 33 | return &offlineRouting{ 34 | datastore: dstore, 35 | validator: validator, 36 | } 37 | } 38 | 39 | // offlineRouting implements the Routing interface, 40 | // but only provides the capability to Put and Get signed dht 41 | // records to and from the local datastore. 42 | type offlineRouting struct { 43 | datastore ds.Datastore 44 | validator record.Validator 45 | } 46 | 47 | func (c *offlineRouting) PutValue(ctx context.Context, key string, val []byte, _ ...routing.Option) error { 48 | if err := c.validator.Validate(key, val); err != nil { 49 | return err 50 | } 51 | if old, err := c.GetValue(ctx, key); err == nil { 52 | // be idempotent to be nice. 53 | if bytes.Equal(old, val) { 54 | return nil 55 | } 56 | // check to see if the older record is better 57 | i, err := c.validator.Select(key, [][]byte{val, old}) 58 | if err != nil { 59 | // this shouldn't happen for validated records. 60 | return err 61 | } 62 | if i != 0 { 63 | return errors.New("can't replace a newer record with an older one") 64 | } 65 | } 66 | rec := record.MakePutRecord(key, val) 67 | data, err := proto.Marshal(rec) 68 | if err != nil { 69 | return err 70 | } 71 | 72 | return c.datastore.Put(ctx, dshelp.NewKeyFromBinary([]byte(key)), data) 73 | } 74 | 75 | func (c *offlineRouting) GetValue(ctx context.Context, key string, _ ...routing.Option) ([]byte, error) { 76 | buf, err := c.datastore.Get(ctx, dshelp.NewKeyFromBinary([]byte(key))) 77 | if err != nil { 78 | return nil, err 79 | } 80 | 81 | rec := new(pb.Record) 82 | err = proto.Unmarshal(buf, rec) 83 | if err != nil { 84 | return nil, err 85 | } 86 | val := rec.GetValue() 87 | 88 | err = c.validator.Validate(key, val) 89 | if err != nil { 90 | return nil, err 91 | } 92 | return val, nil 93 | } 94 | 95 | func (c *offlineRouting) SearchValue(ctx context.Context, key string, _ ...routing.Option) (<-chan []byte, error) { 96 | out := make(chan []byte, 1) 97 | go func() { 98 | defer close(out) 99 | v, err := c.GetValue(ctx, key) 100 | if err == nil { 101 | out <- v 102 | } 103 | }() 104 | return out, nil 105 | } 106 | 107 | func (c *offlineRouting) FindPeer(ctx context.Context, pid peer.ID) (peer.AddrInfo, error) { 108 | return peer.AddrInfo{}, ErrOffline 109 | } 110 | 111 | func (c *offlineRouting) FindProvidersAsync(ctx context.Context, k cid.Cid, max int) <-chan peer.AddrInfo { 112 | out := make(chan peer.AddrInfo) 113 | close(out) 114 | return out 115 | } 116 | 117 | func (c *offlineRouting) Provide(_ context.Context, k cid.Cid, _ bool) error { 118 | return ErrOffline 119 | } 120 | 121 | func (c *offlineRouting) Ping(ctx context.Context, p peer.ID) (time.Duration, error) { 122 | return 0, ErrOffline 123 | } 124 | 125 | func (c *offlineRouting) Bootstrap(context.Context) error { 126 | return nil 127 | } 128 | 129 | // ensure offlineRouting matches the Routing interface 130 | var _ routing.Routing = &offlineRouting{} 131 | -------------------------------------------------------------------------------- /offline/offline_test.go: -------------------------------------------------------------------------------- 1 | package offline 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "testing" 7 | 8 | cid "github.com/ipfs/go-cid" 9 | ds "github.com/ipfs/go-datastore" 10 | 11 | "github.com/libp2p/go-libp2p/core/routing" 12 | "github.com/libp2p/go-libp2p/core/test" 13 | 14 | mh "github.com/multiformats/go-multihash" 15 | ) 16 | 17 | type blankValidator struct{} 18 | 19 | func (blankValidator) Validate(_ string, _ []byte) error { return nil } 20 | func (blankValidator) Select(_ string, _ [][]byte) (int, error) { return 0, nil } 21 | 22 | func TestOfflineRouterStorage(t *testing.T) { 23 | ctx := context.Background() 24 | 25 | nds := ds.NewMapDatastore() 26 | offline := NewOfflineRouter(nds, blankValidator{}) 27 | 28 | if err := offline.PutValue(ctx, "key", []byte("testing 1 2 3")); err != nil { 29 | t.Fatal(err) 30 | } 31 | 32 | val, err := offline.GetValue(ctx, "key") 33 | if err != nil { 34 | t.Fatal(err) 35 | } 36 | if !bytes.Equal([]byte("testing 1 2 3"), val) { 37 | t.Fatal("OfflineRouter does not properly store") 38 | } 39 | 40 | _, err = offline.GetValue(ctx, "notHere") 41 | if err == nil { 42 | t.Fatal("Router should throw errors for unfound records") 43 | } 44 | 45 | local, err := offline.GetValue(ctx, "key", routing.Offline) 46 | if err != nil { 47 | t.Fatal(err) 48 | } 49 | 50 | _, err = offline.GetValue(ctx, "notHere", routing.Offline) 51 | if err == nil { 52 | t.Fatal("Router should throw errors for unfound records") 53 | } 54 | 55 | if !bytes.Equal([]byte("testing 1 2 3"), local) { 56 | t.Fatal("OfflineRouter does not properly store") 57 | } 58 | } 59 | 60 | func TestOfflineRouterLocal(t *testing.T) { 61 | ctx := context.Background() 62 | 63 | nds := ds.NewMapDatastore() 64 | offline := NewOfflineRouter(nds, blankValidator{}) 65 | 66 | id, _ := test.RandPeerID() 67 | _, err := offline.FindPeer(ctx, id) 68 | if err != ErrOffline { 69 | t.Fatal("OfflineRouting should alert that its offline") 70 | } 71 | 72 | h, _ := mh.Sum([]byte("test data1"), mh.SHA2_256, -1) 73 | c1 := cid.NewCidV0(h) 74 | pChan := offline.FindProvidersAsync(ctx, c1, 1) 75 | p, ok := <-pChan 76 | if ok { 77 | t.Fatalf("FindProvidersAsync did not return a closed channel. Instead we got %+v !", p) 78 | } 79 | 80 | h2, _ := mh.Sum([]byte("test data1"), mh.SHA2_256, -1) 81 | c2 := cid.NewCidV0(h2) 82 | err = offline.Provide(ctx, c2, true) 83 | if err != ErrOffline { 84 | t.Fatal("OfflineRouting should alert that its offline") 85 | } 86 | 87 | err = offline.Bootstrap(ctx) 88 | if err != nil { 89 | t.Fatal("You shouldn't be able to bootstrap offline routing.") 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v0.3.1" 3 | } 4 | --------------------------------------------------------------------------------