diff --git a/.circleci/config.yml b/.circleci/config.yml index 35460b09afb..93ef8a70eb9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,16 +6,21 @@ aliases: restore_gomod: &restore_gomod restore_cache: keys: - - v4-dep-{{ .Branch }}-{{ checksum "~/ipfs/go-ipfs/go.sum" }}-{{ .Environment.CIRCLE_JOB }} - - v4-dep-{{ .Branch }}-{{ checksum "~/ipfs/go-ipfs/go.sum" }}- - - v4-dep-{{ .Branch }}- - - v4-dep-master- + - v5-dep-{{ .Branch }}-{{ checksum "~/ipfs/go-ipfs/go.sum" }}-{{ .Environment.CIRCLE_JOB }} + - v5-dep-{{ .Branch }}-{{ checksum "~/ipfs/go-ipfs/go.sum" }}- + - v5-dep-{{ .Branch }}- + - v5-dep-master- store_gomod: &store_gomod save_cache: - key: v4-dep-{{ .Branch }}-{{ checksum "~/ipfs/go-ipfs/go.sum" }}-{{ .Environment.CIRCLE_JOB }} + key: v5-dep-{{ .Branch }}-{{ checksum "~/ipfs/go-ipfs/go.sum" }}-{{ .Environment.CIRCLE_JOB }} paths: - ~/go/pkg/mod - ~/.cache/go-build/ + only-version-tags: &only-version-tags + tags: + only: /^v[0-9].*/ + branches: + ignore: /.*/ default_environment: &default_environment SERVICE: circle-ci @@ -27,12 +32,8 @@ default_environment: &default_environment executors: golang: - parameters: - tag: - type: string - default: "1.12" docker: - - image: circleci/golang:<< parameters.tag >> + - image: circleci/golang:1.13.8 working_directory: ~/ipfs/go-ipfs environment: <<: *default_environment @@ -57,6 +58,12 @@ executors: IPFS_REUSEPORT: false LIBP2P_ALLOW_WEAK_RSA_KEYS: 1 E2E_IPFSD_TYPE: go + dockerizer: + docker: + - image: circleci/golang:1.13.8 + environment: + IMAGE_NAME: ipfs/go-ipfs + WIP_IMAGE_TAG: wip jobs: gobuild: @@ -170,22 +177,17 @@ jobs: git -C interop log -1 - restore_cache: keys: - - v1-interop-{{ checksum "~/ipfs/go-ipfs/interop/package-lock.json" }} - - v1-interop- + - v2-interop-{{ checksum "~/ipfs/go-ipfs/interop/package-lock.json" }} + - v2-interop- - run: name: Installing dependencies command: | npm install working_directory: ~/ipfs/go-ipfs/interop - save_cache: - key: v1-interop-{{ checksum "~/ipfs/go-ipfs/interop/package-lock.json" }} + key: v2-interop-{{ checksum "~/ipfs/go-ipfs/interop/package-lock.json" }} paths: - ~/ipfs/go-ipfs/interop/node_modules - - run: - name: Installing js-ipfs - command: | - npm install ipfs ipfs-http-client - working_directory: ~/ipfs/go-ipfs/interop - run: name: Installing reporting tools command: | @@ -207,9 +209,7 @@ jobs: - store_test_results: path: /tmp/test-results go-ipfs-api: - executor: - name: golang - tag: "1.13" + executor: golang steps: - *make_out_dirs - attach_workspace: @@ -306,8 +306,45 @@ jobs: key: v1-ipfs-webui-{{ checksum "~/ipfs/go-ipfs/ipfs-webui/package-lock.json" }} paths: - ~/ipfs/go-ipfs/ipfs-webui/node_modules + docker-build: + executor: dockerizer + steps: + - checkout + - setup_remote_docker: + version: "18.09.3" + - run: + name: Build Docker image + command: | + docker build -t $IMAGE_NAME:$WIP_IMAGE_TAG . + - run: + name: Archive Docker image + command: docker save -o go-ipfs-image.tar $IMAGE_NAME + - persist_to_workspace: + root: . + paths: + - ./go-ipfs-image.tar + docker-push: + executor: dockerizer + steps: + - checkout + - setup_remote_docker: + version: "18.09.3" + - attach_workspace: + at: /tmp/workspace + - run: + name: Load archived Docker image + command: docker load -i /tmp/workspace/go-ipfs-image.tar + - run: + name: Publish Docker Image to Docker Hub + command: | + echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin + ./bin/push-docker-tags.sh $(date -u +%F) "$CIRCLE_SHA1" "$CIRCLE_BRANCH" "$CIRCLE_TAG" + workflows: version: 2 + + # Runs for all branches, but not on tags + # see: https://circleci.com/docs/2.0/workflows/#executing-workflows-for-a-git-tag test: jobs: - gobuild @@ -327,3 +364,35 @@ workflows: - ipfs-webui: requires: - build + - docker-build + - docker-push: + # Requires dockerhub credentials, from circleci context. + context: dockerhub + requires: + - docker-build + - golint + - gotest + - sharness + - interop + - go-ipfs-api + - go-ipfs-http-client + - ipfs-webui + filters: + branches: + only: + - master + - feat/stabilize-dht + + # NOTE: CircleCI only builds tags if you explicitly filter for them. That + # also means tag-based jobs can only depend on other tag-based jobs, so we + # use a separate workflow because every job needs to be tagged together. + # see: https://circleci.com/docs/2.0/workflows/#executing-workflows-for-a-git-tag + docker-on-tag: + jobs: + - docker-build: + filters: *only-version-tags + - docker-push: + context: dockerhub + filters: *only-version-tags + requires: + - docker-build diff --git a/.gitattributes b/.gitattributes index d6b38c11dd0..831606f194f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,6 +9,8 @@ LICENSE text eol=auto *.png binary *.tar binary *.gz binary +*.xz binary +*.car binary # Binary assets assets/init-doc/* binary diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 1b0fed9acdd..23eab547c51 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -1,8 +1,7 @@ --- name: 'Bug Report' about: 'Report a bug in go-ipfs.' -labels: - - bug +labels: kind/bug, need/triage --- #### Version information: diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000000..594bbf8b898 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,17 @@ +blank_issues_enabled: false +contact_links: + - name: Getting Help on IPFS + url: https://ipfs.io/help + about: All information about how and where to get help on IPFS. + - name: Go-ipfs configuration reference + url: https://github.com/ipfs/go-ipfs/blob/master/docs/config.md + about: Documentation on the different configuration settings + - name: Go-ipfs experimental features docs + url: https://github.com/ipfs/go-ipfs/blob/master/docs/experimental-features.md + about: Documentation on Private Networks, Filestore and other experimental features. + - name: HTTP API Reference + url: https://docs-beta.ipfs.io/reference/http/api/#api-v0-add + about: Documentation of all go-ipfs HTTP API endpoints. + - name: IPFS Official Forum + url: https://discuss.ipfs.io + about: Please post general questions, support requests, and discussions here. diff --git a/.github/ISSUE_TEMPLATE/doc.md b/.github/ISSUE_TEMPLATE/doc.md index 4662fb7bb06..552a2951f55 100644 --- a/.github/ISSUE_TEMPLATE/doc.md +++ b/.github/ISSUE_TEMPLATE/doc.md @@ -1,13 +1,13 @@ --- name: 'Documentation Issue' -about: 'Report missing/erroneous documentation, propose new documentation, report broken links, etc.' -labels: - - documentation +about: 'Report missing, erroneous docs, broken links or propose new go-ipfs docs' +labels: topic/docs-ipfs, need/triage --- + #### Location - + #### Description diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md index 6615bf70e8c..8c1c31c0d9d 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -1,12 +1,11 @@ --- name: 'Enhancement' about: 'Suggest an improvement to an existing go-ipfs feature.' -labels: - - enhancement +labels: kind/enhancement --- diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md index 219a320808a..0cd141dc706 100644 --- a/.github/ISSUE_TEMPLATE/feature.md +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -1,12 +1,11 @@ --- name: 'Feature' about: 'Suggest a new feature in go-ipfs.' -labels: - - feature +labels: kind/feature, need/triage --- + +Default: `false` + + +#### `Gateway.PublicGateways: NoDNSLink` + +A boolean to configure whether DNSLink for hostname present in `Host` +HTTP header should be resolved. Overrides global setting. +If `Paths` are defined, they take priority over DNSLink. + +Default: `false` (DNSLink lookup enabled by default for every defined hostname) + +#### Implicit defaults of `Gateway.PublicGateways` + +Default entries for `localhost` hostname and loopback IPs are always present. +If additional config is provided for those hostnames, it will be merged on top of implicit values: +```json +{ + "Gateway": { + "PublicGateways": { + "localhost": { + "Paths": ["/ipfs", "/ipns"], + "UseSubdomains": true + } + } + } +} +``` + +It is also possible to remove a default by setting it to `null`. +For example, to disable subdomain gateway on `localhost` +and make that hostname act the same as `127.0.0.1`: + +```console +$ ipfs config --json Gateway.PublicGateways '{"localhost": null }' +``` + +### `Gateway` recipes + +Below is a list of the most common public gateway setups. + +* Public [subdomain gateway](https://docs-beta.ipfs.io/how-to/address-ipfs-on-web/#subdomain-gateway) at `http://{cid}.ipfs.dweb.link` (each content root gets its own Origin) + ```console + $ ipfs config --json Gateway.PublicGateways '{ + "dweb.link": { + "UseSubdomains": true, + "Paths": ["/ipfs", "/ipns"] + } + }' + ``` + **Note:** this enables automatic redirects from content paths to subdomains + `http://dweb.link/ipfs/{cid}` → `http://{cid}.ipfs.dweb.link` + +* Public [path gateway](https://docs-beta.ipfs.io/how-to/address-ipfs-on-web/#path-gateway) at `http://ipfs.io/ipfs/{cid}` (no Origin separation) + ```console + $ ipfs config --json Gateway.PublicGateways '{ + "ipfs.io": { + "UseSubdomains": false, + "Paths": ["/ipfs", "/ipns", "/api"] + } + }' + ``` + +* Public [DNSLink](https://dnslink.io/) gateway resolving every hostname passed in `Host` header. + ```console + $ ipfs config --json Gateway.NoDNSLink true + ``` + * Note that `NoDNSLink: false` is the default (it works out of the box unless set to `true` manually) + +* Hardened, site-specific [DNSLink gateway](https://docs-beta.ipfs.io/how-to/address-ipfs-on-web/#dnslink-gateway). + Disable fetching of remote data (`NoFetch: true`) + and resolving DNSLink at unknown hostnames (`NoDNSLink: true`). + Then, enable DNSLink gateway only for the specific hostname (for which data + is already present on the node), without exposing any content-addressing `Paths`: + "NoFetch": true, + "NoDNSLink": true, + ```console + $ ipfs config --json Gateway.NoFetch true + $ ipfs config --json Gateway.NoDNSLink true + $ ipfs config --json Gateway.PublicGateways '{ + "en.wikipedia-on-ipfs.org": { + "NoDNSLink": false, + "Paths": [] + } + }' + ``` + ## `Identity` -- `PeerID` +### `Identity.PeerID` + The unique PKI identity label for this configs peer. Set on init and never read, -its merely here for convenience. Ipfs will always generate the peerID from its +it's merely here for convenience. Ipfs will always generate the peerID from its keypair at runtime. -- `PrivKey` +### `Identity.PrivKey` + The base64 encoded protobuf describing (and containing) the nodes private key. ## `Ipns` -- `RepublishPeriod` +### `Ipns.RepublishPeriod` + A time duration specifying how frequently to republish ipns records to ensure they stay fresh on the network. If unset, we default to 4 hours. -- `RecordLifetime` +### `Ipns.RecordLifetime` + A time duration specifying the value to set on ipns records for their validity lifetime. + If unset, we default to 24 hours. -- `ResolveCacheSize` +### `Ipns.ResolveCacheSize` + The number of entries to store in an LRU cache of resolved ipns entries. Entries will be kept cached until their lifetime is expired. Default: `128` ## `Mounts` + FUSE mount point configuration options. -- `IPFS` +### `Mounts.IPFS` + Mountpoint for `/ipfs/`. -- `IPNS` +### `Mounts.IPNS` + Mountpoint for `/ipns/`. -- `FuseAllowOther` +### `Mounts.FuseAllowOther` + Sets the FUSE allow other option on the mountpoint. ## `Reprovider` -- `Interval` +### `Reprovider.Interval` + Sets the time between rounds of reproviding local content to the routing system. If unset, it defaults to 12 hours. If set to the value `"0"` it will disable content reproviding. @@ -330,7 +713,8 @@ 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. -- `Strategy` +### `Reprovider.Strategy` + Tells reprovider what should be announced. Valid strategies are: - "all" (default) - announce all stored data - "pinned" - only announce pinned data @@ -340,64 +724,117 @@ Tells reprovider what should be announced. Valid strategies are: Options for configuring the swarm. -- `AddrFilters` -An array of address filters (multiaddr netmasks) to filter dials to. -See [this issue](https://github.com/ipfs/go-ipfs/issues/1226#issuecomment-120494604) for more -information. +### `Swarm.AddrFilters` + +An array of addresses (multiaddr netmasks) to not dial. By default, IPFS nodes +advertise _all_ addresses, even internal ones. This makes it easier for nodes on +the same network to reach each other. Unfortunately, this means that an IPFS +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., `192.168.0.0/16`) but +you should always check settings against your own network and/or hosting +provider. + + +### `Swarm.DisableBandwidthMetrics` -- `DisableBandwidthMetrics` A boolean value that when set to true, will cause ipfs to not keep track of bandwidth metrics. Disabling bandwidth metrics can lead to a slight performance improvement, as well as a reduction in memory usage. -- `DisableNatPortMap` -Disable NAT discovery. +### `Swarm.DisableNatPortMap` -- `DisableRelay` -Disables the p2p-circuit relay transport. +Disable automatic NAT port forwarding. -- `EnableRelayHop` -Enables HOP relay for the node. If this is enabled, the node will act as -an intermediate (Hop Relay) node in relay circuits for connected peers. +When not disabled (default), go-ipfs asks NAT devices (e.g., routers), to open +up an external port and forward it to the port go-ipfs is running on. When this +works (i.e., when your router supports NAT port forwarding), it makes the local +go-ipfs node accessible from the public internet. -- `EnableAutoRelay` -Enables automatic relay for this node. -If the node is a HOP relay (`EnableRelayHop` is true) then it will advertise itself as a relay through the DHT. -Otherwise, the node will test its own NAT situation (dialability) using passively discovered AutoNAT services. -If the node is not publicly reachable, then it will seek HOP relays advertised through the DHT and override its public address(es) with relay addresses. +### `Swarm.DisableRelay` -- `EnableAutoNATService` -Enables the AutoNAT service for this node. -The service allows peers to discover their NAT situation by requesting dial backs to their public addresses. -This should only be enabled on publicly reachable nodes. +Disables the p2p-circuit relay transport. This will prevent this node from +connecting to nodes behind relays, or accepting connections from nodes behind +relays. -### `ConnMgr` +### `Swarm.EnableRelayHop` -The connection manager determines which and how many connections to keep and can be configured to keep. +Configures this node to act as a relay "hop". A relay "hop" relays traffic for other peers. -- `Type` -Sets the type of connection manager to use, options are: `"none"` (no connection management) and `"basic"`. +WARNING: Do not enable this option unless you know what you're doing. Other +peers will randomly decide to use your node as a relay and consume _all_ +available bandwidth. There is _no_ rate-limiting. + +### `Swarm.EnableAutoRelay` + +Enables "automatic relay" mode for this node. This option does two _very_ +different things based on the `Swarm.EnableRelayHop`. See +[#7228](https://github.com/ipfs/go-ipfs/issues/7228) for context. + +#### Mode 1: `EnableRelayHop` is `false` + +If `Swarm.EnableAutoRelay` is enabled and `Swarm.EnableRelayHop` is disabled, +your node will automatically _use_ public relays from the network if it detects +that it cannot be reached from the public internet (e.g., it's behind a +firewall). This is likely the feature you're looking for. + +If you enable `EnableAutoRelay`, you should almost certainly disable +`EnableRelayHop`. + +#### Mode 2: `EnableRelayHop` is `true` + +If `EnableAutoRelay` is enabled and `EnableRelayHop` is enabled, your node will +_act_ as a public relay for the network. Furthermore, in addition to simply +relaying traffic, your node will advertise itself as a public relay. Unless you +have the bandwidth of a small ISP, do not enable both of these options at the +same time. + +### `Swarm.EnableAutoNATService` + +**REMOVED** + +Please use [`AutoNAT.ServiceMode`][]. + +### `Swarm.ConnMgr` + +The connection manager determines which and how many connections to keep and can +be configured to keep. + +#### `Swarm.ConnMgr.Type` + +Sets the type of connection manager to use, options are: `"none"` (no connection +management) and `"basic"`. #### Basic Connection Manager -- `LowWater` +##### `Swarm.ConnMgr.LowWater` + LowWater is the minimum number of connections to maintain. -- `HighWater` -HighWater is the number of connections that, when exceeded, will trigger a connection GC operation. +##### `Swarm.ConnMgr.HighWater` + +HighWater is the number of connections that, when exceeded, will trigger a +connection GC operation. -- `GracePeriod` -GracePeriod is a time duration that new connections are immune from being closed by the connection manager. +##### `Swarm.ConnMgr.GracePeriod` -The "basic" connection manager tries to keep between `LowWater` and `HighWater` connections. It works by: +GracePeriod is a time duration that new connections are immune from being closed +by the connection manager. + +The "basic" connection manager tries to keep between `LowWater` and `HighWater` +connections. It works by: 1. Keeping all connections until `HighWater` connections is reached. -2. Once `HighWater` is reached, it closes connections until `LowWater` is reached. -3. To prevent thrashing, it never closes connections established within the `GracePeriod`. +2. Once `HighWater` is reached, it closes connections until `LowWater` is + reached. +3. To prevent thrashing, it never closes connections established within the + `GracePeriod`. **Example:** - ```json { "Swarm": { diff --git a/docs/datastores.md b/docs/datastores.md index bec26c6497e..e7310022b85 100644 --- a/docs/datastores.md +++ b/docs/datastores.md @@ -4,6 +4,7 @@ This document describes the different possible values for the `Datastore.Spec` field in the ipfs configuration file. ## flatfs + Stores each key value pair as a file on the filesystem. The shardFunc is prefixed with `/repo/flatfs/shard/v1` then followed by a descriptor of the sharding strategy. Some example values are: @@ -21,8 +22,7 @@ The shardFunc is prefixed with `/repo/flatfs/shard/v1` then followed by a descri } ``` -NOTE: flatfs should only be used as a block store (mounted at `/blocks`) as the -current implementation is not complete. +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 Uses a leveldb database to store key value pairs. @@ -36,21 +36,23 @@ Uses a leveldb database to store key value pairs. ``` ## badgerds + Uses [badger](https://github.com/dgraph-io/badger) as a key value store. -* `syncWrites`: Synchronize every write to disk. -* `truncate`: Truncate the DB if a corrupted sector is found (otherwise Badger won't start). This option is always set to `true` in Windows if `syncWrites` is set. +* `syncWrites`: Flush every write to disk before continuing. Setting this to false is safe as go-ipfs 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 go-ipfs crashes half-way through a adding a file. ```json { "type": "badgerds", - "path": "", "syncWrites": true|false, "truncate": true|false, } ``` ## mount + Allows specified datastores to handle keys prefixed with a given path. The mountpoints are added as keys within the child datastore definitions. @@ -71,6 +73,7 @@ The mountpoints are added as keys within the child datastore definitions. ``` ## measure + This datastore is a wrapper that adds metrics tracking to any datastore. ```json diff --git a/docs/debug-guide.md b/docs/debug-guide.md index 9ef046a47e1..8eb6d96b74b 100644 --- a/docs/debug-guide.md +++ b/docs/debug-guide.md @@ -15,6 +15,11 @@ When you see ipfs doing something (using lots of CPU, memory, or otherwise being weird), the first thing you want to do is gather all the relevant profiling information. +There's a script (`bin/collect-profiles.sh`) that will do this for you and +bundle the results up into a tarball, ready to be attached to a bug report. + +If you feel intrepid, you can dump this information and investigate it yourself: + - goroutine dump - `curl localhost:5001/debug/pprof/goroutine\?debug=2 > ipfs.stacks` - 30 second cpu profile @@ -26,14 +31,10 @@ profiling information. - system information - `ipfs diag sys > ipfs.sysinfo` -Bundle all that up and include a copy of the ipfs binary that you are running -(having the exact same binary is important, it contains debug info). - -You can investigate yourself if you feel intrepid: ### Analyzing the stack dump -The first thing to look for is hung goroutines -- any goroutine thats been stuck +The first thing to look for is hung goroutines -- any goroutine that's been stuck for over a minute will note that in the trace. It looks something like: ``` diff --git a/docs/environment-variables.md b/docs/environment-variables.md index 82eb5c3126c..b2338ae3fc9 100644 --- a/docs/environment-variables.md +++ b/docs/environment-variables.md @@ -82,6 +82,20 @@ the `--migrate` flag). Default: https://ipfs.io/ipfs/$something (depends on the IPFS version) +## `IPFS_NS_MAP` + +Adds static namesys records for deterministic tests and debugging. +Useful for testing things like DNSLink without real DNS lookup. + +Example: + +```console +$ IPFS_NS_MAP="dnslink-test1.example.com:/ipfs/bafkreicysg23kiwv34eg2d7qweipxwosdo2py4ldv42nbauguluen5v6am,dnslink-test2.example.com:/ipns/dnslink-test1.example.com" ipfs daemon +... +$ ipfs resolve -r /ipns/dnslink-test2.example.com +/ipfs/bafkreicysg23kiwv34eg2d7qweipxwosdo2py4ldv42nbauguluen5v6am +``` + ## `LIBP2P_MUX_PREFS` Tells go-ipfs which multiplexers to use in which order. diff --git a/docs/examples/go-ipfs-as-a-library/README.md b/docs/examples/go-ipfs-as-a-library/README.md new file mode 100644 index 00000000000..c5fa8ee9bd3 --- /dev/null +++ b/docs/examples/go-ipfs-as-a-library/README.md @@ -0,0 +1,113 @@ +# Use go-ipfs as a library to spawn a node and add a file + +> This tutorial is the sibling of the [js-ipfs IPFS 101 tutorial](https://github.com/ipfs/js-ipfs/tree/master/examples/ipfs-101). + +By the end of this tutorial, you will learn how to: + +- Spawn an IPFS node that runs in process (no separate daemon process) +- Create an IPFS repo +- Add files and directories to IPFS +- Retrieve those files and directories using ``cat`` and ``get`` +- Connect to other nodes in the network +- Retrieve a file that only exists on the network +- The difference between a node in DHT client mode and full DHT mode + +All of this using only golang! + +In order to complete this tutorial, you will need: +- golang installed on your machine. See how at https://golang.org/doc/install +- git installed on your machine (so that go can download the repo and the necessary dependencies). See how at https://git-scm.com/downloads +- IPFS Desktop (for convenience) installed and running on your machine. See how at https://github.com/ipfs-shipyard/ipfs-desktop#ipfs-desktop + + +**Disclaimer**: The example code is quite large (more than 300 lines of code) and it has been a great way to understand the scope of the [go-ipfs Core API](https://godoc.org/github.com/ipfs/interface-go-ipfs-core), and how it can be improved to further the user experience. You can expect to be able to come back to this example in the future and see how the number of lines of code have decreased and how the example have become simpler, making other go-ipfs programs simpler as well. + +## Getting started + +**Note:** Make sure you have [![](https://img.shields.io/badge/go-%3E%3D1.13.0-blue.svg?style=flat-square)](https://golang.org/dl/) installed. + +Download go-ipfs and jump into the example folder: + +``` +> go get -u github.com/ipfs/go-ipfs +cd $GOPATH/src/github.com/ipfs/go-ipfs/docs/examples/go-ipfs-as-a-library +``` + +## Running the example as-is + +To run the example, simply do: + +``` +> go run main.go +``` + +You should see the following as output: + +``` +-- Getting an IPFS node running -- +Spawning node on a temporary repo +IPFS node is running + +-- Adding and getting back files & directories -- +Added file to IPFS with CID /ipfs/QmV9tSDx9UiPeWExXEeH6aoDvmihvx6jD5eLb4jbTaKGps +Added directory to IPFS with CID /ipfs/QmdQdu1fkaAUokmkfpWrmPHK78F9Eo9K2nnuWuizUjmhyn +Got file back from IPFS (IPFS path: /ipfs/QmV9tSDx9UiPeWExXEeH6aoDvmihvx6jD5eLb4jbTaKGps) and wrote it to ./example-folder/QmV9tSDx9UiPeWExXEeH6aoDvmihvx6jD5eLb4jbTaKGps +Got directory back from IPFS (IPFS path: /ipfs/QmdQdu1fkaAUokmkfpWrmPHK78F9Eo9K2nnuWuizUjmhyn) and wrote it to ./example-folder/QmdQdu1fkaAUokmkfpWrmPHK78F9Eo9K2nnuWuizUjmhyn + +-- Going to connect to a few nodes in the Network as bootstrappers -- +Fetching a file from the network with CID QmUaoioqU7bxezBQZkUcgcSyokatMY71sxsALxQmRRrHrj +Wrote the file to ./example-folder/QmUaoioqU7bxezBQZkUcgcSyokatMY71sxsALxQmRRrHrj + +All done! You just finalized your first tutorial on how to use go-ipfs as a library +``` + +## Understanding the example + +In this example, we add a file and a directory with files; we get them back from IPFS; and then we use the IPFS network to fetch a file that we didn't have in our machines before. + +Each section below has links to lines of code in the file [main.go](./main.go). The code itself will have comments explaining what is happening for you. + +### The `func main() {}` + +The [main function](./main.go#L202-L331) is where the magic starts, and it is the best place to follow the path of what is happening in the tutorial. + +### Part 1: Getting an IPFS node running + +To get [get a node running](./main.go#L218-L223) as an [ephemeral node](./main.go#L114-L128) (that will cease to exist when the run ends), you will need to: + +- [Prepare and set up the plugins](./main.go#L30-L47) +- [Create an IPFS repo](./main.go#L49-L68) +- [Construct the IPFS node instance itself](./main.go#L72-L96) + +As soon as you construct the IPFS node instance, the node will be running. + +### Part 2: Adding a file and a directory to IPFS + +- [Prepare the file to be added to IPFS](./main.go#L166-L184) +- [Add the file to IPFS](./main.go#L240-L243) +- [Prepare the directory to be added to IPFS](./main.go#L186-L198) +- [Add the directory to IPFS](./main.go#L252-L255) + +### Part 3: Getting the file and directory you added back + +- [Get the file back](./main.go#L265-L268) +- [Write the file to your local filesystem](./main.go#L270-L273) +- [Get the directory back](./main.go#L277-L280) +- [Write the directory to your local filesystem](./main.go#L282-L285) + +### Part 4: Getting a file from the IPFS network + +- [Connect to nodes in the network](./main.go#L293-L310) +- [Get the file from the network](./main.go#L318-L321) +- [Write the file to your local filesystem](./main.go#L323-L326) + +### Bonus: Spawn a daemon on your existing IPFS repo (on the default path ~/.ipfs) + +As a bonus, you can also find lines that show you how to spawn a node over your default path (~/.ipfs) in case you had already started a node there before. To try it: + +- [Comment these lines](./main.go#L219-L223) +- [Uncomment these lines](./main.go#L209-L216) + +## Voilá! You are now a go-ipfs hacker + +You've learned how to spawn a go-ipfs node using the go-ipfs core API. There are many more [methods to experiment next](https://godoc.org/github.com/ipfs/interface-go-ipfs-core). Happy hacking! diff --git a/docs/examples/go-ipfs-as-a-library/example-folder/ipfs.paper.draft3.pdf b/docs/examples/go-ipfs-as-a-library/example-folder/ipfs.paper.draft3.pdf new file mode 100644 index 00000000000..230e6fd5648 Binary files /dev/null and b/docs/examples/go-ipfs-as-a-library/example-folder/ipfs.paper.draft3.pdf differ diff --git a/docs/examples/go-ipfs-as-a-library/example-folder/test-dir/ipfs-logo.png b/docs/examples/go-ipfs-as-a-library/example-folder/test-dir/ipfs-logo.png new file mode 100644 index 00000000000..27a82629faf Binary files /dev/null and b/docs/examples/go-ipfs-as-a-library/example-folder/test-dir/ipfs-logo.png differ diff --git a/docs/examples/go-ipfs-as-a-library/example-folder/test-dir/ipfs.paper.draft3.pdf b/docs/examples/go-ipfs-as-a-library/example-folder/test-dir/ipfs.paper.draft3.pdf new file mode 100644 index 00000000000..230e6fd5648 Binary files /dev/null and b/docs/examples/go-ipfs-as-a-library/example-folder/test-dir/ipfs.paper.draft3.pdf differ diff --git a/docs/examples/go-ipfs-as-a-library/main.go b/docs/examples/go-ipfs-as-a-library/main.go new file mode 100644 index 00000000000..cc390ecebf7 --- /dev/null +++ b/docs/examples/go-ipfs-as-a-library/main.go @@ -0,0 +1,332 @@ +package main + +import ( + "context" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" + "sync" + + config "github.com/ipfs/go-ipfs-config" + files "github.com/ipfs/go-ipfs-files" + libp2p "github.com/ipfs/go-ipfs/core/node/libp2p" + icore "github.com/ipfs/interface-go-ipfs-core" + icorepath "github.com/ipfs/interface-go-ipfs-core/path" + peerstore "github.com/libp2p/go-libp2p-peerstore" + ma "github.com/multiformats/go-multiaddr" + + "github.com/ipfs/go-ipfs/core" + "github.com/ipfs/go-ipfs/core/coreapi" + "github.com/ipfs/go-ipfs/plugin/loader" // This package is needed so that all the preloaded plugins are loaded automatically + "github.com/ipfs/go-ipfs/repo/fsrepo" + "github.com/libp2p/go-libp2p-core/peer" +) + +/// ------ Setting up the IPFS Repo + +func setupPlugins(externalPluginsPath string) error { + // Load any external plugins if available on externalPluginsPath + plugins, err := loader.NewPluginLoader(filepath.Join(externalPluginsPath, "plugins")) + if err != nil { + return fmt.Errorf("error loading plugins: %s", err) + } + + // Load preloaded and external plugins + if err := plugins.Initialize(); err != nil { + return fmt.Errorf("error initializing plugins: %s", err) + } + + if err := plugins.Inject(); err != nil { + return fmt.Errorf("error initializing plugins: %s", err) + } + + return nil +} + +func createTempRepo(ctx context.Context) (string, error) { + repoPath, err := ioutil.TempDir("", "ipfs-shell") + if err != nil { + return "", fmt.Errorf("failed to get temp dir: %s", err) + } + + // Create a config with default options and a 2048 bit key + cfg, err := config.Init(ioutil.Discard, 2048) + if err != nil { + return "", err + } + + // Create the repo with the config + err = fsrepo.Init(repoPath, cfg) + if err != nil { + return "", fmt.Errorf("failed to init ephemeral node: %s", err) + } + + return repoPath, nil +} + +/// ------ Spawning the node + +// Creates an IPFS node and returns its coreAPI +func createNode(ctx context.Context, repoPath string) (icore.CoreAPI, error) { + // Open the repo + repo, err := fsrepo.Open(repoPath) + if err != nil { + return nil, err + } + + // Construct the node + + nodeOptions := &core.BuildCfg{ + Online: true, + Routing: libp2p.DHTOption, // This option sets the node to be a full DHT node (both fetching and storing DHT Records) + // Routing: libp2p.DHTClientOption, // This option sets the node to be a client DHT node (only fetching records) + Repo: repo, + } + + node, err := core.NewNode(ctx, nodeOptions) + if err != nil { + return nil, err + } + + // Attach the Core API to the constructed node + return coreapi.NewCoreAPI(node) +} + +// Spawns a node on the default repo location, if the repo exists +func spawnDefault(ctx context.Context) (icore.CoreAPI, error) { + defaultPath, err := config.PathRoot() + if err != nil { + // shouldn't be possible + return nil, err + } + + if err := setupPlugins(defaultPath); err != nil { + return nil, err + + } + + return createNode(ctx, defaultPath) +} + +// Spawns a node to be used just for this run (i.e. creates a tmp repo) +func spawnEphemeral(ctx context.Context) (icore.CoreAPI, error) { + if err := setupPlugins(""); err != nil { + return nil, err + } + + // Create a Temporary Repo + repoPath, err := createTempRepo(ctx) + if err != nil { + return nil, fmt.Errorf("failed to create temp repo: %s", err) + } + + // Spawning an ephemeral IPFS node + return createNode(ctx, repoPath) +} + +// + +func connectToPeers(ctx context.Context, ipfs icore.CoreAPI, peers []string) error { + var wg sync.WaitGroup + peerInfos := make(map[peer.ID]*peerstore.PeerInfo, len(peers)) + for _, addrStr := range peers { + addr, err := ma.NewMultiaddr(addrStr) + if err != nil { + return err + } + pii, err := peerstore.InfoFromP2pAddr(addr) + if err != nil { + return err + } + pi, ok := peerInfos[pii.ID] + if !ok { + pi = &peerstore.PeerInfo{ID: pii.ID} + peerInfos[pi.ID] = pi + } + pi.Addrs = append(pi.Addrs, pii.Addrs...) + } + + wg.Add(len(peerInfos)) + for _, peerInfo := range peerInfos { + go func(peerInfo *peerstore.PeerInfo) { + defer wg.Done() + err := ipfs.Swarm().Connect(ctx, *peerInfo) + if err != nil { + log.Printf("failed to connect to %s: %s", peerInfo.ID, err) + } + }(peerInfo) + } + wg.Wait() + return nil +} + +func getUnixfsFile(path string) (files.File, error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + + st, err := file.Stat() + if err != nil { + return nil, err + } + + f, err := files.NewReaderPathFile(path, file, st) + if err != nil { + return nil, err + } + + return f, nil +} + +func getUnixfsNode(path string) (files.Node, error) { + st, err := os.Stat(path) + if err != nil { + return nil, err + } + + f, err := files.NewSerialFile(path, false, st) + if err != nil { + return nil, err + } + + return f, nil +} + +/// ------- + +func main() { + /// --- Part I: Getting a IPFS node running + + fmt.Println("-- Getting an IPFS node running -- ") + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + /* + // Spawn a node using the default path (~/.ipfs), assuming that a repo exists there already + fmt.Println("Spawning node on default repo") + ipfs, err := spawnDefault(ctx) + if err != nil { + fmt.Println("No IPFS repo available on the default path") + } + */ + + // Spawn a node using a temporary path, creating a temporary repo for the run + fmt.Println("Spawning node on a temporary repo") + ipfs, err := spawnEphemeral(ctx) + if err != nil { + panic(fmt.Errorf("failed to spawn ephemeral node: %s", err)) + } + + fmt.Println("IPFS node is running") + + /// --- Part II: Adding a file and a directory to IPFS + + fmt.Println("\n-- Adding and getting back files & directories --") + + inputBasePath := "./example-folder/" + inputPathFile := inputBasePath + "ipfs.paper.draft3.pdf" + inputPathDirectory := inputBasePath + "test-dir" + + someFile, err := getUnixfsNode(inputPathFile) + if err != nil { + panic(fmt.Errorf("Could not get File: %s", err)) + } + + cidFile, err := ipfs.Unixfs().Add(ctx, someFile) + if err != nil { + panic(fmt.Errorf("Could not add File: %s", err)) + } + + fmt.Printf("Added file to IPFS with CID %s\n", cidFile.String()) + + someDirectory, err := getUnixfsNode(inputPathDirectory) + if err != nil { + panic(fmt.Errorf("Could not get File: %s", err)) + } + + cidDirectory, err := ipfs.Unixfs().Add(ctx, someDirectory) + if err != nil { + panic(fmt.Errorf("Could not add Directory: %s", err)) + } + + fmt.Printf("Added directory to IPFS with CID %s\n", cidDirectory.String()) + + /// --- Part III: Getting the file and directory you added back + + outputBasePath := "./example-folder/" + outputPathFile := outputBasePath + strings.Split(cidFile.String(), "/")[2] + outputPathDirectory := outputBasePath + strings.Split(cidDirectory.String(), "/")[2] + + rootNodeFile, err := ipfs.Unixfs().Get(ctx, cidFile) + if err != nil { + panic(fmt.Errorf("Could not get file with CID: %s", err)) + } + + err = files.WriteTo(rootNodeFile, outputPathFile) + if err != nil { + panic(fmt.Errorf("Could not write out the fetched CID: %s", err)) + } + + fmt.Printf("Got file back from IPFS (IPFS path: %s) and wrote it to %s\n", cidFile.String(), outputPathFile) + + rootNodeDirectory, err := ipfs.Unixfs().Get(ctx, cidDirectory) + if err != nil { + panic(fmt.Errorf("Could not get file with CID: %s", err)) + } + + err = files.WriteTo(rootNodeDirectory, outputPathDirectory) + if err != nil { + panic(fmt.Errorf("Could not write out the fetched CID: %s", err)) + } + + fmt.Printf("Got directory back from IPFS (IPFS path: %s) and wrote it to %s\n", cidDirectory.String(), outputPathDirectory) + + /// --- Part IV: Getting a file from the IPFS Network + + fmt.Println("\n-- Going to connect to a few nodes in the Network as bootstrappers --") + + bootstrapNodes := []string{ + // IPFS Bootstrapper nodes. + "/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN", + "/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa", + "/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb", + "/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt", + + // IPFS Cluster Pinning nodes + "/ip4/138.201.67.219/tcp/4001/p2p/QmUd6zHcbkbcs7SMxwLs48qZVX3vpcM8errYS7xEczwRMA", + "/ip4/138.201.67.220/tcp/4001/p2p/QmNSYxZAiJHeLdkBg38roksAR9So7Y5eojks1yjEcUtZ7i", + "/ip4/138.201.68.74/tcp/4001/p2p/QmdnXwLrC8p1ueiq2Qya8joNvk3TVVDAut7PrikmZwubtR", + "/ip4/94.130.135.167/tcp/4001/p2p/QmUEMvxS2e7iDrereVYc5SWPauXPyNwxcy9BXZrC1QTcHE", + + // You can add more nodes here, for example, another IPFS node you might have running locally, mine was: + // "/ip4/127.0.0.1/tcp/4010/p2p/QmZp2fhDLxjYue2RiUvLwT9MWdnbDxam32qYFnGmxZDh5L", + } + + go connectToPeers(ctx, ipfs, bootstrapNodes) + + exampleCIDStr := "QmUaoioqU7bxezBQZkUcgcSyokatMY71sxsALxQmRRrHrj" + + fmt.Printf("Fetching a file from the network with CID %s\n", exampleCIDStr) + outputPath := outputBasePath + exampleCIDStr + testCID := icorepath.New(exampleCIDStr) + + rootNode, err := ipfs.Unixfs().Get(ctx, testCID) + if err != nil { + panic(fmt.Errorf("Could not get file with CID: %s", err)) + } + + err = files.WriteTo(rootNode, outputPath) + if err != nil { + panic(fmt.Errorf("Could not write out the fetched CID: %s", err)) + } + + fmt.Printf("Wrote the file to %s\n", outputPath) + + fmt.Println("\nAll done! You just finalized your first tutorial on how to use go-ipfs as a library") +} diff --git a/docs/examples/library-experimental-features/README.md b/docs/examples/library-experimental-features/README.md new file mode 100644 index 00000000000..6387f3618a9 --- /dev/null +++ b/docs/examples/library-experimental-features/README.md @@ -0,0 +1,74 @@ +# Use go-ipfs as a library and enable experimental features + +Before moving on to this tutorial, you must read first the initial [`go-ipfs` as a library tutorial](../go-ipfs-as-a-library/README.md) +as it gives insights on how to create a repository, the daemon and add a file. + +There is only one thing that differs from this example and the first tutorial, which is the function [`createTempRepo`](../go-ipfs-as-a-library/main.go#L49): + +```go +func createTempRepo(ctx context.Context) (string, error) { + repoPath, err := ioutil.TempDir("", "ipfs-shell") + if err != nil { + return "", fmt.Errorf("failed to get temp dir: %s", err) + } + + // Create a config with default options and a 2048 bit key + cfg, err := config.Init(ioutil.Discard, 2048) + if err != nil { + return "", err + } + + // Create the repo with the config + err = fsrepo.Init(repoPath, cfg) + if err != nil { + return "", fmt.Errorf("failed to init ephemeral node: %s", err) + } + + return repoPath, nil +} +``` + +When creating the repository, you can define custom settings on the repository, such as enabling [experimental +features](../../experimental-features.md) or customizing the gateway endpoint. + +To do such things, you should modify the variable `cfg`. For example, to enable the sharding experiment, you would modify the function to: + +```go +func createTempRepo(ctx context.Context) (string, error) { + repoPath, err := ioutil.TempDir("", "ipfs-shell") + if err != nil { + return "", fmt.Errorf("failed to get temp dir: %s", err) + } + + // Create a config with default options and a 2048 bit key + cfg, err := config.Init(ioutil.Discard, 2048) + if err != nil { + return "", err + } + + // https://github.com/ipfs/go-ipfs/blob/master/docs/experimental-features.md#ipfs-filestore + cfg.Experimental.FilestoreEnabled = true + // https://github.com/ipfs/go-ipfs/blob/master/docs/experimental-features.md#ipfs-urlstore + cfg.Experimental.UrlstoreEnabled = true + // https://github.com/ipfs/go-ipfs/blob/master/docs/experimental-features.md#directory-sharding--hamt + cfg.Experimental.ShardingEnabled = true + // https://github.com/ipfs/go-ipfs/blob/master/docs/experimental-features.md#ipfs-p2p + cfg.Experimental.Libp2pStreamMounting = true + // https://github.com/ipfs/go-ipfs/blob/master/docs/experimental-features.md#p2p-http-proxy + cfg.Experimental.P2pHttpProxy = true + // https://github.com/ipfs/go-ipfs/blob/master/docs/experimental-features.md#quic + cfg.Experimental.QUIC = true + // https://github.com/ipfs/go-ipfs/blob/master/docs/experimental-features.md#strategic-providing + cfg.Experimental.StrategicProviding = true + + // Create the repo with the config + err = fsrepo.Init(repoPath, cfg) + if err != nil { + return "", fmt.Errorf("failed to init ephemeral node: %s", err) + } + + return repoPath, nil +} +``` + +There are many other options that you can find through the [documentation](https://godoc.org/github.com/ipfs/go-ipfs-config#Config). diff --git a/docs/experimental-features.md b/docs/experimental-features.md index 9f25ef2a416..3c86d55bb53 100644 --- a/docs/experimental-features.md +++ b/docs/experimental-features.md @@ -8,7 +8,7 @@ removed. Subscribe to https://github.com/ipfs/go-ipfs/issues/3397 to get updates. -When you add a new experimental feature to go-ipfs, or change an experimental +When you add a new experimental feature to go-ipfs or change an experimental feature, you MUST please make a PR updating this document, and link the PR in the above issue. @@ -18,7 +18,6 @@ the above issue. - [Raw leaves for unixfs files](#raw-leaves-for-unixfs-files) - [ipfs filestore](#ipfs-filestore) - [ipfs urlstore](#ipfs-urlstore) -- [BadgerDB datastore](#badger-datastore) - [Private Networks](#private-networks) - [ipfs p2p](#ipfs-p2p) - [p2p http proxy](#p2p-http-proxy) @@ -29,6 +28,8 @@ the above issue. - [QUIC](#quic) - [AutoRelay](#autorelay) - [TLS 1.3 Handshake](#tls-13-as-default-handshake-protocol) +- [Strategic Providing](#strategic-providing) +- [Graphsync](graphsync) --- @@ -36,7 +37,7 @@ the above issue. ### State -experimental, default-disabled. +Candidate, disabled by default but will be enabled by default in 0.6.0. ### In Version @@ -51,7 +52,7 @@ run your daemon with the `--enable-pubsub-experiment` flag. Then use the Gossipsub is a new, experimental routing protocol for pubsub that should waste less bandwidth than floodsub, the current pubsub -protocol. It's backwards compatible with floodsub so enabling this +protocol. It's backward compatible with floodsub so enabling this feature shouldn't break compatibility with existing IPFS nodes. You can enable gossipsub via configuration: @@ -74,79 +75,43 @@ signed) by running: ### Road to being a real feature - [ ] Needs more people to use and report on how well it works -- [ ] Needs authenticated modes to be implemented +- [ ] Needs authenticating modes to be implemented - [ ] needs performance analyses to be done ---- +## Raw Leaves for unixfs files -## Client mode DHT routing -Allows the dht to be run in a mode that doesn't serve requests to the network, -saving bandwidth. +Allows files to be added with no formatting in the leaf nodes of the graph. ### State -experimental. - -### In Version -0.4.5 - -### How to enable -run your daemon with the `--routing=dhtclient` flag. -### Road to being a real feature -- [ ] Needs more people to use and report on how well it works. -- [ ] Needs analysis of effect it has on the network as a whole. - ---- - -## go-multiplex stream muxer -Adds support for using the go-multiplex stream muxer alongside (or instead of) -yamux and spdy. This multiplexer is far simpler, and uses less memory and -bandwidth than the others, but is lacking on congestion control and backpressure -logic. It is available to try out and experiment with. - -### State -Stable +Stable but not used by default. ### In Version + 0.4.5 ### How to enable -To make it the default stream muxer, set the environment variable -`LIBP2P_MUX_PREFS` as follows: -``` -export LIBP2P_MUX_PREFS="/mplex/6.7.0 /yamux/1.0.0 /spdy/3.1.0" -``` - ---- - -## Raw Leaves for unixfs files -Allows files to be added with no formatting in the leaf nodes of the graph. - -### State -experimental. - -### In Version -master, 0.4.5 - -### How to enable -Use `--raw-leaves` flag when calling `ipfs add`. +Use `--raw-leaves` flag when calling `ipfs add`. This will save some space when adding files. ### Road to being a real feature -- [ ] Needs more people to use and report on how well it works. ---- +Enabling this feature _by default_ will change the CIDs (hashes) of all newly imported files and will prevent newly imported files from deduplicating against previously imported files. While we do intend on enabling this by default, we plan on doing so once we have a large batch of "hash-changing" features we can enable all at once. ## ipfs filestore + Allows files to be added without duplicating the space they take up on disk. ### State -experimental. + +Experimental. ### In Version -master, 0.4.7 + +0.4.7 ### How to enable + Modify your ipfs config: ``` ipfs config --json Experimental.FilestoreEnabled true @@ -158,23 +123,26 @@ Finally, when adding files with ipfs add, pass the --nocopy flag to use the filestore instead of copying the files into your local IPFS repo. ### 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 - [ ] Need to write docs on usage, advantages, disadvantages - [ ] Need to merge utility commands to aid in maintenance and repair of filestore ---- - ## ipfs urlstore -Allows ipfs to retrieve blocks contents via a url instead of storing it in the datastore + +Allows ipfs to retrieve blocks contents via a URL instead of storing it in the datastore ### State -experimental. + +Experimental. ### In Version -master, v0.4.17 + +v0.4.17 ### How to enable + Modify your ipfs config: ``` ipfs config --json Experimental.UrlstoreEnabled true @@ -189,19 +157,20 @@ And then add a file at a specific URL using `ipfs urlstore add ` - [ ] Need to implement caching - [ ] Need to add metrics to monitor performance ---- - ## Private Networks -Allows ipfs to only connect to other peers who have a shared secret key. +It allows ipfs to only connect to other peers who have a shared secret key. ### State -Experimental + +Stable but not quite ready for prime-time. ### In Version -master, 0.4.7 + +0.4.7 ### How to enable + 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 @@ -228,7 +197,7 @@ ipfs bootstrap add For example: ``` -ipfs bootstrap add /ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64 +ipfs bootstrap add /ip4/104.236.76.40/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64 ``` Bootstrap nodes are no different from all other nodes in the network apart from @@ -239,28 +208,28 @@ variable to `1` to force the usage of private networks. If no private network is configured, the daemon will fail to start. ### Road to being a real feature -- [ ] Needs more people to use and report on how well it works -- [ ] More documentation ---- +- [x] Needs more people to use and report on how well it works +- [ ] More documentation +- [ ] Needs better tooling/UX. ## ipfs p2p Allows tunneling of TCP connections through Libp2p streams. If you've ever used -port forwarding with SSH (the `-L` option in openssh), this feature is quite +port forwarding with SSH (the `-L` option in OpenSSH), this feature is quite similar. ### State -Experimental +Experimental, will be stabilized in 0.6.0 ### In Version -master, 0.4.10 +0.4.10 ### How to enable -The `p2p` command needs to be enabled in config: +The `p2p` command needs to be enabled in the config: ```sh > ipfs config --json Experimental.Libp2pStreamMounting true @@ -301,7 +270,7 @@ connections on `127.0.0.1:SOME_PORT` to the server node listening on `/x/kickass/1.0`. ```sh -> ipfs p2p forward /x/kickass/1.0 /ip4/127.0.0.1/tcp/$SOME_PORT /ipfs/$SERVER_ID +> ipfs p2p forward /x/kickass/1.0 /ip4/127.0.0.1/tcp/$SOME_PORT /p2p/$SERVER_ID ``` Next, have your application open a connection to `127.0.0.1:$SOME_PORT`. This @@ -342,7 +311,7 @@ ipfs p2p listen /x/ssh /ip4/127.0.0.1/tcp/22 ***Then, on "client" node:*** ```sh -ipfs p2p forward /x/ssh /ip4/127.0.0.1/tcp/2222 /ipfs/$SERVER_ID +ipfs p2p forward /x/ssh /ip4/127.0.0.1/tcp/2222 /p2p/$SERVER_ID ``` You should now be able to connect to your ssh server through a libp2p connection @@ -350,15 +319,12 @@ with `ssh [user]@127.0.0.1 -p 2222`. ### Road to being a real feature -- [ ] Needs more people to use and report on how well it works / fits use cases -- [ ] More documentation -- [ ] Support other protocols (e.g, unix domain sockets, websockets, etc.) ---- +- [ ] More documentation ## p2p http proxy -Allows proxying of HTTP requests over p2p streams. This allows serving any standard http app over p2p streams. +Allows proxying of HTTP requests over p2p streams. This allows serving any standard HTTP app over p2p streams. ### State @@ -366,17 +332,17 @@ Experimental ### In Version -master, 0.4.19 +0.4.19 ### How to enable -The `p2p` command needs to be enabled in config: +The `p2p` command needs to be enabled in the config: ```sh > ipfs config --json Experimental.Libp2pStreamMounting true ``` -On the client, the p2p http proxy needs to be enabled in the config: +On the client, the p2p HTTP proxy needs to be enabled in the config: ```sh > ipfs config --json Experimental.P2pHttpProxy true @@ -425,66 +391,18 @@ the remote machine (which needs to be a http server!) with path `$FORWARDED_PATH > curl http://localhost:8080/p2p/$SERVER_ID/http/ ``` -You should now see the resulting http response: IPFS rocks! +You should now see the resulting HTTP response: IPFS rocks! ### Custom protocol names -We also support use of protocol names of the form /x/$NAME/http where $NAME doesn't contain any "/"'s + +We also support the use of protocol names of the form /x/$NAME/http where $NAME doesn't contain any "/"'s ### Road to being a real feature + - [ ] Needs p2p streams to graduate from experiments - [ ] Needs more people to use and report on how well it works / fits use cases - [ ] More documentation - ---- - -## Circuit Relay - -Allows peers to connect through an intermediate relay node when there -is no direct connectivity. - -### State -Experimental - -### In Version -master, 0.4.11 - -### How to enable - -The relay transport is enabled by default, which allows peers to dial through -relay and listens for incoming relay connections. The transport can be disabled -by setting `Swarm.DisableRelay = true` in the configuration. - -By default, peers don't act as intermediate nodes (relays). This can be enabled -by setting `Swarm.EnableRelayHop = true` in the configuration. Note that the -option needs to be set before online services are started to have an effect; an -already online node would have to be restarted. - -### Basic Usage: - -In order to connect peers QmA and QmB through a relay node QmRelay: - -- Both peers should connect to the relay: -`ipfs swarm connect /transport/address/ipfs/QmRelay` -- Peer QmA can then connect to peer QmB using the relay: -`ipfs swarm connect /ipfs/QmRelay/p2p-circuit/ipfs/QmB` - -Peers can also connect with an unspecific relay address, which will -try to dial through known relays: -`ipfs swarm connect /p2p-circuit/ipfs/QmB` - -Peers can see their (unspecific) relay address in the output of -`ipfs swarm addrs listen` - -### Road to being a real feature - -- [ ] Needs more people to use it and report on how well it works. -- [ ] Advertise relay addresses to the DHT for NATed or otherwise unreachable - peers. -- [ ] Active relay discovery for specific relay address advertisement. We would - like advertised relay addresses to designate specific relays for efficient - dialing. -- [ ] Dialing priorities for relay addresses; arguably, relay addresses should - have lower priority than direct dials. +- [ ] Need better integration with the subdomain gateway feature. ## Plugins @@ -494,7 +412,7 @@ Peers can see their (unspecific) relay address in the output of ### State Experimental -Plugins allow to add functionality without the need to recompile the daemon. +Plugins allow adding functionality without the need to recompile the daemon. ### Basic Usage: @@ -502,37 +420,11 @@ See [Plugin docs](./plugins.md) ### Road to being a real feature -- [ ] Better support for platforms other than Linux -- [ ] More plugins and plugin types +- [x] More plugins and plugin types +- [ ] A way to reliably build and distribute plugins. +- [ ] Better support for platforms other than Linux & MacOS - [ ] Feedback on stability - ## Badger datastore - - ### In Version - 0.4.11 - - Badger-ds is new datastore implementation based on - https://github.com/dgraph-io/badger - - ### Basic Usage - - ``` - $ ipfs init --profile=badgerds - ``` - or install https://github.com/ipfs/ipfs-ds-convert/ and - ``` - [BACKUP ~/.ipfs] - $ ipfs config profile apply badgerds - $ ipfs-ds-convert convert - ``` - -### - -### Road to being a real feature - -- [ ] Needs more testing -- [ ] Make sure there are no unknown major problems - ## Directory Sharding / HAMT ### In Version @@ -541,8 +433,11 @@ See [Plugin docs](./plugins.md) ### State Experimental -Allows to create directories with unlimited number of entries - currently -size of unixfs directories is limited by the maximum block size +Allows creating directories with an unlimited number of entries. + +**Caveats:** +1. right now it is a GLOBAL FLAG which will impact the final CID of all directories produced by `ipfs.add` (even the small ones) +2. currently size of unixfs directories is limited by the maximum block size ### Basic Usage: @@ -555,8 +450,6 @@ ipfs config --json Experimental.ShardingEnabled true - [ ] Make sure that objects that don't have to be sharded aren't - [ ] Generalize sharding and define a new layer between IPLD and IPFS ---- - ## IPNS pubsub ### In Version @@ -573,14 +466,9 @@ When it is enabled: - IPNS publishers push records to a name-specific pubsub topic, in addition to publishing to the DHT. - IPNS resolvers subscribe to the name-specific topic on first - resolution and receive subsequently published records through pubsub - in real time. This makes subsequent resolutions instant, as they - are resolved through the local cache. Note that the initial - resolution still goes through the DHT, as there is no message - history in pubsub. + resolution and receive subsequently published records through pubsub in real time. This makes subsequent resolutions instant, as they are resolved through the local cache. Note that the initial resolution still goes through the DHT, as there is no message history in pubsub. -Both the publisher and the resolver nodes need to have the feature enabled for it -to work effectively. +Both the publisher and the resolver nodes need to have the feature enabled for it to work effectively. ### How to enable @@ -593,8 +481,6 @@ run your daemon with the `--enable-namesys-pubsub` flag; enables pubsub. so that we don't have to hit the DHT for the initial resolution. Alternatively, we could republish the last record periodically. - - ## QUIC ### In Version @@ -603,7 +489,7 @@ run your daemon with the `--enable-namesys-pubsub` flag; enables pubsub. ### State -Experiment, disabled by default +Candidate, disabled by default but it will be enabled by default in 0.6.0. ### How to enable @@ -613,14 +499,14 @@ Modify your ipfs config: ipfs config --json Experimental.QUIC true ``` -For listening on a QUIC address, add it the swarm addresses, e.g. `/ip4/0.0.0.0/udp/4001/quic`. +For listening on a QUIC address, add it to the swarm addresses, e.g. `/ip4/0.0.0.0/udp/4001/quic`. ### Road to being a real feature -- [ ] The IETF QUIC specification needs to be finalised. +- [ ] The IETF QUIC specification needs to be finalized. - [ ] Make sure QUIC connections work reliably -- [ ] Make sure QUIC connection offer equal or better performance than TCP connections on real world networks +- [ ] Make sure QUIC connection offer equal or better performance than TCP connections on real-world networks - [ ] Finalize libp2p-TLS handshake spec. @@ -628,7 +514,7 @@ For listening on a QUIC address, add it the swarm addresses, e.g. `/ip4/0.0.0.0/ ### In Version -0.4.19-dev +0.4.19 ### State @@ -641,36 +527,62 @@ Automatically discovers relays and advertises relay addresses when the node is b Modify your ipfs config: ``` +ipfs config --json Swarm.EnableRelayHop false ipfs config --json Swarm.EnableAutoRelay true ``` -Bootstrappers (and other public nodes) need to also enable the AutoNATService: -``` -ipfs config --json Swarm.EnableAutoNATService true -``` +NOTE: Ensuring `Swarm.EnableRelayHop` is _false_ is extremely important here. If you set it to true, you will _act_ as a public relay for the rest of the network instead of _using_ the public relays. ### Road to being a real feature - [ ] needs testing - -## TLS 1.3 as default handshake protocol +## Strategic Providing ### State -Every go-ipfs node (>=0.4.21) accepts secio and TLS 1.3 connections but prefers -secio over TLS when dialing. To prefer TLS when dialing, you'll have to enable -this feature. +Experimental, disabled by default. + +Replaces the existing provide mechanism with a robust, strategic provider system. ### How to enable Modify your ipfs config: ``` -ipfs config --json Experimental.PreferTLS true +ipfs config --json Experimental.StrategicProviding true ``` ### Road to being a real feature -- [ ] needs testing +- [ ] needs real-world testing - [ ] needs adoption +- [ ] needs to support all provider subsystem features + - [X] provide nothing + - [ ] provide roots + - [ ] provide all + - [ ] provide strategic + +## GraphSync + +### State + +Experimental, disabled by default. + +[GraphSync](https://github.com/ipfs/go-graphsync) is the next-gen graph exchange +protocol for IPFS. + +When this feature is enabled, IPFS will make files available over the graphsync +protocol. However, IPFS will not currently use this protocol to _fetch_ files. + +### How to enable + +Modify your ipfs config: + +``` +ipfs config --json Experimental.GraphsyncEnabled true +``` + +### Road to being a real feature + +- [ ] We need to confirm that it can't be used to DoS a node. The server-side logic for GraphSync is quite complex and, if we're not careful, the server might end up performing unbounded work when responding to a malicious request. diff --git a/docs/file-transfer.md b/docs/file-transfer.md index 39cc63809b2..247993489ff 100644 --- a/docs/file-transfer.md +++ b/docs/file-transfer.md @@ -45,8 +45,8 @@ addresses (like the example below), then your nodes are online. "ID": "QmTNwsFkLAed15kQEC1ZJWPfoNbBQnMFojfJKQ9sZj1dk8", "PublicKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZb6znj3LQZKP1+X81exf+vbnqNCMtHjZ5RKTCm7Fytnfe+AI1fhs9YbZdkgFkM1HLxmIOLQj2bMXPIGxUM+EnewN8tWurx4B3+lR/LWNwNYcCFL+jF2ltc6SE6BC8kMLEZd4zidOLPZ8lIRpd0x3qmsjhGefuRwrKeKlR4tQ3C76ziOms47uLdiVVkl5LyJ5+mn4rXOjNKt/oy2O4m1St7X7/yNt8qQgYsPfe/hCOywxCEIHEkqmil+vn7bu4RpAtsUzCcBDoLUIWuU3i6qfytD05hP8Clo+at+l//ctjMxylf3IQ5qyP+yfvazk+WHcsB0tWueEmiU5P2nfUUIR3AgMBAAE=", "Addresses": [ - "/ip4/127.0.0.1/tcp/4001/ipfs/QmTNwsFkLAed15kQEC1ZJWPfoNbBQnMFojfJKQ9sZj1dk8", - "/ip4/192.168.2.131/tcp/4001/ipfs/QmTNwsFkLAed15kQEC1ZJWPfoNbBQnMFojfJKQ9sZj1dk8", + "/ip4/127.0.0.1/tcp/4001/p2p/QmTNwsFkLAed15kQEC1ZJWPfoNbBQnMFojfJKQ9sZj1dk8", + "/ip4/192.168.2.131/tcp/4001/p2p/QmTNwsFkLAed15kQEC1ZJWPfoNbBQnMFojfJKQ9sZj1dk8", ], "AgentVersion": "go-ipfs/0.4.11-dev/", "ProtocolVersion": "ipfs/0.1.0" diff --git a/docs/fuse.md b/docs/fuse.md index f26b0e31d3e..a6399eeba44 100644 --- a/docs/fuse.md +++ b/docs/fuse.md @@ -31,7 +31,7 @@ ssh connection or by re-logging to the system. It has been discovered that versions of `osxfuse` prior to `2.7.0` will cause a kernel panic. For everyone's sake, please upgrade (latest at time of writing is `2.7.4`). The installer can be found at https://osxfuse.github.io/. There is -also a homebrew formula (`brew install osxfuse`) but users report best results +also a homebrew formula (`brew cask install osxfuse`) but users report best results installing from the official OSXFUSE installer package. Note that `ipfs` attempts an automatic version check on `osxfuse` to prevent you @@ -62,7 +62,21 @@ sudo chown /ipfs sudo chown /ipns ``` -Depending on whether you are using OSX or Linux, follow the proceeding instructions. +Depending on whether you are using OSX or Linux, follow the proceeding instructions. + +## Make sure IPFS daemon is not running + +You'll need to stop the IPFS daemon if you have it started, otherwise the mount will complain. + +``` +# Check to see if IPFS daemon is running +ps aux | grep ipfs + +# Kill the IPFS daemon +pkill -f ipfs + +# Verify that it has been killed +``` ## Mounting IPFS diff --git a/docs/gateway.md b/docs/gateway.md index fe4beb891e2..2344ee55ea8 100644 --- a/docs/gateway.md +++ b/docs/gateway.md @@ -31,6 +31,12 @@ a directory: `go-get=1` parameter. See [PR#3964](https://github.com/ipfs/go-ipfs/pull/3963) for details +## Static Websites + +You can use an IPFS gateway to serve static websites at a custom domain using +[DNSLink](https://dnslink.io). See [Example: IPFS +Gateway](https://dnslink.io/#example-ipfs-gateway) for instructions. + ## Filenames When downloading files, browsers will usually guess a file's filename by looking diff --git a/docs/plugins.md b/docs/plugins.md index a40201d1e00..124f8f8b2e9 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -21,6 +21,9 @@ directory (by default `~/.ipfs/plugins`). ## Plugin Types +Plugins can implement one or more plugin types, defined in the +[plugin](https://godoc.org/github.com/ipfs/go-ipfs/plugin) package. + ### IPLD IPLD plugins add support for additional formats to `ipfs dag` and other IPLD @@ -45,6 +48,43 @@ application without IPC and without forking go-ipfs. Note: We eventually plan to make go-ipfs usable as a library. However, this plugin type is likely the best interim solution. +### Internal + +(never stable) + +Internal plugins are like daemon plugins _except_ that they can access, replace, +and modify all internal state. Use this plugin type to extend go-ipfs in +arbitrary ways. However, be aware that your plugin will likely break every time +go-ipfs updated. + +## Configuration + +Plugins can be configured in the `Plugins` section of the config file. Here, +plugins can be: + +1. Passed an arbitrary config object via the `Config` field. +2. Disabled via the `Disabled` field. + +Example: + +```js +{ + // ... + "Plugins": { + "Plugins": { + // plugin named "plugin-foo" + "plugin-foo": { + "Config": { /* arbitrary json */ } + }, + // plugin named "plugin-bar" + "plugin-bar": { + "Disabled": true // "plugin-bar" will not be loaded + } + } + } +} +``` + ## Available Plugins | Name | Type | Preloaded | Description | @@ -124,6 +164,13 @@ To preload a go-ipfs plugin: go-ipfs$ make build ``` +You can also preload an in-tree but disabled-by-default plugin by adding it to +the IPFS_PLUGINS variable. For example, to enable plugins foo, bar, and baz: + +```bash +go-ipfs$ make build IPFS_PLUGINS="foo bar baz" +``` + ## Creating A Plugin To create your own out-of-tree plugin, use the [example diff --git a/docs/releases.md b/docs/releases.md index fb75ed8e766..3170ffcb578 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1,39 +1,105 @@ -# go-ipfs releases - -## Release Schedule -go-ipfs is on a six week release schedule. Following a release, there will be -five weeks for code of any type (features, bugfixes, etc) to be added. After -the five weeks is up, a release candidate is tagged and only important bugfixes -will be allowed up to release day. - -## Release Candidate Checklist -- [ ] CHANGELOG.md has been updated - - use `./bin/mkreleaselog` to generate a nice starter list -- [ ] version string in `version.go` has been updated -- [ ] tag commit with vX.Y.Z-rcN - -## Pre-Release Checklist -- [ ] before release, tag 'release candidate' for users to test against - - if bugs are found/fixed, do another release candidate -- [ ] all tests pass (no exceptions) -- [ ] run interop tests https://github.com/ipfs/interop#test-with-a-non-yet-released-version-of-go-ipfs -- [ ] webui works (for most definitions of 'works') - Test the multiple pages and verify that no visible errors are shown. -- [ ] CHANGELOG.md has been updated - - use `./bin/mkreleaselog` to generate a nice starter list -- [ ] version string in `repo/version.go` has been updated -- [ ] tag commit with vX.Y.Z -- [ ] update release branch to point to release commit (`git merge vX.Y.Z`). -- [ ] publish dist.ipfs.io -- [ ] publish next version to https://github.com/ipfs/npm-go-ipfs - -## Post-Release -- [ ] Bump version string in `repo/version.go` to `vX.Y.Z-dev` -- [ ] Upload the final release to the github releases page: https://github.com/ipfs/go-ipfs/releases -- Communication - - [ ] Create the release issue - - [ ] Announcements (both pre-release and post-release) - - [ ] Twitter - - [ ] IRC - - [ ] Reddit - - [ ] Blog post (at minimum, paste the changelog. optionally add context and thank contributors.) -- [ ] Update HTTP-API Documentation on the Website using https://github.com/ipfs/http-api-docs +# `go-ipfs` Release Flow + +## Table of Contents + +- [Release Philosophy](#release-philosophy) +- [Release Flow](#release-flow) + - [Stage 0 - Automated Testing](#stage-0---automated-testing) + - [Stage 1 - Internal Testing](#stage-1---internal-testing) + - [Stage 2 - Community Dev Testing](#stage-2---community-dev-testing) + - [Stage 3 - Community Prod Testing](#stage-3---community-prod-testing) + - [Stage 4 - Release](#stage-4---release) +- [Release Cycle](#release-cycle) + - [Patch Releases](#patch-releases) +- [Performing a Release](#performing-a-release) +- [Release Version Numbers (aka semver)](#release-version-numbers-aka-semver) + +## Release Philosophy + +`go-ipfs` aims to have release every six weeks, two releases per quarter. During these 6 week releases, we go through 4 different stages that gives us the opportunity to test the new version against our test environments (unit, interop, integration), QA in our current production environment, IPFS apps (e.g. Desktop and WebUI) and with our community and _early testers_[1] that have IPFS running in production. + +We might expand the six week release schedule in case of: + +- No new updates to be added +- In case of a large community event that takes the core team availability away (e.g. IPFS Conf, Dev Meetings, IPFS Camp, etc.) + +## Release Flow + +`go-ipfs` releases come in 5 stages designed to gradually roll out changes and reduce the impact of any regressions that may have been introduced. If we need to merge non-trivial[2] changes during the process, we start over at stage 0. + +![go-ipfs-release-process-illustration](https://user-images.githubusercontent.com/618519/62986422-653fee00-bdf0-11e9-8f61-197117b61da2.png) + +### Stage 0 - Automated Testing + +At this stage, we expect _all_ automated tests (interop, testlab, performance, etc.) to pass. + +### Stage 1 - Internal Testing + +At this stage, we'll: + +1. Start a partial-rollout to our own infrastructure. +2. Test against ipfs and ipfs-shipyard applications. + +**Goals:** + +1. Make sure we haven't introduced any obvious regressions. +2. Test the release in an environment we can monitor and easily roll back (i.e. our own infra). + +### Stage 2 - Community Dev Testing + +At this stage, we'll announce the impending release to the community and ask for beta testers. + +**Goal:** + +Test the release in as many non-production environments as possible. This is relatively low-risk but gives us a _breadth_ of testing internal testing can't. + +### Stage 3 - Community Prod Testing + +At this stage, we consider the release to be "production ready" and will ask the community and our early testers to (partially) deploy the release to their production infrastructure. + +**Goals:** + +1. Test the release in some production environments with heavy workloads. +2. Partially roll-out an upgrade to see how it affects the network. +3. Retain the ability to ship last-minute fixes before the final release. + +### Stage 4 - Release + +At this stage, the release is "battle hardened" and ready for wide deployment. + +## Release Cycle + +A full release process should take about 3 weeks, a week per stage 1-3. We will start a new process every 6 weeks, regardless of when the previous release landed unless it's still ongoing. + +### Patch Releases + +If we encounter a serious bug in the stable latest release, we will create a patch release based on this release. For now, bug fixes will _not_ be backported to previous releases. + +Patch releases will usually follow a compressed release cycle and should take 2-3 days. In a patch release: + +1. Automated and internal testing (stage 0 and 1) will be compressed into a few hours - ideally less than a day. +2. Stage 2 will be skipped. +3. Community production testing will be shortened to 1-2 days of opt-in testing in production (early testers can choose to pass). + +Some patch releases, especially ones fixing one or more complex bugs, may undergo the full release process. + +## Performing a Release + +The release is managed by the `Lead Maintainer` for `go-ipfs`. It starts with the opening of an issue containing the content available on the [RELEASE_ISSUE_TEMPLATE](./RELEASE_ISSUE_TEMPLATE.md) not more than **48 hours** after the previous release. + +This issue is pinned and labeled ["release"](https://github.com/ipfs/go-ipfs/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Arelease). When the cycle is due to begin the 5 stages will be followed until the release is done. + +## Release Version Numbers (aka semver) + +Until `go-ipfs` 0.4.X, `go-ipfs` was not using semver to communicate the type of release + +Post `go-ipfs` 0.5.X, `go-ipfs` will use semver. This means that patch releases will not contain any breaking changes nor new features. Minor releases might contain breaking changes and always contain some new feature + +Post `go-ipfs` 1.X.X (future), `go-ipfs` will use semver. This means that only major releases will contain breaking changes, minors will be reserved for new features and patches for bug fixes. + +We do not yet retroactively apply fixes to older releases (no Long Term Support releases for now), which means that we always recommend users to update to the latest, whenever possible. + +---------------------------- + +- **[1]** - _early testers_ is an IPFS programme in which members of the community can self-volunteer to help test `go-ipfs` Release Candidates. You find more info about it at [EARLY_TESTERS.md](./EARLY_TESTERS.md) +- **[2]** - A non-trivial change is any change that could potentially introduce an issue not trivially caught by automated testing. This is up to the discretion of the Lead Maintainer but the assumption is that every change is non-trivial unless proven otherwise. diff --git a/docs/transports.md b/docs/transports.md index 39ce127db03..f70fff6d7ba 100644 --- a/docs/transports.md +++ b/docs/transports.md @@ -1,6 +1,6 @@ ## /ws and /wss -- websockets -If you want browsers to connect to e.g. `/dns4/example.com/tcp/443/wss/ipfs/QmFoo` +If you want browsers to connect to e.g. `/dns4/example.com/tcp/443/wss/p2p/QmFoo` - [ ] An SSL cert matching the `/dns4` or `/dns6` name - [ ] go-ipfs listening on `/ip4/127.0.0.1/tcp/8081/ws` diff --git a/docs/windows.md b/docs/windows.md index 2687805e202..4487e64ffe9 100644 --- a/docs/windows.md +++ b/docs/windows.md @@ -1,6 +1,8 @@ # Building on Windows ![](https://ipfs.io/ipfs/QmccXW7JSZMVXidSc7tHsU6aktuaiV923q4yBGHUsdymYo/build.gif) +If you just want to install go-ipfs, please download it from https://dist.ipfs.io/#go-ipfs. This document explains how to build it from source. + ## Install Go `go-ipfs` is built on Golang and thus depends on it for all building methods. https://golang.org/doc/install @@ -103,27 +105,20 @@ SETX PATH %PATH% ``` ## Minimal -While it's possible to build `go-ipfs` with `go` alone, we'll be using `git` and `gx` for practical source management. -You can use whichever version of `git` you wish but we recommend the Windows builds at . `git` must be in your [`PATH`](https://ss64.com/nt/path.html) for `go get` to recognize and use it. -### `gx` -You may install prebuilt binaries for [`gx`](https://dist.ipfs.io/#gx) & [`gx-go`](https://dist.ipfs.io/#gx-go) if they're available for your platform. -Alternatively, you can build them from source and install them to `%GOPATH%\bin` by running the following: +While it's possible to build `go-ipfs` with `go` alone, we'll be using `git` to fetch the source. -``` -go get -u github.com/whyrusleeping/gx -go get -u github.com/whyrusleeping/gx-go -``` +You can use whichever version of `git` you wish but we recommend the Windows builds at . `git` must be in your [`PATH`](https://ss64.com/nt/path.html) for `go get` to recognize and use it. + +### go-ipfs -### `go-ipfs` +Clone and change directory to the source code, if you haven't already: ``` -SET PATH=%PATH%;%GOPATH%\bin -go get -u -d github.com/ipfs/go-ipfs -cd %GOPATH%/src/github.com/ipfs/go-ipfs -gx --verbose install --global -cd cmd\ipfs +git clone https://github.com/ipfs/go-ipfs %GOPATH%/src/github.com/ipfs/go-ipfs +cd %GOPATH%/src/github.com/ipfs/go-ipfs/cmd/ipfs ``` + We need the `git` commit hash to be included in our build so that in the extremely rare event a bug is found, we have a reference point later for tracking it. We'll ask `git` for it and store it in a variable. The syntax for the next command is different depending on whether you're using the interactive command line or writing a batch file. Use the one that applies to you. - interactive: `FOR /F %V IN ('git rev-parse --short HEAD') do set SHA=%V` - interpreter: `FOR /F %%V IN ('git rev-parse --short HEAD') do set SHA=%%V` diff --git a/filestore/filestore.go b/filestore/filestore.go deleted file mode 100644 index be4d954beb7..00000000000 --- a/filestore/filestore.go +++ /dev/null @@ -1,251 +0,0 @@ -// Package filestore implements a Blockstore which is able to read certain -// blocks of data directly from its original location in the filesystem. -// -// In a Filestore, object leaves are stored as FilestoreNodes. FilestoreNodes -// include a filesystem path and an offset, allowing a Blockstore dealing with -// such blocks to avoid storing the whole contents and reading them from their -// filesystem location instead. -package filestore - -import ( - "context" - "errors" - - blocks "github.com/ipfs/go-block-format" - cid "github.com/ipfs/go-cid" - dsq "github.com/ipfs/go-datastore/query" - blockstore "github.com/ipfs/go-ipfs-blockstore" - posinfo "github.com/ipfs/go-ipfs-posinfo" - logging "github.com/ipfs/go-log" -) - -var log = logging.Logger("filestore") - -var ErrFilestoreNotEnabled = errors.New("filestore is not enabled, see https://git.io/vNItf") -var ErrUrlstoreNotEnabled = errors.New("urlstore is not enabled") - -// Filestore implements a Blockstore by combining a standard Blockstore -// to store regular blocks and a special Blockstore called -// FileManager to store blocks which data exists in an external file. -type Filestore struct { - fm *FileManager - bs blockstore.Blockstore -} - -// FileManager returns the FileManager in Filestore. -func (f *Filestore) FileManager() *FileManager { - return f.fm -} - -// MainBlockstore returns the standard Blockstore in the Filestore. -func (f *Filestore) MainBlockstore() blockstore.Blockstore { - return f.bs -} - -// NewFilestore creates one using the given Blockstore and FileManager. -func NewFilestore(bs blockstore.Blockstore, fm *FileManager) *Filestore { - return &Filestore{fm, bs} -} - -// AllKeysChan returns a channel from which to read the keys stored in -// the blockstore. If the given context is cancelled the channel will be closed. -func (f *Filestore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) { - ctx, cancel := context.WithCancel(ctx) - - a, err := f.bs.AllKeysChan(ctx) - if err != nil { - cancel() - return nil, err - } - - out := make(chan cid.Cid, dsq.KeysOnlyBufSize) - go func() { - defer cancel() - defer close(out) - - var done bool - for !done { - select { - case c, ok := <-a: - if !ok { - done = true - continue - } - select { - case out <- c: - case <-ctx.Done(): - return - } - case <-ctx.Done(): - return - } - } - - // Can't do these at the same time because the abstractions around - // leveldb make us query leveldb for both operations. We apparently - // cant query leveldb concurrently - b, err := f.fm.AllKeysChan(ctx) - if err != nil { - log.Error("error querying filestore: ", err) - return - } - - done = false - for !done { - select { - case c, ok := <-b: - if !ok { - done = true - continue - } - select { - case out <- c: - case <-ctx.Done(): - return - } - case <-ctx.Done(): - return - } - } - }() - return out, nil -} - -// DeleteBlock deletes the block with the given key from the -// blockstore. As expected, in the case of FileManager blocks, only the -// reference is deleted, not its contents. It may return -// ErrNotFound when the block is not stored. -func (f *Filestore) DeleteBlock(c cid.Cid) error { - err1 := f.bs.DeleteBlock(c) - if err1 != nil && err1 != blockstore.ErrNotFound { - return err1 - } - - err2 := f.fm.DeleteBlock(c) - // if we successfully removed something from the blockstore, but the - // filestore didnt have it, return success - - switch err2 { - case nil: - return nil - case blockstore.ErrNotFound: - if err1 == blockstore.ErrNotFound { - return blockstore.ErrNotFound - } - return nil - default: - return err2 - } -} - -// Get retrieves the block with the given Cid. It may return -// ErrNotFound when the block is not stored. -func (f *Filestore) Get(c cid.Cid) (blocks.Block, error) { - blk, err := f.bs.Get(c) - switch err { - case nil: - return blk, nil - case blockstore.ErrNotFound: - return f.fm.Get(c) - default: - return nil, err - } -} - -// GetSize returns the size of the requested block. It may return ErrNotFound -// when the block is not stored. -func (f *Filestore) GetSize(c cid.Cid) (int, error) { - size, err := f.bs.GetSize(c) - switch err { - case nil: - return size, nil - case blockstore.ErrNotFound: - return f.fm.GetSize(c) - default: - return -1, err - } -} - -// Has returns true if the block with the given Cid is -// stored in the Filestore. -func (f *Filestore) Has(c cid.Cid) (bool, error) { - has, err := f.bs.Has(c) - if err != nil { - return false, err - } - - if has { - return true, nil - } - - return f.fm.Has(c) -} - -// Put stores a block in the Filestore. For blocks of -// underlying type FilestoreNode, the operation is -// delegated to the FileManager, while the rest of blocks -// are handled by the regular blockstore. -func (f *Filestore) Put(b blocks.Block) error { - has, err := f.Has(b.Cid()) - if err != nil { - return err - } - - if has { - return nil - } - - switch b := b.(type) { - case *posinfo.FilestoreNode: - return f.fm.Put(b) - default: - return f.bs.Put(b) - } -} - -// PutMany is like Put(), but takes a slice of blocks, allowing -// the underlying blockstore to perform batch transactions. -func (f *Filestore) PutMany(bs []blocks.Block) error { - var normals []blocks.Block - var fstores []*posinfo.FilestoreNode - - for _, b := range bs { - has, err := f.Has(b.Cid()) - if err != nil { - return err - } - - if has { - continue - } - - switch b := b.(type) { - case *posinfo.FilestoreNode: - fstores = append(fstores, b) - default: - normals = append(normals, b) - } - } - - if len(normals) > 0 { - err := f.bs.PutMany(normals) - if err != nil { - return err - } - } - - if len(fstores) > 0 { - err := f.fm.PutMany(fstores) - if err != nil { - return err - } - } - return nil -} - -// HashOnRead calls blockstore.HashOnRead. -func (f *Filestore) HashOnRead(enabled bool) { - f.bs.HashOnRead(enabled) -} - -var _ blockstore.Blockstore = (*Filestore)(nil) diff --git a/filestore/filestore_test.go b/filestore/filestore_test.go deleted file mode 100644 index 783dc86f941..00000000000 --- a/filestore/filestore_test.go +++ /dev/null @@ -1,177 +0,0 @@ -package filestore - -import ( - "bytes" - "context" - "io/ioutil" - "math/rand" - "testing" - - dag "github.com/ipfs/go-merkledag" - - cid "github.com/ipfs/go-cid" - ds "github.com/ipfs/go-datastore" - blockstore "github.com/ipfs/go-ipfs-blockstore" - posinfo "github.com/ipfs/go-ipfs-posinfo" -) - -func newTestFilestore(t *testing.T) (string, *Filestore) { - mds := ds.NewMapDatastore() - - testdir, err := ioutil.TempDir("", "filestore-test") - if err != nil { - t.Fatal(err) - } - fm := NewFileManager(mds, testdir) - fm.AllowFiles = true - - bs := blockstore.NewBlockstore(mds) - fstore := NewFilestore(bs, fm) - return testdir, fstore -} - -func makeFile(dir string, data []byte) (string, error) { - f, err := ioutil.TempFile(dir, "file") - if err != nil { - return "", err - } - - _, err = f.Write(data) - if err != nil { - return "", err - } - - return f.Name(), nil -} - -func TestBasicFilestore(t *testing.T) { - dir, fs := newTestFilestore(t) - - buf := make([]byte, 1000) - rand.Read(buf) - - fname, err := makeFile(dir, buf) - if err != nil { - t.Fatal(err) - } - - var cids []cid.Cid - for i := 0; i < 100; i++ { - n := &posinfo.FilestoreNode{ - PosInfo: &posinfo.PosInfo{ - FullPath: fname, - Offset: uint64(i * 10), - }, - Node: dag.NewRawNode(buf[i*10 : (i+1)*10]), - } - - err := fs.Put(n) - if err != nil { - t.Fatal(err) - } - cids = append(cids, n.Node.Cid()) - } - - for i, c := range cids { - blk, err := fs.Get(c) - if err != nil { - t.Fatal(err) - } - - if !bytes.Equal(blk.RawData(), buf[i*10:(i+1)*10]) { - t.Fatal("data didnt match on the way out") - } - } - - kch, err := fs.AllKeysChan(context.Background()) - if err != nil { - t.Fatal(err) - } - - out := make(map[string]struct{}) - for c := range kch { - out[c.KeyString()] = struct{}{} - } - - if len(out) != len(cids) { - t.Fatal("mismatch in number of entries") - } - - for _, c := range cids { - if _, ok := out[c.KeyString()]; !ok { - t.Fatal("missing cid: ", c) - } - } -} - -func randomFileAdd(t *testing.T, fs *Filestore, dir string, size int) (string, []cid.Cid) { - buf := make([]byte, size) - rand.Read(buf) - - fname, err := makeFile(dir, buf) - if err != nil { - t.Fatal(err) - } - - var out []cid.Cid - for i := 0; i < size/10; i++ { - n := &posinfo.FilestoreNode{ - PosInfo: &posinfo.PosInfo{ - FullPath: fname, - Offset: uint64(i * 10), - }, - Node: dag.NewRawNode(buf[i*10 : (i+1)*10]), - } - err := fs.Put(n) - if err != nil { - t.Fatal(err) - } - out = append(out, n.Cid()) - } - - return fname, out -} - -func TestDeletes(t *testing.T) { - dir, fs := newTestFilestore(t) - _, cids := randomFileAdd(t, fs, dir, 100) - todelete := cids[:4] - for _, c := range todelete { - err := fs.DeleteBlock(c) - if err != nil { - t.Fatal(err) - } - } - - deleted := make(map[string]bool) - for _, c := range todelete { - _, err := fs.Get(c) - if err != blockstore.ErrNotFound { - t.Fatal("expected blockstore not found error") - } - deleted[c.KeyString()] = true - } - - keys, err := fs.AllKeysChan(context.Background()) - if err != nil { - t.Fatal(err) - } - - for c := range keys { - if deleted[c.KeyString()] { - t.Fatal("shouldnt have reference to this key anymore") - } - } -} - -func TestIsURL(t *testing.T) { - if !IsURL("http://www.example.com") { - t.Fatal("IsURL failed: http://www.example.com") - } - if !IsURL("https://www.example.com") { - t.Fatal("IsURL failed: https://www.example.com") - } - if IsURL("adir/afile") || IsURL("http:/ /afile") || IsURL("http:/a/file") { - t.Fatal("IsURL recognized non-url") - } -} diff --git a/filestore/fsrefstore.go b/filestore/fsrefstore.go deleted file mode 100644 index 320ee5928b7..00000000000 --- a/filestore/fsrefstore.go +++ /dev/null @@ -1,330 +0,0 @@ -package filestore - -import ( - "context" - "fmt" - "io" - "net/http" - "os" - "path/filepath" - - pb "github.com/ipfs/go-ipfs/filestore/pb" - - proto "github.com/gogo/protobuf/proto" - blocks "github.com/ipfs/go-block-format" - cid "github.com/ipfs/go-cid" - ds "github.com/ipfs/go-datastore" - dsns "github.com/ipfs/go-datastore/namespace" - dsq "github.com/ipfs/go-datastore/query" - blockstore "github.com/ipfs/go-ipfs-blockstore" - dshelp "github.com/ipfs/go-ipfs-ds-help" - posinfo "github.com/ipfs/go-ipfs-posinfo" -) - -// FilestorePrefix identifies the key prefix for FileManager blocks. -var FilestorePrefix = ds.NewKey("filestore") - -// FileManager is a blockstore implementation which stores special -// blocks FilestoreNode type. These nodes only contain a reference -// to the actual location of the block data in the filesystem -// (a path and an offset). -type FileManager struct { - AllowFiles bool - AllowUrls bool - ds ds.Batching - root string -} - -// CorruptReferenceError implements the error interface. -// It is used to indicate that the block contents pointed -// by the referencing blocks cannot be retrieved (i.e. the -// file is not found, or the data changed as it was being read). -type CorruptReferenceError struct { - Code Status - Err error -} - -// Error() returns the error message in the CorruptReferenceError -// as a string. -func (c CorruptReferenceError) Error() string { - return c.Err.Error() -} - -// NewFileManager initializes a new file manager with the given -// datastore and root. All FilestoreNodes paths are relative to the -// root path given here, which is prepended for any operations. -func NewFileManager(ds ds.Batching, root string) *FileManager { - return &FileManager{ds: dsns.Wrap(ds, FilestorePrefix), root: root} -} - -// AllKeysChan returns a channel from which to read the keys stored in -// the FileManager. If the given context is cancelled the channel will be -// closed. -func (f *FileManager) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) { - q := dsq.Query{KeysOnly: true} - - res, err := f.ds.Query(q) - if err != nil { - return nil, err - } - - out := make(chan cid.Cid, dsq.KeysOnlyBufSize) - go func() { - defer close(out) - for { - v, ok := res.NextSync() - if !ok { - return - } - - k := ds.RawKey(v.Key) - c, err := dshelp.DsKeyToCid(k) - if err != nil { - log.Errorf("decoding cid from filestore: %s", err) - continue - } - - select { - case out <- c: - case <-ctx.Done(): - return - } - } - }() - - return out, nil -} - -// DeleteBlock deletes the reference-block from the underlying -// datastore. It does not touch the referenced data. -func (f *FileManager) DeleteBlock(c cid.Cid) error { - err := f.ds.Delete(dshelp.CidToDsKey(c)) - if err == ds.ErrNotFound { - return blockstore.ErrNotFound - } - return err -} - -// Get reads a block from the datastore. Reading a block -// is done in two steps: the first step retrieves the reference -// block from the datastore. The second step uses the stored -// path and offsets to read the raw block data directly from disk. -func (f *FileManager) Get(c cid.Cid) (blocks.Block, error) { - dobj, err := f.getDataObj(c) - if err != nil { - return nil, err - } - out, err := f.readDataObj(c, dobj) - if err != nil { - return nil, err - } - - return blocks.NewBlockWithCid(out, c) -} - -// GetSize gets the size of the block from the datastore. -// -// This method may successfully return the size even if returning the block -// would fail because the associated file is no longer available. -func (f *FileManager) GetSize(c cid.Cid) (int, error) { - dobj, err := f.getDataObj(c) - if err != nil { - return -1, err - } - return int(dobj.GetSize_()), nil -} - -func (f *FileManager) readDataObj(c cid.Cid, d *pb.DataObj) ([]byte, error) { - if IsURL(d.GetFilePath()) { - return f.readURLDataObj(c, d) - } - return f.readFileDataObj(c, d) -} - -func (f *FileManager) getDataObj(c cid.Cid) (*pb.DataObj, error) { - o, err := f.ds.Get(dshelp.CidToDsKey(c)) - switch err { - case ds.ErrNotFound: - return nil, blockstore.ErrNotFound - default: - return nil, err - case nil: - // - } - - return unmarshalDataObj(o) -} - -func unmarshalDataObj(data []byte) (*pb.DataObj, error) { - var dobj pb.DataObj - if err := proto.Unmarshal(data, &dobj); err != nil { - return nil, err - } - - return &dobj, nil -} - -func (f *FileManager) readFileDataObj(c cid.Cid, d *pb.DataObj) ([]byte, error) { - if !f.AllowFiles { - return nil, ErrFilestoreNotEnabled - } - - p := filepath.FromSlash(d.GetFilePath()) - abspath := filepath.Join(f.root, p) - - fi, err := os.Open(abspath) - if os.IsNotExist(err) { - return nil, &CorruptReferenceError{StatusFileNotFound, err} - } else if err != nil { - return nil, &CorruptReferenceError{StatusFileError, err} - } - defer fi.Close() - - _, err = fi.Seek(int64(d.GetOffset()), io.SeekStart) - if err != nil { - return nil, &CorruptReferenceError{StatusFileError, err} - } - - outbuf := make([]byte, d.GetSize_()) - _, err = io.ReadFull(fi, outbuf) - if err == io.EOF || err == io.ErrUnexpectedEOF { - return nil, &CorruptReferenceError{StatusFileChanged, err} - } else if err != nil { - return nil, &CorruptReferenceError{StatusFileError, err} - } - - outcid, err := c.Prefix().Sum(outbuf) - if err != nil { - return nil, err - } - - if !c.Equals(outcid) { - return nil, &CorruptReferenceError{StatusFileChanged, - fmt.Errorf("data in file did not match. %s offset %d", d.GetFilePath(), d.GetOffset())} - } - - return outbuf, nil -} - -// reads and verifies the block from URL -func (f *FileManager) readURLDataObj(c cid.Cid, d *pb.DataObj) ([]byte, error) { - if !f.AllowUrls { - return nil, ErrUrlstoreNotEnabled - } - - req, err := http.NewRequest("GET", d.GetFilePath(), nil) - if err != nil { - return nil, err - } - - req.Header.Add("Range", fmt.Sprintf("bytes=%d-%d", d.GetOffset(), d.GetOffset()+d.GetSize_()-1)) - - res, err := http.DefaultClient.Do(req) - if err != nil { - return nil, &CorruptReferenceError{StatusFileError, err} - } - if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusPartialContent { - return nil, &CorruptReferenceError{StatusFileError, - fmt.Errorf("expected HTTP 200 or 206 got %d", res.StatusCode)} - } - - outbuf := make([]byte, d.GetSize_()) - _, err = io.ReadFull(res.Body, outbuf) - if err == io.EOF || err == io.ErrUnexpectedEOF { - return nil, &CorruptReferenceError{StatusFileChanged, err} - } else if err != nil { - return nil, &CorruptReferenceError{StatusFileError, err} - } - res.Body.Close() - - outcid, err := c.Prefix().Sum(outbuf) - if err != nil { - return nil, err - } - - if !c.Equals(outcid) { - return nil, &CorruptReferenceError{StatusFileChanged, - fmt.Errorf("data in file did not match. %s offset %d", d.GetFilePath(), d.GetOffset())} - } - - return outbuf, nil -} - -// Has returns if the FileManager is storing a block reference. It does not -// validate the data, nor checks if the reference is valid. -func (f *FileManager) Has(c cid.Cid) (bool, error) { - // NOTE: interesting thing to consider. Has doesnt validate the data. - // So the data on disk could be invalid, and we could think we have it. - dsk := dshelp.CidToDsKey(c) - return f.ds.Has(dsk) -} - -type putter interface { - Put(ds.Key, []byte) error -} - -// Put adds a new reference block to the FileManager. It does not check -// that the reference is valid. -func (f *FileManager) Put(b *posinfo.FilestoreNode) error { - return f.putTo(b, f.ds) -} - -func (f *FileManager) putTo(b *posinfo.FilestoreNode, to putter) error { - var dobj pb.DataObj - - if IsURL(b.PosInfo.FullPath) { - if !f.AllowUrls { - return ErrUrlstoreNotEnabled - } - dobj.FilePath = b.PosInfo.FullPath - } else { - if !f.AllowFiles { - return ErrFilestoreNotEnabled - } - if !filepath.HasPrefix(b.PosInfo.FullPath, f.root) { //nolint:staticcheck - return fmt.Errorf("cannot add filestore references outside ipfs root (%s)", f.root) - } - - p, err := filepath.Rel(f.root, b.PosInfo.FullPath) - if err != nil { - return err - } - - dobj.FilePath = filepath.ToSlash(p) - } - dobj.Offset = b.PosInfo.Offset - dobj.Size_ = uint64(len(b.RawData())) - - data, err := proto.Marshal(&dobj) - if err != nil { - return err - } - - return to.Put(dshelp.CidToDsKey(b.Cid()), data) -} - -// PutMany is like Put() but takes a slice of blocks instead, -// allowing it to create a batch transaction. -func (f *FileManager) PutMany(bs []*posinfo.FilestoreNode) error { - batch, err := f.ds.Batch() - if err != nil { - return err - } - - for _, b := range bs { - if err := f.putTo(b, batch); err != nil { - return err - } - } - - return batch.Commit() -} - -// IsURL returns true if the string represents a valid URL that the -// urlstore can handle. More specifically it returns true if a string -// begins with 'http://' or 'https://'. -func IsURL(str string) bool { - return (len(str) > 7 && str[0] == 'h' && str[1] == 't' && str[2] == 't' && str[3] == 'p') && - ((len(str) > 8 && str[4] == 's' && str[5] == ':' && str[6] == '/' && str[7] == '/') || - (str[4] == ':' && str[5] == '/' && str[6] == '/')) -} diff --git a/filestore/pb/Rules.mk b/filestore/pb/Rules.mk deleted file mode 100644 index 505f70e7541..00000000000 --- a/filestore/pb/Rules.mk +++ /dev/null @@ -1,8 +0,0 @@ -include mk/header.mk - -PB_$(d) = $(wildcard $(d)/*.proto) -TGTS_$(d) = $(PB_$(d):.proto=.pb.go) - -#DEPS_GO += $(TGTS_$(d)) - -include mk/footer.mk diff --git a/filestore/pb/dataobj.pb.go b/filestore/pb/dataobj.pb.go deleted file mode 100644 index 59650a11c10..00000000000 --- a/filestore/pb/dataobj.pb.go +++ /dev/null @@ -1,399 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: filestore/pb/dataobj.proto - -package datastore_pb - -import ( - fmt "fmt" - proto "github.com/gogo/protobuf/proto" - io "io" - math "math" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package - -type DataObj struct { - FilePath string `protobuf:"bytes,1,opt,name=FilePath" json:"FilePath"` - Offset uint64 `protobuf:"varint,2,opt,name=Offset" json:"Offset"` - Size_ uint64 `protobuf:"varint,3,opt,name=Size" json:"Size"` -} - -func (m *DataObj) Reset() { *m = DataObj{} } -func (m *DataObj) String() string { return proto.CompactTextString(m) } -func (*DataObj) ProtoMessage() {} -func (*DataObj) Descriptor() ([]byte, []int) { - return fileDescriptor_86a3613fbaff9a6c, []int{0} -} -func (m *DataObj) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *DataObj) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_DataObj.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalTo(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *DataObj) XXX_Merge(src proto.Message) { - xxx_messageInfo_DataObj.Merge(m, src) -} -func (m *DataObj) XXX_Size() int { - return m.Size() -} -func (m *DataObj) XXX_DiscardUnknown() { - xxx_messageInfo_DataObj.DiscardUnknown(m) -} - -var xxx_messageInfo_DataObj proto.InternalMessageInfo - -func (m *DataObj) GetFilePath() string { - if m != nil { - return m.FilePath - } - return "" -} - -func (m *DataObj) GetOffset() uint64 { - if m != nil { - return m.Offset - } - return 0 -} - -func (m *DataObj) GetSize_() uint64 { - if m != nil { - return m.Size_ - } - return 0 -} - -func init() { - proto.RegisterType((*DataObj)(nil), "datastore.pb.DataObj") -} - -func init() { proto.RegisterFile("filestore/pb/dataobj.proto", fileDescriptor_86a3613fbaff9a6c) } - -var fileDescriptor_86a3613fbaff9a6c = []byte{ - // 160 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4a, 0xcb, 0xcc, 0x49, - 0x2d, 0x2e, 0xc9, 0x2f, 0x4a, 0xd5, 0x2f, 0x48, 0xd2, 0x4f, 0x49, 0x2c, 0x49, 0xcc, 0x4f, 0xca, - 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x01, 0x71, 0xc1, 0x72, 0x7a, 0x05, 0x49, 0x4a, - 0xc9, 0x5c, 0xec, 0x2e, 0x89, 0x25, 0x89, 0xfe, 0x49, 0x59, 0x42, 0x0a, 0x5c, 0x1c, 0x6e, 0x99, - 0x39, 0xa9, 0x01, 0x89, 0x25, 0x19, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x4e, 0x2c, 0x27, 0xee, - 0xc9, 0x33, 0x04, 0xc1, 0x45, 0x85, 0x64, 0xb8, 0xd8, 0xfc, 0xd3, 0xd2, 0x8a, 0x53, 0x4b, 0x24, - 0x98, 0x14, 0x18, 0x35, 0x58, 0xa0, 0xf2, 0x50, 0x31, 0x21, 0x09, 0x2e, 0x96, 0xe0, 0xcc, 0xaa, - 0x54, 0x09, 0x66, 0x24, 0x39, 0xb0, 0x88, 0x93, 0xc4, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, - 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, - 0xcb, 0x31, 0x00, 0x02, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x87, 0xf5, 0x88, 0xa9, 0x00, 0x00, 0x00, -} - -func (m *DataObj) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *DataObj) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - dAtA[i] = 0xa - i++ - i = encodeVarintDataobj(dAtA, i, uint64(len(m.FilePath))) - i += copy(dAtA[i:], m.FilePath) - dAtA[i] = 0x10 - i++ - i = encodeVarintDataobj(dAtA, i, uint64(m.Offset)) - dAtA[i] = 0x18 - i++ - i = encodeVarintDataobj(dAtA, i, uint64(m.Size_)) - return i, nil -} - -func encodeVarintDataobj(dAtA []byte, offset int, v uint64) int { - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return offset + 1 -} -func (m *DataObj) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.FilePath) - n += 1 + l + sovDataobj(uint64(l)) - n += 1 + sovDataobj(uint64(m.Offset)) - n += 1 + sovDataobj(uint64(m.Size_)) - return n -} - -func sovDataobj(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n -} -func sozDataobj(x uint64) (n int) { - return sovDataobj(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *DataObj) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDataobj - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: DataObj: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: DataObj: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field FilePath", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDataobj - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthDataobj - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthDataobj - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.FilePath = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Offset", wireType) - } - m.Offset = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDataobj - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Offset |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Size_", wireType) - } - m.Size_ = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDataobj - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Size_ |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipDataobj(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthDataobj - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthDataobj - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipDataobj(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowDataobj - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowDataobj - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - return iNdEx, nil - case 1: - iNdEx += 8 - return iNdEx, nil - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowDataobj - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthDataobj - } - iNdEx += length - if iNdEx < 0 { - return 0, ErrInvalidLengthDataobj - } - return iNdEx, nil - case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowDataobj - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipDataobj(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - if iNdEx < 0 { - return 0, ErrInvalidLengthDataobj - } - } - return iNdEx, nil - case 4: - return iNdEx, nil - case 5: - iNdEx += 4 - return iNdEx, nil - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - } - panic("unreachable") -} - -var ( - ErrInvalidLengthDataobj = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowDataobj = fmt.Errorf("proto: integer overflow") -) diff --git a/filestore/pb/dataobj.proto b/filestore/pb/dataobj.proto deleted file mode 100644 index 909d22b77f9..00000000000 --- a/filestore/pb/dataobj.proto +++ /dev/null @@ -1,9 +0,0 @@ -syntax = "proto2"; - -package datastore.pb; - -message DataObj { - optional string FilePath = 1; - optional uint64 Offset = 2; - optional uint64 Size = 3; -} diff --git a/filestore/util.go b/filestore/util.go deleted file mode 100644 index 4f39495915a..00000000000 --- a/filestore/util.go +++ /dev/null @@ -1,287 +0,0 @@ -package filestore - -import ( - "fmt" - "sort" - - pb "github.com/ipfs/go-ipfs/filestore/pb" - - cid "github.com/ipfs/go-cid" - ds "github.com/ipfs/go-datastore" - dsq "github.com/ipfs/go-datastore/query" - blockstore "github.com/ipfs/go-ipfs-blockstore" - dshelp "github.com/ipfs/go-ipfs-ds-help" -) - -// Status is used to identify the state of the block data referenced -// by a FilestoreNode. Among other places, it is used by CorruptReferenceError. -type Status int32 - -// These are the supported Status codes. -const ( - StatusOk Status = 0 - StatusFileError Status = 10 // Backing File Error - StatusFileNotFound Status = 11 // Backing File Not Found - StatusFileChanged Status = 12 // Contents of the file changed - StatusOtherError Status = 20 // Internal Error, likely corrupt entry - StatusKeyNotFound Status = 30 -) - -// String provides a human-readable representation for Status codes. -func (s Status) String() string { - switch s { - case StatusOk: - return "ok" - case StatusFileError: - return "error" - case StatusFileNotFound: - return "no-file" - case StatusFileChanged: - return "changed" - case StatusOtherError: - return "ERROR" - case StatusKeyNotFound: - return "missing" - default: - return "???" - } -} - -// Format returns the status formatted as a string -// with leading 0s. -func (s Status) Format() string { - return fmt.Sprintf("%-7s", s.String()) -} - -// ListRes wraps the response of the List*() functions, which -// allows to obtain and verify blocks stored by the FileManager -// of a Filestore. It includes information about the referenced -// block. -type ListRes struct { - Status Status - ErrorMsg string - Key cid.Cid - FilePath string - Offset uint64 - Size uint64 -} - -// FormatLong returns a human readable string for a ListRes object -func (r *ListRes) FormatLong(enc func(cid.Cid) string) string { - if enc == nil { - enc = (cid.Cid).String - } - switch { - case !r.Key.Defined(): - return "" - case r.FilePath == "": - return r.Key.String() - default: - return fmt.Sprintf("%-50s %6d %s %d", enc(r.Key), r.Size, r.FilePath, r.Offset) - } -} - -// List fetches the block with the given key from the Filemanager -// of the given Filestore and returns a ListRes object with the information. -// List does not verify that the reference is valid or whether the -// raw data is accesible. See Verify(). -func List(fs *Filestore, key cid.Cid) *ListRes { - return list(fs, false, key) -} - -// ListAll returns a function as an iterator which, once invoked, returns -// one by one each block in the Filestore's FileManager. -// ListAll does not verify that the references are valid or whether -// the raw data is accessible. See VerifyAll(). -func ListAll(fs *Filestore, fileOrder bool) (func() *ListRes, error) { - if fileOrder { - return listAllFileOrder(fs, false) - } - return listAll(fs, false) -} - -// Verify fetches the block with the given key from the Filemanager -// of the given Filestore and returns a ListRes object with the information. -// Verify makes sure that the reference is valid and the block data can be -// read. -func Verify(fs *Filestore, key cid.Cid) *ListRes { - return list(fs, true, key) -} - -// VerifyAll returns a function as an iterator which, once invoked, -// returns one by one each block in the Filestore's FileManager. -// VerifyAll checks that the reference is valid and that the block data -// can be read. -func VerifyAll(fs *Filestore, fileOrder bool) (func() *ListRes, error) { - if fileOrder { - return listAllFileOrder(fs, true) - } - return listAll(fs, true) -} - -func list(fs *Filestore, verify bool, key cid.Cid) *ListRes { - dobj, err := fs.fm.getDataObj(key) - if err != nil { - return mkListRes(key, nil, err) - } - if verify { - _, err = fs.fm.readDataObj(key, dobj) - } - return mkListRes(key, dobj, err) -} - -func listAll(fs *Filestore, verify bool) (func() *ListRes, error) { - q := dsq.Query{} - qr, err := fs.fm.ds.Query(q) - if err != nil { - return nil, err - } - - return func() *ListRes { - cid, dobj, err := next(qr) - if dobj == nil && err == nil { - return nil - } else if err == nil && verify { - _, err = fs.fm.readDataObj(cid, dobj) - } - return mkListRes(cid, dobj, err) - }, nil -} - -func next(qr dsq.Results) (cid.Cid, *pb.DataObj, error) { - v, ok := qr.NextSync() - if !ok { - return cid.Cid{}, nil, nil - } - - k := ds.RawKey(v.Key) - c, err := dshelp.DsKeyToCid(k) - if err != nil { - return cid.Cid{}, nil, fmt.Errorf("decoding cid from filestore: %s", err) - } - - dobj, err := unmarshalDataObj(v.Value) - if err != nil { - return c, nil, err - } - - return c, dobj, nil -} - -func listAllFileOrder(fs *Filestore, verify bool) (func() *ListRes, error) { - q := dsq.Query{} - qr, err := fs.fm.ds.Query(q) - if err != nil { - return nil, err - } - - var entries listEntries - - for { - v, ok := qr.NextSync() - if !ok { - break - } - dobj, err := unmarshalDataObj(v.Value) - if err != nil { - entries = append(entries, &listEntry{ - dsKey: v.Key, - err: err, - }) - } else { - entries = append(entries, &listEntry{ - dsKey: v.Key, - filePath: dobj.GetFilePath(), - offset: dobj.GetOffset(), - size: dobj.GetSize_(), - }) - } - } - sort.Sort(entries) - - i := 0 - return func() *ListRes { - if i >= len(entries) { - return nil - } - v := entries[i] - i++ - // attempt to convert the datastore key to a CID, - // store the error but don't use it yet - cid, keyErr := dshelp.DsKeyToCid(ds.RawKey(v.dsKey)) - // first if they listRes already had an error return that error - if v.err != nil { - return mkListRes(cid, nil, v.err) - } - // now reconstruct the DataObj - dobj := pb.DataObj{ - FilePath: v.filePath, - Offset: v.offset, - Size_: v.size, - } - // now if we could not convert the datastore key return that - // error - if keyErr != nil { - return mkListRes(cid, &dobj, keyErr) - } - // finally verify the dataobj if requested - var err error - if verify { - _, err = fs.fm.readDataObj(cid, &dobj) - } - return mkListRes(cid, &dobj, err) - }, nil -} - -type listEntry struct { - filePath string - offset uint64 - dsKey string - size uint64 - err error -} - -type listEntries []*listEntry - -func (l listEntries) Len() int { return len(l) } -func (l listEntries) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -func (l listEntries) Less(i, j int) bool { - if l[i].filePath == l[j].filePath { - if l[i].offset == l[j].offset { - return l[i].dsKey < l[j].dsKey - } - return l[i].offset < l[j].offset - } - return l[i].filePath < l[j].filePath -} - -func mkListRes(c cid.Cid, d *pb.DataObj, err error) *ListRes { - status := StatusOk - errorMsg := "" - if err != nil { - if err == ds.ErrNotFound || err == blockstore.ErrNotFound { - status = StatusKeyNotFound - } else if err, ok := err.(*CorruptReferenceError); ok { - status = err.Code - } else { - status = StatusOtherError - } - errorMsg = err.Error() - } - if d == nil { - return &ListRes{ - Status: status, - ErrorMsg: errorMsg, - Key: c, - } - } - - return &ListRes{ - Status: status, - ErrorMsg: errorMsg, - Key: c, - FilePath: d.FilePath, - Size: d.Size_, - Offset: d.Offset, - } -} diff --git a/fuse/ipns/common.go b/fuse/ipns/common.go index c626dac94a2..48129a92e98 100644 --- a/fuse/ipns/common.go +++ b/fuse/ipns/common.go @@ -7,7 +7,7 @@ import ( nsys "github.com/ipfs/go-ipfs/namesys" path "github.com/ipfs/go-path" ft "github.com/ipfs/go-unixfs" - ci "github.com/libp2p/go-libp2p-crypto" + ci "github.com/libp2p/go-libp2p-core/crypto" ) // InitializeKeyspace sets the ipns record for the given key to @@ -23,7 +23,7 @@ func InitializeKeyspace(n *core.IpfsNode, key ci.PrivKey) error { return err } - err = n.Pinning.Flush() + err = n.Pinning.Flush(ctx) if err != nil { return err } diff --git a/fuse/ipns/ipns_test.go b/fuse/ipns/ipns_test.go index 80ab4a52ecf..fe9e5a5ae8d 100644 --- a/fuse/ipns/ipns_test.go +++ b/fuse/ipns/ipns_test.go @@ -1,4 +1,4 @@ -// +build !nofuse +// +build !nofuse,!openbsd,!netbsd package ipns @@ -16,11 +16,12 @@ import ( "bazil.org/fuse" core "github.com/ipfs/go-ipfs/core" + coreapi "github.com/ipfs/go-ipfs/core/coreapi" fstest "bazil.org/fuse/fs/fstestutil" racedet "github.com/ipfs/go-detect-race" u "github.com/ipfs/go-ipfs-util" - ci "github.com/libp2p/go-testutil/ci" + ci "github.com/libp2p/go-libp2p-testing/ci" ) func maybeSkipFuseTests(t *testing.T) { @@ -115,7 +116,12 @@ func setupIpnsTest(t *testing.T, node *core.IpfsNode) (*core.IpfsNode, *mountWra } } - fs, err := NewFileSystem(node, node.PrivateKey, "", "") + coreApi, err := coreapi.NewCoreAPI(node) + if err != nil { + t.Fatal(err) + } + + fs, err := NewFileSystem(node.Context(), coreApi, "", "") if err != nil { t.Fatal(err) } @@ -265,7 +271,7 @@ func TestFileSizeReporting(t *testing.T) { } } -// Test to make sure you cant create multiple entries with the same name +// Test to make sure you can't create multiple entries with the same name func TestDoubleEntryFailure(t *testing.T) { if testing.Short() { t.SkipNow() @@ -452,7 +458,7 @@ func TestFSThrash(t *testing.T) { } if !bytes.Equal(data, out) { - t.Errorf("Data didnt match in %s: expected %v, got %v", name, data, out) + t.Errorf("Data didn't match in %s: expected %v, got %v", name, data, out) } } } diff --git a/fuse/ipns/ipns_unix.go b/fuse/ipns/ipns_unix.go index a662ab22e78..64233a3be38 100644 --- a/fuse/ipns/ipns_unix.go +++ b/fuse/ipns/ipns_unix.go @@ -1,4 +1,4 @@ -// +build !nofuse +// +build !nofuse,!openbsd,!netbsd // package fuse/ipns implements a fuse filesystem that interfaces // with ipns, the naming system for ipfs. @@ -10,22 +10,19 @@ import ( "fmt" "io" "os" - - core "github.com/ipfs/go-ipfs/core" - namesys "github.com/ipfs/go-ipfs/namesys" - resolve "github.com/ipfs/go-ipfs/namesys/resolve" + "strings" dag "github.com/ipfs/go-merkledag" - path "github.com/ipfs/go-path" ft "github.com/ipfs/go-unixfs" + path "github.com/ipfs/interface-go-ipfs-core/path" fuse "bazil.org/fuse" fs "bazil.org/fuse/fs" cid "github.com/ipfs/go-cid" logging "github.com/ipfs/go-log" mfs "github.com/ipfs/go-mfs" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" + iface "github.com/ipfs/interface-go-ipfs-core" + options "github.com/ipfs/interface-go-ipfs-core/options" ) func init() { @@ -40,17 +37,17 @@ var log = logging.Logger("fuse/ipns") // FileSystem is the readwrite IPNS Fuse Filesystem. type FileSystem struct { - Ipfs *core.IpfsNode + Ipfs iface.CoreAPI RootNode *Root } // NewFileSystem constructs new fs using given core.IpfsNode instance. -func NewFileSystem(ipfs *core.IpfsNode, sk ci.PrivKey, ipfspath, ipnspath string) (*FileSystem, error) { - - kmap := map[string]ci.PrivKey{ - "local": sk, +func NewFileSystem(ctx context.Context, ipfs iface.CoreAPI, ipfspath, ipnspath string) (*FileSystem, error) { + key, err := ipfs.Key().Self(ctx) + if err != nil { + return nil, err } - root, err := CreateRoot(ipfs, kmap, ipfspath, ipnspath) + root, err := CreateRoot(ctx, ipfs, map[string]iface.Key{"local": key}, ipfspath, ipnspath) if err != nil { return nil, err } @@ -73,80 +70,62 @@ func (f *FileSystem) Destroy() { // Root is the root object of the filesystem tree. type Root struct { - Ipfs *core.IpfsNode - Keys map[string]ci.PrivKey + Ipfs iface.CoreAPI + Keys map[string]iface.Key // Used for symlinking into ipfs IpfsRoot string IpnsRoot string LocalDirs map[string]fs.Node - Roots map[string]*keyRoot + Roots map[string]*mfs.Root LocalLinks map[string]*Link } -func ipnsPubFunc(ipfs *core.IpfsNode, k ci.PrivKey) mfs.PubFunc { +func ipnsPubFunc(ipfs iface.CoreAPI, key iface.Key) mfs.PubFunc { return func(ctx context.Context, c cid.Cid) error { - return ipfs.Namesys.Publish(ctx, k, path.FromCid(c)) + _, err := ipfs.Name().Publish(ctx, path.IpfsPath(c), options.Name.Key(key.Name())) + return err } } -func loadRoot(ctx context.Context, rt *keyRoot, ipfs *core.IpfsNode, name string) (fs.Node, error) { - p, err := path.ParsePath("/ipns/" + name) - if err != nil { - log.Errorf("mkpath %s: %s", name, err) - return nil, err - } - - node, err := resolve.Resolve(ctx, ipfs.Namesys, ipfs.Resolver, p) +func loadRoot(ctx context.Context, ipfs iface.CoreAPI, key iface.Key) (*mfs.Root, fs.Node, error) { + node, err := ipfs.ResolveNode(ctx, key.Path()) switch err { case nil: - case namesys.ErrResolveFailed: + case iface.ErrResolveFailed: node = ft.EmptyDirNode() default: - log.Errorf("looking up %s: %s", p, err) - return nil, err + log.Errorf("looking up %s: %s", key.Path(), err) + return nil, nil, err } pbnode, ok := node.(*dag.ProtoNode) if !ok { - return nil, dag.ErrNotProtobuf + return nil, nil, dag.ErrNotProtobuf } - root, err := mfs.NewRoot(ctx, ipfs.DAG, pbnode, ipnsPubFunc(ipfs, rt.k)) + root, err := mfs.NewRoot(ctx, ipfs.Dag(), pbnode, ipnsPubFunc(ipfs, key)) if err != nil { - return nil, err + return nil, nil, err } - rt.root = root - - return &Directory{dir: root.GetDirectory()}, nil -} - -type keyRoot struct { - k ci.PrivKey - alias string - root *mfs.Root + return root, &Directory{dir: root.GetDirectory()}, nil } -func CreateRoot(ipfs *core.IpfsNode, keys map[string]ci.PrivKey, ipfspath, ipnspath string) (*Root, error) { +func CreateRoot(ctx context.Context, ipfs iface.CoreAPI, keys map[string]iface.Key, ipfspath, ipnspath string) (*Root, error) { ldirs := make(map[string]fs.Node) - roots := make(map[string]*keyRoot) + roots := make(map[string]*mfs.Root) links := make(map[string]*Link) for alias, k := range keys { - pid, err := peer.IDFromPrivateKey(k) + root, fsn, err := loadRoot(ctx, ipfs, k) if err != nil { return nil, err } - name := pid.Pretty() - kr := &keyRoot{k: k, alias: alias} - fsn, err := loadRoot(ipfs.Context(), kr, ipfs, name) - if err != nil { - return nil, err - } + name := k.ID().String() - roots[name] = kr + roots[name] = root ldirs[name] = fsn // set up alias symlink @@ -199,25 +178,22 @@ func (s *Root) Lookup(ctx context.Context, name string) (fs.Node, error) { // other links go through ipns resolution and are symlinked into the ipfs mountpoint ipnsName := "/ipns/" + name - resolved, err := s.Ipfs.Namesys.Resolve(s.Ipfs.Context(), ipnsName) + resolved, err := s.Ipfs.Name().Resolve(ctx, ipnsName) if err != nil { - log.Warningf("ipns: namesys resolve error: %s", err) + log.Warnf("ipns: namesys resolve error: %s", err) return nil, fuse.ENOENT } - segments := resolved.Segments() - if segments[0] == "ipfs" { - p := path.Join(resolved.Segments()[1:]) - return &Link{s.IpfsRoot + "/" + p}, nil + if resolved.Namespace() != "ipfs" { + return nil, errors.New("invalid path from ipns record") } - log.Error("Invalid path.Path: ", resolved) - return nil, errors.New("invalid path from ipns record") + return &Link{s.IpfsRoot + "/" + strings.TrimPrefix("/ipfs/", resolved.String())}, nil } func (r *Root) Close() error { for _, mr := range r.Roots { - err := mr.root.Close() + err := mr.Close() if err != nil { return err } @@ -241,12 +217,8 @@ func (r *Root) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { var listing []fuse.Dirent for alias, k := range r.Keys { - pid, err := peer.IDFromPrivateKey(k) - if err != nil { - continue - } ent := fuse.Dirent{ - Name: pid.Pretty(), + Name: k.ID().Pretty(), Type: fuse.DT_Dir, } link := fuse.Dirent{ diff --git a/fuse/ipns/link_unix.go b/fuse/ipns/link_unix.go index fade3692af6..3cc9effd645 100644 --- a/fuse/ipns/link_unix.go +++ b/fuse/ipns/link_unix.go @@ -1,4 +1,4 @@ -// +build !nofuse +// +build !nofuse,!openbsd,!netbsd package ipns diff --git a/fuse/ipns/mount_unix.go b/fuse/ipns/mount_unix.go index 54e62df6018..7c24e53beff 100644 --- a/fuse/ipns/mount_unix.go +++ b/fuse/ipns/mount_unix.go @@ -5,11 +5,17 @@ package ipns import ( core "github.com/ipfs/go-ipfs/core" + coreapi "github.com/ipfs/go-ipfs/core/coreapi" mount "github.com/ipfs/go-ipfs/fuse/mount" ) // Mount mounts ipns at a given location, and returns a mount.Mount instance. func Mount(ipfs *core.IpfsNode, ipnsmp, ipfsmp string) (mount.Mount, error) { + coreApi, err := coreapi.NewCoreAPI(ipfs) + if err != nil { + return nil, err + } + cfg, err := ipfs.Repo.Config() if err != nil { return nil, err @@ -17,7 +23,7 @@ func Mount(ipfs *core.IpfsNode, ipnsmp, ipfsmp string) (mount.Mount, error) { allow_other := cfg.Mounts.FuseAllowOther - fsys, err := NewFileSystem(ipfs, ipfs.PrivateKey, ipfsmp, ipnsmp) + fsys, err := NewFileSystem(ipfs.Context(), coreApi, ipfsmp, ipnsmp) if err != nil { return nil, err } diff --git a/fuse/mount/fuse.go b/fuse/mount/fuse.go index 41d14cc3696..1c5f0d2ce8d 100644 --- a/fuse/mount/fuse.go +++ b/fuse/mount/fuse.go @@ -1,5 +1,4 @@ -// +build !nofuse -// +build !windows +// +build !nofuse,!windows,!openbsd,!netbsd package mount @@ -111,7 +110,7 @@ func (m *mount) unmount() error { m.setActive(false) return nil } - log.Warningf("fuse unmount err: %s", err) + log.Warnf("fuse unmount err: %s", err) // try closing the fuseConn err = m.fuseConn.Close() @@ -119,7 +118,7 @@ func (m *mount) unmount() error { m.setActive(false) return nil } - log.Warningf("fuse conn error: %s", err) + log.Warnf("fuse conn error: %s", err) // try mount.ForceUnmountManyTimes if err := ForceUnmountManyTimes(m, 10); err != nil { diff --git a/fuse/mount/mount.go b/fuse/mount/mount.go index 84df699e8af..52784a16d27 100644 --- a/fuse/mount/mount.go +++ b/fuse/mount/mount.go @@ -36,7 +36,7 @@ type Mount interface { // It does so by calling diskutil or fusermount directly. func ForceUnmount(m Mount) error { point := m.MountPoint() - log.Warningf("Force-Unmounting %s...", point) + log.Warnf("Force-Unmounting %s...", point) cmd, err := UnmountCmd(point) if err != nil { @@ -98,7 +98,7 @@ type closer struct { } func (c *closer) Close() error { - log.Warning(" (c *closer) Close(),", c.M.MountPoint()) + log.Warn(" (c *closer) Close(),", c.M.MountPoint()) return c.M.Unmount() } diff --git a/fuse/node/mount_darwin.go b/fuse/node/mount_darwin.go index 9172a7273f7..ea859756597 100644 --- a/fuse/node/mount_darwin.go +++ b/fuse/node/mount_darwin.go @@ -42,7 +42,7 @@ For more help, see: ` // errStrNoFuseHeaders is included in the output of `go get ` if there -// are no fuse headers. this means they dont have OSXFUSE installed. +// are no fuse headers. this means they don't have OSXFUSE installed. var errStrNoFuseHeaders = "no such file or directory: '/usr/local/lib/libosxfuse.dylib'" var errStrUpgradeFuse = `OSXFUSE version %s not supported. @@ -208,10 +208,10 @@ func ensureFuseVersionIsInstalled() error { cmd.Stdout = cmdout cmd.Stderr = cmdout if err := cmd.Run(); err != nil { - // Ok, install fuse-version failed. is it they dont have fuse? + // Ok, install fuse-version failed. is it they don't have fuse? cmdoutstr := cmdout.String() if strings.Contains(cmdoutstr, errStrNoFuseHeaders) { - // yes! it is! they dont have fuse! + // yes! it is! they don't have fuse! return fmt.Errorf(errStrFuseRequired) } @@ -233,7 +233,7 @@ func ensureFuseVersionIsInstalled() error { func userAskedToSkipFuseCheck(node *core.IpfsNode) (skip bool, err error) { val, err := node.Repo.GetConfigKey(dontCheckOSXFUSEConfigKey) if err != nil { - return false, nil // failed to get config value. dont skip check. + return false, nil // failed to get config value. don't skip check. } switch val := val.(type) { @@ -242,7 +242,7 @@ func userAskedToSkipFuseCheck(node *core.IpfsNode) (skip bool, err error) { case bool: return val, nil default: - // got config value, but it's invalid... dont skip check, ask the user to fix it... + // got config value, but it's invalid... don't skip check, ask the user to fix it... return false, fmt.Errorf(errStrFixConfig, dontCheckOSXFUSEConfigKey, val, dontCheckOSXFUSEConfigKey) } diff --git a/fuse/node/mount_notsupp.go b/fuse/node/mount_notsupp.go new file mode 100644 index 00000000000..847abb059f2 --- /dev/null +++ b/fuse/node/mount_notsupp.go @@ -0,0 +1,13 @@ +// +build !nofuse,openbsd !nofuse,netbsd + +package node + +import ( + "errors" + + core "github.com/ipfs/go-ipfs/core" +) + +func Mount(node *core.IpfsNode, fsdir, nsdir string) error { + return errors.New("FUSE not supported on OpenBSD or NetBSD. See #5334 (https://git.io/fjMuC).") +} diff --git a/fuse/node/mount_test.go b/fuse/node/mount_test.go index 9c8783901ac..7b051453a90 100644 --- a/fuse/node/mount_test.go +++ b/fuse/node/mount_test.go @@ -1,4 +1,4 @@ -// +build !nofuse +// +build !openbsd,!nofuse,!netbsd package node @@ -17,7 +17,7 @@ import ( ipns "github.com/ipfs/go-ipfs/fuse/ipns" mount "github.com/ipfs/go-ipfs/fuse/mount" - ci "github.com/libp2p/go-testutil/ci" + ci "github.com/libp2p/go-libp2p-testing/ci" ) func maybeSkipFuseTests(t *testing.T) { diff --git a/fuse/node/mount_unix.go b/fuse/node/mount_unix.go index 8fee8694749..8c89c94b670 100644 --- a/fuse/node/mount_unix.go +++ b/fuse/node/mount_unix.go @@ -1,4 +1,4 @@ -// +build !windows,!nofuse +// +build !windows,!openbsd,!netbsd,!nofuse package node diff --git a/fuse/readonly/ipfs_test.go b/fuse/readonly/ipfs_test.go index 3f03779ad1b..e6d38507e69 100644 --- a/fuse/readonly/ipfs_test.go +++ b/fuse/readonly/ipfs_test.go @@ -1,4 +1,4 @@ -// +build !nofuse +// +build !nofuse,!openbsd,!netbsd package readonly @@ -31,7 +31,7 @@ import ( importer "github.com/ipfs/go-unixfs/importer" uio "github.com/ipfs/go-unixfs/io" ipath "github.com/ipfs/interface-go-ipfs-core/path" - ci "github.com/libp2p/go-testutil/ci" + ci "github.com/libp2p/go-libp2p-testing/ci" ) func maybeSkipFuseTests(t *testing.T) { diff --git a/fuse/readonly/mount_unix.go b/fuse/readonly/mount_unix.go index 656e23c4925..e1065a2a1cd 100644 --- a/fuse/readonly/mount_unix.go +++ b/fuse/readonly/mount_unix.go @@ -1,4 +1,4 @@ -// +build linux darwin freebsd netbsd openbsd +// +build linux darwin freebsd // +build !nofuse package readonly diff --git a/fuse/readonly/readonly_unix.go b/fuse/readonly/readonly_unix.go index ee4708e88ae..866cdca1a08 100644 --- a/fuse/readonly/readonly_unix.go +++ b/fuse/readonly/readonly_unix.go @@ -1,4 +1,4 @@ -// +build linux darwin freebsd netbsd openbsd +// +build linux darwin freebsd // +build !nofuse package readonly @@ -20,7 +20,6 @@ import ( fs "bazil.org/fuse/fs" ipld "github.com/ipfs/go-ipld-format" logging "github.com/ipfs/go-log" - lgbl "github.com/libp2p/go-libp2p-loggables" ) var log = logging.Logger("fuse/ipfs") @@ -186,7 +185,7 @@ func (s *Node) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { } nd, err := s.Ipfs.DAG.Get(ctx, lnk.Cid) if err != nil { - log.Warning("error fetching directory child node: ", err) + log.Warn("error fetching directory child node: ", err) } t := fuse.DT_Unknown @@ -195,7 +194,7 @@ func (s *Node) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { t = fuse.DT_File case *mdag.ProtoNode: if fsn, err := ft.FSNodeFromBytes(nd.Data()); err != nil { - log.Warning("failed to unmarshal protonode data field:", err) + log.Warn("failed to unmarshal protonode data field:", err) } else { switch fsn.Type() { case ft.TDirectory, ft.THAMTShard: @@ -225,7 +224,7 @@ func (s *Node) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { } func (s *Node) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse) error { - // TODO: is nil the right response for 'bug off, we aint got none' ? + // TODO: is nil the right response for 'bug off, we ain't got none' ? resp.Xattr = nil return nil } @@ -238,33 +237,24 @@ func (s *Node) Readlink(ctx context.Context, req *fuse.ReadlinkRequest) (string, } func (s *Node) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error { - c := s.Nd.Cid() - - // setup our logging event - lm := make(lgbl.DeferredMap) - lm["fs"] = "ipfs" - lm["key"] = func() interface{} { return c.String() } - lm["req_offset"] = req.Offset - lm["req_size"] = req.Size - defer log.EventBegin(ctx, "fuseRead", lm).Done() - r, err := uio.NewDagReader(ctx, s.Nd, s.Ipfs.DAG) if err != nil { return err } - o, err := r.Seek(req.Offset, io.SeekStart) - lm["res_offset"] = o + _, err = r.Seek(req.Offset, io.SeekStart) if err != nil { return err } - - buf := resp.Data[:min(req.Size, int(int64(r.Size())-req.Offset))] + // Data has a capacity of Size + buf := resp.Data[:int(req.Size)] n, err := io.ReadFull(r, buf) - if err != nil && err != io.EOF { + resp.Data = buf[:n] + switch err { + case nil, io.EOF, io.ErrUnexpectedEOF: + default: return err } resp.Data = resp.Data[:n] - lm["res_size"] = n return nil // may be non-nil / not succeeded } @@ -287,10 +277,3 @@ type roNode interface { } var _ roNode = (*Node)(nil) - -func min(a, b int) int { - if a < b { - return a - } - return b -} diff --git a/pin/gc/gc.go b/gc/gc.go similarity index 88% rename from pin/gc/gc.go rename to gc/gc.go index bf8b7b10fa1..4b0e6c5d790 100644 --- a/pin/gc/gc.go +++ b/gc/gc.go @@ -8,15 +8,14 @@ import ( "strings" bserv "github.com/ipfs/go-blockservice" - pin "github.com/ipfs/go-ipfs/pin" - dag "github.com/ipfs/go-merkledag" - cid "github.com/ipfs/go-cid" dstore "github.com/ipfs/go-datastore" bstore "github.com/ipfs/go-ipfs-blockstore" offline "github.com/ipfs/go-ipfs-exchange-offline" + pin "github.com/ipfs/go-ipfs-pinner" ipld "github.com/ipfs/go-ipld-format" logging "github.com/ipfs/go-log" + dag "github.com/ipfs/go-merkledag" "github.com/ipfs/go-verifcid" ) @@ -41,11 +40,7 @@ type Result struct { func GC(ctx context.Context, bs bstore.GCBlockstore, dstor dstore.Datastore, pn pin.Pinner, bestEffortRoots []cid.Cid) <-chan Result { ctx, cancel := context.WithCancel(ctx) - elock := log.EventBegin(ctx, "GC.lockWait") unlocker := bs.GCLock() - elock.Done() - elock = log.EventBegin(ctx, "GC.locked") - emark := log.EventBegin(ctx, "GC.mark") bsrv := bserv.New(bs, offline.Exchange(bs)) ds := dag.NewDAGService(bsrv) @@ -56,7 +51,6 @@ func GC(ctx context.Context, bs bstore.GCBlockstore, dstor dstore.Datastore, pn defer cancel() defer close(output) defer unlocker.Unlock() - defer elock.Done() gcs, err := ColoredSet(ctx, pn, ds, bestEffortRoots, output) if err != nil { @@ -66,12 +60,6 @@ func GC(ctx context.Context, bs bstore.GCBlockstore, dstor dstore.Datastore, pn } return } - emark.Append(logging.LoggableMap{ - "blackSetSize": fmt.Sprintf("%d", gcs.Len()), - }) - emark.Done() - esweep := log.EventBegin(ctx, "GC.sweep") - keychan, err := bs.AllKeysChan(ctx) if err != nil { select { @@ -114,10 +102,6 @@ func GC(ctx context.Context, bs bstore.GCBlockstore, dstor dstore.Datastore, pn break loop } } - esweep.Append(logging.LoggableMap{ - "whiteSetSize": fmt.Sprintf("%d", removed), - }) - esweep.Done() if errors { select { case output <- Result{Error: ErrCannotDeleteSomeBlocks}: @@ -126,7 +110,6 @@ func GC(ctx context.Context, bs bstore.GCBlockstore, dstor dstore.Datastore, pn } } - defer log.EventBegin(ctx, "GC.datastore").Done() gds, ok := dstor.(dstore.GCDatastore) if !ok { return @@ -170,10 +153,8 @@ func Descendants(ctx context.Context, getLinks dag.GetLinks, set *cid.Set, roots } for _, c := range roots { - set.Add(c) - - // EnumerateChildren recursively walks the dag and adds the keys to the given set - err := dag.EnumerateChildren(ctx, verifyGetLinks, c, set.Visit) + // Walk recursively walks the dag and adds the keys to the given set + err := dag.Walk(ctx, verifyGetLinks, c, set.Visit, dag.Concurrent()) if err != nil { err = verboseCidError(err) @@ -203,7 +184,11 @@ func ColoredSet(ctx context.Context, pn pin.Pinner, ng ipld.NodeGetter, bestEffo } return links, nil } - err := Descendants(ctx, getLinks, gcs, pn.RecursiveKeys()) + rkeys, err := pn.RecursiveKeys(ctx) + if err != nil { + return nil, err + } + err = Descendants(ctx, getLinks, gcs, rkeys) if err != nil { errors = true select { @@ -235,11 +220,19 @@ func ColoredSet(ctx context.Context, pn pin.Pinner, ng ipld.NodeGetter, bestEffo } } - for _, k := range pn.DirectKeys() { + dkeys, err := pn.DirectKeys(ctx) + if err != nil { + return nil, err + } + for _, k := range dkeys { gcs.Add(k) } - err = Descendants(ctx, getLinks, gcs, pn.InternalPins()) + ikeys, err := pn.InternalPins(ctx) + if err != nil { + return nil, err + } + err = Descendants(ctx, getLinks, gcs, ikeys) if err != nil { errors = true select { @@ -257,7 +250,7 @@ func ColoredSet(ctx context.Context, pn pin.Pinner, ng ipld.NodeGetter, bestEffo } // ErrCannotFetchAllLinks is returned as the last Result in the GC output -// channel when there was a error creating the marked set because of a +// channel when there was an error creating the marked set because of a // problem when finding descendants. var ErrCannotFetchAllLinks = errors.New("garbage collection aborted: could not retrieve some links") diff --git a/go.mod b/go.mod index 1bb95da6f44..6d1fee214ee 100644 --- a/go.mod +++ b/go.mod @@ -1,124 +1,110 @@ module github.com/ipfs/go-ipfs require ( - bazil.org/fuse v0.0.0-20180421153158-65cc252bf669 + bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect - github.com/Kubuxu/go-os-helper v0.0.1 github.com/blang/semver v3.5.1+incompatible github.com/bren2010/proquint v0.0.0-20160323162903-38337c27106d - github.com/cenkalti/backoff v2.1.1+incompatible + github.com/coreos/go-systemd/v22 v22.0.0 github.com/dustin/go-humanize v1.0.0 github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302 - github.com/fatih/color v1.7.0 // indirect - github.com/fsnotify/fsnotify v1.4.7 - github.com/gogo/protobuf v1.2.1 - github.com/hashicorp/go-multierror v1.0.0 - github.com/hashicorp/golang-lru v0.5.1 - github.com/hsanjuan/go-libp2p-http v0.0.2 - github.com/ipfs/bbloom v0.0.4 // indirect - github.com/ipfs/dir-index-html v1.0.3 - github.com/ipfs/go-bitswap v0.0.8-0.20200117195305-e37498cf10d6 + github.com/fatih/color v1.9.0 // indirect + github.com/fsnotify/fsnotify v1.4.9 + github.com/go-bindata/go-bindata/v3 v3.1.3 + github.com/gogo/protobuf v1.3.1 + github.com/hashicorp/go-multierror v1.1.0 + github.com/hashicorp/golang-lru v0.5.4 + github.com/ipfs/go-bitswap v0.2.13 github.com/ipfs/go-block-format v0.0.2 - github.com/ipfs/go-blockservice v0.0.3 - github.com/ipfs/go-cid v0.0.4 + github.com/ipfs/go-blockservice v0.1.3 + github.com/ipfs/go-cid v0.0.5 github.com/ipfs/go-cidutil v0.0.2 - github.com/ipfs/go-datastore v0.0.5 + github.com/ipfs/go-datastore v0.4.4 github.com/ipfs/go-detect-race v0.0.1 - github.com/ipfs/go-ds-badger v0.0.5 - github.com/ipfs/go-ds-flatfs v0.0.2 - github.com/ipfs/go-ds-leveldb v0.0.2 - github.com/ipfs/go-ds-measure v0.0.1 - github.com/ipfs/go-fs-lock v0.0.1 - github.com/ipfs/go-ipfs-addr v0.0.1 - github.com/ipfs/go-ipfs-blockstore v0.0.1 - github.com/ipfs/go-ipfs-blocksutil v0.0.1 - github.com/ipfs/go-ipfs-chunker v0.0.1 - github.com/ipfs/go-ipfs-cmds v0.0.8 - github.com/ipfs/go-ipfs-config v0.0.3 - github.com/ipfs/go-ipfs-ds-help v0.0.1 + github.com/ipfs/go-ds-badger v0.2.4 + github.com/ipfs/go-ds-flatfs v0.4.4 + github.com/ipfs/go-ds-leveldb v0.4.2 + github.com/ipfs/go-ds-measure v0.1.0 + github.com/ipfs/go-filestore v0.0.3 + github.com/ipfs/go-fs-lock v0.0.4 + github.com/ipfs/go-graphsync v0.0.5 + github.com/ipfs/go-ipfs-blockstore v0.1.4 + github.com/ipfs/go-ipfs-chunker v0.0.5 + github.com/ipfs/go-ipfs-cmds v0.2.2 + github.com/ipfs/go-ipfs-config v0.5.3 + github.com/ipfs/go-ipfs-ds-help v0.1.1 github.com/ipfs/go-ipfs-exchange-interface v0.0.1 github.com/ipfs/go-ipfs-exchange-offline v0.0.1 - github.com/ipfs/go-ipfs-files v0.0.3 + github.com/ipfs/go-ipfs-files v0.0.8 + github.com/ipfs/go-ipfs-pinner v0.0.4 github.com/ipfs/go-ipfs-posinfo v0.0.1 - github.com/ipfs/go-ipfs-routing v0.0.1 + github.com/ipfs/go-ipfs-provider v0.4.3 + github.com/ipfs/go-ipfs-routing v0.1.0 github.com/ipfs/go-ipfs-util v0.0.1 - github.com/ipfs/go-ipld-cbor v0.0.2 - github.com/ipfs/go-ipld-format v0.0.2 - github.com/ipfs/go-ipld-git v0.0.2 - github.com/ipfs/go-ipns v0.0.1 - github.com/ipfs/go-log v0.0.1 - github.com/ipfs/go-merkledag v0.0.3 + github.com/ipfs/go-ipld-cbor v0.0.4 + github.com/ipfs/go-ipld-format v0.2.0 + github.com/ipfs/go-ipld-git v0.0.3 + github.com/ipfs/go-ipns v0.0.2 + github.com/ipfs/go-log v1.0.4 + github.com/ipfs/go-merkledag v0.3.2 github.com/ipfs/go-metrics-interface v0.0.1 github.com/ipfs/go-metrics-prometheus v0.0.2 - github.com/ipfs/go-mfs v0.0.7 - github.com/ipfs/go-path v0.0.4 - github.com/ipfs/go-unixfs v0.0.6 + github.com/ipfs/go-mfs v0.1.1 + github.com/ipfs/go-path v0.0.7 + github.com/ipfs/go-unixfs v0.2.4 github.com/ipfs/go-verifcid v0.0.1 - github.com/ipfs/interface-go-ipfs-core v0.0.8 - github.com/jbenet/go-is-domain v1.0.2 + github.com/ipfs/interface-go-ipfs-core v0.2.7 + github.com/ipld/go-car v0.1.0 + github.com/jbenet/go-is-domain v1.0.3 github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c - github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2 - github.com/jbenet/goprocess v0.1.3 - github.com/libp2p/go-flow-metrics v0.0.3 // indirect - github.com/libp2p/go-libp2p v0.0.32 - github.com/libp2p/go-libp2p-autonat-svc v0.0.5 - github.com/libp2p/go-libp2p-circuit v0.0.9 - github.com/libp2p/go-libp2p-connmgr v0.0.7 - github.com/libp2p/go-libp2p-crypto v0.0.2 - github.com/libp2p/go-libp2p-host v0.0.3 - github.com/libp2p/go-libp2p-interface-connmgr v0.0.5 - github.com/libp2p/go-libp2p-kad-dht v0.0.15 - github.com/libp2p/go-libp2p-kbucket v0.1.1 - github.com/libp2p/go-libp2p-loggables v0.0.1 - github.com/libp2p/go-libp2p-metrics v0.0.1 - github.com/libp2p/go-libp2p-mplex v0.1.1 - github.com/libp2p/go-libp2p-net v0.0.2 - github.com/libp2p/go-libp2p-peer v0.1.1 - github.com/libp2p/go-libp2p-peerstore v0.0.6 - github.com/libp2p/go-libp2p-pnet v0.0.1 - github.com/libp2p/go-libp2p-protocol v0.0.1 - github.com/libp2p/go-libp2p-pubsub v0.0.3 - github.com/libp2p/go-libp2p-pubsub-router v0.0.3 - github.com/libp2p/go-libp2p-quic-transport v0.0.3 - github.com/libp2p/go-libp2p-record v0.0.1 - github.com/libp2p/go-libp2p-routing v0.0.1 - github.com/libp2p/go-libp2p-routing-helpers v0.0.2 - github.com/libp2p/go-libp2p-secio v0.0.3 - github.com/libp2p/go-libp2p-swarm v0.0.7 - github.com/libp2p/go-libp2p-tls v0.0.2 - github.com/libp2p/go-libp2p-yamux v0.1.3 - github.com/libp2p/go-maddr-filter v0.0.4 - github.com/libp2p/go-stream-muxer v0.0.1 - github.com/libp2p/go-testutil v0.0.1 - github.com/libp2p/go-ws-transport v0.0.6 // indirect - github.com/mattn/go-runewidth v0.0.4 // indirect - github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect + github.com/jbenet/go-temp-err-catcher v0.1.0 + github.com/jbenet/goprocess v0.1.4 + github.com/libp2p/go-libp2p v0.8.3 + github.com/libp2p/go-libp2p-circuit v0.2.2 + github.com/libp2p/go-libp2p-connmgr v0.2.1 + github.com/libp2p/go-libp2p-core v0.5.2 + github.com/libp2p/go-libp2p-discovery v0.4.0 + github.com/libp2p/go-libp2p-http v0.1.5 + github.com/libp2p/go-libp2p-kad-dht v0.7.10 + github.com/libp2p/go-libp2p-kbucket v0.4.1 + github.com/libp2p/go-libp2p-loggables v0.1.0 + github.com/libp2p/go-libp2p-mplex v0.2.3 + github.com/libp2p/go-libp2p-peerstore v0.2.3 + github.com/libp2p/go-libp2p-pubsub v0.2.7 + github.com/libp2p/go-libp2p-pubsub-router v0.2.1 + github.com/libp2p/go-libp2p-quic-transport v0.3.5 + github.com/libp2p/go-libp2p-record v0.1.2 + github.com/libp2p/go-libp2p-routing-helpers v0.2.2 + github.com/libp2p/go-libp2p-secio v0.2.2 + github.com/libp2p/go-libp2p-swarm v0.2.3 + github.com/libp2p/go-libp2p-testing v0.1.1 + github.com/libp2p/go-libp2p-tls v0.1.3 + github.com/libp2p/go-libp2p-yamux v0.2.7 + github.com/libp2p/go-maddr-filter v0.0.5 + github.com/libp2p/go-sockaddr v0.1.0 // indirect + github.com/libp2p/go-socket-activation v0.0.2 + github.com/mattn/go-runewidth v0.0.8 // indirect github.com/mitchellh/go-homedir v1.1.0 - github.com/mr-tron/base58 v1.1.2 - github.com/multiformats/go-multiaddr v0.0.4 - github.com/multiformats/go-multiaddr-dns v0.0.3 - github.com/multiformats/go-multiaddr-net v0.0.1 - github.com/multiformats/go-multibase v0.0.1 - github.com/multiformats/go-multihash v0.0.10 + github.com/mr-tron/base58 v1.1.3 + github.com/multiformats/go-multiaddr v0.2.1 + github.com/multiformats/go-multiaddr-dns v0.2.0 + github.com/multiformats/go-multiaddr-net v0.1.4 + github.com/multiformats/go-multibase v0.0.2 + github.com/multiformats/go-multihash v0.0.13 github.com/opentracing/opentracing-go v1.1.0 - github.com/pkg/errors v0.8.1 - github.com/prometheus/client_golang v0.9.3 - github.com/prometheus/procfs v0.0.0-20190519111021-9935e8e0588d // indirect + github.com/pkg/errors v0.9.1 + github.com/prometheus/client_golang v1.5.1 github.com/syndtr/goleveldb v1.0.0 github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c - go.uber.org/atomic v1.4.0 // indirect - go.uber.org/dig v1.7.0 // indirect - go.uber.org/fx v1.9.0 - go.uber.org/goleak v0.10.0 // indirect - go.uber.org/multierr v1.1.0 // indirect - go4.org v0.0.0-20190313082347-94abd6928b1d // indirect - golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect - golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb - golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect + go.uber.org/fx v1.12.0 + go.uber.org/zap v1.14.1 + golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 + golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect + golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 gopkg.in/cheggaaa/pb.v1 v1.0.28 ) -go 1.12 +go 1.13 diff --git a/go.sum b/go.sum index dabf443e080..7d568b69c81 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,15 @@ -bazil.org/fuse v0.0.0-20180421153158-65cc252bf669 h1:FNCRpXiquG1aoyqcIWVFmpTSKVcx2bQD38uZZeGtdlw= -bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc h1:utDghgcjE8u+EBjHOgYT+dJPcnDF05KqWMBcjuJy510= +bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi81xWQA2QIVxjWkFHptGgC547vchpUbtFo= +cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= +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/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9 h1:HD8gA2tkByhMAwYaFAX9w2l7vxvBQ5NMoxDrkhqhtn4= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= @@ -11,787 +17,1261 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Kubuxu/go-os-helper v0.0.1 h1:EJiD2VUQyh5A9hWJLmc6iWg6yIcJ7jpBcwC8GMGXfDk= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= +github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/Stebalien/go-bitfield v0.0.0-20180330043415-076a62f9ce6e h1:2Z+EBRrOJsA3psnUPcEWMIH2EIga1xHflQcr/EZslx8= github.com/Stebalien/go-bitfield v0.0.0-20180330043415-076a62f9ce6e/go.mod h1:3oM7gXIttpYDAJXpVNnSCiUMYBLIZ6cb1t+Ip982MRo= github.com/Stebalien/go-bitfield v0.0.1 h1:X3kbSSPUaJK60wV2hjOPZwmpljr6VGCqdq4cBLhbQBo= github.com/Stebalien/go-bitfield v0.0.1/go.mod h1:GNjFpasyUVkHMsfEOk8EFLJ9syQ6SI+XWrX9Wf2XH0s= -github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= +github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75 h1:3ILjVyslFbc4jl1w5TWuvvslFD/nDfR2H8tVaMVLrEY= +github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75/go.mod h1:uAXEEpARkRhCZfEvy/y0Jcc888f9tHCc1W7/UeEtreE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= +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/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/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= 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/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/bren2010/proquint v0.0.0-20160323162903-38337c27106d h1:QgeLLoPD3kRVmeu/1al9iIpIANMi9O1zXFm8BnYGCJg= github.com/bren2010/proquint v0.0.0-20160323162903-38337c27106d/go.mod h1:Jbj8eKecMNwf0KFI75skSUZqMB4UCRcndUScVBTWyUI= -github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= -github.com/btcsuite/btcd v0.0.0-20190427004231-96897255fd17 h1:m0N5Vg5nP3zEz8TREZpwX3gt4Biw3/8fbIf4A3hO96g= -github.com/btcsuite/btcd v0.0.0-20190427004231-96897255fd17/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3 h1:A/EVblehb75cUgXA5njHPn0kLAsykn6mJGz7rnmW5W0= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= -github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.2.1-0.20180108230905-e214231b295a h1:U0BbGfKnviqVBJQB4etvm+mKx53KfkumNLBt6YeF/0Q= github.com/coreos/go-semver v0.2.1-0.20180108230905-e214231b295a/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +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.0.0 h1:XJIw/+VlJ+87J+doOxznsAWIdmWuViOVhkQamW5YV28= +github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= +github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= github.com/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 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0= github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= -github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f h1:6itBiEUtu+gOzXZWn46bM5/qm8LlV6/byR7Yflx/y6M= github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= github.com/dgraph-io/badger v1.6.0-rc1 h1:JphPpoBZJ3WHha133BGYlQqltSGIhV+VsEID0++nN9A= github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= -github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f h1:dDxpBYafY/GYpcl+LS4Bn3ziLPuEdGRkRjYAbSlWxSA= +github.com/dgraph-io/badger v1.6.0 h1:DshxFxZWXUcO0xX476VJC07Xsr6ZCBVRHKZ93Oh7Evo= +github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgraph-io/badger v1.6.1 h1:w9pSFNSdq/JPM1N12Fz/F/bzo993Is1W+Q7HjPzi7yg= +github.com/dgraph-io/badger v1.6.1/go.mod h1:FRmFw3uxvcpa8zG3Rxs0th+hCLIuaQg8HlNV5bjgnuU= +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/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/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/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.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fd/go-nat v1.0.0 h1:DPyQ97sxA9ThrWYRPcWUz/z9TnpTIGRYODIQc/dy64M= +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/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= +github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +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-bindata/go-bindata/v3 v3.1.3 h1:F0nVttLC3ws0ojc7p60veTurcOm//D4QBODNM7EGrCI= +github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I= github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= -github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 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-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/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 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.4.0 h1:Rd1kQnQu0Hq3qvJppYSG0HtP+f5LPPUiDswTLiEegLg= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/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 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY= +github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +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/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +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/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/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/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= -github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824 h1:TF4mX7zXpeyz/xintezebSa7ZDxAGBnqDwcoobvaz2o= github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824/go.mod h1:OiEWyHgK+CWrmOlVquHaIK1vhpUJydC9m0Je6mhaiNE= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hsanjuan/go-libp2p-gostream v0.0.31 h1:9dIgHQPR0VWxhOyTZrbgLzTx0xvZ5rTpmhG9huGEPjY= -github.com/hsanjuan/go-libp2p-gostream v0.0.31/go.mod h1:cWvV5/NQ5XWi0eQZnX/svsAk6NLc4U26pItvj0eDeRk= -github.com/hsanjuan/go-libp2p-http v0.0.2 h1:hviJbUD3h1Ez2FYTUdnRjrkAzn/9i2V/cLZpFPgnuP8= -github.com/hsanjuan/go-libp2p-http v0.0.2/go.mod h1:MynY94gfOZxrw/0lVF4o7vbV2Zr84IC8sLBXmj8F5IE= -github.com/huin/goupnp v0.0.0-20180415215157-1395d1447324 h1:PV190X5/DzQ/tbFFG5YpT5mH6q+cHlfgqI5JuRnH9oE= github.com/huin/goupnp v0.0.0-20180415215157-1395d1447324/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag= github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150 h1:vlNjIqmUZ9CMAWsbURYl3a6wZbw7q5RHVvlXTNS/Bs8= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/ipfs/bbloom v0.0.1 h1:s7KkiBPfxCeDVo47KySjK0ACPc5GJRUxFpdyWEuDjhw= github.com/ipfs/bbloom v0.0.1/go.mod h1:oqo8CVWsJFMOZqTglBG4wydCE4IQA/G2/SEofB0rjUI= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/dir-index-html v1.0.3 h1:cKdOjJBKJgewgcv97zOlqsNOle52N91d3nAkbQadnuY= -github.com/ipfs/dir-index-html v1.0.3/go.mod h1:TG9zbaH/+4MnkGel0xF4SLNhk+YZvBNo6jjBkO/LaWc= -github.com/ipfs/go-bitswap v0.0.3 h1:uFcSI9dkjUn67S7IM60vr2wA27aAvn8o9xYjaQCug3o= github.com/ipfs/go-bitswap v0.0.3/go.mod h1:jadAZYsP/tcRMl47ZhFxhaNuDQoXawT8iHMg+iFoQbg= -github.com/ipfs/go-bitswap v0.0.8-0.20200117195305-e37498cf10d6 h1:ECVkHrFqgeQxEMxIoD+x47+blG1HmkXYv+F6/1WFlkQ= -github.com/ipfs/go-bitswap v0.0.8-0.20200117195305-e37498cf10d6/go.mod h1:XqOviwWKh3sq0oF678Aw8VR+4blyY4MbqfpdrqkUuqk= +github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3UPrwvis= +github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= +github.com/ipfs/go-bitswap v0.1.2/go.mod h1:qxSWS4NXGs7jQ6zQvoPY3+NmOfHHG47mhkiLzBpJQIs= +github.com/ipfs/go-bitswap v0.1.3/go.mod h1:YEQlFy0kkxops5Vy+OxWdRSEZIoS7I7KDIwoa5Chkps= +github.com/ipfs/go-bitswap v0.1.8/go.mod h1:TOWoxllhccevbWFUR2N7B1MTSVVge1s6XSMiCSA4MzM= +github.com/ipfs/go-bitswap v0.2.13 h1:R8mUGpY0vwHljlnBeDE9PdR3DKKiPKevAMkq9qB8cyA= +github.com/ipfs/go-bitswap v0.2.13/go.mod h1:SDXpLeKZagyVVc8/z7sGtmM/lz8lyAmSzrUx3Ge3GXw= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= -github.com/ipfs/go-blockservice v0.0.3 h1:40OvwrxeudTAlUGUAKNYnNPcwQeLtXedjzTWecnUinQ= github.com/ipfs/go-blockservice v0.0.3/go.mod h1:/NNihwTi6V2Yr6g8wBI+BSwPuURpBRMtYNGrlxZ8KuI= -github.com/ipfs/go-cid v0.0.1 h1:GBjWPktLnNyX0JiQCNFpUuUSoMw5KMyqrsejHYlILBE= +github.com/ipfs/go-blockservice v0.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbRhbvNSdgc/7So= +github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= +github.com/ipfs/go-blockservice v0.1.1/go.mod h1:t+411r7psEUhLueM8C7aPA7cxCclv4O3VsUVxt9kz2I= +github.com/ipfs/go-blockservice v0.1.2 h1:fqFeeu1EG0lGVrqUo+BVJv7LZV31I4ZsyNthCOMAJRc= +github.com/ipfs/go-blockservice v0.1.2/go.mod h1:t+411r7psEUhLueM8C7aPA7cxCclv4O3VsUVxt9kz2I= +github.com/ipfs/go-blockservice v0.1.3 h1:9XgsPMwwWJSC9uVr2pMDsW2qFTBSkxpGMhmna8mIjPM= +github.com/ipfs/go-blockservice v0.1.3/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.2 h1:tuuKaZPU1M6HcejsO3AcYWW8sZ8MTvyxfc4uqB4eFE8= github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.3 h1:UIAh32wymBpStoe83YCzwVQQ5Oy/H0FdxvUS6DJDzms= +github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.4 h1:UlfXKrZx1DjZoBhQHmNHLC1fK1dUJDN20Y28A7s+gJ8= github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= +github.com/ipfs/go-cid v0.0.5 h1:o0Ix8e/ql7Zb5UVUJEUfjsWCIY8t48++9lR8qi6oiJU= +github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= github.com/ipfs/go-cidutil v0.0.2 h1:CNOboQf1t7Qp0nuNh8QMmhJs0+Q//bRL1axtCnIB1Yo= github.com/ipfs/go-cidutil v0.0.2/go.mod h1:ewllrvrxG6AMYStla3GD7Cqn+XYSLqjK0vc+086tB6s= -github.com/ipfs/go-datastore v0.0.1 h1:AW/KZCScnBWlSb5JbnEnLKFWXL224LBEh/9KXXOrUms= github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-datastore v0.0.3 h1:/eP3nMDmLzMJNoWSSYvEkmMTTrm9FFCN+JraP9NdlwU= -github.com/ipfs/go-datastore v0.0.3/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-datastore v0.0.5 h1:q3OfiOZV5rlsK1H5V8benjeUApRfMGs4Mrhmr6NriQo= github.com/ipfs/go-datastore v0.0.5/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-datastore v0.1.0 h1:TOxI04l8CmO4zGtesENhzm4PwkFwJXY3rKiYaaMf9fI= +github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-datastore v0.1.1 h1:F4k0TkTAZGLFzBOrVKDAvch6JZtuN4NHkfdcEZL50aI= +github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= +github.com/ipfs/go-datastore v0.3.0/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= +github.com/ipfs/go-datastore v0.3.1 h1:SS1t869a6cctoSYmZXUk8eL6AzVXgASmKIWFNQkQ1jU= +github.com/ipfs/go-datastore v0.3.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= +github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= +github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= +github.com/ipfs/go-datastore v0.4.4 h1:rjvQ9+muFaJ+QZ7dN5B1MSDNQ0JVZKkkES/rMZmA8X8= +github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= -github.com/ipfs/go-ds-badger v0.0.2 h1:7ToQt7QByBhOTuZF2USMv+PGlMcBC7FW7FdgQ4FCsoo= github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= github.com/ipfs/go-ds-badger v0.0.5 h1:dxKuqw5T1Jm8OuV+lchA76H9QZFyPKZeLuT6bN42hJQ= github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= -github.com/ipfs/go-ds-flatfs v0.0.2 h1:1zujtU5bPBH6B8roE+TknKIbBCrpau865xUk0dH3x2A= -github.com/ipfs/go-ds-flatfs v0.0.2/go.mod h1:YsMGWjUieue+smePAWeH/YhHtlmEMnEGhiwIn6K6rEM= -github.com/ipfs/go-ds-leveldb v0.0.1 h1:Z0lsTFciec9qYsyngAw1f/czhRU35qBLR2vhavPFgqA= +github.com/ipfs/go-ds-badger v0.0.7 h1:NMyh88Q50HG6/S2YD58DLkq0c0/ZQPMbSojONH+PRf4= +github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= +github.com/ipfs/go-ds-badger v0.2.1 h1:RsC9DDlwFhFdfT+s2PeC8joxbSp2YMufK8w/RBOxKtk= +github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= +github.com/ipfs/go-ds-badger v0.2.3 h1:J27YvAcpuA5IvZUbeBxOcQgqnYHUPxoygc6QxxkodZ4= +github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= +github.com/ipfs/go-ds-badger v0.2.4 h1:UPGB0y7luFHk+mY/tUZrif/272M8o+hFsW+avLUeWrM= +github.com/ipfs/go-ds-badger v0.2.4/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= +github.com/ipfs/go-ds-flatfs v0.4.4 h1:DmGZ4qOYQLNgu8Mltuz1DtUHpm+BjWMcVN3F3H3VJzQ= +github.com/ipfs/go-ds-flatfs v0.4.4/go.mod h1:e4TesLyZoA8k1gV/yCuBTnt2PJtypn4XUlB5n8KQMZY= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= -github.com/ipfs/go-ds-leveldb v0.0.2 h1:P5HB59Zblym0B5XYOeEyw3YtPtbpIqQCavCSWaWEEk8= -github.com/ipfs/go-ds-leveldb v0.0.2/go.mod h1:CWFeBh5IAAscWyG/QRH+lJaAlnLWjsfPSNs4teyPUp0= -github.com/ipfs/go-ds-measure v0.0.1 h1:PrCueug+yZLkDCOthZTXKinuoCal/GvlAT7cNxzr03g= -github.com/ipfs/go-ds-measure v0.0.1/go.mod h1:wiH6bepKsgyNKpz3nyb4erwhhIVpIxnZbsjN1QpVbbE= -github.com/ipfs/go-fs-lock v0.0.1 h1:XHX8uW4jQBYWHj59XXcjg7BHlHxV9ZOYs6Y43yb7/l0= -github.com/ipfs/go-fs-lock v0.0.1/go.mod h1:DNBekbboPKcxs1aukPSaOtFA3QfSdi5C855v0i9XJ8Y= -github.com/ipfs/go-ipfs-addr v0.0.1 h1:DpDFybnho9v3/a1dzJ5KnWdThWD1HrFLpQ+tWIyBaFI= -github.com/ipfs/go-ipfs-addr v0.0.1/go.mod h1:uKTDljHT3Q3SUWzDLp3aYUi8MrY32fgNgogsIa0npjg= -github.com/ipfs/go-ipfs-blockstore v0.0.1 h1:O9n3PbmTYZoNhkgkEyrXTznbmktIXif62xLX+8dPHzc= +github.com/ipfs/go-ds-leveldb v0.1.0 h1:OsCuIIh1LMTk4WIQ1UJH7e3j01qlOP+KWVhNS6lBDZY= +github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= +github.com/ipfs/go-ds-leveldb v0.4.1 h1:zaoLcP8zs4Aj9k8fA4cowyOyNBIvy9Dnt6hf7mHRY7s= +github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= +github.com/ipfs/go-ds-leveldb v0.4.2 h1:QmQoAJ9WkPMUfBLnu1sBVy0xWWlJPg0m4kRAiJL9iaw= +github.com/ipfs/go-ds-leveldb v0.4.2/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= +github.com/ipfs/go-ds-measure v0.1.0 h1:vE4TyY4aeLeVgnnPBC5QzKIjKrqzha0NCujTfgvVbVQ= +github.com/ipfs/go-ds-measure v0.1.0/go.mod h1:1nDiFrhLlwArTME1Ees2XaBOl49OoCgd2A3f8EchMSY= +github.com/ipfs/go-filestore v0.0.3 h1:MhZ1jT5K3NewZwim6rS/akcJLm1xM+r6nz6foeB9EwE= +github.com/ipfs/go-filestore v0.0.3/go.mod h1:dvXRykFzyyXN2CdNlRGzDAkXMDPyI+D7JE066SiKLSE= +github.com/ipfs/go-fs-lock v0.0.4 h1:VhlO2E7awjMxkj6a4nCsrPScRFvEPZxhULtbYdJNZhQ= +github.com/ipfs/go-fs-lock v0.0.4/go.mod h1:SUaaFT1boYZewW+QBw5FZjcDbxkZIWgNdYb1ab93zaY= +github.com/ipfs/go-graphsync v0.0.5 h1:5U9iC58JgYfUSZI55oRXe22Cj6Ln0Xjd5VF4Eoo3foc= +github.com/ipfs/go-graphsync v0.0.5/go.mod h1:SGKa4rVgCCz3KDNqe38wLEDYFa/PUF6w/ertGSQk33I= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= +github.com/ipfs/go-ipfs-blockstore v0.1.0 h1:V1GZorHFUIB6YgTJQdq7mcaIpUfCM3fCyVi+MTo9O88= +github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= +github.com/ipfs/go-ipfs-blockstore v0.1.4 h1:2SGI6U1B44aODevza8Rde3+dY30Pb+lbcObe1LETxOQ= +github.com/ipfs/go-ipfs-blockstore v0.1.4/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86HgIYJW/D/MwqeYQ= github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk= github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE27SEw= github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= -github.com/ipfs/go-ipfs-cmds v0.0.8 h1:ZMo0ZeQOr10ZKY4yxYA3lRHUbnF/ZYcV9cpU0IrlGFI= -github.com/ipfs/go-ipfs-cmds v0.0.8/go.mod h1:TiK4e7/V31tuEb8YWDF8lN3qrnDH+BS7ZqWIeYJlAs8= -github.com/ipfs/go-ipfs-config v0.0.3 h1:Ep4tRdP1iVK76BgOprD9B/qtOEdpno+1Xb57BqydgGk= -github.com/ipfs/go-ipfs-config v0.0.3/go.mod h1:KDbHjNyg4e6LLQSQpkgQMBz6Jf4LXiWAcmnkcwmH0DU= +github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8= +github.com/ipfs/go-ipfs-chunker v0.0.5/go.mod h1:jhgdF8vxRHycr00k13FM8Y0E+6BoalYeobXmUyTreP8= +github.com/ipfs/go-ipfs-cmds v0.2.2 h1:F2pro/Q3ifRUsdxEKIS8cg8lO4R6WiwAyERiaG8I9no= +github.com/ipfs/go-ipfs-cmds v0.2.2/go.mod h1:kqlUrp6m2ceoaJe40cXpADCi5aS6NKRn0NIeuLp5CeM= +github.com/ipfs/go-ipfs-config v0.5.3 h1:3GpI/xR9FoJNTjU6YvCMRbYyEi0dBVY5UtlUTcNRlSA= +github.com/ipfs/go-ipfs-config v0.5.3/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-ds-help v0.0.1 h1:QBg+Ts2zgeemK/dB0saiF/ykzRGgfoFMT90Rzo0OnVU= github.com/ipfs/go-ipfs-ds-help v0.0.1/go.mod h1:gtP9xRaZXqIQRh1HRpp595KbBEdgqWFxefeVKOV8sxo= +github.com/ipfs/go-ipfs-ds-help v0.1.1 h1:IW/bXGeaAZV2VH0Kuok+Ohva/zHkHmeLFBxC1k7mNPc= +github.com/ipfs/go-ipfs-ds-help v0.1.1/go.mod h1:SbBafGJuGsPI/QL3j9Fc5YPLeAu+SzOkI0gFwAg+mOs= github.com/ipfs/go-ipfs-exchange-interface v0.0.1 h1:LJXIo9W7CAmugqI+uofioIpRb6rY30GUu7G6LUfpMvM= github.com/ipfs/go-ipfs-exchange-interface v0.0.1/go.mod h1:c8MwfHjtQjPoDyiy9cFquVtVHkO9b9Ob3FG91qJnWCM= github.com/ipfs/go-ipfs-exchange-offline v0.0.1 h1:P56jYKZF7lDDOLx5SotVh5KFxoY6C81I1NSHW1FxGew= github.com/ipfs/go-ipfs-exchange-offline v0.0.1/go.mod h1:WhHSFCVYX36H/anEKQboAzpUws3x7UeEGkzQc3iNkM0= -github.com/ipfs/go-ipfs-files v0.0.2 h1:fEEjF4H+1t8SFOHqUGp0KqcwgIRlbD2bu8CAS2sIggE= github.com/ipfs/go-ipfs-files v0.0.2/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= -github.com/ipfs/go-ipfs-files v0.0.3 h1:ME+QnC3uOyla1ciRPezDW0ynQYK2ikOh9OCKAEg4uUA= github.com/ipfs/go-ipfs-files v0.0.3/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= -github.com/ipfs/go-ipfs-flags v0.0.1 h1:OH5cEkJYL0QgA+bvD55TNG9ud8HA2Nqaav47b2c/UJk= +github.com/ipfs/go-ipfs-files v0.0.4/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= +github.com/ipfs/go-ipfs-files v0.0.8 h1:8o0oFJkJ8UkO/ABl8T6ac6tKF3+NIpj67aAB6ZpusRg= +github.com/ipfs/go-ipfs-files v0.0.8/go.mod h1:wiN/jSG8FKyk7N0WyctKSvq3ljIa2NNTiZB55kpTdOs= github.com/ipfs/go-ipfs-flags v0.0.1/go.mod h1:RnXBb9WV53GSfTrSDVK61NLTFKvWc60n+K9EgCDh+rA= +github.com/ipfs/go-ipfs-pinner v0.0.4 h1:EmxhS3vDsCK/rZrsgxX0Le9m2drBcGlUd7ah/VyFYVE= +github.com/ipfs/go-ipfs-pinner v0.0.4/go.mod h1:s4kFZWLWGDudN8Jyd/GTpt222A12C2snA2+OTdy/7p8= github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= -github.com/ipfs/go-ipfs-pq v0.0.1 h1:zgUotX8dcAB/w/HidJh1zzc1yFq6Vm8J7T2F4itj/RU= github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= -github.com/ipfs/go-ipfs-routing v0.0.1 h1:394mZeTLcbM/LDO12PneBYvkZAUA+nRnmC0lAzDXKOY= +github.com/ipfs/go-ipfs-pq v0.0.2 h1:e1vOOW6MuOwG2lqxcLA+wEn93i/9laCY8sXAw76jFOY= +github.com/ipfs/go-ipfs-pq v0.0.2/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= +github.com/ipfs/go-ipfs-provider v0.4.3 h1:k54OHXZcFBkhL6l3GnPS9PfpaLeLqZjVASG1bgfBdfQ= +github.com/ipfs/go-ipfs-provider v0.4.3/go.mod h1:rcQBVqfblDQRk5LaCtf2uxuKxMJxvKmF5pLS0pO4au4= github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= +github.com/ipfs/go-ipfs-routing v0.1.0 h1:gAJTT1cEeeLj6/DlLX6t+NxD9fQe2ymTO6qWRDI/HQQ= +github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50= github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= -github.com/ipfs/go-ipld-cbor v0.0.1 h1:g7yh27SznWP4CUbkFgjR+WQRjEeyxCpTR4iKVmXx1wA= github.com/ipfs/go-ipld-cbor v0.0.1/go.mod h1:RXHr8s4k0NE0TKhnrxqZC9M888QfsBN9rhS5NjfKzY8= -github.com/ipfs/go-ipld-cbor v0.0.2 h1:amzFztBQQQ69UA5+f7JRfoXF/z2l//MGfEDHVkS20+s= github.com/ipfs/go-ipld-cbor v0.0.2/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc= -github.com/ipfs/go-ipld-format v0.0.1 h1:HCu4eB/Gh+KD/Q0M8u888RFkorTWNIL3da4oc5dwc80= +github.com/ipfs/go-ipld-cbor v0.0.3 h1:ENsxvybwkmke7Z/QJOmeJfoguj6GH3Y0YOaGrfy9Q0I= +github.com/ipfs/go-ipld-cbor v0.0.3/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc= +github.com/ipfs/go-ipld-cbor v0.0.4 h1:Aw3KPOKXjvrm6VjwJvFf1F1ekR/BH3jdof3Bk7OTiSA= +github.com/ipfs/go-ipld-cbor v0.0.4/go.mod h1:BkCduEx3XBCO6t2Sfo5BaHzuok7hbhdMm9Oh8B2Ftq4= github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms= github.com/ipfs/go-ipld-format v0.0.2 h1:OVAGlyYT6JPZ0pEfGntFPS40lfrDmaDbQwNHEY2G9Zs= github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k= -github.com/ipfs/go-ipld-git v0.0.2 h1:dn5Quu9lgjkSqkc9CaTsRjzg90kaIitj9wENtigVMH8= -github.com/ipfs/go-ipld-git v0.0.2/go.mod h1:RuvMXa9qtJpDbqngyICCU/d+cmLFXxLsbIclmD0Lcr0= -github.com/ipfs/go-ipns v0.0.1 h1:5vX0+ehF55YWxE8Pmf4eB8szcP+fh24AXnvCkOmSLCc= -github.com/ipfs/go-ipns v0.0.1/go.mod h1:HOiAXgGiH0wCSwsFM1IKdOy6YGT4iZafcsUKni703/g= +github.com/ipfs/go-ipld-format v0.2.0 h1:xGlJKkArkmBvowr+GMCX0FEZtkro71K1AwiKnL37mwA= +github.com/ipfs/go-ipld-format v0.2.0/go.mod h1:3l3C1uKoadTPbeNfrDi+xMInYKlx2Cvg1BuydPSdzQs= +github.com/ipfs/go-ipld-git v0.0.3 h1:/YjkjCyo5KYRpW+suby8Xh9Cm/iH9dAgGV6qyZ1dGus= +github.com/ipfs/go-ipld-git v0.0.3/go.mod h1:RuvMXa9qtJpDbqngyICCU/d+cmLFXxLsbIclmD0Lcr0= +github.com/ipfs/go-ipns v0.0.2 h1:oq4ErrV4hNQ2Eim257RTYRgfOSV/s8BDaf9iIl4NwFs= +github.com/ipfs/go-ipns v0.0.2/go.mod h1:WChil4e0/m9cIINWLxZe1Jtf77oz5L05rO2ei/uKJ5U= github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= -github.com/ipfs/go-merkledag v0.0.3 h1:A5DlOMzqTRDVmdgkf3dzCKCFmVWH4Zqwb0cbYXUs+Ro= +github.com/ipfs/go-log v1.0.1 h1:5lIEEOQTk/vd1WuPFBRqz2mcp+5G1fMVcW+Ib/H5Hfo= +github.com/ipfs/go-log v1.0.1/go.mod h1:HuWlQttfN6FWNHRhlY5yMk/lW7evQC0HHGOxEwMRR8I= +github.com/ipfs/go-log v1.0.2 h1:s19ZwJxH8rPWzypjcDpqPLIyV7BnbLqvpli3iZoqYK0= +github.com/ipfs/go-log v1.0.2/go.mod h1:1MNjMxe0u6xvJZgeqbJ8vdo2TKaGwZ1a0Bpza+sr2Sk= +github.com/ipfs/go-log v1.0.3 h1:Gg7SUYSZ7BrqaKMwM+hRgcAkKv4QLfzP4XPQt5Sx/OI= +github.com/ipfs/go-log v1.0.3/go.mod h1:OsLySYkwIbiSUR/yBTdv1qPtcE4FW3WPWk/ewz9Ru+A= +github.com/ipfs/go-log v1.0.4 h1:6nLQdX4W8P9yZZFH7mO+X/PzjN8Laozm/lMJ6esdgzY= +github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= +github.com/ipfs/go-log/v2 v2.0.1 h1:mnR9XFltezAtO8A6tj5U7nKkRzhEQNEw/wT11U2HhPM= +github.com/ipfs/go-log/v2 v2.0.1/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= +github.com/ipfs/go-log/v2 v2.0.2 h1:xguurydRdfKMJjKyxNXNU8lYP0VZH1NUwJRwUorjuEw= +github.com/ipfs/go-log/v2 v2.0.2/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= +github.com/ipfs/go-log/v2 v2.0.3 h1:Q2gXcBoCALyLN/pUQlz1qgu0x3uFV6FzP9oXhpfyJpc= +github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= +github.com/ipfs/go-log/v2 v2.0.5 h1:fL4YI+1g5V/b1Yxr1qAiXTMg1H8z9vx/VmJxBuQMHvU= +github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= github.com/ipfs/go-merkledag v0.0.3/go.mod h1:Oc5kIXLHokkE1hWGMBHw+oxehkAaTOqtEb7Zbh6BhLA= +github.com/ipfs/go-merkledag v0.0.6/go.mod h1:QYPdnlvkOg7GnQRofu9XZimC5ZW5Wi3bKys/4GQQfto= +github.com/ipfs/go-merkledag v0.1.0/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= +github.com/ipfs/go-merkledag v0.2.3 h1:aMdkK9G1hEeNvn3VXfiEMLY0iJnbiQQUHnM0HFJREsE= +github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= +github.com/ipfs/go-merkledag v0.2.4/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= +github.com/ipfs/go-merkledag v0.3.0 h1:1bXv/ZRPZLVdij/a33CkXMVdxUdred9sz4xyph+0ls0= +github.com/ipfs/go-merkledag v0.3.0/go.mod h1:4pymaZLhSLNVuiCITYrpViD6vmfZ/Ws4n/L9tfNv3S4= +github.com/ipfs/go-merkledag v0.3.1 h1:3UqWINBEr3/N+r6OwgFXAddDP/8zpQX/8J7IGVOCqRQ= +github.com/ipfs/go-merkledag v0.3.1/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= +github.com/ipfs/go-merkledag v0.3.2 h1:MRqj40QkrWkvPswXs4EfSslhZ4RVPRbxwX11js0t1xY= +github.com/ipfs/go-merkledag v0.3.2/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= github.com/ipfs/go-metrics-prometheus v0.0.2 h1:9i2iljLg12S78OhC6UAiXi176xvQGiZaGVF1CUVdE+s= github.com/ipfs/go-metrics-prometheus v0.0.2/go.mod h1:ELLU99AQQNi+zX6GCGm2lAgnzdSH3u5UVlCdqSXnEks= -github.com/ipfs/go-mfs v0.0.7 h1:Xjqk0jAhgwhMHO39oH4jqP1QkeAGqDelxa814voygN0= -github.com/ipfs/go-mfs v0.0.7/go.mod h1:10Hdow7wUbSlIamnOduxeP6MEp58TozZmdnAhugOKz8= -github.com/ipfs/go-path v0.0.3 h1:G/VFcCMXtp36JUPPyytYQ1I3UsBUBf47M//uSdTLnFg= +github.com/ipfs/go-mfs v0.1.1 h1:tjYEWFIl0W6vRFuM/EnySHaaYzPmDcQWwTjtYWMGQ1A= +github.com/ipfs/go-mfs v0.1.1/go.mod h1:nk17h6kCOrfaNqXvx2VJ3SqkJ0VYUzJFAsc+BA0sqaw= github.com/ipfs/go-path v0.0.3/go.mod h1:zIRQUez3LuQIU25zFjC2hpBTHimWx7VK5bjZgRLbbdo= -github.com/ipfs/go-path v0.0.4 h1:zG/id80tV51XAfvCsRJIEGQSHGuTDBi8RWrtr3EfcfY= -github.com/ipfs/go-path v0.0.4/go.mod h1:zIRQUez3LuQIU25zFjC2hpBTHimWx7VK5bjZgRLbbdo= -github.com/ipfs/go-peertaskqueue v0.0.5-0.20190704154349-f09820a0a5b6 h1:/8zfOPbZ8q0YadOu7snck13TtYW9f08v65XDWag9+jU= -github.com/ipfs/go-peertaskqueue v0.0.5-0.20190704154349-f09820a0a5b6/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP1MX6Kd+aN+rMQ= -github.com/ipfs/go-todocounter v0.0.1 h1:kITWA5ZcQZfrUnDNkRn04Xzh0YFaDFXsoO2A81Eb6Lw= -github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= -github.com/ipfs/go-unixfs v0.0.4 h1:IApzQ+SnY0tfjqM7aU2b80CFYLZNHvhLmEZDIWr4e/E= +github.com/ipfs/go-path v0.0.7 h1:H06hKMquQ0aYtHiHryOMLpQC1qC3QwXwkahcEVD51Ho= +github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd2Sno= +github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP1MX6Kd+aN+rMQ= +github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= +github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= +github.com/ipfs/go-peertaskqueue v0.2.0 h1:2cSr7exUGKYyDeUyQ7P/nHPs9P7Ht/B+ROrpN1EJOjc= +github.com/ipfs/go-peertaskqueue v0.2.0/go.mod h1:5/eNrBEbtSKWCG+kQK8K8fGNixoYUnr+P7jivavs9lY= github.com/ipfs/go-unixfs v0.0.4/go.mod h1:eIo/p9ADu/MFOuyxzwU+Th8D6xoxU//r590vUpWyfz8= -github.com/ipfs/go-unixfs v0.0.6 h1:mQ6KS3NK4GA9hyUpGdGItqt5llzyIx0Qy2UxC/A7bEo= -github.com/ipfs/go-unixfs v0.0.6/go.mod h1:g41FlHFM/qacA3jzMPOYKIwNwbgTQEKJH2hQiq19Zrc= +github.com/ipfs/go-unixfs v0.1.0/go.mod h1:lysk5ELhOso8+Fed9U1QTGey2ocsfaZ18h0NCO2Fj9s= +github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb/go.mod h1:IwAAgul1UQIcNZzKPYZWOCijryFBeCV79cNubPzol+k= +github.com/ipfs/go-unixfs v0.2.4 h1:6NwppOXefWIyysZ4LR/qUBPvXd5//8J3jiMdvpbw6Lo= +github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= -github.com/ipfs/interface-go-ipfs-core v0.0.8 h1:nmEYOfK6QRf3VIdggoZ4rmbKXcC2g6cEdU13Z1CvmL4= -github.com/ipfs/interface-go-ipfs-core v0.0.8/go.mod h1:RU+DSZXV+JdA7Yagu3OrSoB6hngSmMtK1w6ENOqmfQ8= -github.com/jackpal/gateway v1.0.4 h1:LS5EHkLuQ6jzaHwULi0vL+JO0mU/n4yUtK8oUjHHOlM= +github.com/ipfs/interface-go-ipfs-core v0.2.7 h1:HCwVmU9Tmba6jdMGxMcPsfwKUBY4y+6bLHp8T+t9hTU= +github.com/ipfs/interface-go-ipfs-core v0.2.7/go.mod h1:Tihp8zxGpUeE3Tokr94L6zWZZdkRQvG5TL6i9MuNE+s= +github.com/ipld/go-car v0.1.0 h1:AaIEA5ITRnFA68uMyuIPYGM2XXllxsu8sNjFJP797us= +github.com/ipld/go-car v0.1.0/go.mod h1:RCWzaUh2i4mOEkB3W45Vc+9jnS/M6Qay5ooytiBHl3g= +github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785 h1:fASnkvtR+SmB2y453RxmDD3Uvd4LonVUgFGk9JoDaZs= +github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= +github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5 h1:lSip43rAdyGA+yRQuy6ju0ucZkWpYc1F2CTQtZTVW/4= +github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU= github.com/jackpal/gateway v1.0.4/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec h1:DQqZhhDvrTrEQ3Qod5yfavcA064e53xlQ+xajiorXgM= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs= github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jbenet/go-is-domain v1.0.2 h1:11r5MSptcNFZyBoqubBQnVMUKRWLuRjL1banaIk+iYo= -github.com/jbenet/go-is-domain v1.0.2/go.mod h1:xbRLRb0S7FgzDBTJlguhDVwLYM/5yNtvktxj2Ttfy7Q= +github.com/jbenet/go-is-domain v1.0.3 h1:FuRBJ0h79p00eseyaLckJT5KnE8RyqI+HLopvNSyNE0= +github.com/jbenet/go-is-domain v1.0.3/go.mod h1:xbRLRb0S7FgzDBTJlguhDVwLYM/5yNtvktxj2Ttfy7Q= github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c h1:uUx61FiAa1GI6ZmVd2wf2vULeQZIKG66eybjNXKYCz4= github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c/go.mod h1:sdx1xVM9UuLw1tXnhJWN3piypTUO3vCIHYmG15KE/dU= github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2 h1:vhC1OXXiT9R2pczegwz6moDvuRpggaroAXhPIseh57A= github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs= -github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8 h1:bspPhN+oKYFk5fcGNuQzp6IGzYQSenLEgH3s6jkXrWw= +github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0= +github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= +github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= +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/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= +github.com/kisielk/errcheck v1.2.0 h1:reN85Pxc5larApoH1keMBiu2GWtPqXQ1nc9gx+jOU+E= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= 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.0-20180514024734-4a0ed625a78b h1:wxtKgYHEncAU00muMD06dzLiahtGM1eouRNOzVV7tdQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= +github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d h1:68u9r4wEvL3gYg2jvAOgROwZ3H+Y3hIDk4tbbmIjcYQ= +github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/libp2p/go-addr-util v0.0.1 h1:TpTQm9cXVRVSKsYbgQ7GKc3KbbHVTnbostgGaDEP+88= github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ= -github.com/libp2p/go-buffer-pool v0.0.1 h1:9Rrn/H46cXjaA2HQ5Y8lyhOS1NhTkZ4yuEs2r3Eechg= github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= -github.com/libp2p/go-conn-security v0.0.1 h1:4kMMrqrt9EUNCNjX1xagSJC+bq16uqjMe9lk1KBMVNs= github.com/libp2p/go-conn-security v0.0.1/go.mod h1:bGmu51N0KU9IEjX7kl2PQjgZa40JQWnayTvNMgD/vyk= -github.com/libp2p/go-conn-security-multistream v0.0.1 h1:XefjAQRHcnUaxKb26RGupToucx3uU4ecbOZ3aACXlDU= github.com/libp2p/go-conn-security-multistream v0.0.1/go.mod h1:nc9vud7inQ+d6SO0I/6dSWrdMnHnzZNHeyUQqrAJulE= -github.com/libp2p/go-conn-security-multistream v0.0.2 h1:Ykz0lnNjxk+0SdslUmlLNyrleqdpS1S/VW+dxFdt74Y= github.com/libp2p/go-conn-security-multistream v0.0.2/go.mod h1:nc9vud7inQ+d6SO0I/6dSWrdMnHnzZNHeyUQqrAJulE= +github.com/libp2p/go-conn-security-multistream v0.1.0 h1:aqGmto+ttL/uJgX0JtQI0tD21CIEy5eYd1Hlp0juHY0= +github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= +github.com/libp2p/go-conn-security-multistream v0.2.0 h1:uNiDjS58vrvJTg9jO6bySd1rMKejieG7v45ekqHbZ1M= +github.com/libp2p/go-conn-security-multistream v0.2.0/go.mod h1:hZN4MjlNetKD3Rq5Jb/P5ohUnFLNzEAR4DLSzpn2QLU= +github.com/libp2p/go-eventbus v0.0.2/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk= +github.com/libp2p/go-eventbus v0.0.3/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk= +github.com/libp2p/go-eventbus v0.1.0 h1:mlawomSAjjkk97QnYiEmHsLu7E136+2oCWSHRUvMfzQ= +github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= +github.com/libp2p/go-flow-metrics v0.0.2 h1:U5TvqfoyR6GVRM+bC15Ux1ltar1kbj6Zw6xOVR02CZs= +github.com/libp2p/go-flow-metrics v0.0.2/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM= github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= -github.com/libp2p/go-libp2p v0.0.2 h1:+jvgi0Zy3y4TKXJKApchCk3pCBPZf1T54z3+vKie3gw= github.com/libp2p/go-libp2p v0.0.2/go.mod h1:Qu8bWqFXiocPloabFGUcVG4kk94fLvfC8mWTDdFC9wE= github.com/libp2p/go-libp2p v0.0.30/go.mod h1:XWT8FGHlhptAv1+3V/+J5mEpzyui/5bvFsNuWYs611A= -github.com/libp2p/go-libp2p v0.0.32 h1:6BpTCct+6SEVxMk/2R7K1l5aIqa1Rio8tlzxjGK4z4U= -github.com/libp2p/go-libp2p v0.0.32/go.mod h1:XWT8FGHlhptAv1+3V/+J5mEpzyui/5bvFsNuWYs611A= -github.com/libp2p/go-libp2p-autonat v0.0.2 h1:ilo9QPzNPf1hMkqaPG55yzvhILf5ZtijstJhcii+l3s= +github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM= +github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8= +github.com/libp2p/go-libp2p v0.2.1/go.mod h1:HZbtEOrgZN4F1fGZVvkV+930Wx3DkqlpBlO8dIoZWds= +github.com/libp2p/go-libp2p v0.6.0 h1:EFArryT9N7AVA70LCcOh8zxsW+FeDnxwcpWQx9k7+GM= +github.com/libp2p/go-libp2p v0.6.0/go.mod h1:mfKWI7Soz3ABX+XEBR61lGbg+ewyMtJHVt043oWeqwg= +github.com/libp2p/go-libp2p v0.6.1 h1:mxabyJf4l6AmotDOKObwSfBNBWjL5VYXysVFLUMAuB8= +github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZkfEI5sT54= +github.com/libp2p/go-libp2p v0.7.0 h1:qWmciout2lJclKfRlxqdepsQB7JihcbRhgcRcssP4rc= +github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= +github.com/libp2p/go-libp2p v0.7.4 h1:xVj1oSlN0C+FlxqiLuHC8WruMvq24xxfeVxmNhTG0r0= +github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= +github.com/libp2p/go-libp2p v0.8.2 h1:gVuk8nZGjnRagJ/mLpBCSJw7bW1yWJrq3EwOk/AC6FM= +github.com/libp2p/go-libp2p v0.8.2/go.mod h1:NQDA/F/qArMHGe0J7sDScaKjW8Jh4y/ozQqBbYJ+BnA= +github.com/libp2p/go-libp2p v0.8.3 h1:IFWeNzxkBaNO1N8stN9ayFGdC6RmVuSsKd5bou7qpK0= +github.com/libp2p/go-libp2p v0.8.3/go.mod h1:EsH1A+8yoWK+L4iKcbPYu6MPluZ+CHWI9El8cTaefiM= github.com/libp2p/go-libp2p-autonat v0.0.2/go.mod h1:fs71q5Xk+pdnKU014o2iq1RhMs9/PMaG5zXRFNnIIT4= -github.com/libp2p/go-libp2p-autonat v0.0.3 h1:PUD+pAx8Qs9hh+Bowzxq8RCkg/Vwrz5oCFC4peixXQk= -github.com/libp2p/go-libp2p-autonat v0.0.3/go.mod h1:fs71q5Xk+pdnKU014o2iq1RhMs9/PMaG5zXRFNnIIT4= -github.com/libp2p/go-libp2p-autonat v0.0.6 h1:OCStANLLpeyQeWFUuqZJ7aS9+Bx0/uoVb1PtLA9fGTQ= github.com/libp2p/go-libp2p-autonat v0.0.6/go.mod h1:uZneLdOkZHro35xIhpbtTzLlgYturpu4J5+0cZK3MqE= -github.com/libp2p/go-libp2p-autonat-svc v0.0.5 h1:bTom7QFAkJMXiA8ibSsKQ2+LKEHsXZz2IAWYolg/YYg= -github.com/libp2p/go-libp2p-autonat-svc v0.0.5/go.mod h1:6aLiQelA0CKEcPR0TvE9bqJ7U8Mc0nVdwCoho3ROdck= -github.com/libp2p/go-libp2p-blankhost v0.0.1 h1:/mZuuiwntNR8RywnCFlGHLKrKLYne+qciBpQXWqp5fk= +github.com/libp2p/go-libp2p-autonat v0.1.0 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= +github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= +github.com/libp2p/go-libp2p-autonat v0.1.1 h1:WLBZcIRsjZlWdAZj9CiBSvU2wQXoUOiS1Zk1tM7DTJI= +github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= +github.com/libp2p/go-libp2p-autonat v0.2.0 h1:Kok+0M/4jiz6TTmxtBqAa5tLyHb/U+G/7o/JEeW7Wok= +github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= +github.com/libp2p/go-libp2p-autonat v0.2.1 h1:T0CRQhrvTBKfBSYw6Xo2K3ixtNpAnRCraxof3AAfgQA= +github.com/libp2p/go-libp2p-autonat v0.2.1/go.mod h1:MWtAhV5Ko1l6QBsHQNSuM6b1sRkXrpk0/LqCr+vCVxI= +github.com/libp2p/go-libp2p-autonat v0.2.2 h1:4dlgcEEugTFWSvdG2UIFxhnOMpX76QaZSRAtXmYB8n4= +github.com/libp2p/go-libp2p-autonat v0.2.2/go.mod h1:HsM62HkqZmHR2k1xgX34WuWDzk/nBwNHoeyyT4IWV6A= github.com/libp2p/go-libp2p-blankhost v0.0.1/go.mod h1:Ibpbw/7cPPYwFb7PACIWdvxxv0t0XCCI10t7czjAjTc= -github.com/libp2p/go-libp2p-circuit v0.0.1 h1:DYbjyQ5ZY3QVAVYZWG4uzBQ6Wmcd1C82Bk8Q/pJlM1I= +github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= +github.com/libp2p/go-libp2p-blankhost v0.1.3/go.mod h1:KML1//wiKR8vuuJO0y3LUd1uLv+tlkGTAr3jC0S5cLg= +github.com/libp2p/go-libp2p-blankhost v0.1.4 h1:I96SWjR4rK9irDHcHq3XHN6hawCRTPUADzkJacgZLvk= +github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU= github.com/libp2p/go-libp2p-circuit v0.0.1/go.mod h1:Dqm0s/BiV63j8EEAs8hr1H5HudqvCAeXxDyic59lCwE= -github.com/libp2p/go-libp2p-circuit v0.0.9 h1:tjdgP9hv8+Pa/xsprBpEFngq4t8aLvjfibBYoDjO9i4= github.com/libp2p/go-libp2p-circuit v0.0.9/go.mod h1:uU+IBvEQzCu953/ps7bYzC/D/R0Ho2A9LfKVVCatlqU= -github.com/libp2p/go-libp2p-connmgr v0.0.7 h1:fpIv25cRIsh7GGEWAV95k50VdsO4eONG5gHHLrjq27E= -github.com/libp2p/go-libp2p-connmgr v0.0.7/go.mod h1:uwDfgdgqB5248sQYib1xo603cSsMg9PgAKu0Z+Y65Qk= -github.com/libp2p/go-libp2p-crypto v0.0.1 h1:JNQd8CmoGTohO/akqrH16ewsqZpci2CbgYH/LmYl8gw= +github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= +github.com/libp2p/go-libp2p-circuit v0.1.4 h1:Phzbmrg3BkVzbqd4ZZ149JxCuUWu2wZcXf/Kr6hZJj8= +github.com/libp2p/go-libp2p-circuit v0.1.4/go.mod h1:CY67BrEjKNDhdTk8UgBX1Y/H5c3xkAcs3gnksxY7osU= +github.com/libp2p/go-libp2p-circuit v0.2.1 h1:BDiBcQxX/ZJJ/yDl3sqZt1bjj4PkZCEi7IEpwxXr13k= +github.com/libp2p/go-libp2p-circuit v0.2.1/go.mod h1:BXPwYDN5A8z4OEY9sOfr2DUQMLQvKt/6oku45YUmjIo= +github.com/libp2p/go-libp2p-circuit v0.2.2 h1:87RLabJ9lrhoiSDDZyCJ80ZlI5TLJMwfyoGAaWXzWqA= +github.com/libp2p/go-libp2p-circuit v0.2.2/go.mod h1:nkG3iE01tR3FoQ2nMm06IUrCpCyJp1Eo4A1xYdpjfs4= +github.com/libp2p/go-libp2p-connmgr v0.2.1 h1:1ed0HFhCb39sIMK7QYgRBW0vibBBqFQMs4xt9a9AalY= +github.com/libp2p/go-libp2p-connmgr v0.2.1/go.mod h1:JReKEFcgzSHKT9lL3rhYcUtXBs9uMIiMKJGM1tl3xJE= +github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= +github.com/libp2p/go-libp2p-core v0.0.2/go.mod h1:9dAcntw/n46XycV4RnlBq3BpgrmyUi9LuoTNdPrbUco= +github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE= +github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= +github.com/libp2p/go-libp2p-core v0.0.6/go.mod h1:0d9xmaYAVY5qmbp/fcgxHT3ZJsLjYeYPMJAUKpaCHrE= +github.com/libp2p/go-libp2p-core v0.0.9/go.mod h1:0d9xmaYAVY5qmbp/fcgxHT3ZJsLjYeYPMJAUKpaCHrE= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= +github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g= +github.com/libp2p/go-libp2p-core v0.2.5 h1:iP1PIiIrlRrGbE1fYq2918yBc5NlCH3pFuIPSWU9hds= +github.com/libp2p/go-libp2p-core v0.2.5/go.mod h1:6+5zJmKhsf7yHn1RbmYDu08qDUpIUxGdqHuEZckmZOA= +github.com/libp2p/go-libp2p-core v0.3.0 h1:F7PqduvrztDtFsAa/bcheQ3azmNo+Nq7m8hQY5GiUW8= +github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= +github.com/libp2p/go-libp2p-core v0.3.1 h1:hEnSDjScfjYvPHoTgZhC4F62M8K1x1Oco/BY0RZ1N3s= +github.com/libp2p/go-libp2p-core v0.3.1/go.mod h1:thvWy0hvaSBhnVBaW37BvzgVV68OUhgJJLAa6almrII= +github.com/libp2p/go-libp2p-core v0.4.0 h1:LjZJP/Yy4q8kc724izkYQ9v6YkAmkKCOaE5jLv/NZRo= +github.com/libp2p/go-libp2p-core v0.4.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= +github.com/libp2p/go-libp2p-core v0.5.0 h1:FBQ1fpq2Fo/ClyjojVJ5AKXlKhvNc/B6U0O+7AN1ffE= +github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= +github.com/libp2p/go-libp2p-core v0.5.1 h1:6Cu7WljPQtGY2krBlMoD8L/zH3tMUsCbqNFH7cZwCoI= +github.com/libp2p/go-libp2p-core v0.5.1/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= +github.com/libp2p/go-libp2p-core v0.5.2 h1:hevsCcdLiazurKBoeNn64aPYTVOPdY4phaEGeLtHOAs= +github.com/libp2p/go-libp2p-core v0.5.2/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE= -github.com/libp2p/go-libp2p-crypto v0.0.2 h1:TTdJ4y6Uoa6NxQcuEaVkQfFRcQeCE2ReDk8Ok4I0Fyw= github.com/libp2p/go-libp2p-crypto v0.0.2/go.mod h1:eETI5OUfBnvARGOHrJz2eWNyTUxEGZnBxMcbUjfIj4I= -github.com/libp2p/go-libp2p-discovery v0.0.1 h1:VkjCKmJQMwpDUwtA8Qc1z3TQAHJgQ5nGQ6cdN0wQXOw= +github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= +github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= github.com/libp2p/go-libp2p-discovery v0.0.1/go.mod h1:ZkkF9xIFRLA1xCc7bstYFkd80gBGK8Fc1JqGoU2i+zI= -github.com/libp2p/go-libp2p-discovery v0.0.5 h1:VpPd7u2odnrrRcW+gVdjLDcXsc35k0Tjxqgbzlre6Uo= github.com/libp2p/go-libp2p-discovery v0.0.5/go.mod h1:YtF20GUxjgoKZ4zmXj8j3Nb2TUSBHFlOCetzYdbZL5I= -github.com/libp2p/go-libp2p-host v0.0.1 h1:dnqusU+DheGcdxrE718kG4XgHNuL2n9eEv8Rg5zy8hQ= +github.com/libp2p/go-libp2p-discovery v0.1.0 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6SrqMymQhmvs= +github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g= +github.com/libp2p/go-libp2p-discovery v0.2.0 h1:1p3YSOq7VsgaL+xVHPi8XAmtGyas6D2J6rWBEfz/aiY= +github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg= +github.com/libp2p/go-libp2p-discovery v0.3.0 h1:+JnYBRLzZQtRq0mK3xhyjBwHytLmJXMTZkQfbw+UrGA= +github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw= +github.com/libp2p/go-libp2p-discovery v0.4.0 h1:dK78UhopBk48mlHtRCzbdLm3q/81g77FahEBTjcqQT8= +github.com/libp2p/go-libp2p-discovery v0.4.0/go.mod h1:bZ0aJSrFc/eX2llP0ryhb1kpgkPyTo23SJ5b7UQCMh4= +github.com/libp2p/go-libp2p-gostream v0.2.1 h1:JjA9roGokaR2BgWmaI/3HQu1/+jSbVVDLatQGnVdGjI= +github.com/libp2p/go-libp2p-gostream v0.2.1/go.mod h1:1Mjp3LDmkqICe5tH9yLVNCqFaRTy6OwBvuJV6j1b9Nk= github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= -github.com/libp2p/go-libp2p-host v0.0.3 h1:BB/1Z+4X0rjKP5lbQTmjEjLbDVbrcmLOlA6QDsN5/j4= github.com/libp2p/go-libp2p-host v0.0.3/go.mod h1:Y/qPyA6C8j2coYyos1dfRm0I8+nvd4TGrDGt4tA7JR8= -github.com/libp2p/go-libp2p-interface-connmgr v0.0.1 h1:Q9EkNSLAOF+u90L88qmE9z/fTdjLh8OsJwGw74mkwk4= +github.com/libp2p/go-libp2p-http v0.1.5 h1:FfLnzjlEzV4/6UCXCpPXRYZNoGCfogqCFjd7eF0Jbm8= +github.com/libp2p/go-libp2p-http v0.1.5/go.mod h1:2YfPjsQxUlBGFQl2u461unkQ7ukwiSs7NX2eSslOJiU= github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= -github.com/libp2p/go-libp2p-interface-connmgr v0.0.4 h1:/LngXETpII5qOD7YjAcQiIxhVtdAk/NQe5t9sC6BR0E= github.com/libp2p/go-libp2p-interface-connmgr v0.0.4/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= -github.com/libp2p/go-libp2p-interface-connmgr v0.0.5 h1:KG/KNYL2tYzXAfMvQN5K1aAGTYSYUMJ1prgYa2/JI1E= github.com/libp2p/go-libp2p-interface-connmgr v0.0.5/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= -github.com/libp2p/go-libp2p-interface-pnet v0.0.1 h1:7GnzRrBTJHEsofi1ahFdPN9Si6skwXQE9UqR2S+Pkh8= github.com/libp2p/go-libp2p-interface-pnet v0.0.1/go.mod h1:el9jHpQAXK5dnTpKA4yfCNBZXvrzdOU75zz+C6ryp3k= -github.com/libp2p/go-libp2p-kad-dht v0.0.15 h1:nFty5RHPewD2eNm686qtOg/5i+dfQvM8vltR3aadkxk= -github.com/libp2p/go-libp2p-kad-dht v0.0.15/go.mod h1:8Rkh52UJyFBvN/EUT+dyV9VrjB2eMjtQ01CfKyQLvlc= -github.com/libp2p/go-libp2p-kbucket v0.1.1 h1:ZrvW3qCM+lAuv7nrNts/zfEiClq+GZe8OIzX4Vb3Dwo= -github.com/libp2p/go-libp2p-kbucket v0.1.1/go.mod h1:Y0iQDHRTk/ZgM8PC4jExoF+E4j+yXWwRkdldkMa5Xm4= -github.com/libp2p/go-libp2p-loggables v0.0.1 h1:HVww9oAnINIxbt69LJNkxD8lnbfgteXR97Xm4p3l9ps= +github.com/libp2p/go-libp2p-kad-dht v0.7.10 h1:Usixca9o8e3t+pSdHkzyWdU+WSbeTaMvpIcXxQrbImE= +github.com/libp2p/go-libp2p-kad-dht v0.7.10/go.mod h1:COi43/398wedaaNzvnbnWQ8qeG629Nu7Aj0WixHmD3A= +github.com/libp2p/go-libp2p-kbucket v0.4.1 h1:6FyzbQuGLPzbMv3HiD232zqscIz5iB8ppJwb380+OGI= +github.com/libp2p/go-libp2p-kbucket v0.4.1/go.mod h1:7sCeZx2GkNK1S6lQnGUW5JYZCFPnXzAZCCBBS70lytY= github.com/libp2p/go-libp2p-loggables v0.0.1/go.mod h1:lDipDlBNYbpyqyPX/KcoO+eq0sJYEVR2JgOexcivchg= -github.com/libp2p/go-libp2p-metrics v0.0.1 h1:yumdPC/P2VzINdmcKZd0pciSUCpou+s0lwYCjBbzQZU= +github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= +github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= github.com/libp2p/go-libp2p-metrics v0.0.1/go.mod h1:jQJ95SXXA/K1VZi13h52WZMa9ja78zjyy5rspMsC/08= -github.com/libp2p/go-libp2p-mplex v0.1.1 h1:lSPS1VJ36P01gGO//KgcsmSah5uoC3X9r7WY5j+iP4c= github.com/libp2p/go-libp2p-mplex v0.1.1/go.mod h1:KUQWpGkCzfV7UIpi8SKsAVxyBgz1c9R5EvxgnwLsb/I= -github.com/libp2p/go-libp2p-nat v0.0.2 h1:sKI5hiCsGFhuEKdXMsF9mywQu2qhfoIGX6a+VG6zelE= +github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= +github.com/libp2p/go-libp2p-mplex v0.2.1 h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8iGvirYI= +github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= +github.com/libp2p/go-libp2p-mplex v0.2.2 h1:+Ld7YDAfVERQ0E+qqjE7o6fHwKuM0SqTzYiwN1lVVSA= +github.com/libp2p/go-libp2p-mplex v0.2.2/go.mod h1:74S9eum0tVQdAfFiKxAyKzNdSuLqw5oadDq7+L/FELo= +github.com/libp2p/go-libp2p-mplex v0.2.3 h1:2zijwaJvpdesST2MXpI5w9wWFRgYtMcpRX7rrw0jmOo= +github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxWDkm+dVvjfuG3ek= github.com/libp2p/go-libp2p-nat v0.0.2/go.mod h1:QrjXQSD5Dj4IJOdEcjHRkWTSomyxRo6HnUkf/TfQpLQ= github.com/libp2p/go-libp2p-nat v0.0.4 h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2wwmyw= github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= -github.com/libp2p/go-libp2p-net v0.0.1 h1:xJ4Vh4yKF/XKb8fd1Ev0ebAGzVjMxXzrxG2kjtU+F5Q= +github.com/libp2p/go-libp2p-nat v0.0.5 h1:/mH8pXFVKleflDL1YwqMg27W9GD8kjEx7NY0P6eGc98= +github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= +github.com/libp2p/go-libp2p-nat v0.0.6 h1:wMWis3kYynCbHoyKLPBEMu4YRLltbm8Mk08HGSfvTkU= +github.com/libp2p/go-libp2p-nat v0.0.6/go.mod h1:iV59LVhB3IkFvS6S6sauVTSOrNEANnINbI/fkaLimiw= github.com/libp2p/go-libp2p-net v0.0.1/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= -github.com/libp2p/go-libp2p-net v0.0.2 h1:qP06u4TYXfl7uW/hzqPhlVVTSA2nw1B/bHBJaUnbh6M= github.com/libp2p/go-libp2p-net v0.0.2/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= -github.com/libp2p/go-libp2p-netutil v0.0.1 h1:LgD6+skofkOx8z6odD9+MZHKjupv3ng1u6KRhaADTnA= github.com/libp2p/go-libp2p-netutil v0.0.1/go.mod h1:GdusFvujWZI9Vt0X5BKqwWWmZFxecf9Gt03cKxm2f/Q= -github.com/libp2p/go-libp2p-peer v0.0.1 h1:0qwAOljzYewINrU+Kndoc+1jAL7vzY/oY2Go4DCGfyY= +github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ= +github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo= -github.com/libp2p/go-libp2p-peer v0.1.1 h1:qGCWD1a+PyZcna6htMPo26jAtqirVnJ5NvBQIKV7rRY= github.com/libp2p/go-libp2p-peer v0.1.1/go.mod h1:jkF12jGB4Gk/IOo+yomm+7oLWxF278F7UnrYUQ1Q8es= -github.com/libp2p/go-libp2p-peerstore v0.0.1 h1:twKovq8YK5trLrd3nB7PD2Zu9JcyAIdm7Bz9yBWjhq8= +github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY= +github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= github.com/libp2p/go-libp2p-peerstore v0.0.1/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= -github.com/libp2p/go-libp2p-peerstore v0.0.6 h1:RgX/djPFXqZGktW0j2eF4NAX0pzDsCot45jO2GewC+g= github.com/libp2p/go-libp2p-peerstore v0.0.6/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= -github.com/libp2p/go-libp2p-pnet v0.0.1 h1:2e5d15M8XplUKsU4Fqrll5eDfqGg/7mHUufLkhbfKHM= -github.com/libp2p/go-libp2p-pnet v0.0.1/go.mod h1:bWN8HqdpgCdKnXSCsJhbWjiU3UZFa/tIe4no5jCmHVw= -github.com/libp2p/go-libp2p-protocol v0.0.1 h1:+zkEmZ2yFDi5adpVE3t9dqh/N9TbpFWywowzeEzBbLM= +github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= +github.com/libp2p/go-libp2p-peerstore v0.1.2/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= +github.com/libp2p/go-libp2p-peerstore v0.1.3 h1:wMgajt1uM2tMiqf4M+4qWKVyyFc8SfA+84VV9glZq1M= +github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= +github.com/libp2p/go-libp2p-peerstore v0.1.4 h1:d23fvq5oYMJ/lkkbO4oTwBp/JP+I/1m5gZJobNXCE/k= +github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs= +github.com/libp2p/go-libp2p-peerstore v0.2.0 h1:XcgJhI8WyUOCbHyRLNEX5542YNj8hnLSJ2G1InRjDhk= +github.com/libp2p/go-libp2p-peerstore v0.2.0/go.mod h1:N2l3eVIeAitSg3Pi2ipSrJYnqhVnMNQZo9nkSCuAbnQ= +github.com/libp2p/go-libp2p-peerstore v0.2.1 h1:u+gOfsKgu73ZkGWhvckRm03z9C+iS9TrLqpANweELGs= +github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= +github.com/libp2p/go-libp2p-peerstore v0.2.2 h1:iqc/m03jHn5doXN3+kS6JKvqQRHEltiXljQB85iVHWE= +github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= +github.com/libp2p/go-libp2p-peerstore v0.2.3 h1:MofRq2l3c15vQpEygTetV+zRRrncz+ktiXW7H2EKoEQ= +github.com/libp2p/go-libp2p-peerstore v0.2.3/go.mod h1:K8ljLdFn590GMttg/luh4caB/3g0vKuY01psze0upRw= +github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= +github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= -github.com/libp2p/go-libp2p-pubsub v0.0.1 h1:iJWpvBDZiZOoRBGqEifu9yUHti9ptnSODHt6tgrBC6c= -github.com/libp2p/go-libp2p-pubsub v0.0.1/go.mod h1:fYKlZBOF2yrJzYlgeEVFSbYWfbS+E8Zix6gMZ0A6WgE= -github.com/libp2p/go-libp2p-pubsub v0.0.3 h1:DKVoDac2u1Dr8gX7B1HFjCrXkMxr8tfbnt0Fk1mmkgk= -github.com/libp2p/go-libp2p-pubsub v0.0.3/go.mod h1:fYKlZBOF2yrJzYlgeEVFSbYWfbS+E8Zix6gMZ0A6WgE= -github.com/libp2p/go-libp2p-pubsub-router v0.0.3 h1:2EF+8nueIsA9Unpj1MxdlS9+dX29kwCxSttchMMfXsI= -github.com/libp2p/go-libp2p-pubsub-router v0.0.3/go.mod h1:h5z0kyMFRu2J46tt15eEuLHKEmu1MrFghsGHqTc/iII= -github.com/libp2p/go-libp2p-quic-transport v0.0.3 h1:FGEPXsjpY9K6P3iMtJQPKGl45eXickBY1+xSJ84lVVI= -github.com/libp2p/go-libp2p-quic-transport v0.0.3/go.mod h1:v2oVuaFLkxlFpkFbXUty3dfEYSlNb0sCzvf8cRi1m/k= -github.com/libp2p/go-libp2p-record v0.0.1 h1:zN7AS3X46qmwsw5JLxdDuI43cH5UYwovKxHPjKBYQxw= +github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= +github.com/libp2p/go-libp2p-pubsub v0.2.5 h1:tPKbkjAUI0xLGN3KKTKKy9TQEviVfrP++zJgH5Muke4= +github.com/libp2p/go-libp2p-pubsub v0.2.5/go.mod h1:9Q2RRq8ofXkoewORcyVlgUFDKLKw7BuYSlJVWRcVk3Y= +github.com/libp2p/go-libp2p-pubsub v0.2.7 h1:PBuK5+NfWsoaoEaAUZ7YQPETQh8UqBi8CbMJ1CZ5sNI= +github.com/libp2p/go-libp2p-pubsub v0.2.7/go.mod h1:R4R0kH/6p2vu8O9xsue0HNSjEuXMEPBgg4h3nVDI15o= +github.com/libp2p/go-libp2p-pubsub-router v0.2.1 h1:F5JYaHQuuMKVbSgLsH2POQwT1rloWpc7fUCOq6PBjyE= +github.com/libp2p/go-libp2p-pubsub-router v0.2.1/go.mod h1:cl46APmxgKgzgpCGFb8Ns7++cqnJ29CxESXCQATp55k= +github.com/libp2p/go-libp2p-quic-transport v0.3.5 h1:zu1XFNE9FX8AaR/cptzD2P4uFvtDPj8ivQnZC+IhgsQ= +github.com/libp2p/go-libp2p-quic-transport v0.3.5/go.mod h1:cZNHoobzHTzkQhGnkHB1Kv349N6ESPCpE0TtAk0uRU0= github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q= -github.com/libp2p/go-libp2p-routing v0.0.1 h1:hPMAWktf9rYi3ME4MG48qE7dq1ofJxiQbfdvpNntjhc= +github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q= +github.com/libp2p/go-libp2p-record v0.1.2 h1:M50VKzWnmUrk/M5/Dz99qO9Xh4vs8ijsK+7HkJvRP+0= +github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGdsU/9W//C8dqjQDk= github.com/libp2p/go-libp2p-routing v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= -github.com/libp2p/go-libp2p-routing-helpers v0.0.2 h1:SLX7eDQE8Xo197NwNM/hM7WnH3w6fSGY9+G9HkiYwqQ= -github.com/libp2p/go-libp2p-routing-helpers v0.0.2/go.mod h1:zf1ook9HoOQpfnVXrF4gGorkPrGGf1g25vgH5+4SRNU= -github.com/libp2p/go-libp2p-secio v0.0.1 h1:CqE/RdsizOwItdgLe632iyft/w0tshDLmZGAiKDcUAI= +github.com/libp2p/go-libp2p-routing-helpers v0.2.1 h1:tV5fxxkl1cEEFXIv9yl5OGbLjEwngtq1qf5G/beLRvQ= +github.com/libp2p/go-libp2p-routing-helpers v0.2.1/go.mod h1:rTLUHlGDZbXHANJAWP2xW7ruPNJLj41/GnCBiR+qgjU= +github.com/libp2p/go-libp2p-routing-helpers v0.2.2 h1:gG4g5tyk3dS0iLdyOfsbGYDB6FyuiBcFUJhxX6QHEa4= +github.com/libp2p/go-libp2p-routing-helpers v0.2.2/go.mod h1:rTLUHlGDZbXHANJAWP2xW7ruPNJLj41/GnCBiR+qgjU= github.com/libp2p/go-libp2p-secio v0.0.1/go.mod h1:IdG6iQybdcYmbTzxp4J5dwtUEDTOvZrT0opIDVNPrJs= -github.com/libp2p/go-libp2p-secio v0.0.3 h1:h3fPeDrej7bvvARnC2oSjAfcLZOaS4REZKgWCRQNpE4= github.com/libp2p/go-libp2p-secio v0.0.3/go.mod h1:hS7HQ00MgLhRO/Wyu1bTX6ctJKhVpm+j2/S2A5UqYb0= -github.com/libp2p/go-libp2p-swarm v0.0.1 h1:Vne+hjaDwXqzgNwQ2vb2YKbnbOTyXjtS47stT66Apc4= +github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= +github.com/libp2p/go-libp2p-secio v0.1.1/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= +github.com/libp2p/go-libp2p-secio v0.2.0 h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXYwAWqHng= +github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= +github.com/libp2p/go-libp2p-secio v0.2.1 h1:eNWbJTdyPA7NxhP7J3c5lT97DC5d+u+IldkgCYFTPVA= +github.com/libp2p/go-libp2p-secio v0.2.1/go.mod h1:cWtZpILJqkqrSkiYcDBh5lA3wbT2Q+hz3rJQq3iftD8= +github.com/libp2p/go-libp2p-secio v0.2.2 h1:rLLPvShPQAcY6eNurKNZq3eZjPWfU9kXF2eI9jIYdrg= +github.com/libp2p/go-libp2p-secio v0.2.2/go.mod h1:wP3bS+m5AUnFA+OFO7Er03uO1mncHG0uVwGrwvjYlNY= github.com/libp2p/go-libp2p-swarm v0.0.1/go.mod h1:mh+KZxkbd3lQnveQ3j2q60BM1Cw2mX36XXQqwfPOShs= -github.com/libp2p/go-libp2p-swarm v0.0.6 h1:gE0P/v2h+KEXtAi9YTw2UBOSODJ4m9VuuJ+ktc2LVUo= github.com/libp2p/go-libp2p-swarm v0.0.6/go.mod h1:s5GZvzg9xXe8sbeESuFpjt8CJPTCa8mhEusweJqyFy8= -github.com/libp2p/go-libp2p-swarm v0.0.7 h1:Ma/ob07+9GwjDNxrSK5oP4cqilDir1p8FzwKBsWqPGg= -github.com/libp2p/go-libp2p-swarm v0.0.7/go.mod h1:s5GZvzg9xXe8sbeESuFpjt8CJPTCa8mhEusweJqyFy8= -github.com/libp2p/go-libp2p-tls v0.0.2 h1:bKuIE5fqyYiFJEtz8ovRkFogtvvAwQqCLZhbnSVMu8g= -github.com/libp2p/go-libp2p-tls v0.0.2/go.mod h1:FHAVvksSmbluc1v4sDcIK6oF46Hy0MW0wFk0LyrFghY= +github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= +github.com/libp2p/go-libp2p-swarm v0.1.1/go.mod h1:4NVJaLwq/dr5kEq79Jo6pMin7ZFwLx73ln1FTefR91Q= +github.com/libp2p/go-libp2p-swarm v0.2.2 h1:T4hUpgEs2r371PweU3DuH7EOmBIdTBCwWs+FLcgx3bQ= +github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU= +github.com/libp2p/go-libp2p-swarm v0.2.3 h1:uVkCb8Blfg7HQ/f30TyHn1g/uCwXsAET7pU0U59gx/A= +github.com/libp2p/go-libp2p-swarm v0.2.3/go.mod h1:P2VO/EpxRyDxtChXz/VPVXyTnszHvokHKRhfkEgFKNM= +github.com/libp2p/go-libp2p-testing v0.0.1/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.1.0 h1:WaFRj/t3HdMZGNZqnU2pS7pDRBmMeoDx7/HDNpeyT9U= +github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= +github.com/libp2p/go-libp2p-testing v0.1.1 h1:U03z3HnGI7Ni8Xx6ONVZvUFOAzWYmolWf5W5jAOPNmU= +github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= +github.com/libp2p/go-libp2p-tls v0.1.3 h1:twKMhMu44jQO+HgQK9X8NHO5HkeJu2QbhLzLJpa8oNM= +github.com/libp2p/go-libp2p-tls v0.1.3/go.mod h1:wZfuewxOndz5RTnCAxFliGjvYSDA40sKitV4c50uI1M= github.com/libp2p/go-libp2p-transport v0.0.1/go.mod h1:UzbUs9X+PHOSw7S3ZmeOxfnwaQY5vGDzZmKPod3N3tk= -github.com/libp2p/go-libp2p-transport v0.0.4 h1:/CPHQMN75/IQwkhBxxIo6p6PtL3rwFZtlzBROT3e8mw= github.com/libp2p/go-libp2p-transport v0.0.4/go.mod h1:StoY3sx6IqsP6XKoabsPnHCwqKXWUMWU7Rfcsubee/A= -github.com/libp2p/go-libp2p-transport v0.0.5 h1:pV6+UlRxyDpASSGD+60vMvdifSCby6JkJDfi+yUMHac= github.com/libp2p/go-libp2p-transport v0.0.5/go.mod h1:StoY3sx6IqsP6XKoabsPnHCwqKXWUMWU7Rfcsubee/A= -github.com/libp2p/go-libp2p-transport-upgrader v0.0.1 h1:rNtXkY6dty46mxYOHHAZQchI7gQdJStF683FhVnei/k= github.com/libp2p/go-libp2p-transport-upgrader v0.0.1/go.mod h1:NJpUAgQab/8K6K0m+JmZCe5RUXG10UMEx4kWe9Ipj5c= -github.com/libp2p/go-libp2p-transport-upgrader v0.0.4 h1:uGMOd14BL1oFlfb/cGfOxPjiTKBhzWV4aMjjoCF1Z1o= github.com/libp2p/go-libp2p-transport-upgrader v0.0.4/go.mod h1:RGq+tupk+oj7PzL2kn/m1w6YXxcIAYJYeI90h6BGgUc= -github.com/libp2p/go-libp2p-yamux v0.1.2 h1:DgGItlrWi0j9y1OhRMC8qqL4zj2MEPWeKJTHb55R16Q= +github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw= +github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= +github.com/libp2p/go-libp2p-transport-upgrader v0.2.0 h1:5EhPgQhXZNyfL22ERZTUoVp9UVVbNowWNVtELQaKCHk= +github.com/libp2p/go-libp2p-transport-upgrader v0.2.0/go.mod h1:mQcrHj4asu6ArfSoMuyojOdjx73Q47cYD7s5+gZOlns= github.com/libp2p/go-libp2p-yamux v0.1.2/go.mod h1:xUoV/RmYkg6BW/qGxA9XJyg+HzXFYkeXbnhjmnYzKp8= -github.com/libp2p/go-libp2p-yamux v0.1.3 h1:HmKvv2jWJ4GEm3iP7cEKjuw0POa6rK+Hcsu1FBKzpLc= github.com/libp2p/go-libp2p-yamux v0.1.3/go.mod h1:VGSQVrqkh6y4nm0189qqxMtvyBft44MOYYPpYKXiVt4= -github.com/libp2p/go-maddr-filter v0.0.1 h1:apvYTg0aIxxQyBX+XHKOR+0+lYhGs1Yv+JmTH9nyl5I= +github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= +github.com/libp2p/go-libp2p-yamux v0.2.1 h1:Q3XYNiKCC2vIxrvUJL+Jg1kiyeEaIDNKLjgEjo3VQdI= +github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZKkAQzZbkSQt5fI= +github.com/libp2p/go-libp2p-yamux v0.2.2 h1:eGvbqWqWY9S5lrpe2gA0UCOLCdzCgYSAR3vo/xCsNQg= +github.com/libp2p/go-libp2p-yamux v0.2.2/go.mod h1:lIohaR0pT6mOt0AZ0L2dFze9hds9Req3OfS+B+dv4qw= +github.com/libp2p/go-libp2p-yamux v0.2.5 h1:MuyItOqz03oi8npvjgMJxgnhllJLZnO/dKVOpTZ9+XI= +github.com/libp2p/go-libp2p-yamux v0.2.5/go.mod h1:Zpgj6arbyQrmZ3wxSZxfBmbdnWtbZ48OpsfmQVTErwA= +github.com/libp2p/go-libp2p-yamux v0.2.7 h1:vzKu0NVtxvEIDGCv6mjKRcK0gipSgaXmJZ6jFv0d/dk= +github.com/libp2p/go-libp2p-yamux v0.2.7/go.mod h1:X28ENrBMU/nm4I3Nx4sZ4dgjZ6VhLEn0XhIoZ5viCwU= github.com/libp2p/go-maddr-filter v0.0.1/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= -github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= -github.com/libp2p/go-mplex v0.0.1 h1:dn2XGSrUxLtz3/8u85bGrwhUEKPX8MOF3lpmcWBZCWc= +github.com/libp2p/go-maddr-filter v0.0.5 h1:CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg= +github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M= github.com/libp2p/go-mplex v0.0.1/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= -github.com/libp2p/go-mplex v0.0.3 h1:YiMaevQcZtFU6DmKIF8xEO0vaui5kM5HJ1V1xkWQv14= github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= -github.com/libp2p/go-mplex v0.0.4 h1:043XJ3Zr7/Oz5cfyUaJwxUZyP02TngTpt4oq8R5UizQ= github.com/libp2p/go-mplex v0.0.4/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= -github.com/libp2p/go-msgio v0.0.1 h1:znj97n5FtXGCLDwe9x8jpHmY770SW4WStBGcCDh6GJw= +github.com/libp2p/go-mplex v0.1.0 h1:/nBTy5+1yRyY82YaO6HXQRnO5IAGsXTjEJaR3LdTPc0= +github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= +github.com/libp2p/go-mplex v0.1.1 h1:huPH/GGRJzmsHR9IZJJsrSwIM5YE2gL4ssgl1YWb/ps= +github.com/libp2p/go-mplex v0.1.1/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= +github.com/libp2p/go-mplex v0.1.2 h1:qOg1s+WdGLlpkrczDqmhYzyk3vCfsQ8+RxRTQjOZWwI= +github.com/libp2p/go-mplex v0.1.2/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= github.com/libp2p/go-msgio v0.0.1/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= -github.com/libp2p/go-msgio v0.0.2 h1:ivPvEKHxmVkTClHzg6RXTYHqaJQ0V9cDbq+6lKb3UV0= github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.3/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-nat v0.0.3 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI= github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI= +github.com/libp2p/go-nat v0.0.4 h1:KbizNnq8YIf7+Hn7+VFL/xE0eDrkPru2zIO9NMwL8UQ= +github.com/libp2p/go-nat v0.0.4/go.mod h1:Nmw50VAvKuk38jUBcmNh6p9lUJLoODbJRvYAa/+KSDo= +github.com/libp2p/go-nat v0.0.5 h1:qxnwkco8RLKqVh1NmjQ+tJ8p8khNLFxuElYG/TwqW4Q= +github.com/libp2p/go-nat v0.0.5/go.mod h1:B7NxsVNPZmRLvMOwiEO1scOSyjA56zxYAGv1yQgRkEU= +github.com/libp2p/go-netroute v0.1.2 h1:UHhB35chwgvcRI392znJA3RCBtZ3MpE3ahNCN5MR4Xg= +github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-openssl v0.0.2 h1:9pP2d3Ubaxkv7ZisLjx9BFwgOGnQdQYnfcH29HNY3ls= +github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= +github.com/libp2p/go-openssl v0.0.3 h1:wjlG7HvQkt4Fq4cfH33Ivpwp0omaElYEi9z26qaIkIk= +github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.4 h1:d27YZvLoTyMhIN4njrkr8zMDOM4lfpHIp6A+TK9fovg= +github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= -github.com/libp2p/go-reuseport-transport v0.0.1 h1:UIRneNxLDmEGNjGHpIiWzSWkZ5bhxMCP9x3Vh7BSc7E= github.com/libp2p/go-reuseport-transport v0.0.1/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4= github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= -github.com/libp2p/go-stream-muxer v0.0.1 h1:Ce6e2Pyu+b5MC1k3eeFtAax0pW4gc6MosYSLV05UeLw= +github.com/libp2p/go-reuseport-transport v0.0.3 h1:zzOeXnTooCkRvoH+bSXEfXhn76+LAiwoneM0gnXjF2M= +github.com/libp2p/go-reuseport-transport v0.0.3/go.mod h1:Spv+MPft1exxARzP2Sruj2Wb5JSyHNncjf1Oi2dEbzM= +github.com/libp2p/go-sockaddr v0.0.2 h1:tCuXfpA9rq7llM/v834RKc/Xvovy/AqM9kHvTV/jY/Q= +github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-sockaddr v0.1.0 h1:Y4s3/jNoryVRKEBrkJ576F17CPOaMIzUeCsg7dlTDj0= +github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-socket-activation v0.0.2 h1:VLU3IbrUUqu4DMhxA9857Q63qUpEAbCz5RqSnLCx5jE= +github.com/libp2p/go-socket-activation v0.0.2/go.mod h1:KP44C+yZ7gA8sTxavgaD0b8vXVFJwam2CEW0s7+f094= github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= -github.com/libp2p/go-stream-muxer-multistream v0.1.1 h1:DhHqb4nu1fQv/vQKeLAaZGmhLsUA4SF77IdYJiWE1d4= +github.com/libp2p/go-stream-muxer v0.1.0/go.mod h1:8JAVsjeRBCWwPoZeH0W1imLOcriqXJyFvB0mR4A04sQ= github.com/libp2p/go-stream-muxer-multistream v0.1.1/go.mod h1:zmGdfkQ1AzOECIAcccoL8L//laqawOsO03zX8Sa+eGw= -github.com/libp2p/go-tcp-transport v0.0.1 h1:WyvJVw2lYAnr6CU+GZZ4oCt06fvORlmvBlFX2+ZpZDM= +github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROmAFwUHpeRidG+q7LTQOg= +github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc= +github.com/libp2p/go-stream-muxer-multistream v0.3.0 h1:TqnSHPJEIqDEO7h1wZZ0p3DXdvDSiLHQidKKUGZtiOY= +github.com/libp2p/go-stream-muxer-multistream v0.3.0/go.mod h1:yDh8abSIzmZtqtOt64gFJUXEryejzNb0lisTt+fAMJA= github.com/libp2p/go-tcp-transport v0.0.1/go.mod h1:mnjg0o0O5TmXUaUIanYPUqkW4+u6mK0en8rlpA6BBTs= -github.com/libp2p/go-tcp-transport v0.0.4 h1:2iRu994wCT/iEz62F+c60FUoSkijNEQ0q2Itc+79XlQ= github.com/libp2p/go-tcp-transport v0.0.4/go.mod h1:+E8HvC8ezEVOxIo3V5vCK9l1y/19K427vCzQ+xHKH/o= -github.com/libp2p/go-testutil v0.0.1 h1:Xg+O0G2HIMfHqBOBDcMS1iSZJ3GEcId4qOxCQvsGZHk= +github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= +github.com/libp2p/go-tcp-transport v0.1.1 h1:yGlqURmqgNA2fvzjSgZNlHcsd/IulAnKM8Ncu+vlqnw= +github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= +github.com/libp2p/go-tcp-transport v0.2.0 h1:YoThc549fzmNJIh7XjHVtMIFaEDRtIrtWciG5LyYAPo= +github.com/libp2p/go-tcp-transport v0.2.0/go.mod h1:vX2U0CnWimU4h0SGSEsg++AzvBcroCGYw28kh94oLe0= github.com/libp2p/go-testutil v0.0.1/go.mod h1:iAcJc/DKJQanJ5ws2V+u5ywdL2n12X1WbbEG+Jjy69I= -github.com/libp2p/go-ws-transport v0.0.1 h1:9ytMqq86Xvp8rcnC/1ZNuH612eXLDglvcu4ZHseJl8s= +github.com/libp2p/go-testutil v0.1.0/go.mod h1:81b2n5HypcVyrCg/MJx4Wgfp/VHojytjVe/gLzZ2Ehc= github.com/libp2p/go-ws-transport v0.0.1/go.mod h1:p3bKjDWHEgtuKKj+2OdPYs5dAPIjtpQGHF2tJfGz7Ww= github.com/libp2p/go-ws-transport v0.0.5/go.mod h1:Qbl4BxPfXXhhd/o0wcrgoaItHqA9tnZjoFZnxykuaXU= -github.com/libp2p/go-ws-transport v0.0.6 h1:sjlnUfV3MthmPD/mbGuiwyw7yimEDpaEm/7+ayKWy4A= -github.com/libp2p/go-ws-transport v0.0.6/go.mod h1:Qbl4BxPfXXhhd/o0wcrgoaItHqA9tnZjoFZnxykuaXU= -github.com/libp2p/go-yamux v1.2.1 h1:VumHkMhJ2iFk1lzAeoDRgekiZSylGc6NnAEihVdBCiw= +github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo= +github.com/libp2p/go-ws-transport v0.2.0 h1:MJCw2OrPA9+76YNRvdo1wMnSOxb9Bivj6sVFY1Xrj6w= +github.com/libp2p/go-ws-transport v0.2.0/go.mod h1:9BHJz/4Q5A9ludYWKoGCFC5gUElzlHoKzu0yY9p/klM= +github.com/libp2p/go-ws-transport v0.3.0 h1:mjo6pL5aVR9rCjl9wNq3DupbaQlyR61pzoOT2MdtxaA= +github.com/libp2p/go-ws-transport v0.3.0/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= +github.com/libp2p/go-ws-transport v0.3.1 h1:ZX5rWB8nhRRJVaPO6tmkGI/Xx8XNboYX20PW5hXIscw= +github.com/libp2p/go-ws-transport v0.3.1/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= github.com/libp2p/go-yamux v1.2.1/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.2.2 h1:s6J6o7+ajoQMjHe7BEnq+EynOj5D2EoG8CuQgL3F2vg= github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI= github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/lucas-clemente/quic-go v0.11.1 h1:zasajC848Dqq/+WqfqBCkmPw+YHNe1MBts/z7y7nXf4= -github.com/lucas-clemente/quic-go v0.11.1/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= -github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= +github.com/libp2p/go-yamux v1.3.0 h1:FsYzT16Wq2XqUGJsBbOxoz9g+dFklvNi7jN6YFPfl7U= +github.com/libp2p/go-yamux v1.3.0/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.3.3 h1:mWuzZRCAeTBFdynLlsYgA/EIeMOLr8XY04wa52NRhsE= +github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.3.5 h1:ibuz4naPAully0pN6J/kmUARiqLpnDQIzI/8GCOrljg= +github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/lucas-clemente/quic-go v0.15.5 h1:2DR5qCVt4k1qnDmknf+idj1FDJIrkiDyS6a0uIR+UJY= +github.com/lucas-clemente/quic-go v0.15.5/go.mod h1:Myi1OyS0FOjL3not4BxT7KN29bRkcMUV5JVVFLKtDp8= +github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/marten-seemann/qtls v0.2.3 h1:0yWJ43C62LsZt08vuQJDK1uC1czUc3FJeCLPoNAI4vA= -github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= -github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= +github.com/marten-seemann/qtls v0.9.1 h1:O0YKQxNVPaiFgMng0suWEOY2Sb4LT2sRn9Qimq3Z1IQ= +github.com/marten-seemann/qtls v0.9.1/go.mod h1:T1MmAdDPyISzxlK6kjRr0pcZFBVd1OZbBb/j3cvzHhk= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +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 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -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-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-runewidth v0.0.8 h1:3tS41NlGYSmhhe/8fhGRzc+z3AYCw1Fe1WAyLuujKs0= +github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/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/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0= +github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.12 h1:WMhc1ik4LNkTg8U9l3hI1LvxKmIL+f1+WV/SZtCbDDA= github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.28 h1:gQhy5bsJa8zTlVI8lywCTZp1lguor+xevFoYlzeCTQY= +github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5 h1:l16XLUUJ34wIz+RIvLhSwGvLvKyy+W598b135bJN6mg= github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo= +github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= 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 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ= +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/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc= +github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= -github.com/multiformats/go-multiaddr v0.0.1 h1:/QUV3VBMDI6pi6xfiw7lr6xhDWWvQKn9udPn68kLSdY= github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.0.2 h1:RBysRCv5rv3FWlhKWKoXv8tnsCUpEpIZpCmqAGZos2s= github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1 h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oPbOMeS0ZDnE= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.2.0 h1:lR52sFwcTCuQb6bTfnXF6zA2XfyYvyd+5a9qECv/J90= +github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= +github.com/multiformats/go-multiaddr v0.2.1 h1:SgG/cw5vqyB5QQe5FPe2TqggU9WtrA9X4nZw7LlVqOI= +github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-dns v0.0.3 h1:P19q/k9jwmtgh+qXFkKfgFM7rCg/9l5AVqh7VNxSXhs= github.com/multiformats/go-multiaddr-dns v0.0.3/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= +github.com/multiformats/go-multiaddr-dns v0.2.0 h1:YWJoIDwLePniH7OU5hBnDZV6SWuvJqJ0YtN6pLeH9zA= +github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= +github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= +github.com/multiformats/go-multiaddr-net v0.1.0 h1:ZepO8Ezwovd+7b5XPPDhQhayk1yt0AJpzQBpq9fejx4= +github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= +github.com/multiformats/go-multiaddr-net v0.1.1 h1:jFFKUuXTXv+3ARyHZi3XUqQO+YWMKgBdhEvuGRfnL6s= +github.com/multiformats/go-multiaddr-net v0.1.1/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= +github.com/multiformats/go-multiaddr-net v0.1.2 h1:P7zcBH9FRETdPkDrylcXVjQLQ2t1JQtNItZULWNWgeg= +github.com/multiformats/go-multiaddr-net v0.1.2/go.mod h1:QsWt3XK/3hwvNxZJp92iMQKME1qHfpYmyIjFVsSOY6Y= +github.com/multiformats/go-multiaddr-net v0.1.3 h1:q/IYAvoPKuRzGeERn3uacWgm0LIWkLZBAvO5DxSzq3g= +github.com/multiformats/go-multiaddr-net v0.1.3/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= +github.com/multiformats/go-multiaddr-net v0.1.4 h1:g6gwydsfADqFvrHoMkS0n9Ok9CG6F7ytOH/bJDkhIOY= +github.com/multiformats/go-multiaddr-net v0.1.4/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= -github.com/multiformats/go-multicodec v0.1.6 h1:4u6lcjbE4VVVoigU4QJSSVYsGVP4j2jtDkR8lPwOrLE= -github.com/multiformats/go-multicodec v0.1.6/go.mod h1:lliaRHbcG8q33yf4Ot9BGD7JqR/Za9HE7HTyVyKwrUQ= -github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= +github.com/multiformats/go-multibase v0.0.2 h1:2pAgScmS1g9XjH7EtAfNhTuyrWYEWcxy0G5Wo85hWDA= +github.com/multiformats/go-multibase v0.0.2/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= -github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/multiformats/go-multihash v0.0.6/go.mod h1:XuKXPp8VHcTygube3OWZC+aZrA+H1IhmjoCDtJc7PXM= +github.com/multiformats/go-multihash v0.0.7/go.mod h1:XuKXPp8VHcTygube3OWZC+aZrA+H1IhmjoCDtJc7PXM= +github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.9 h1:aoijQXYYl7Xtb2pUUP68R+ys1TlnlR3eX6wmozr0Hp4= +github.com/multiformats/go-multihash v0.0.9/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multihash v0.0.10 h1:lMoNbh2Ssd9PUF74Nz008KGzGPlfeV6wH3rit5IIGCM= github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multistream v0.0.1 h1:JV4VfSdY9n7ECTtY59/TlSyFCzRILvYx4T4Ws8ZgihU= +github.com/multiformats/go-multihash v0.0.13 h1:06x+mk/zj1FoMsgNejLpy6QTvJqlSt/BhLEy87zidlc= +github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= -github.com/multiformats/go-multistream v0.0.4 h1:rNgWgFyzRSTI9L+xISrz7kN5MdNXoEcoIeeCH05wLKA= github.com/multiformats/go-multistream v0.0.4/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223 h1:F9x/1yl3T2AeKLr2AMdilSD8+f9bvMnNN8VS5iDtovc= +github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ= +github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= +github.com/multiformats/go-multistream v0.1.1 h1:JlAdpIFhBhGRLxe9W6Om0w++Gd6KMWoFPZL/dEnm9nI= +github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= +github.com/multiformats/go-varint v0.0.1 h1:TR/0rdQtnNxuN2IhiB639xC3tWM4IUi7DkTBVTdGW/M= +github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg= +github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +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/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.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/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 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/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992 h1:bzMe+2coZJYHnhGgVlcQKuRy4FSny4ds8dLQjw5P1XE= github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= +github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14 h1:2m16U/rLwVaRdz7ANkHtHTodP3zTP3N451MADg64x5k= +github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= +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 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA= +github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +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 h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.0-20190519111021-9935e8e0588d h1:Z5QMcUKnQw7ouB1wDuyZM6TL/rm+brJcNk6Ai8ut3zM= -github.com/prometheus/procfs v0.0.0-20190519111021-9935e8e0588d/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI= -github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +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/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= +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= +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/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.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa h1:E+gaaifzi2xF65PbDmuKI3PhLWY6G5opMLniFq8vmXA= +github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8= +github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= -github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 h1:N8Bg45zpk/UcpNGnfJt2y/3lRWASHNTUET8owPYCgYI= +github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smola/gocompat v0.2.0 h1:6b1oIMlUXIpz//VKEDzPVBK8KG7beVwmHIUEBIs/Pns= +github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/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/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= +github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436 h1:qOpVTI+BrstcjTZLm2Yz/3sOnqkzj3FQoh0g+E5s3Gc= +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-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= +github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830 h1:8kxMKmKzXXL4Ru1nyhvdms/JjWt+3YLpvRb/bAjO/y0= +github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/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/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0= -github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 h1:WXhVOwj2USAXB5oMDwRl3piOux2XMV9TANaYxXHdkoE= +github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= +github.com/whyrusleeping/go-logging v0.0.1 h1:fwpzlmT0kRC/Fmd0MdmGgJG/CXIZ6gFq46FQZjprUcc= +github.com/whyrusleeping/go-logging v0.0.1/go.mod h1:lDPYj54zutzG1XYfHAhcc7oNXEburHQBn+Iqd4yS4vE= github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f h1:M/lL30eFZTKnomXY6huvM6G0+gVquFNf6mxghaWlFUg= github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8= -github.com/whyrusleeping/go-smux-multiplex v3.0.16+incompatible h1:iqksILj8STw03EJQe7Laj4ubnw+ojOyik18cd5vPL1o= github.com/whyrusleeping/go-smux-multiplex v3.0.16+incompatible/go.mod h1:34LEDbeKFZInPUrAG+bjuJmUXONGdEFW7XL0SpTY1y4= -github.com/whyrusleeping/go-smux-multistream v2.0.2+incompatible h1:BdYHctE9HJZLquG9tpTdwWcbG4FaX6tVKPGjCGgiVxo= github.com/whyrusleeping/go-smux-multistream v2.0.2+incompatible/go.mod h1:dRWHHvc4HDQSHh9gbKEBbUZ+f2Q8iZTPG3UOGYODxSQ= -github.com/whyrusleeping/go-smux-yamux v2.0.8+incompatible h1:IGm/UP/JpEFS6D787sZnZg7RA6fZIR9c/Ms9DeAVNuk= github.com/whyrusleeping/go-smux-yamux v2.0.8+incompatible/go.mod h1:6qHUzBXUbB9MXmw3AUdB52L8sEb/hScCqOdW2kj/wuI= -github.com/whyrusleeping/go-smux-yamux v2.0.9+incompatible h1:nVkExQ7pYlN9e45LcqTCOiDD0904fjtm0flnHZGbXkw= github.com/whyrusleeping/go-smux-yamux v2.0.9+incompatible/go.mod h1:6qHUzBXUbB9MXmw3AUdB52L8sEb/hScCqOdW2kj/wuI= github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1 h1:ctS9Anw/KozviCCtK6VWMz5kPL9nbQzbQY4yfqlIV4M= github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1/go.mod h1:tKH72zYNt/exx6/5IQO6L9LoQ0rEjd5SbbWaDTs9Zso= github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg59EbA= github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= -github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30 h1:nMCC9Pwz1pxfC1Y6mYncdk+kq8d5aLx0Q+/gyZGE44M= github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9 h1:Y1/FEOpaCpD21WxrmfeIYCFPuVPRCY2XZTWzTNHGw30= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c h1:GGsyl0dZ2jJgVT+VvWBf/cNijrHRhkrTjkmp5wg7li0= github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c/go.mod h1:xxcJeBb7SIUl/Wzkz1eVKJE/CB34YNrqX2TQI6jY9zs= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= -github.com/whyrusleeping/yamux v1.1.5 h1:4CK3aUUJQu0qpKZv5gEWJjNOQtdbdDhVVS6PJ+HimdE= github.com/whyrusleeping/yamux v1.1.5/go.mod h1:E8LnQQ8HKx5KD29HZFUwM1PxCOdPRzGwur1mcYhXcD8= +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= -go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= +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= +go.opencensus.io v0.22.1 h1:8dP3SGL7MPB94crU3bEPplMPe83FI4EouesJUeFHv50= +go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= +go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/dig v1.7.0 h1:E5/L92iQTNJTjfgJF2KgU+/JpMaiuvK2DHLBj0+kSZk= -go.uber.org/dig v1.7.0/go.mod h1:z+dSd2TP9Usi48jL8M3v63iSBVkiwtVyMKxMZYYauPg= -go.uber.org/fx v1.9.0 h1:7OAz8ucp35AU8eydejpYG7QrbE8rLKzGhHbZlJi5LYY= -go.uber.org/fx v1.9.0/go.mod h1:mFdUyAUuJ3w4jAckiKSKbldsxy1ojpAMJ+dVZg5Y0Aw= +go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/dig v1.9.0 h1:pJTDXKEhRqBI8W7rU7kwT5EgyRZuSMVSFcZolOvKK9U= +go.uber.org/dig v1.9.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= +go.uber.org/fx v1.12.0 h1:+1+3Cz9M0dFMPy9SW9XUIUHye8bnPUm7q7DroNGWYG4= +go.uber.org/fx v1.12.0/go.mod h1:egT3Kyg1JFYQkvKLZ3EsykxkNrZxgXS+gKoKo7abERY= go.uber.org/goleak v0.10.0 h1:G3eWbSNIskeRqtsN/1uI5B+eP73y3JUuBsv9AZjehb4= go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= +go.uber.org/goleak v1.0.0 h1:qsup4IcBdlmsnGfqyLl4Ntn3C2XCCuKAE7DwHpScyUo= +go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go4.org v0.0.0-20190218023631-ce4c26f7be8e h1:m9LfARr2VIOW0vsV19kEKp/sWQvZnGobA8JHui/XJoY= -go4.org v0.0.0-20190218023631-ce4c26f7be8e/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= -go4.org v0.0.0-20190313082347-94abd6928b1d h1:JkRdGP3zvTtTbabWSAC6n67ka30y7gOzWAah4XYJSfw= -go4.org v0.0.0-20190313082347-94abd6928b1d/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E= +go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.14.1 h1:nYDKopTbvAPq/NrUVZwT15y2lpROBiLLyoRTbXOYWOo= +go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +go4.org v0.0.0-20200104003542-c7e774b10ea0 h1:M6XsnQeLwG+rHQ+/rrGh3puBI3WZEy9TBWmf2H+enQA= +go4.org v0.0.0-20200104003542-c7e774b10ea0/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25 h1:jsG6UpNLt9iAsb0S2AGW28DveNzzgmbXR+ENoPjUeIU= golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/LemDnOc1GiZL5FCVlORJ5zo= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= +golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d h1:2+ZP7EfsZV7Vvmx3TIqSlSzATMkTAKqM14YGFPoSKjI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw= +golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 h1:Q7tZBpemrlsc2I7IyODzhtallWRSm4Q0d09pL6XbQtU= +golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20180524181706-dfa909b99c79/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/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 h1:C2F/nMkR/9sfUTpvR3QrjBuTdvMUC/cFajkphs1YLQo= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= +golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522135303-fa69b94a3b58 h1:AZ8FNE2w7DVDFDK6u/iC9/Mqh73UupjaqSd/2qMoECQ= -golang.org/x/net v0.0.0-20190522135303-fa69b94a3b58/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 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/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 h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ= 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 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20181107165924-66b7b1311ac8/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-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190302025703-b6889370fb10 h1:xQJI9OEiErEQ++DoXOHqEpzsGMrAv2Q2jyCpi7DmfpQ= golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 h1:f005F/Jl5JLP036x7QIvUVhNTqxvSYwFIiyOh2q12iU= -golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= +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-20190524122548-abf6ff778158/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190524152521-dbbf3f1254d4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/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-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= +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-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY= +golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635 h1:2eB4G6bDQDeP69ZXbOKC00S2Kf6TIiRS+DzfKsKeQU0= +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/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= +golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522 h1:bhOzK9QyoD0ogCnFro1m2mz41+Ib0oOhfJnBp5MR4K4= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg= +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-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191030062658-86caa796c7ab/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191114200427-caa0b0f7d508 h1:0FYNp0PF9kFm/ZUrvcJiQ12IUJJG7iAc6Cu01wbKrbU= +golang.org/x/tools v0.0.0-20191114200427-caa0b0f7d508/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f h1:kDxGY2VmgABOe55qheT/TFqUMtcTHnomIPS1iv3G4Ms= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnfG5kSmgy9KZR9sW3W5QeA= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= +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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/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= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 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 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 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/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 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 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +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.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +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/keystore/keystore.go b/keystore/keystore.go index d9467f263cb..9b2109ccdf2 100644 --- a/keystore/keystore.go +++ b/keystore/keystore.go @@ -7,15 +7,19 @@ import ( "path/filepath" "strings" + base32 "encoding/base32" + logging "github.com/ipfs/go-log" - ci "github.com/libp2p/go-libp2p-crypto" + ci "github.com/libp2p/go-libp2p-core/crypto" ) var log = logging.Logger("keystore") +var codec = base32.StdEncoding.WithPadding(base32.NoPadding) + // Keystore provides a key management interface type Keystore interface { - // Has returns whether or not a key exist in the Keystore + // Has returns whether or not a key exists in the Keystore Has(string) (bool, error) // Put stores a key in the Keystore, if a key with the same name already exists, returns ErrKeyExists Put(string, ci.PrivKey) error @@ -28,87 +32,67 @@ type Keystore interface { List() ([]string, error) } +// ErrNoSuchKey is an error message returned when no key of a given name was found. var ErrNoSuchKey = fmt.Errorf("no key by the given name was found") + +// ErrKeyExists is an error message returned when a key already exists var ErrKeyExists = fmt.Errorf("key by that name already exists, refusing to overwrite") +const keyFilenamePrefix = "key_" + // FSKeystore is a keystore backed by files in a given directory stored on disk. type FSKeystore struct { dir string } -func validateName(name string) error { - if name == "" { - return fmt.Errorf("key names must be at least one character") - } - - if strings.Contains(name, "/") { - return fmt.Errorf("key names may not contain slashes") - } - - if strings.HasPrefix(name, ".") { - return fmt.Errorf("key names may not begin with a period") - } - - return nil -} - +// NewFSKeystore returns a new filesystem-backed keystore. func NewFSKeystore(dir string) (*FSKeystore, error) { - _, err := os.Stat(dir) - if err != nil { - if !os.IsNotExist(err) { - return nil, err - } - if err := os.Mkdir(dir, 0700); err != nil { - return nil, err - } + err := os.Mkdir(dir, 0700) + switch { + case os.IsExist(err): + case err == nil: + default: + return nil, err } - return &FSKeystore{dir}, nil } -// Has returns whether or not a key exist in the Keystore +// Has returns whether or not a key exists in the Keystore func (ks *FSKeystore) Has(name string) (bool, error) { + name, err := encode(name) + if err != nil { + return false, err + } + kp := filepath.Join(ks.dir, name) - _, err := os.Stat(kp) + _, err = os.Stat(kp) if os.IsNotExist(err) { return false, nil } - - if err != nil { - return false, err - } - - if err := validateName(name); err != nil { - return false, err - } - - return true, nil + return err == nil, err } // Put stores a key in the Keystore, if a key with the same name already exists, returns ErrKeyExists func (ks *FSKeystore) Put(name string, k ci.PrivKey) error { - if err := validateName(name); err != nil { + name, err := encode(name) + if err != nil { return err } - b, err := k.Bytes() + b, err := ci.MarshalPrivateKey(k) if err != nil { return err } kp := filepath.Join(ks.dir, name) - _, err = os.Stat(kp) - if err == nil { - return ErrKeyExists - } else if !os.IsNotExist(err) { - return err - } - - fi, err := os.Create(kp) + fi, err := os.OpenFile(kp, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0400) if err != nil { + if os.IsExist(err) { + err = ErrKeyExists + } return err } defer fi.Close() @@ -121,7 +105,8 @@ func (ks *FSKeystore) Put(name string, k ci.PrivKey) error { // Get retrieves a key from the Keystore if it exists, and returns ErrNoSuchKey // otherwise. func (ks *FSKeystore) Get(name string) (ci.PrivKey, error) { - if err := validateName(name); err != nil { + name, err := encode(name) + if err != nil { return nil, err } @@ -140,7 +125,8 @@ func (ks *FSKeystore) Get(name string) (ci.PrivKey, error) { // Delete removes a key from the Keystore func (ks *FSKeystore) Delete(name string) error { - if err := validateName(name); err != nil { + name, err := encode(name) + if err != nil { return err } @@ -164,13 +150,40 @@ func (ks *FSKeystore) List() ([]string, error) { list := make([]string, 0, len(dirs)) for _, name := range dirs { - err := validateName(name) + decodedName, err := decode(name) if err == nil { - list = append(list, name) + list = append(list, decodedName) } else { - log.Warningf("Ignoring the invalid keyfile: %s", name) + log.Errorf("Ignoring keyfile with invalid encoded filename: %s", name) } } return list, nil } + +func encode(name string) (string, error) { + if name == "" { + return "", fmt.Errorf("key name must be at least one character") + } + + encodedName := codec.EncodeToString([]byte(name)) + log.Debugf("Encoded key name: %s to: %s", name, encodedName) + + return keyFilenamePrefix + strings.ToLower(encodedName), nil +} + +func decode(name string) (string, error) { + if !strings.HasPrefix(name, keyFilenamePrefix) { + return "", fmt.Errorf("key's filename has unexpected format") + } + + nameWithoutPrefix := strings.ToUpper(name[len(keyFilenamePrefix):]) + decodedName, err := codec.DecodeString(nameWithoutPrefix) + if err != nil { + return "", err + } + + log.Debugf("Decoded key name: %s to: %s", name, decodedName) + + return string(decodedName), nil +} diff --git a/keystore/keystore_test.go b/keystore/keystore_test.go index d7118d7564b..06f2fccc533 100644 --- a/keystore/keystore_test.go +++ b/keystore/keystore_test.go @@ -9,7 +9,7 @@ import ( "sort" "testing" - ci "github.com/libp2p/go-libp2p-crypto" + ci "github.com/libp2p/go-libp2p-core/crypto" ) type rr struct{} @@ -132,16 +132,16 @@ func TestKeystoreBasics(t *testing.T) { t.Fatal(err) } - if err := ks.Put("..///foo/", k1); err == nil { - t.Fatal("shouldnt be able to put a poorly named key") + if err := ks.Put("..///foo/", k1); err != nil { + t.Fatal(err) } if err := ks.Put("", k1); err == nil { - t.Fatal("shouldnt be able to put a key with no name") + t.Fatal("shouldn't be able to put a key with no name") } - if err := ks.Put(".foo", k1); err == nil { - t.Fatal("shouldnt be able to put a key with a 'hidden' name") + if err := ks.Put(".foo", k1); err != nil { + t.Fatal(err) } } @@ -166,12 +166,17 @@ func TestInvalidKeyFiles(t *testing.T) { t.Fatal(err) } - err = ioutil.WriteFile(filepath.Join(ks.dir, "valid"), bytes, 0644) + encodedName, err := encode("valid") if err != nil { t.Fatal(err) } - err = ioutil.WriteFile(filepath.Join(ks.dir, ".invalid"), bytes, 0644) + err = ioutil.WriteFile(filepath.Join(ks.dir, encodedName), bytes, 0644) + if err != nil { + t.Fatal(err) + } + + err = ioutil.WriteFile(filepath.Join(ks.dir, "z.invalid"), bytes, 0644) if err != nil { t.Fatal(err) } @@ -197,10 +202,6 @@ func TestInvalidKeyFiles(t *testing.T) { if err != nil { t.Fatal(err) } - - if _, err = ks.Has(".invalid"); err == nil { - t.Fatal("shouldnt be able to put a key with a 'hidden' name") - } } func TestNonExistingKey(t *testing.T) { @@ -231,13 +232,13 @@ func TestMakeKeystoreNoDir(t *testing.T) { } func assertGetKey(ks Keystore, name string, exp ci.PrivKey) error { - out_k, err := ks.Get(name) + outK, err := ks.Get(name) if err != nil { return err } - if !out_k.Equals(exp) { - return fmt.Errorf("key we got out didnt match expectation") + if !outK.Equals(exp) { + return fmt.Errorf("key we got out didn't match expectation") } return nil @@ -255,7 +256,11 @@ func assertDirContents(dir string, exp []string) error { var names []string for _, fi := range finfos { - names = append(names, fi.Name()) + decodedName, err := decode(fi.Name()) + if err != nil { + return err + } + names = append(names, decodedName) } sort.Strings(names) diff --git a/keystore/memkeystore.go b/keystore/memkeystore.go index 4f505a995b5..94411144d4c 100644 --- a/keystore/memkeystore.go +++ b/keystore/memkeystore.go @@ -1,6 +1,10 @@ package keystore -import ci "github.com/libp2p/go-libp2p-crypto" +import ( + "errors" + + ci "github.com/libp2p/go-libp2p-core/crypto" +) // MemKeystore is an in memory keystore implementation that is not persisted to // any backing storage. @@ -8,11 +12,12 @@ type MemKeystore struct { keys map[string]ci.PrivKey } +// NewMemKeystore creates a MemKeystore. func NewMemKeystore() *MemKeystore { return &MemKeystore{make(map[string]ci.PrivKey)} } -// Has return whether or not a key exist in the Keystore +// Has return whether or not a key exists in the Keystore func (mk *MemKeystore) Has(name string) (bool, error) { _, ok := mk.keys[name] return ok, nil @@ -20,8 +25,8 @@ func (mk *MemKeystore) Has(name string) (bool, error) { // Put store a key in the Keystore func (mk *MemKeystore) Put(name string, k ci.PrivKey) error { - if err := validateName(name); err != nil { - return err + if name == "" { + return errors.New("key name must be at least one character") } _, ok := mk.keys[name] @@ -35,10 +40,6 @@ func (mk *MemKeystore) Put(name string, k ci.PrivKey) error { // Get retrieve a key from the Keystore func (mk *MemKeystore) Get(name string) (ci.PrivKey, error) { - if err := validateName(name); err != nil { - return nil, err - } - k, ok := mk.keys[name] if !ok { return nil, ErrNoSuchKey @@ -49,10 +50,6 @@ func (mk *MemKeystore) Get(name string) (ci.PrivKey, error) { // Delete remove a key from the Keystore func (mk *MemKeystore) Delete(name string) error { - if err := validateName(name); err != nil { - return err - } - delete(mk.keys, name) return nil } diff --git a/keystore/memkeystore_test.go b/keystore/memkeystore_test.go index 62533d54b92..907cbbd0e7e 100644 --- a/keystore/memkeystore_test.go +++ b/keystore/memkeystore_test.go @@ -85,15 +85,15 @@ func TestMemKeyStoreBasics(t *testing.T) { t.Fatal(err) } - if err := ks.Put("..///foo/", k1); err == nil { - t.Fatal("shouldnt be able to put a poorly named key") + if err := ks.Put("..///foo/", k1); err != nil { + t.Fatal(err) } if err := ks.Put("", k1); err == nil { - t.Fatal("shouldnt be able to put a key with no name") + t.Fatal("shouldn't be able to put a key with no name") } - if err := ks.Put(".foo", k1); err == nil { - t.Fatal("shouldnt be able to put a key with a 'hidden' name") + if err := ks.Put(".foo", k1); err != nil { + t.Fatal(err) } } diff --git a/misc/completion/ipfs-completion.bash b/misc/completion/ipfs-completion.bash index c1487cb34bc..7bb1a02327a 100644 --- a/misc/completion/ipfs-completion.bash +++ b/misc/completion/ipfs-completion.bash @@ -19,7 +19,7 @@ _ipfs_add() elif [ "${prev}" == "--pin" ] ; then _ipfs_comp "true false" elif [[ ${word} == -* ]] ; then - _ipfs_comp "--recursive --quiet --silent --progress --trickle --only-hash --wrap-with-directory --hidden --chunker= --pin= --raw-leaves --help " + _ipfs_comp "--recursive --dereference-args --stdin-name= --hidden --ignore= --ignore-rules-path= --quiet --quieter --silent --progress --trickle --only-hash --wrap-with-directory --chunker= --pin= --raw-leaves --nocopy --fscache --cid-version= --hash= --inline --inline-limit= --help " else _ipfs_filesystem_complete fi @@ -172,9 +172,9 @@ _ipfs_dag_get() _ipfs_dag_put() { if [[ ${prev} == "--format" ]] ; then - _ipfs_comp "cbor placeholder1" # TODO: a) Which format more then cbor is valid? b) Solve autocomplete bug for "=" + _ipfs_comp "cbor placeholder1" # TODO: a) Which format more than cbor is valid? b) Solve autocomplete bug for "=" elif [[ ${prev} == "--input-enc" ]] ; then - _ipfs_comp "json placeholder1" # TODO: a) Which format more then json is valid? b) Solve autocomplete bug for "=" + _ipfs_comp "json placeholder1" # TODO: a) Which format more than json is valid? b) Solve autocomplete bug for "=" elif [[ ${word} == -* ]] ; then _ipfs_comp "--format= --input-enc= --help" else @@ -227,7 +227,7 @@ _ipfs_diag_cmds() if [[ ${prev} == "clear" ]] ; then return 0 elif [[ ${prev} =~ ^-?[0-9]+$ ]] ; then - _ipfs_comp "ns us µs ms s m h" # TODO: Trigger with out space, eg. "ipfs diag set-time 10ns" not "... set-time 10 ns" + _ipfs_comp "ns us µs ms s m h" # TODO: Trigger without space, eg. "ipfs diag set-time 10ns" not "... set-time 10 ns" elif [[ ${prev} == "set-time" ]] ; then _ipfs_help_only elif [[ ${word} == -* ]] ; then diff --git a/misc/systemd/ipfs-api.socket b/misc/systemd/ipfs-api.socket new file mode 100644 index 00000000000..10dbd675794 --- /dev/null +++ b/misc/systemd/ipfs-api.socket @@ -0,0 +1,15 @@ +# Enabling this will *completely override* any API listeners configured in your +# config. + +[Unit] +Description=IPFS API Socket + +[Socket] +Service=ipfs.service +FileDescriptorName=io.ipfs.api +BindIPv6Only=true +ListenStream=127.0.0.1:5001 +ListenStream=[::1]:5001 + +[Install] +WantedBy=sockets.target diff --git a/misc/systemd/ipfs-gateway.socket b/misc/systemd/ipfs-gateway.socket new file mode 100644 index 00000000000..5e20bd83a1f --- /dev/null +++ b/misc/systemd/ipfs-gateway.socket @@ -0,0 +1,15 @@ +# Enabling this will *completely override* any Gateway listeners configured in +# your config. + +[Unit] +Description=IPFS Gateway Socket + +[Socket] +Service=ipfs.service +FileDescriptorName=io.ipfs.gateway +BindIPv6Only=true +ListenStream=127.0.0.1:8080 +ListenStream=[::1]:8080 + +[Install] +WantedBy=sockets.target diff --git a/misc/systemd/ipfs.service b/misc/systemd/ipfs.service new file mode 100644 index 00000000000..0ee585ac693 --- /dev/null +++ b/misc/systemd/ipfs.service @@ -0,0 +1,10 @@ +[Unit] +Description=IPFS Daemon + +[Service] +Type=notify +ExecStart=/usr/bin/ipfs daemon --init --migrate +KillSignal=SIGINT + +[Install] +WantedBy=default.target diff --git a/mk/golang.mk b/mk/golang.mk index d8aefa0dff8..5634c1d6b5f 100644 --- a/mk/golang.mk +++ b/mk/golang.mk @@ -1,5 +1,5 @@ # golang utilities -GO_MIN_VERSION = 1.12 +GO_MIN_VERSION = 1.13.8 export GO111MODULE=on @@ -10,6 +10,9 @@ unexport GOFLAGS GOFLAGS ?= GOTFLAGS ?= +# Try to make building as reproducible as possible by stripping the go path. +GOFLAGS += "-asmflags=all='-trimpath=$(GOPATH)'" "-gcflags=all='-trimpath=$(GOPATH)'" + ifeq ($(tarball-is),1) GOFLAGS += -mod=vendor endif diff --git a/mk/util.mk b/mk/util.mk index fa6eae8e443..48e5fa72ae3 100644 --- a/mk/util.mk +++ b/mk/util.mk @@ -20,17 +20,24 @@ SUPPORTED_PLATFORMS += linux-amd64 SUPPORTED_PLATFORMS += darwin-386 SUPPORTED_PLATFORMS += darwin-amd64 +SUPPORTED_PLATFORMS += freebsd-386 SUPPORTED_PLATFORMS += freebsd-amd64 +SUPPORTED_PLATFORMS += openbsd-386 +SUPPORTED_PLATFORMS += openbsd-amd64 + +SUPPORTED_PLATFORMS += netbsd-386 +SUPPORTED_PLATFORMS += netbsd-amd64 + space:= space+= comma:=, join-with=$(subst $(space),$1,$(strip $2)) -# debug target, prints varaible. Example: `make print-GOFLAGS` +# debug target, prints variable. Example: `make print-GOFLAGS` print-%: @echo $*=$($*) -# phony target that will mean that recipe is always exectued +# phony target that will mean that recipe is always executed ALWAYS: .PHONY: ALWAYS diff --git a/namesys/cache.go b/namesys/cache.go index 4a5cb5113ae..b2b1f43a8d8 100644 --- a/namesys/cache.go +++ b/namesys/cache.go @@ -7,6 +7,14 @@ import ( ) func (ns *mpns) cacheGet(name string) (path.Path, bool) { + // existence of optional mapping defined via IPFS_NS_MAP is checked first + if ns.staticMap != nil { + val, ok := ns.staticMap[name] + if ok { + return val, true + } + } + if ns.cache == nil { return "", false } @@ -41,6 +49,13 @@ func (ns *mpns) cacheSet(name string, val path.Path, ttl time.Duration) { }) } +func (ns *mpns) cacheInvalidate(name string) { + if ns.cache == nil { + return + } + ns.cache.Remove(name) +} + type cacheEntry struct { val path.Path eol time.Time diff --git a/namesys/dns.go b/namesys/dns.go index 931edec0019..984a27aa80c 100644 --- a/namesys/dns.go +++ b/namesys/dns.go @@ -11,6 +11,9 @@ import ( isd "github.com/jbenet/go-is-domain" ) +const ethTLD = "eth" +const linkTLD = "link" + type LookupTXTFunc func(name string) (txt []string, err error) // DNSResolver implements a Resolver on DNS domains @@ -62,6 +65,12 @@ func (r *DNSResolver) resolveOnceAsync(ctx context.Context, name string, options fqdn = domain + "." } + if strings.HasSuffix(fqdn, "."+ethTLD+".") { + // This is an ENS name. As we're resolving via an arbitrary DNS server + // that may not know about .eth we need to add our link domain suffix. + fqdn += linkTLD + "." + } + rootChan := make(chan lookupRes, 1) go workDomain(r, fqdn, rootChan) diff --git a/namesys/dns_test.go b/namesys/dns_test.go index 8d53887be5c..653c3c7887f 100644 --- a/namesys/dns_test.go +++ b/namesys/dns_test.go @@ -126,6 +126,9 @@ func newMockDNS() *mockDNS { "fqdn.example.com.": []string{ "dnslink=/ipfs/QmYvMB9yrsSf7RKBghkfwmHJkzJhW2ZgVwq3LxBXXPasFr", }, + "www.wealdtech.eth.link.": []string{ + "dnslink=/ipns/ipfs.example.com", + }, }, } } @@ -163,4 +166,7 @@ func TestDNSResolution(t *testing.T) { testResolution(t, r, "double.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil) testResolution(t, r, "conflict.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjE", nil) testResolution(t, r, "fqdn.example.com.", opts.DefaultDepthLimit, "/ipfs/QmYvMB9yrsSf7RKBghkfwmHJkzJhW2ZgVwq3LxBXXPasFr", nil) + testResolution(t, r, "www.wealdtech.eth", 1, "/ipns/ipfs.example.com", ErrResolveRecursion) + testResolution(t, r, "www.wealdtech.eth", 2, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil) + testResolution(t, r, "www.wealdtech.eth.link", 2, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil) } diff --git a/namesys/interface.go b/namesys/interface.go index 4db95ab3ca1..ecd80943be8 100644 --- a/namesys/interface.go +++ b/namesys/interface.go @@ -37,7 +37,7 @@ import ( path "github.com/ipfs/go-path" opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" - ci "github.com/libp2p/go-libp2p-crypto" + ci "github.com/libp2p/go-libp2p-core/crypto" ) // ErrResolveFailed signals an error when attempting to resolve. diff --git a/namesys/ipns_resolver_validation_test.go b/namesys/ipns_resolver_validation_test.go index 71335b52239..1fd7488b9ed 100644 --- a/namesys/ipns_resolver_validation_test.go +++ b/namesys/ipns_resolver_validation_test.go @@ -9,18 +9,17 @@ import ( dssync "github.com/ipfs/go-datastore/sync" mockrouting "github.com/ipfs/go-ipfs-routing/mock" offline "github.com/ipfs/go-ipfs-routing/offline" - u "github.com/ipfs/go-ipfs-util" ipns "github.com/ipfs/go-ipns" path "github.com/ipfs/go-path" opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" + routing "github.com/libp2p/go-libp2p-core/routing" + "github.com/libp2p/go-libp2p-core/test" pstoremem "github.com/libp2p/go-libp2p-peerstore/pstoremem" record "github.com/libp2p/go-libp2p-record" - routing "github.com/libp2p/go-libp2p-routing" - ropts "github.com/libp2p/go-libp2p-routing/options" - testutil "github.com/libp2p/go-testutil" + testutil "github.com/libp2p/go-libp2p-testing/net" ) func TestResolverValidation(t *testing.T) { @@ -138,19 +137,15 @@ func TestResolverValidation(t *testing.T) { } func genKeys(t *testing.T) (ci.PrivKey, peer.ID, string, string) { - sr := u.NewTimeSeededRand() - priv, _, err := ci.GenerateKeyPairWithReader(ci.RSA, 1024, sr) + sk, pk, err := test.RandTestKeyPair(ci.RSA, 2048) if err != nil { t.Fatal(err) } - - // Create entry with expiry in one hour - pid, err := peer.IDFromPrivateKey(priv) + id, err := peer.IDFromPublicKey(pk) if err != nil { t.Fatal(err) } - - return priv, pid, PkKeyForID(pid), ipns.RecordKey(pid) + return sk, id, PkKeyForID(id), ipns.RecordKey(id) } type mockValueStore struct { @@ -168,11 +163,11 @@ func newMockValueStore(id testutil.Identity, dstore ds.Datastore, kbook pstore.K } } -func (m *mockValueStore) GetValue(ctx context.Context, k string, opts ...ropts.Option) ([]byte, error) { +func (m *mockValueStore) GetValue(ctx context.Context, k string, opts ...routing.Option) ([]byte, error) { return m.r.GetValue(ctx, k, opts...) } -func (m *mockValueStore) SearchValue(ctx context.Context, k string, opts ...ropts.Option) (<-chan []byte, error) { +func (m *mockValueStore) SearchValue(ctx context.Context, k string, opts ...routing.Option) (<-chan []byte, error) { return m.r.SearchValue(ctx, k, opts...) } @@ -196,6 +191,6 @@ func (m *mockValueStore) GetPublicKey(ctx context.Context, p peer.ID) (ci.PubKey return pk, m.kbook.AddPubKey(p, pk) } -func (m *mockValueStore) PutValue(ctx context.Context, k string, d []byte, opts ...ropts.Option) error { +func (m *mockValueStore) PutValue(ctx context.Context, k string, d []byte, opts ...routing.Option) error { return m.r.PutValue(ctx, k, d, opts...) } diff --git a/namesys/namesys.go b/namesys/namesys.go index 31b54153874..933ce789db6 100644 --- a/namesys/namesys.go +++ b/namesys/namesys.go @@ -2,18 +2,20 @@ package namesys import ( "context" + "fmt" + "os" "strings" "time" lru "github.com/hashicorp/golang-lru" + cid "github.com/ipfs/go-cid" ds "github.com/ipfs/go-datastore" path "github.com/ipfs/go-path" opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" isd "github.com/jbenet/go-is-domain" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" - routing "github.com/libp2p/go-libp2p-routing" - mh "github.com/multiformats/go-multihash" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" + routing "github.com/libp2p/go-libp2p-core/routing" ) // mpns (a multi-protocol NameSystem) implements generic IPFS naming. @@ -29,25 +31,45 @@ type mpns struct { dnsResolver, proquintResolver, ipnsResolver resolver ipnsPublisher Publisher - cache *lru.Cache + staticMap map[string]path.Path + cache *lru.Cache } // NewNameSystem will construct the IPFS naming system based on Routing func NewNameSystem(r routing.ValueStore, ds ds.Datastore, cachesize int) NameSystem { - var cache *lru.Cache + var ( + cache *lru.Cache + staticMap map[string]path.Path + ) if cachesize > 0 { cache, _ = lru.New(cachesize) } + // Prewarm namesys cache with static records for deterministic tests and debugging. + // Useful for testing things like DNSLink without real DNS lookup. + // Example: + // IPFS_NS_MAP="dnslink-test.example.com:/ipfs/bafkreicysg23kiwv34eg2d7qweipxwosdo2py4ldv42nbauguluen5v6am" + if list := os.Getenv("IPFS_NS_MAP"); list != "" { + staticMap = make(map[string]path.Path) + for _, pair := range strings.Split(list, ",") { + mapping := strings.SplitN(pair, ":", 2) + key := mapping[0] + value := path.FromString(mapping[1]) + staticMap[key] = value + } + } + return &mpns{ dnsResolver: NewDNSResolver(), proquintResolver: new(ProquintResolver), ipnsResolver: NewIpnsResolver(r), ipnsPublisher: NewIpnsPublisher(r, ds), + staticMap: staticMap, cache: cache, } } +// DefaultResolverCacheTTL defines max ttl of a record placed in namesys cache. const DefaultResolverCacheTTL = time.Minute // Resolve implements Resolver. @@ -112,12 +134,28 @@ func (ns *mpns) resolveOnceAsync(ctx context.Context, name string, options opts. } // Resolver selection: - // 1. if it is a multihash resolve through "ipns". + // 1. if it is a PeerID/CID/multihash resolve through "ipns". // 2. if it is a domain name, resolve through "dns" // 3. otherwise resolve through the "proquint" resolver var res resolver - if _, err := mh.FromB58String(key); err == nil { + _, err := peer.Decode(key) + + // CIDs in IPNS are expected to have libp2p-key multicodec + // We ease the transition by returning a more meaningful error with a valid CID + if err != nil && err.Error() == "can't convert CID of type protobuf to a peer ID" { + ipnsCid, cidErr := cid.Decode(key) + if cidErr == nil && ipnsCid.Version() == 1 && ipnsCid.Type() != cid.Libp2pKey { + fixedCid := cid.NewCidV1(cid.Libp2pKey, ipnsCid.Hash()).String() + codecErr := fmt.Errorf("peer ID represented as CIDv1 require libp2p-key multicodec: retry with /ipns/%s", fixedCid) + log.Debugf("RoutingResolver: could not convert public key hash %s to peer ID: %s\n", key, codecErr) + out <- onceResult{err: codecErr} + close(out) + return out + } + } + + if err == nil { res = ns.ipnsResolver } else if isd.IsDomain(key) { res = ns.dnsResolver @@ -180,6 +218,9 @@ func (ns *mpns) PublishWithEOL(ctx context.Context, name ci.PrivKey, value path. return err } if err := ns.ipnsPublisher.PublishWithEOL(ctx, name, value, eol); err != nil { + // Invalidate the cache. Publishing may _partially_ succeed but + // still return an error. + ns.cacheInvalidate(peer.Encode(id)) return err } ttl := DefaultResolverCacheTTL @@ -189,6 +230,6 @@ func (ns *mpns) PublishWithEOL(ctx context.Context, name ci.PrivKey, value path. if ttEol := time.Until(eol); ttEol < ttl { ttl = ttEol } - ns.cacheSet(peer.IDB58Encode(id), value, ttl) + ns.cacheSet(peer.Encode(id), value, ttl) return nil } diff --git a/namesys/namesys_test.go b/namesys/namesys_test.go index 2cf316cf32c..b3e963c9e9e 100644 --- a/namesys/namesys_test.go +++ b/namesys/namesys_test.go @@ -4,16 +4,17 @@ import ( "context" "fmt" "testing" + "time" ds "github.com/ipfs/go-datastore" dssync "github.com/ipfs/go-datastore/sync" offroute "github.com/ipfs/go-ipfs-routing/offline" ipns "github.com/ipfs/go-ipns" path "github.com/ipfs/go-path" - "github.com/ipfs/go-unixfs" + unixfs "github.com/ipfs/go-unixfs" opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" pstoremem "github.com/libp2p/go-libp2p-peerstore/pstoremem" record "github.com/libp2p/go-libp2p-record" ) @@ -48,9 +49,12 @@ func (r *mockResolver) resolveOnceAsync(ctx context.Context, name string, option func mockResolverOne() *mockResolver { return &mockResolver{ entries: map[string]string{ - "QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy": "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", - "QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n": "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", - "QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD": "/ipns/ipfs.io", + "QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy": "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", + "QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n": "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", + "QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD": "/ipns/ipfs.io", + "QmQ4QZh8nrsczdUEwTyfBope4THUhqxqc1fx6qYhhzZQei": "/ipfs/QmP3ouCnU8NNLsW6261pAx2pNLV2E4dQoisB1sgda12Act", + "12D3KooWFB51PRY9BxcXSH6khFXw1BZeszeLDy7C8GciskqCTZn5": "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", // ed25519+identity multihash + "bafzbeickencdqw37dpz3ha36ewrh4undfjt2do52chtcky4rxkj447qhdm": "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", // cidv1 in base32 with libp2p-key multicodec }, } } @@ -80,11 +84,13 @@ func TestNamesysResolution(t *testing.T) { testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", 1, "/ipns/ipfs.io", ErrResolveRecursion) testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", 2, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", ErrResolveRecursion) testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", 3, "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", ErrResolveRecursion) + testResolution(t, r, "/ipns/12D3KooWFB51PRY9BxcXSH6khFXw1BZeszeLDy7C8GciskqCTZn5", 1, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", ErrResolveRecursion) + testResolution(t, r, "/ipns/bafzbeickencdqw37dpz3ha36ewrh4undfjt2do52chtcky4rxkj447qhdm", 1, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", ErrResolveRecursion) } func TestPublishWithCache0(t *testing.T) { dst := dssync.MutexWrap(ds.NewMapDatastore()) - priv, _, err := ci.GenerateKeyPair(ci.RSA, 1024) + priv, _, err := ci.GenerateKeyPair(ci.RSA, 2048) if err != nil { t.Fatal(err) } @@ -113,3 +119,51 @@ func TestPublishWithCache0(t *testing.T) { t.Fatal(err) } } + +func TestPublishWithTTL(t *testing.T) { + dst := dssync.MutexWrap(ds.NewMapDatastore()) + priv, _, err := ci.GenerateKeyPair(ci.RSA, 2048) + if err != nil { + t.Fatal(err) + } + ps := pstoremem.NewPeerstore() + pid, err := peer.IDFromPrivateKey(priv) + if err != nil { + t.Fatal(err) + } + err = ps.AddPrivKey(pid, priv) + if err != nil { + t.Fatal(err) + } + + routing := offroute.NewOfflineRouter(dst, record.NamespacedValidator{ + "ipns": ipns.Validator{KeyBook: ps}, + "pk": record.PublicKeyValidator{}, + }) + + nsys := NewNameSystem(routing, dst, 128) + p, err := path.ParsePath(unixfs.EmptyDirNode().Cid().String()) + if err != nil { + t.Fatal(err) + } + + ttl := 1 * time.Second + eol := time.Now().Add(2 * time.Second) + + ctx := context.WithValue(context.Background(), "ipns-publish-ttl", ttl) + err = nsys.Publish(ctx, priv, p) + if err != nil { + t.Fatal(err) + } + ientry, ok := nsys.(*mpns).cache.Get(pid.Pretty()) + if !ok { + t.Fatal("cache get failed") + } + entry, ok := ientry.(cacheEntry) + if !ok { + t.Fatal("bad cache item returned") + } + if entry.eol.Sub(eol) > 10*time.Millisecond { + t.Fatalf("bad cache ttl: expected %s, got %s", eol, entry.eol) + } +} diff --git a/namesys/publisher.go b/namesys/publisher.go index e43858d02f6..1fa0c96c9c4 100644 --- a/namesys/publisher.go +++ b/namesys/publisher.go @@ -6,18 +6,17 @@ import ( "sync" "time" - pin "github.com/ipfs/go-ipfs/pin" - proto "github.com/gogo/protobuf/proto" ds "github.com/ipfs/go-datastore" dsquery "github.com/ipfs/go-datastore/query" + pin "github.com/ipfs/go-ipfs-pinner" ipns "github.com/ipfs/go-ipns" pb "github.com/ipfs/go-ipns/pb" path "github.com/ipfs/go-path" ft "github.com/ipfs/go-unixfs" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" - routing "github.com/libp2p/go-libp2p-routing" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" + routing "github.com/libp2p/go-libp2p-core/routing" base32 "github.com/whyrusleeping/base32" ) @@ -180,7 +179,11 @@ func (p *IpnsPublisher) updateRecord(ctx context.Context, k ci.PrivKey, value pa } // Put the new record. - if err := p.ds.Put(IpnsDsKey(id), data); err != nil { + key := IpnsDsKey(id) + if err := p.ds.Put(key, data); err != nil { + return nil, err + } + if err := p.ds.Sync(key); err != nil { return nil, err } return entry, nil @@ -298,7 +301,7 @@ func InitializeKeyspace(ctx context.Context, pub Publisher, pins pin.Pinner, key return err } - err = pins.Flush() + err = pins.Flush(ctx) if err != nil { return err } diff --git a/namesys/publisher_test.go b/namesys/publisher_test.go index 53cc6735eee..62510338353 100644 --- a/namesys/publisher_test.go +++ b/namesys/publisher_test.go @@ -3,6 +3,7 @@ package namesys import ( "context" "crypto/rand" + "github.com/ipfs/go-path" "testing" "time" @@ -11,9 +12,9 @@ import ( dshelp "github.com/ipfs/go-ipfs-ds-help" mockrouting "github.com/ipfs/go-ipfs-routing/mock" ipns "github.com/ipfs/go-ipns" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" - testutil "github.com/libp2p/go-testutil" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" + testutil "github.com/libp2p/go-libp2p-testing/net" ma "github.com/multiformats/go-multiaddr" ) @@ -110,3 +111,45 @@ func TestRSAPublisher(t *testing.T) { func TestEd22519Publisher(t *testing.T) { testNamekeyPublisher(t, ci.Ed25519, ds.ErrNotFound, false) } + +func TestAsyncDS(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + rt := mockrouting.NewServer().Client(testutil.RandIdentityOrFatal(t)) + ds := &checkSyncDS{ + Datastore: ds.NewMapDatastore(), + syncKeys: make(map[ds.Key]struct{}), + } + publisher := NewIpnsPublisher(rt, ds) + + ipnsFakeID := testutil.RandIdentityOrFatal(t) + ipnsVal, err := path.ParsePath("/ipns/foo.bar") + if err != nil { + t.Fatal(err) + } + + if err := publisher.Publish(ctx, ipnsFakeID.PrivateKey(), ipnsVal); err != nil { + t.Fatal(err) + } + + ipnsKey := IpnsDsKey(ipnsFakeID.ID()) + + for k := range ds.syncKeys { + if k.IsAncestorOf(ipnsKey) || k.Equal(ipnsKey) { + return + } + } + + t.Fatal("ipns key not synced") +} + +type checkSyncDS struct { + ds.Datastore + syncKeys map[ds.Key]struct{} +} + +func (d *checkSyncDS) Sync(prefix ds.Key) error { + d.syncKeys[prefix] = struct{}{} + return d.Datastore.Sync(prefix) +} diff --git a/namesys/republisher/repub.go b/namesys/republisher/repub.go index 1092ba3a57c..9e7272d32e0 100644 --- a/namesys/republisher/repub.go +++ b/namesys/republisher/repub.go @@ -15,8 +15,8 @@ import ( logging "github.com/ipfs/go-log" goprocess "github.com/jbenet/goprocess" gpctx "github.com/jbenet/goprocess/context" - ic "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" + ic "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" ) var errNoEntry = errors.New("no previous entry") diff --git a/namesys/republisher/repub_test.go b/namesys/republisher/repub_test.go index 48a0b086f0c..470d460ba20 100644 --- a/namesys/republisher/repub_test.go +++ b/namesys/republisher/repub_test.go @@ -14,7 +14,7 @@ import ( path "github.com/ipfs/go-path" goprocess "github.com/jbenet/goprocess" - pstore "github.com/libp2p/go-libp2p-peerstore" + peer "github.com/libp2p/go-libp2p-core/peer" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" ) @@ -29,10 +29,7 @@ func TestRepublish(t *testing.T) { var nodes []*core.IpfsNode for i := 0; i < 10; i++ { - nd, err := core.NewNode(ctx, &core.BuildCfg{ - Online: true, - Host: mock.MockHostOption(mn), - }) + nd, err := mock.MockPublicNode(ctx, mn) if err != nil { t.Fatal(err) } @@ -47,7 +44,7 @@ func TestRepublish(t *testing.T) { } bsinf := bootstrap.BootstrapConfigWithPeers( - []pstore.PeerInfo{ + []peer.AddrInfo{ nodes[0].Peerstore.PeerInfo(nodes[0].Identity), }, ) @@ -95,7 +92,7 @@ func TestRepublish(t *testing.T) { // The republishers that are contained within the nodes have their timeout set // to 12 hours. Instead of trying to tweak those, we're just going to pretend - // they dont exist and make our own. + // they don't exist and make our own. repub := NewRepublisher(rp, publisher.Repo.Datastore(), publisher.PrivateKey, publisher.Repo.Keystore()) repub.Interval = time.Second repub.RecordLifetime = time.Second * 5 diff --git a/namesys/resolve/pathresolver_test.go b/namesys/resolve/pathresolver_test.go deleted file mode 100644 index 3d9c04fa2f1..00000000000 --- a/namesys/resolve/pathresolver_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package resolve_test - -import ( - "testing" - - coremock "github.com/ipfs/go-ipfs/core/mock" - "github.com/ipfs/go-ipfs/namesys/resolve" - - path "github.com/ipfs/go-path" -) - -func TestResolveNoComponents(t *testing.T) { - n, err := coremock.NewMockNode() - if n == nil || err != nil { - t.Fatal("Should have constructed a mock node", err) - } - - _, err = resolve.Resolve(n.Context(), n.Namesys, n.Resolver, path.Path("/ipns/")) - if err.Error() != "invalid path \"/ipns/\": ipns path missing IPNS ID" { - t.Error("Should error with no components (/ipns/).", err) - } - - _, err = resolve.Resolve(n.Context(), n.Namesys, n.Resolver, path.Path("/ipfs/")) - if err.Error() != "invalid path \"/ipfs/\": not enough path components" { - t.Error("Should error with no components (/ipfs/).", err) - } - - _, err = resolve.Resolve(n.Context(), n.Namesys, n.Resolver, path.Path("/../..")) - if err.Error() != "invalid path \"/../..\": unknown namespace \"..\"" { - t.Error("Should error with invalid path.", err) - } -} diff --git a/namesys/resolve/resolve.go b/namesys/resolve/resolve.go index 44f735a1f49..f838a6611f7 100644 --- a/namesys/resolve/resolve.go +++ b/namesys/resolve/resolve.go @@ -6,16 +6,11 @@ import ( "fmt" "strings" - "github.com/ipfs/go-ipld-format" - logging "github.com/ipfs/go-log" "github.com/ipfs/go-path" - "github.com/ipfs/go-path/resolver" "github.com/ipfs/go-ipfs/namesys" ) -var log = logging.Logger("nsresolv") - // ErrNoNamesys is an explicit error for when an IPFS node doesn't // (yet) have a name system var ErrNoNamesys = errors.New( @@ -24,13 +19,8 @@ var ErrNoNamesys = errors.New( // ResolveIPNS resolves /ipns paths func ResolveIPNS(ctx context.Context, nsys namesys.NameSystem, p path.Path) (path.Path, error) { if strings.HasPrefix(p.String(), "/ipns/") { - evt := log.EventBegin(ctx, "resolveIpnsPath") - defer evt.Done() - // resolve ipns paths - // TODO(cryptix): we should be able to query the local cache for the path if nsys == nil { - evt.Append(logging.LoggableMap{"error": ErrNoNamesys.Error()}) return "", ErrNoNamesys } @@ -38,42 +28,25 @@ func ResolveIPNS(ctx context.Context, nsys namesys.NameSystem, p path.Path) (pat if len(seg) < 2 || seg[1] == "" { // just "/" without further segments err := fmt.Errorf("invalid path %q: ipns path missing IPNS ID", p) - evt.Append(logging.LoggableMap{"error": err}) return "", err } extensions := seg[2:] resolvable, err := path.FromSegments("/", seg[0], seg[1]) if err != nil { - evt.Append(logging.LoggableMap{"error": err.Error()}) return "", err } respath, err := nsys.Resolve(ctx, resolvable.String()) if err != nil { - evt.Append(logging.LoggableMap{"error": err.Error()}) return "", err } segments := append(respath.Segments(), extensions...) p, err = path.FromSegments("/", segments...) if err != nil { - evt.Append(logging.LoggableMap{"error": err.Error()}) return "", err } } return p, nil } - -// Resolve resolves the given path by parsing out protocol-specific -// entries (e.g. /ipns/) and then going through the /ipfs/ -// entries and returning the final node. -func Resolve(ctx context.Context, nsys namesys.NameSystem, r *resolver.Resolver, p path.Path) (format.Node, error) { - p, err := ResolveIPNS(ctx, nsys, p) - if err != nil { - return nil, err - } - - // ok, we have an IPFS path now (or what we'll treat as one) - return r.ResolvePath(ctx, p) -} diff --git a/namesys/resolve_test.go b/namesys/resolve_test.go index 88206144868..4f92a2d0d0e 100644 --- a/namesys/resolve_test.go +++ b/namesys/resolve_test.go @@ -11,8 +11,8 @@ import ( mockrouting "github.com/ipfs/go-ipfs-routing/mock" ipns "github.com/ipfs/go-ipns" path "github.com/ipfs/go-path" - peer "github.com/libp2p/go-libp2p-peer" - testutil "github.com/libp2p/go-testutil" + testutil "github.com/libp2p/go-libp2p-testing/net" + tnet "github.com/libp2p/go-libp2p-testing/net" ) func TestRoutingResolve(t *testing.T) { @@ -24,23 +24,15 @@ func TestRoutingResolve(t *testing.T) { resolver := NewIpnsResolver(d) publisher := NewIpnsPublisher(d, dstore) - privk, pubk, err := testutil.RandTestKeyPair(512) - if err != nil { - t.Fatal(err) - } + identity := tnet.RandIdentityOrFatal(t) h := path.FromString("/ipfs/QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN") - err = publisher.Publish(context.Background(), privk, h) + err := publisher.Publish(context.Background(), identity.PrivateKey(), h) if err != nil { t.Fatal(err) } - pid, err := peer.IDFromPublicKey(pubk) - if err != nil { - t.Fatal(err) - } - - res, err := resolver.Resolve(context.Background(), pid.Pretty()) + res, err := resolver.Resolve(context.Background(), identity.ID().Pretty()) if err != nil { t.Fatal(err) } @@ -57,36 +49,28 @@ func TestPrexistingExpiredRecord(t *testing.T) { resolver := NewIpnsResolver(d) publisher := NewIpnsPublisher(d, dstore) - privk, pubk, err := testutil.RandTestKeyPair(512) - if err != nil { - t.Fatal(err) - } - - id, err := peer.IDFromPublicKey(pubk) - if err != nil { - t.Fatal(err) - } + identity := tnet.RandIdentityOrFatal(t) // Make an expired record and put it in the datastore h := path.FromString("/ipfs/QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN") eol := time.Now().Add(time.Hour * -1) - entry, err := ipns.Create(privk, []byte(h), 0, eol) + entry, err := ipns.Create(identity.PrivateKey(), []byte(h), 0, eol) if err != nil { t.Fatal(err) } - err = PutRecordToRouting(context.Background(), d, pubk, entry) + err = PutRecordToRouting(context.Background(), d, identity.PublicKey(), entry) if err != nil { t.Fatal(err) } // Now, with an old record in the system already, try and publish a new one - err = publisher.Publish(context.Background(), privk, h) + err = publisher.Publish(context.Background(), identity.PrivateKey(), h) if err != nil { t.Fatal(err) } - err = verifyCanResolve(resolver, id.Pretty(), h) + err = verifyCanResolve(resolver, identity.ID().Pretty(), h) if err != nil { t.Fatal(err) } @@ -99,35 +83,27 @@ func TestPrexistingRecord(t *testing.T) { resolver := NewIpnsResolver(d) publisher := NewIpnsPublisher(d, dstore) - privk, pubk, err := testutil.RandTestKeyPair(512) - if err != nil { - t.Fatal(err) - } - - id, err := peer.IDFromPublicKey(pubk) - if err != nil { - t.Fatal(err) - } + identity := tnet.RandIdentityOrFatal(t) // Make a good record and put it in the datastore h := path.FromString("/ipfs/QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN") eol := time.Now().Add(time.Hour) - entry, err := ipns.Create(privk, []byte(h), 0, eol) + entry, err := ipns.Create(identity.PrivateKey(), []byte(h), 0, eol) if err != nil { t.Fatal(err) } - err = PutRecordToRouting(context.Background(), d, pubk, entry) + err = PutRecordToRouting(context.Background(), d, identity.PublicKey(), entry) if err != nil { t.Fatal(err) } // Now, with an old record in the system already, try and publish a new one - err = publisher.Publish(context.Background(), privk, h) + err = publisher.Publish(context.Background(), identity.PrivateKey(), h) if err != nil { t.Fatal(err) } - err = verifyCanResolve(resolver, id.Pretty(), h) + err = verifyCanResolve(resolver, identity.ID().Pretty(), h) if err != nil { t.Fatal(err) } diff --git a/namesys/routing.go b/namesys/routing.go index e89dd9c9d4f..60928fbca69 100644 --- a/namesys/routing.go +++ b/namesys/routing.go @@ -12,9 +12,9 @@ import ( logging "github.com/ipfs/go-log" path "github.com/ipfs/go-path" opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" + peer "github.com/libp2p/go-libp2p-core/peer" + routing "github.com/libp2p/go-libp2p-core/routing" dht "github.com/libp2p/go-libp2p-kad-dht" - peer "github.com/libp2p/go-libp2p-peer" - routing "github.com/libp2p/go-libp2p-routing" mh "github.com/multiformats/go-multihash" ) @@ -59,7 +59,8 @@ func (r *IpnsResolver) resolveOnceAsync(ctx context.Context, name string, option } name = strings.TrimPrefix(name, "/ipns/") - pid, err := peer.IDB58Decode(name) + + pid, err := peer.Decode(name) if err != nil { log.Debugf("RoutingResolver: could not convert public key hash %s to peer ID: %s\n", name, err) out <- onceResult{err: err} diff --git a/p2p/listener.go b/p2p/listener.go index ff7859b0310..65fe87c2040 100644 --- a/p2p/listener.go +++ b/p2p/listener.go @@ -4,9 +4,9 @@ import ( "errors" "sync" - p2phost "github.com/libp2p/go-libp2p-host" - net "github.com/libp2p/go-libp2p-net" - "github.com/libp2p/go-libp2p-protocol" + p2phost "github.com/libp2p/go-libp2p-core/host" + net "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/protocol" ma "github.com/multiformats/go-multiaddr" ) diff --git a/p2p/local.go b/p2p/local.go index b96afa91987..836e80f33e9 100644 --- a/p2p/local.go +++ b/p2p/local.go @@ -5,9 +5,9 @@ import ( "time" tec "github.com/jbenet/go-temp-err-catcher" - "github.com/libp2p/go-libp2p-net" - "github.com/libp2p/go-libp2p-peer" - "github.com/libp2p/go-libp2p-protocol" + net "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/protocol" ma "github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr-net" ) @@ -76,7 +76,7 @@ func (l *localListener) setupStream(local manet.Conn) { remote, err := l.dial(l.ctx) if err != nil { local.Close() - log.Warningf("failed to dial to remote %s/%s", l.peer.Pretty(), l.proto) + log.Warnf("failed to dial to remote %s/%s", l.peer.Pretty(), l.proto) return } diff --git a/p2p/p2p.go b/p2p/p2p.go index 21132120a00..078ba51c477 100644 --- a/p2p/p2p.go +++ b/p2p/p2p.go @@ -2,9 +2,9 @@ package p2p import ( logging "github.com/ipfs/go-log" - p2phost "github.com/libp2p/go-libp2p-host" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" + p2phost "github.com/libp2p/go-libp2p-core/host" + peer "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" ) var log = logging.Logger("p2p-mount") diff --git a/p2p/remote.go b/p2p/remote.go index f6b956829f8..a89b2f2f656 100644 --- a/p2p/remote.go +++ b/p2p/remote.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - net "github.com/libp2p/go-libp2p-net" - protocol "github.com/libp2p/go-libp2p-protocol" + net "github.com/libp2p/go-libp2p-core/network" + protocol "github.com/libp2p/go-libp2p-core/protocol" ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr-net" ) diff --git a/p2p/stream.go b/p2p/stream.go index e29c965b024..137f14c114c 100644 --- a/p2p/stream.go +++ b/p2p/stream.go @@ -4,10 +4,10 @@ import ( "io" "sync" - ifconnmgr "github.com/libp2p/go-libp2p-interface-connmgr" - net "github.com/libp2p/go-libp2p-net" - peer "github.com/libp2p/go-libp2p-peer" - protocol "github.com/libp2p/go-libp2p-protocol" + ifconnmgr "github.com/libp2p/go-libp2p-core/connmgr" + net "github.com/libp2p/go-libp2p-core/network" + peer "github.com/libp2p/go-libp2p-core/peer" + protocol "github.com/libp2p/go-libp2p-core/protocol" ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr-net" ) diff --git a/package-list.json b/package-list.json index 5551193d6a7..934e5e34515 100644 --- a/package-list.json +++ b/package-list.json @@ -6,6 +6,18 @@ "Description" ], "rows": [ + "Libp2p", + ["libp2p/go-libp2p", "go-libp2p", "p2p networking library"], + ["libp2p/go-libp2p-pubsub", "go-libp2p-pubsub", "pubsub built on libp2p"], + ["libp2p/go-libp2p-kad-dht", "go-libp2p-kad-dht", "dht-backed router"], + ["libp2p/go-libp2p-pubsub-router", "go-libp2p-pubsub-router", "pubsub-backed router"], + + "Multiformats", + ["ipfs/go-cid", "go-cid", "CID implementation"], + ["multiformats/go-multiaddr", "go-multiaddr", "multiaddr implementation"], + ["multiformats/go-multihash", "go-multihash", "multihash implementation"], + ["multiformats/go-multibase", "go-multibase", "mulitbase implementation"], + "Files", ["ipfs/go-unixfs", "go-unixfs", "the core 'filesystem' logic"], ["ipfs/go-mfs", "go-mfs", "a mutable filesystem editor for unixfs"], @@ -34,13 +46,20 @@ ["ipfs/go-fs-lock", "go-fs-lock", "lockfile management functions"], ["ipfs/fs-repo-migrations", "fs-repo-migrations", "repo migrations"], - "Blocks", + "IPLD", ["ipfs/go-block-format", "go-block-format", "block interfaces and implementations"], ["ipfs/go-ipfs-blockstore", "go-ipfs-blockstore", "blockstore interfaces and implementations"], + ["ipfs/go-ipld-format", "go-ipld-format", "IPLD interfaces"], + ["ipfs/go-ipld-cbor", "go-ipld-cbor", "IPLD-CBOR implementation"], + ["ipfs/go-ipld-git", "go-ipld-git", "IPLD-Git implementation"], + ["ipfs/go-merkledag", "go-merkledag", "IPLD-Merkledag implementation (and then some)"], "Commands", ["ipfs/go-ipfs-cmds", "go-ipfs-cmds", "CLI & HTTP commands library"], - ["ipfs/go-ipfs-api", "go-ipfs-api", "a shell for the IPFS HTTP API"], + ["ipfs/go-ipfs-files", "go-ipfs-files", "CLI & HTTP commands library"], + ["ipfs/go-ipfs-api", "go-ipfs-api", "an old, stable shell for the IPFS HTTP API"], + ["ipfs/go-ipfs-http-client", "go-ipfs-http-client", "a new, unstable shell for the IPFS HTTP API"], + ["ipfs/interface-go-ipfs-core", "interface-go-ipfs-core", "core go-ipfs API interface definitions"], "Metrics & Logging", ["ipfs/go-metrics-interface", "go-metrics-interface", "metrics collection interfaces"], diff --git a/pin/internal/pb/Rules.mk b/pin/internal/pb/Rules.mk deleted file mode 100644 index 505f70e7541..00000000000 --- a/pin/internal/pb/Rules.mk +++ /dev/null @@ -1,8 +0,0 @@ -include mk/header.mk - -PB_$(d) = $(wildcard $(d)/*.proto) -TGTS_$(d) = $(PB_$(d):.proto=.pb.go) - -#DEPS_GO += $(TGTS_$(d)) - -include mk/footer.mk diff --git a/pin/internal/pb/doc.go b/pin/internal/pb/doc.go deleted file mode 100644 index 95d4afe6718..00000000000 --- a/pin/internal/pb/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -package pb - -//go:generate protoc --gogo_out=. header.proto diff --git a/pin/internal/pb/header.pb.go b/pin/internal/pb/header.pb.go deleted file mode 100644 index 71196b26310..00000000000 --- a/pin/internal/pb/header.pb.go +++ /dev/null @@ -1,381 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: pin/internal/pb/header.proto - -package pb - -import ( - encoding_binary "encoding/binary" - fmt "fmt" - proto "github.com/gogo/protobuf/proto" - io "io" - math "math" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package - -type Set struct { - // 1 for now, library will refuse to handle entries with an unrecognized version. - Version uint32 `protobuf:"varint,1,opt,name=version" json:"version"` - // how many of the links are subtrees - Fanout uint32 `protobuf:"varint,2,opt,name=fanout" json:"fanout"` - // hash seed for subtree selection, a random number - Seed uint32 `protobuf:"fixed32,3,opt,name=seed" json:"seed"` -} - -func (m *Set) Reset() { *m = Set{} } -func (m *Set) String() string { return proto.CompactTextString(m) } -func (*Set) ProtoMessage() {} -func (*Set) Descriptor() ([]byte, []int) { - return fileDescriptor_cda303a5a3ed87e7, []int{0} -} -func (m *Set) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Set) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Set.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalTo(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *Set) XXX_Merge(src proto.Message) { - xxx_messageInfo_Set.Merge(m, src) -} -func (m *Set) XXX_Size() int { - return m.Size() -} -func (m *Set) XXX_DiscardUnknown() { - xxx_messageInfo_Set.DiscardUnknown(m) -} - -var xxx_messageInfo_Set proto.InternalMessageInfo - -func (m *Set) GetVersion() uint32 { - if m != nil { - return m.Version - } - return 0 -} - -func (m *Set) GetFanout() uint32 { - if m != nil { - return m.Fanout - } - return 0 -} - -func (m *Set) GetSeed() uint32 { - if m != nil { - return m.Seed - } - return 0 -} - -func init() { - proto.RegisterType((*Set)(nil), "ipfs.pin.Set") -} - -func init() { proto.RegisterFile("pin/internal/pb/header.proto", fileDescriptor_cda303a5a3ed87e7) } - -var fileDescriptor_cda303a5a3ed87e7 = []byte{ - // 162 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x29, 0xc8, 0xcc, 0xd3, - 0xcf, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x2f, 0x48, 0xd2, 0xcf, 0x48, 0x4d, 0x4c, - 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0xc8, 0x2c, 0x48, 0x2b, 0xd6, 0x2b, - 0xc8, 0xcc, 0x53, 0x8a, 0xe5, 0x62, 0x0e, 0x4e, 0x2d, 0x11, 0x92, 0xe3, 0x62, 0x2f, 0x4b, 0x2d, - 0x2a, 0xce, 0xcc, 0xcf, 0x93, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x75, 0x62, 0x39, 0x71, 0x4f, 0x9e, - 0x21, 0x08, 0x26, 0x28, 0x24, 0xc3, 0xc5, 0x96, 0x96, 0x98, 0x97, 0x5f, 0x5a, 0x22, 0xc1, 0x84, - 0x24, 0x0d, 0x15, 0x13, 0x92, 0xe0, 0x62, 0x29, 0x4e, 0x4d, 0x4d, 0x91, 0x60, 0x56, 0x60, 0xd4, - 0x60, 0x87, 0xca, 0x81, 0x45, 0x9c, 0x64, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, - 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, - 0x21, 0x8a, 0xa9, 0x20, 0x09, 0x10, 0x00, 0x00, 0xff, 0xff, 0x20, 0x85, 0x2f, 0x24, 0xa5, 0x00, - 0x00, 0x00, -} - -func (m *Set) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *Set) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - dAtA[i] = 0x8 - i++ - i = encodeVarintHeader(dAtA, i, uint64(m.Version)) - dAtA[i] = 0x10 - i++ - i = encodeVarintHeader(dAtA, i, uint64(m.Fanout)) - dAtA[i] = 0x1d - i++ - encoding_binary.LittleEndian.PutUint32(dAtA[i:], uint32(m.Seed)) - i += 4 - return i, nil -} - -func encodeVarintHeader(dAtA []byte, offset int, v uint64) int { - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return offset + 1 -} -func (m *Set) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - n += 1 + sovHeader(uint64(m.Version)) - n += 1 + sovHeader(uint64(m.Fanout)) - n += 5 - return n -} - -func sovHeader(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n -} -func sozHeader(x uint64) (n int) { - return sovHeader(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *Set) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowHeader - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Set: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Set: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) - } - m.Version = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowHeader - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Version |= uint32(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Fanout", wireType) - } - m.Fanout = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowHeader - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Fanout |= uint32(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 5 { - return fmt.Errorf("proto: wrong wireType = %d for field Seed", wireType) - } - m.Seed = 0 - if (iNdEx + 4) > l { - return io.ErrUnexpectedEOF - } - m.Seed = uint32(encoding_binary.LittleEndian.Uint32(dAtA[iNdEx:])) - iNdEx += 4 - default: - iNdEx = preIndex - skippy, err := skipHeader(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthHeader - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthHeader - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipHeader(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowHeader - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowHeader - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - return iNdEx, nil - case 1: - iNdEx += 8 - return iNdEx, nil - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowHeader - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthHeader - } - iNdEx += length - if iNdEx < 0 { - return 0, ErrInvalidLengthHeader - } - return iNdEx, nil - case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowHeader - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipHeader(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - if iNdEx < 0 { - return 0, ErrInvalidLengthHeader - } - } - return iNdEx, nil - case 4: - return iNdEx, nil - case 5: - iNdEx += 4 - return iNdEx, nil - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - } - panic("unreachable") -} - -var ( - ErrInvalidLengthHeader = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowHeader = fmt.Errorf("proto: integer overflow") -) diff --git a/pin/internal/pb/header.proto b/pin/internal/pb/header.proto deleted file mode 100644 index 36b32b36dd1..00000000000 --- a/pin/internal/pb/header.proto +++ /dev/null @@ -1,14 +0,0 @@ -syntax = "proto2"; - -package ipfs.pin; - -option go_package = "pb"; - -message Set { - // 1 for now, library will refuse to handle entries with an unrecognized version. - optional uint32 version = 1; - // how many of the links are subtrees - optional uint32 fanout = 2; - // hash seed for subtree selection, a random number - optional fixed32 seed = 3; -} diff --git a/pin/pin.go b/pin/pin.go deleted file mode 100644 index 63fa663c16d..00000000000 --- a/pin/pin.go +++ /dev/null @@ -1,642 +0,0 @@ -// Package pin implements structures and methods to keep track of -// which objects a user wants to keep stored locally. -package pin - -import ( - "context" - "fmt" - "os" - "sync" - "time" - - "github.com/ipfs/go-ipfs/dagutils" - mdag "github.com/ipfs/go-merkledag" - - cid "github.com/ipfs/go-cid" - ds "github.com/ipfs/go-datastore" - ipld "github.com/ipfs/go-ipld-format" - logging "github.com/ipfs/go-log" -) - -var log = logging.Logger("pin") - -var pinDatastoreKey = ds.NewKey("/local/pins") - -var emptyKey cid.Cid - -func init() { - e, err := cid.Decode("QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n") - if err != nil { - log.Error("failed to decode empty key constant") - os.Exit(1) - } - emptyKey = e -} - -const ( - linkRecursive = "recursive" - linkDirect = "direct" - linkIndirect = "indirect" - linkInternal = "internal" - linkNotPinned = "not pinned" - linkAny = "any" - linkAll = "all" -) - -// Mode allows to specify different types of pin (recursive, direct etc.). -// See the Pin Modes constants for a full list. -type Mode int - -// Pin Modes -const ( - // Recursive pins pin the target cids along with any reachable children. - Recursive Mode = iota - - // Direct pins pin just the target cid. - Direct - - // Indirect pins are cids who have some ancestor pinned recursively. - Indirect - - // Internal pins are cids used to keep the internal state of the pinner. - Internal - - // NotPinned - NotPinned - - // Any refers to any pinned cid - Any -) - -// ModeToString returns a human-readable name for the Mode. -func ModeToString(mode Mode) (string, bool) { - m := map[Mode]string{ - Recursive: linkRecursive, - Direct: linkDirect, - Indirect: linkIndirect, - Internal: linkInternal, - NotPinned: linkNotPinned, - Any: linkAny, - } - s, ok := m[mode] - return s, ok -} - -// StringToMode parses the result of ModeToString() back to a Mode. -// It returns a boolean which is set to false if the mode is unknown. -func StringToMode(s string) (Mode, bool) { - m := map[string]Mode{ - linkRecursive: Recursive, - linkDirect: Direct, - linkIndirect: Indirect, - linkInternal: Internal, - linkNotPinned: NotPinned, - linkAny: Any, - linkAll: Any, // "all" and "any" means the same thing - } - mode, ok := m[s] - return mode, ok -} - -// A Pinner provides the necessary methods to keep track of Nodes which are -// to be kept locally, according to a pin mode. In practice, a Pinner is in -// in charge of keeping the list of items from the local storage that should -// not be garbage-collected. -type Pinner interface { - // IsPinned returns whether or not the given cid is pinned - // and an explanation of why its pinned - IsPinned(cid.Cid) (string, bool, error) - - // IsPinnedWithType returns whether or not the given cid is pinned with the - // given pin type, as well as returning the type of pin its pinned with. - IsPinnedWithType(cid.Cid, Mode) (string, bool, error) - - // Pin the given node, optionally recursively. - Pin(ctx context.Context, node ipld.Node, recursive bool) error - - // Unpin the given cid. If recursive is true, removes either a recursive or - // a direct pin. If recursive is false, only removes a direct pin. - Unpin(ctx context.Context, cid cid.Cid, recursive bool) error - - // Update updates a recursive pin from one cid to another - // this is more efficient than simply pinning the new one and unpinning the - // old one - Update(ctx context.Context, from, to cid.Cid, unpin bool) error - - // Check if a set of keys are pinned, more efficient than - // calling IsPinned for each key - CheckIfPinned(cids ...cid.Cid) ([]Pinned, error) - - // PinWithMode is for manually editing the pin structure. Use with - // care! If used improperly, garbage collection may not be - // successful. - PinWithMode(cid.Cid, Mode) - - // RemovePinWithMode is for manually editing the pin structure. - // Use with care! If used improperly, garbage collection may not - // be successful. - RemovePinWithMode(cid.Cid, Mode) - - // Flush writes the pin state to the backing datastore - Flush() error - - // DirectKeys returns all directly pinned cids - DirectKeys() []cid.Cid - - // DirectKeys returns all recursively pinned cids - RecursiveKeys() []cid.Cid - - // InternalPins returns all cids kept pinned for the internal state of the - // pinner - InternalPins() []cid.Cid -} - -// Pinned represents CID which has been pinned with a pinning strategy. -// The Via field allows to identify the pinning parent of this CID, in the -// case that the item is not pinned directly (but rather pinned recursively -// by some ascendant). -type Pinned struct { - Key cid.Cid - Mode Mode - Via cid.Cid -} - -// Pinned returns whether or not the given cid is pinned -func (p Pinned) Pinned() bool { - return p.Mode != NotPinned -} - -// String Returns pin status as string -func (p Pinned) String() string { - switch p.Mode { - case NotPinned: - return "not pinned" - case Indirect: - return fmt.Sprintf("pinned via %s", p.Via) - default: - modeStr, _ := ModeToString(p.Mode) - return fmt.Sprintf("pinned: %s", modeStr) - } -} - -// pinner implements the Pinner interface -type pinner struct { - lock sync.RWMutex - recursePin *cid.Set - directPin *cid.Set - - // Track the keys used for storing the pinning state, so gc does - // not delete them. - internalPin *cid.Set - dserv ipld.DAGService - internal ipld.DAGService // dagservice used to store internal objects - dstore ds.Datastore -} - -// NewPinner creates a new pinner using the given datastore as a backend -func NewPinner(dstore ds.Datastore, serv, internal ipld.DAGService) Pinner { - - rcset := cid.NewSet() - dirset := cid.NewSet() - - return &pinner{ - recursePin: rcset, - directPin: dirset, - dserv: serv, - dstore: dstore, - internal: internal, - internalPin: cid.NewSet(), - } -} - -// Pin the given node, optionally recursive -func (p *pinner) Pin(ctx context.Context, node ipld.Node, recurse bool) error { - p.lock.Lock() - defer p.lock.Unlock() - err := p.dserv.Add(ctx, node) - if err != nil { - return err - } - - c := node.Cid() - - if recurse { - if p.recursePin.Has(c) { - return nil - } - - p.lock.Unlock() - // fetch entire graph - err := mdag.FetchGraph(ctx, c, p.dserv) - p.lock.Lock() - if err != nil { - return err - } - - if p.recursePin.Has(c) { - return nil - } - - if p.directPin.Has(c) { - p.directPin.Remove(c) - } - - p.recursePin.Add(c) - } else { - p.lock.Unlock() - _, err := p.dserv.Get(ctx, c) - p.lock.Lock() - if err != nil { - return err - } - - if p.recursePin.Has(c) { - return fmt.Errorf("%s already pinned recursively", c.String()) - } - - p.directPin.Add(c) - } - return nil -} - -// ErrNotPinned is returned when trying to unpin items which are not pinned. -var ErrNotPinned = fmt.Errorf("not pinned or pinned indirectly") - -// Unpin a given key -func (p *pinner) Unpin(ctx context.Context, c cid.Cid, recursive bool) error { - p.lock.Lock() - defer p.lock.Unlock() - if p.recursePin.Has(c) { - if !recursive { - return fmt.Errorf("%s is pinned recursively", c) - } - p.recursePin.Remove(c) - return nil - } - if p.directPin.Has(c) { - p.directPin.Remove(c) - return nil - } - return ErrNotPinned -} - -func (p *pinner) isInternalPin(c cid.Cid) bool { - return p.internalPin.Has(c) -} - -// IsPinned returns whether or not the given key is pinned -// and an explanation of why its pinned -func (p *pinner) IsPinned(c cid.Cid) (string, bool, error) { - p.lock.RLock() - defer p.lock.RUnlock() - return p.isPinnedWithType(c, Any) -} - -// IsPinnedWithType returns whether or not the given cid is pinned with the -// given pin type, as well as returning the type of pin its pinned with. -func (p *pinner) IsPinnedWithType(c cid.Cid, mode Mode) (string, bool, error) { - p.lock.RLock() - defer p.lock.RUnlock() - return p.isPinnedWithType(c, mode) -} - -// isPinnedWithType is the implementation of IsPinnedWithType that does not lock. -// intended for use by other pinned methods that already take locks -func (p *pinner) isPinnedWithType(c cid.Cid, mode Mode) (string, bool, error) { - switch mode { - case Any, Direct, Indirect, Recursive, Internal: - default: - err := fmt.Errorf("invalid Pin Mode '%d', must be one of {%d, %d, %d, %d, %d}", - mode, Direct, Indirect, Recursive, Internal, Any) - return "", false, err - } - if (mode == Recursive || mode == Any) && p.recursePin.Has(c) { - return linkRecursive, true, nil - } - if mode == Recursive { - return "", false, nil - } - - if (mode == Direct || mode == Any) && p.directPin.Has(c) { - return linkDirect, true, nil - } - if mode == Direct { - return "", false, nil - } - - if (mode == Internal || mode == Any) && p.isInternalPin(c) { - return linkInternal, true, nil - } - if mode == Internal { - return "", false, nil - } - - // Default is Indirect - visitedSet := cid.NewSet() - for _, rc := range p.recursePin.Keys() { - has, err := hasChild(p.dserv, rc, c, visitedSet.Visit) - if err != nil { - return "", false, err - } - if has { - return rc.String(), true, nil - } - } - return "", false, nil -} - -// CheckIfPinned Checks if a set of keys are pinned, more efficient than -// calling IsPinned for each key, returns the pinned status of cid(s) -func (p *pinner) CheckIfPinned(cids ...cid.Cid) ([]Pinned, error) { - p.lock.RLock() - defer p.lock.RUnlock() - pinned := make([]Pinned, 0, len(cids)) - toCheck := cid.NewSet() - - // First check for non-Indirect pins directly - for _, c := range cids { - if p.recursePin.Has(c) { - pinned = append(pinned, Pinned{Key: c, Mode: Recursive}) - } else if p.directPin.Has(c) { - pinned = append(pinned, Pinned{Key: c, Mode: Direct}) - } else if p.isInternalPin(c) { - pinned = append(pinned, Pinned{Key: c, Mode: Internal}) - } else { - toCheck.Add(c) - } - } - - // Now walk all recursive pins to check for indirect pins - var checkChildren func(cid.Cid, cid.Cid) error - checkChildren = func(rk, parentKey cid.Cid) error { - links, err := ipld.GetLinks(context.TODO(), p.dserv, parentKey) - if err != nil { - return err - } - for _, lnk := range links { - c := lnk.Cid - - if toCheck.Has(c) { - pinned = append(pinned, - Pinned{Key: c, Mode: Indirect, Via: rk}) - toCheck.Remove(c) - } - - err := checkChildren(rk, c) - if err != nil { - return err - } - - if toCheck.Len() == 0 { - return nil - } - } - return nil - } - - for _, rk := range p.recursePin.Keys() { - err := checkChildren(rk, rk) - if err != nil { - return nil, err - } - if toCheck.Len() == 0 { - break - } - } - - // Anything left in toCheck is not pinned - for _, k := range toCheck.Keys() { - pinned = append(pinned, Pinned{Key: k, Mode: NotPinned}) - } - - return pinned, nil -} - -// RemovePinWithMode is for manually editing the pin structure. -// Use with care! If used improperly, garbage collection may not -// be successful. -func (p *pinner) RemovePinWithMode(c cid.Cid, mode Mode) { - p.lock.Lock() - defer p.lock.Unlock() - switch mode { - case Direct: - p.directPin.Remove(c) - case Recursive: - p.recursePin.Remove(c) - default: - // programmer error, panic OK - panic("unrecognized pin type") - } -} - -func cidSetWithValues(cids []cid.Cid) *cid.Set { - out := cid.NewSet() - for _, c := range cids { - out.Add(c) - } - return out -} - -// LoadPinner loads a pinner and its keysets from the given datastore -func LoadPinner(d ds.Datastore, dserv, internal ipld.DAGService) (Pinner, error) { - p := new(pinner) - - rootKey, err := d.Get(pinDatastoreKey) - if err != nil { - return nil, fmt.Errorf("cannot load pin state: %v", err) - } - rootCid, err := cid.Cast(rootKey) - if err != nil { - return nil, err - } - - ctx, cancel := context.WithTimeout(context.TODO(), time.Second*5) - defer cancel() - - root, err := internal.Get(ctx, rootCid) - if err != nil { - return nil, fmt.Errorf("cannot find pinning root object: %v", err) - } - - rootpb, ok := root.(*mdag.ProtoNode) - if !ok { - return nil, mdag.ErrNotProtobuf - } - - internalset := cid.NewSet() - internalset.Add(rootCid) - recordInternal := internalset.Add - - { // load recursive set - recurseKeys, err := loadSet(ctx, internal, rootpb, linkRecursive, recordInternal) - if err != nil { - return nil, fmt.Errorf("cannot load recursive pins: %v", err) - } - p.recursePin = cidSetWithValues(recurseKeys) - } - - { // load direct set - directKeys, err := loadSet(ctx, internal, rootpb, linkDirect, recordInternal) - if err != nil { - return nil, fmt.Errorf("cannot load direct pins: %v", err) - } - p.directPin = cidSetWithValues(directKeys) - } - - p.internalPin = internalset - - // assign services - p.dserv = dserv - p.dstore = d - p.internal = internal - - return p, nil -} - -// DirectKeys returns a slice containing the directly pinned keys -func (p *pinner) DirectKeys() []cid.Cid { - p.lock.RLock() - defer p.lock.RUnlock() - - return p.directPin.Keys() -} - -// RecursiveKeys returns a slice containing the recursively pinned keys -func (p *pinner) RecursiveKeys() []cid.Cid { - p.lock.RLock() - defer p.lock.RUnlock() - - return p.recursePin.Keys() -} - -// Update updates a recursive pin from one cid to another -// this is more efficient than simply pinning the new one and unpinning the -// old one -func (p *pinner) Update(ctx context.Context, from, to cid.Cid, unpin bool) error { - if from == to { - // Nothing to do. Don't remove this check or we'll end up - // _removing_ the pin. - // - // See #6648 - return nil - } - - p.lock.Lock() - defer p.lock.Unlock() - - if !p.recursePin.Has(from) { - return fmt.Errorf("'from' cid was not recursively pinned already") - } - - err := dagutils.DiffEnumerate(ctx, p.dserv, from, to) - if err != nil { - return err - } - - p.recursePin.Add(to) - if unpin { - p.recursePin.Remove(from) - } - return nil -} - -// Flush encodes and writes pinner keysets to the datastore -func (p *pinner) Flush() error { - p.lock.Lock() - defer p.lock.Unlock() - - ctx := context.TODO() - - internalset := cid.NewSet() - recordInternal := internalset.Add - - root := &mdag.ProtoNode{} - { - n, err := storeSet(ctx, p.internal, p.directPin.Keys(), recordInternal) - if err != nil { - return err - } - if err := root.AddNodeLink(linkDirect, n); err != nil { - return err - } - } - - { - n, err := storeSet(ctx, p.internal, p.recursePin.Keys(), recordInternal) - if err != nil { - return err - } - if err := root.AddNodeLink(linkRecursive, n); err != nil { - return err - } - } - - // add the empty node, its referenced by the pin sets but never created - err := p.internal.Add(ctx, new(mdag.ProtoNode)) - if err != nil { - return err - } - - err = p.internal.Add(ctx, root) - if err != nil { - return err - } - - k := root.Cid() - - internalset.Add(k) - if err := p.dstore.Put(pinDatastoreKey, k.Bytes()); err != nil { - return fmt.Errorf("cannot store pin state: %v", err) - } - p.internalPin = internalset - return nil -} - -// InternalPins returns all cids kept pinned for the internal state of the -// pinner -func (p *pinner) InternalPins() []cid.Cid { - p.lock.Lock() - defer p.lock.Unlock() - var out []cid.Cid - out = append(out, p.internalPin.Keys()...) - return out -} - -// PinWithMode allows the user to have fine grained control over pin -// counts -func (p *pinner) PinWithMode(c cid.Cid, mode Mode) { - p.lock.Lock() - defer p.lock.Unlock() - switch mode { - case Recursive: - p.recursePin.Add(c) - case Direct: - p.directPin.Add(c) - } -} - -// hasChild recursively looks for a Cid among the children of a root Cid. -// The visit function can be used to shortcut already-visited branches. -func hasChild(ng ipld.NodeGetter, root cid.Cid, child cid.Cid, visit func(cid.Cid) bool) (bool, error) { - links, err := ipld.GetLinks(context.TODO(), ng, root) - if err != nil { - return false, err - } - for _, lnk := range links { - c := lnk.Cid - if lnk.Cid.Equals(child) { - return true, nil - } - if visit(c) { - has, err := hasChild(ng, c, child, visit) - if err != nil { - return false, err - } - - if has { - return has, nil - } - } - } - return false, nil -} diff --git a/pin/pin_test.go b/pin/pin_test.go deleted file mode 100644 index 27e4c71dee5..00000000000 --- a/pin/pin_test.go +++ /dev/null @@ -1,416 +0,0 @@ -package pin - -import ( - "context" - "io" - "testing" - "time" - - bs "github.com/ipfs/go-blockservice" - mdag "github.com/ipfs/go-merkledag" - - cid "github.com/ipfs/go-cid" - ds "github.com/ipfs/go-datastore" - dssync "github.com/ipfs/go-datastore/sync" - blockstore "github.com/ipfs/go-ipfs-blockstore" - offline "github.com/ipfs/go-ipfs-exchange-offline" - util "github.com/ipfs/go-ipfs-util" -) - -var rand = util.NewTimeSeededRand() - -func randNode() (*mdag.ProtoNode, cid.Cid) { - nd := new(mdag.ProtoNode) - nd.SetData(make([]byte, 32)) - _, err := io.ReadFull(rand, nd.Data()) - if err != nil { - panic(err) - } - k := nd.Cid() - return nd, k -} - -func assertPinned(t *testing.T, p Pinner, c cid.Cid, failmsg string) { - _, pinned, err := p.IsPinned(c) - if err != nil { - t.Fatal(err) - } - - if !pinned { - t.Fatal(failmsg) - } -} - -func assertUnpinned(t *testing.T, p Pinner, c cid.Cid, failmsg string) { - _, pinned, err := p.IsPinned(c) - if err != nil { - t.Fatal(err) - } - - if pinned { - t.Fatal(failmsg) - } -} - -func TestPinnerBasic(t *testing.T) { - ctx := context.Background() - - dstore := dssync.MutexWrap(ds.NewMapDatastore()) - bstore := blockstore.NewBlockstore(dstore) - bserv := bs.New(bstore, offline.Exchange(bstore)) - - dserv := mdag.NewDAGService(bserv) - - // TODO does pinner need to share datastore with blockservice? - p := NewPinner(dstore, dserv, dserv) - - a, ak := randNode() - err := dserv.Add(ctx, a) - if err != nil { - t.Fatal(err) - } - - // Pin A{} - err = p.Pin(ctx, a, false) - if err != nil { - t.Fatal(err) - } - - assertPinned(t, p, ak, "Failed to find key") - - // create new node c, to be indirectly pinned through b - c, _ := randNode() - err = dserv.Add(ctx, c) - if err != nil { - t.Fatal(err) - } - ck := c.Cid() - - // Create new node b, to be parent to a and c - b, _ := randNode() - err = b.AddNodeLink("child", a) - if err != nil { - t.Fatal(err) - } - - err = b.AddNodeLink("otherchild", c) - if err != nil { - t.Fatal(err) - } - - err = dserv.Add(ctx, b) - if err != nil { - t.Fatal(err) - } - bk := b.Cid() - - // recursively pin B{A,C} - err = p.Pin(ctx, b, true) - if err != nil { - t.Fatal(err) - } - - assertPinned(t, p, ck, "child of recursively pinned node not found") - - assertPinned(t, p, bk, "Recursively pinned node not found..") - - d, _ := randNode() - _ = d.AddNodeLink("a", a) - _ = d.AddNodeLink("c", c) - - e, _ := randNode() - _ = d.AddNodeLink("e", e) - - // Must be in dagserv for unpin to work - err = dserv.Add(ctx, e) - if err != nil { - t.Fatal(err) - } - err = dserv.Add(ctx, d) - if err != nil { - t.Fatal(err) - } - - // Add D{A,C,E} - err = p.Pin(ctx, d, true) - if err != nil { - t.Fatal(err) - } - - dk := d.Cid() - assertPinned(t, p, dk, "pinned node not found.") - - // Test recursive unpin - err = p.Unpin(ctx, dk, true) - if err != nil { - t.Fatal(err) - } - - err = p.Flush() - if err != nil { - t.Fatal(err) - } - - np, err := LoadPinner(dstore, dserv, dserv) - if err != nil { - t.Fatal(err) - } - - // Test directly pinned - assertPinned(t, np, ak, "Could not find pinned node!") - - // Test recursively pinned - assertPinned(t, np, bk, "could not find recursively pinned node") -} - -func TestIsPinnedLookup(t *testing.T) { - // We are going to test that lookups work in pins which share - // the same branches. For that we will construct this tree: - // - // A5->A4->A3->A2->A1->A0 - // / / - // B------- / - // \ / - // C--------------- - // - // We will ensure that IsPinned works for all objects both when they - // are pinned and once they have been unpinned. - aBranchLen := 6 - if aBranchLen < 3 { - t.Fatal("set aBranchLen to at least 3") - } - - ctx := context.Background() - dstore := dssync.MutexWrap(ds.NewMapDatastore()) - bstore := blockstore.NewBlockstore(dstore) - bserv := bs.New(bstore, offline.Exchange(bstore)) - - dserv := mdag.NewDAGService(bserv) - - // TODO does pinner need to share datastore with blockservice? - p := NewPinner(dstore, dserv, dserv) - - aNodes := make([]*mdag.ProtoNode, aBranchLen) - aKeys := make([]cid.Cid, aBranchLen) - for i := 0; i < aBranchLen; i++ { - a, _ := randNode() - if i >= 1 { - err := a.AddNodeLink("child", aNodes[i-1]) - if err != nil { - t.Fatal(err) - } - } - - err := dserv.Add(ctx, a) - if err != nil { - t.Fatal(err) - } - //t.Logf("a[%d] is %s", i, ak) - aNodes[i] = a - aKeys[i] = a.Cid() - } - - // Pin A5 recursively - if err := p.Pin(ctx, aNodes[aBranchLen-1], true); err != nil { - t.Fatal(err) - } - - // Create node B and add A3 as child - b, _ := randNode() - if err := b.AddNodeLink("mychild", aNodes[3]); err != nil { - t.Fatal(err) - } - - // Create C node - c, _ := randNode() - // Add A0 as child of C - if err := c.AddNodeLink("child", aNodes[0]); err != nil { - t.Fatal(err) - } - - // Add C - err := dserv.Add(ctx, c) - if err != nil { - t.Fatal(err) - } - ck := c.Cid() - //t.Logf("C is %s", ck) - - // Add C to B and Add B - if err := b.AddNodeLink("myotherchild", c); err != nil { - t.Fatal(err) - } - err = dserv.Add(ctx, b) - if err != nil { - t.Fatal(err) - } - bk := b.Cid() - //t.Logf("B is %s", bk) - - // Pin C recursively - - if err := p.Pin(ctx, c, true); err != nil { - t.Fatal(err) - } - - // Pin B recursively - - if err := p.Pin(ctx, b, true); err != nil { - t.Fatal(err) - } - - assertPinned(t, p, aKeys[0], "A0 should be pinned") - assertPinned(t, p, aKeys[1], "A1 should be pinned") - assertPinned(t, p, ck, "C should be pinned") - assertPinned(t, p, bk, "B should be pinned") - - // Unpin A5 recursively - if err := p.Unpin(ctx, aKeys[5], true); err != nil { - t.Fatal(err) - } - - assertPinned(t, p, aKeys[0], "A0 should still be pinned through B") - assertUnpinned(t, p, aKeys[4], "A4 should be unpinned") - - // Unpin B recursively - if err := p.Unpin(ctx, bk, true); err != nil { - t.Fatal(err) - } - assertUnpinned(t, p, bk, "B should be unpinned") - assertUnpinned(t, p, aKeys[1], "A1 should be unpinned") - assertPinned(t, p, aKeys[0], "A0 should still be pinned through C") -} - -func TestDuplicateSemantics(t *testing.T) { - ctx := context.Background() - dstore := dssync.MutexWrap(ds.NewMapDatastore()) - bstore := blockstore.NewBlockstore(dstore) - bserv := bs.New(bstore, offline.Exchange(bstore)) - - dserv := mdag.NewDAGService(bserv) - - // TODO does pinner need to share datastore with blockservice? - p := NewPinner(dstore, dserv, dserv) - - a, _ := randNode() - err := dserv.Add(ctx, a) - if err != nil { - t.Fatal(err) - } - - // pin is recursively - err = p.Pin(ctx, a, true) - if err != nil { - t.Fatal(err) - } - - // pinning directly should fail - err = p.Pin(ctx, a, false) - if err == nil { - t.Fatal("expected direct pin to fail") - } - - // pinning recursively again should succeed - err = p.Pin(ctx, a, true) - if err != nil { - t.Fatal(err) - } -} - -func TestFlush(t *testing.T) { - dstore := dssync.MutexWrap(ds.NewMapDatastore()) - bstore := blockstore.NewBlockstore(dstore) - bserv := bs.New(bstore, offline.Exchange(bstore)) - - dserv := mdag.NewDAGService(bserv) - p := NewPinner(dstore, dserv, dserv) - _, k := randNode() - - p.PinWithMode(k, Recursive) - if err := p.Flush(); err != nil { - t.Fatal(err) - } - assertPinned(t, p, k, "expected key to still be pinned") -} - -func TestPinRecursiveFail(t *testing.T) { - ctx := context.Background() - dstore := dssync.MutexWrap(ds.NewMapDatastore()) - bstore := blockstore.NewBlockstore(dstore) - bserv := bs.New(bstore, offline.Exchange(bstore)) - dserv := mdag.NewDAGService(bserv) - - p := NewPinner(dstore, dserv, dserv) - - a, _ := randNode() - b, _ := randNode() - err := a.AddNodeLink("child", b) - if err != nil { - t.Fatal(err) - } - - // NOTE: This isnt a time based test, we expect the pin to fail - mctx, cancel := context.WithTimeout(ctx, time.Millisecond) - defer cancel() - - err = p.Pin(mctx, a, true) - if err == nil { - t.Fatal("should have failed to pin here") - } - - err = dserv.Add(ctx, b) - if err != nil { - t.Fatal(err) - } - - err = dserv.Add(ctx, a) - if err != nil { - t.Fatal(err) - } - - // this one is time based... but shouldnt cause any issues - mctx, cancel = context.WithTimeout(ctx, time.Second) - defer cancel() - err = p.Pin(mctx, a, true) - if err != nil { - t.Fatal(err) - } -} - -func TestPinUpdate(t *testing.T) { - ctx := context.Background() - - dstore := dssync.MutexWrap(ds.NewMapDatastore()) - bstore := blockstore.NewBlockstore(dstore) - bserv := bs.New(bstore, offline.Exchange(bstore)) - - dserv := mdag.NewDAGService(bserv) - p := NewPinner(dstore, dserv, dserv) - n1, c1 := randNode() - n2, c2 := randNode() - - if err := dserv.Add(ctx, n1); err != nil { - t.Fatal(err) - } - if err := dserv.Add(ctx, n2); err != nil { - t.Fatal(err) - } - - if err := p.Pin(ctx, n1, true); err != nil { - t.Fatal(err) - } - - if err := p.Update(ctx, c1, c2, true); err != nil { - t.Fatal(err) - } - - assertPinned(t, p, c2, "c2 should be pinned now") - assertUnpinned(t, p, c1, "c1 should no longer be pinned") - - if err := p.Update(ctx, c2, c1, false); err != nil { - t.Fatal(err) - } - - assertPinned(t, p, c2, "c2 should be pinned still") - assertPinned(t, p, c1, "c1 should be pinned now") -} diff --git a/pin/set.go b/pin/set.go deleted file mode 100644 index b050c31c43b..00000000000 --- a/pin/set.go +++ /dev/null @@ -1,297 +0,0 @@ -package pin - -import ( - "bytes" - "context" - "encoding/binary" - "errors" - "fmt" - "hash/fnv" - "sort" - - "github.com/ipfs/go-ipfs/pin/internal/pb" - "github.com/ipfs/go-merkledag" - - "github.com/gogo/protobuf/proto" - cid "github.com/ipfs/go-cid" - ipld "github.com/ipfs/go-ipld-format" -) - -const ( - // defaultFanout specifies the default number of fan-out links per layer - defaultFanout = 256 - - // maxItems is the maximum number of items that will fit in a single bucket - maxItems = 8192 -) - -func hash(seed uint32, c cid.Cid) uint32 { - var buf [4]byte - binary.LittleEndian.PutUint32(buf[:], seed) - h := fnv.New32a() - _, _ = h.Write(buf[:]) - _, _ = h.Write(c.Bytes()) - return h.Sum32() -} - -type itemIterator func() (c cid.Cid, ok bool) - -type keyObserver func(cid.Cid) - -type sortByHash struct { - links []*ipld.Link -} - -func (s sortByHash) Len() int { - return len(s.links) -} - -func (s sortByHash) Less(a, b int) bool { - return bytes.Compare(s.links[a].Cid.Bytes(), s.links[b].Cid.Bytes()) == -1 -} - -func (s sortByHash) Swap(a, b int) { - s.links[a], s.links[b] = s.links[b], s.links[a] -} - -func storeItems(ctx context.Context, dag ipld.DAGService, estimatedLen uint64, depth uint32, iter itemIterator, internalKeys keyObserver) (*merkledag.ProtoNode, error) { - links := make([]*ipld.Link, 0, defaultFanout+maxItems) - for i := 0; i < defaultFanout; i++ { - links = append(links, &ipld.Link{Cid: emptyKey}) - } - - // add emptyKey to our set of internal pinset objects - n := &merkledag.ProtoNode{} - n.SetLinks(links) - - internalKeys(emptyKey) - - hdr := &pb.Set{ - Version: 1, - Fanout: defaultFanout, - Seed: depth, - } - if err := writeHdr(n, hdr); err != nil { - return nil, err - } - - if estimatedLen < maxItems { - // it'll probably fit - links := n.Links() - for i := 0; i < maxItems; i++ { - k, ok := iter() - if !ok { - // all done - break - } - - links = append(links, &ipld.Link{Cid: k}) - } - - n.SetLinks(links) - - // sort by hash, also swap item Data - s := sortByHash{ - links: n.Links()[defaultFanout:], - } - sort.Stable(s) - } - - hashed := make([][]cid.Cid, defaultFanout) - for { - // This loop essentially enumerates every single item in the set - // and maps them all into a set of buckets. Each bucket will be recursively - // turned into its own sub-set, and so on down the chain. Each sub-set - // gets added to the dagservice, and put into its place in a set nodes - // links array. - // - // Previously, the bucket was selected by taking an int32 from the hash of - // the input key + seed. This was erroneous as we would later be assigning - // the created sub-sets into an array of length 256 by the modulus of the - // int32 hash value with 256. This resulted in overwriting existing sub-sets - // and losing pins. The fix (a few lines down from this comment), is to - // map the hash value down to the 8 bit keyspace here while creating the - // buckets. This way, we avoid any overlapping later on. - k, ok := iter() - if !ok { - break - } - h := hash(depth, k) % defaultFanout - hashed[h] = append(hashed[h], k) - } - - for h, items := range hashed { - if len(items) == 0 { - // recursion base case - continue - } - - childIter := getCidListIterator(items) - - // recursively create a pinset from the items for this bucket index - child, err := storeItems(ctx, dag, uint64(len(items)), depth+1, childIter, internalKeys) - if err != nil { - return nil, err - } - - size, err := child.Size() - if err != nil { - return nil, err - } - - err = dag.Add(ctx, child) - if err != nil { - return nil, err - } - childKey := child.Cid() - - internalKeys(childKey) - - // overwrite the 'empty key' in the existing links array - n.Links()[h] = &ipld.Link{ - Cid: childKey, - Size: size, - } - } - return n, nil -} - -func readHdr(n *merkledag.ProtoNode) (*pb.Set, error) { - hdrLenRaw, consumed := binary.Uvarint(n.Data()) - if consumed <= 0 { - return nil, errors.New("invalid Set header length") - } - - pbdata := n.Data()[consumed:] - if hdrLenRaw > uint64(len(pbdata)) { - return nil, errors.New("impossibly large Set header length") - } - // as hdrLenRaw was <= an int, we now know it fits in an int - hdrLen := int(hdrLenRaw) - var hdr pb.Set - if err := proto.Unmarshal(pbdata[:hdrLen], &hdr); err != nil { - return nil, err - } - - if v := hdr.GetVersion(); v != 1 { - return nil, fmt.Errorf("unsupported Set version: %d", v) - } - if uint64(hdr.GetFanout()) > uint64(len(n.Links())) { - return nil, errors.New("impossibly large Fanout") - } - return &hdr, nil -} - -func writeHdr(n *merkledag.ProtoNode, hdr *pb.Set) error { - hdrData, err := proto.Marshal(hdr) - if err != nil { - return err - } - - // make enough space for the length prefix and the marshaled header data - data := make([]byte, binary.MaxVarintLen64, binary.MaxVarintLen64+len(hdrData)) - - // write the uvarint length of the header data - uvarlen := binary.PutUvarint(data, uint64(len(hdrData))) - - // append the actual protobuf data *after* the length value we wrote - data = append(data[:uvarlen], hdrData...) - - n.SetData(data) - return nil -} - -type walkerFunc func(idx int, link *ipld.Link) error - -func walkItems(ctx context.Context, dag ipld.DAGService, n *merkledag.ProtoNode, fn walkerFunc, children keyObserver) error { - hdr, err := readHdr(n) - if err != nil { - return err - } - // readHdr guarantees fanout is a safe value - fanout := hdr.GetFanout() - for i, l := range n.Links()[fanout:] { - if err := fn(i, l); err != nil { - return err - } - } - for _, l := range n.Links()[:fanout] { - c := l.Cid - children(c) - if c.Equals(emptyKey) { - continue - } - subtree, err := l.GetNode(ctx, dag) - if err != nil { - return err - } - - stpb, ok := subtree.(*merkledag.ProtoNode) - if !ok { - return merkledag.ErrNotProtobuf - } - - if err := walkItems(ctx, dag, stpb, fn, children); err != nil { - return err - } - } - return nil -} - -func loadSet(ctx context.Context, dag ipld.DAGService, root *merkledag.ProtoNode, name string, internalKeys keyObserver) ([]cid.Cid, error) { - l, err := root.GetNodeLink(name) - if err != nil { - return nil, err - } - - lnkc := l.Cid - internalKeys(lnkc) - - n, err := l.GetNode(ctx, dag) - if err != nil { - return nil, err - } - - pbn, ok := n.(*merkledag.ProtoNode) - if !ok { - return nil, merkledag.ErrNotProtobuf - } - - var res []cid.Cid - walk := func(idx int, link *ipld.Link) error { - res = append(res, link.Cid) - return nil - } - - if err := walkItems(ctx, dag, pbn, walk, internalKeys); err != nil { - return nil, err - } - return res, nil -} - -func getCidListIterator(cids []cid.Cid) itemIterator { - return func() (c cid.Cid, ok bool) { - if len(cids) == 0 { - return cid.Cid{}, false - } - - first := cids[0] - cids = cids[1:] - return first, true - } -} - -func storeSet(ctx context.Context, dag ipld.DAGService, cids []cid.Cid, internalKeys keyObserver) (*merkledag.ProtoNode, error) { - iter := getCidListIterator(cids) - - n, err := storeItems(ctx, dag, uint64(len(cids)), 0, iter, internalKeys) - if err != nil { - return nil, err - } - err = dag.Add(ctx, n) - if err != nil { - return nil, err - } - internalKeys(n.Cid()) - return n, nil -} diff --git a/pin/set_test.go b/pin/set_test.go deleted file mode 100644 index d9a573c5fa2..00000000000 --- a/pin/set_test.go +++ /dev/null @@ -1,101 +0,0 @@ -package pin - -import ( - "context" - "encoding/binary" - "testing" - - bserv "github.com/ipfs/go-blockservice" - dag "github.com/ipfs/go-merkledag" - - cid "github.com/ipfs/go-cid" - ds "github.com/ipfs/go-datastore" - dsq "github.com/ipfs/go-datastore/query" - blockstore "github.com/ipfs/go-ipfs-blockstore" - offline "github.com/ipfs/go-ipfs-exchange-offline" -) - -func ignoreCids(_ cid.Cid) {} - -func objCount(d ds.Datastore) int { - q := dsq.Query{KeysOnly: true} - res, err := d.Query(q) - if err != nil { - panic(err) - } - - var count int - for { - _, ok := res.NextSync() - if !ok { - break - } - - count++ - } - return count -} - -func TestSet(t *testing.T) { - dst := ds.NewMapDatastore() - bstore := blockstore.NewBlockstore(dst) - ds := dag.NewDAGService(bserv.New(bstore, offline.Exchange(bstore))) - - // this value triggers the creation of a recursive shard. - // If the recursive sharding is done improperly, this will result in - // an infinite recursion and crash (OOM) - limit := uint32((defaultFanout * maxItems) + 1) - - var inputs []cid.Cid - buf := make([]byte, 4) - for i := uint32(0); i < limit; i++ { - binary.BigEndian.PutUint32(buf, i) - c := dag.NewRawNode(buf).Cid() - inputs = append(inputs, c) - } - - _, err := storeSet(context.Background(), ds, inputs[:len(inputs)-1], ignoreCids) - if err != nil { - t.Fatal(err) - } - - objs1 := objCount(dst) - - out, err := storeSet(context.Background(), ds, inputs, ignoreCids) - if err != nil { - t.Fatal(err) - } - - objs2 := objCount(dst) - if objs2-objs1 > 2 { - t.Fatal("set sharding does not appear to be deterministic") - } - - // weird wrapper node because loadSet expects us to pass an - // object pointing to multiple named sets - setroot := &dag.ProtoNode{} - err = setroot.AddNodeLink("foo", out) - if err != nil { - t.Fatal(err) - } - - outset, err := loadSet(context.Background(), ds, setroot, "foo", ignoreCids) - if err != nil { - t.Fatal(err) - } - - if uint32(len(outset)) != limit { - t.Fatal("got wrong number", len(outset), limit) - } - - seen := cid.NewSet() - for _, c := range outset { - seen.Add(c) - } - - for _, c := range inputs { - if !seen.Has(c) { - t.Fatalf("expected to have '%s', didnt find it", c) - } - } -} diff --git a/plugin/daemon.go b/plugin/daemon.go index 8ed86b764ee..04b18b33b96 100644 --- a/plugin/daemon.go +++ b/plugin/daemon.go @@ -10,5 +10,4 @@ type PluginDaemon interface { Plugin Start(coreiface.CoreAPI) error - Close() error } diff --git a/plugin/daemoninternal.go b/plugin/daemoninternal.go new file mode 100644 index 00000000000..cb4c2448d03 --- /dev/null +++ b/plugin/daemoninternal.go @@ -0,0 +1,14 @@ +package plugin + +import "github.com/ipfs/go-ipfs/core" + +// PluginDaemonInternal is an interface for daemon plugins. These plugins will be run on +// the daemon and will be given a direct access to the IpfsNode. +// +// Note: PluginDaemonInternal is considered internal and no guarantee is made concerning +// the stability of its API. If you can, use PluginAPI instead. +type PluginDaemonInternal interface { + Plugin + + Start(*core.IpfsNode) error +} diff --git a/plugin/loader/Rules.mk b/plugin/loader/Rules.mk index 01f50e277fb..7d99bd7a4b6 100644 --- a/plugin/loader/Rules.mk +++ b/plugin/loader/Rules.mk @@ -1,10 +1,13 @@ include mk/header.mk +IPFS_PLUGINS ?= +export IPFS_PLUGINS + $(d)/preload.go: d:=$(d) -$(d)/preload.go: $(d)/preload_list $(d)/preload.sh +$(d)/preload.go: $(d)/preload_list $(d)/preload.sh ALWAYS $(d)/preload.sh > $@ go fmt $@ >/dev/null DEPS_GO += $(d)/preload.go - + include mk/footer.mk diff --git a/plugin/loader/load_linux.go b/plugin/loader/load_unix.go similarity index 93% rename from plugin/loader/load_linux.go rename to plugin/loader/load_unix.go index 19c1e994bbd..db1eb5d970f 100644 --- a/plugin/loader/load_linux.go +++ b/plugin/loader/load_unix.go @@ -1,4 +1,5 @@ // +build !noplugin +// +build linux,cgo darwin,cgo package loader @@ -25,7 +26,7 @@ func linuxLoadFunc(pluginDir string) ([]iplugin.Plugin, error) { } if info.IsDir() { if fi != pluginDir { - log.Warningf("found directory inside plugins directory: %s", fi) + log.Warnf("found directory inside plugins directory: %s", fi) } return nil } diff --git a/plugin/loader/loader.go b/plugin/loader/loader.go index b5a2d08edf9..9693118ebc6 100644 --- a/plugin/loader/loader.go +++ b/plugin/loader/loader.go @@ -2,62 +2,175 @@ package loader import ( "fmt" + "io" "os" + "path/filepath" "strings" + config "github.com/ipfs/go-ipfs-config" + cserialize "github.com/ipfs/go-ipfs-config/serialize" + + "github.com/ipfs/go-ipfs/core" + "github.com/ipfs/go-ipfs/core/coreapi" coredag "github.com/ipfs/go-ipfs/core/coredag" plugin "github.com/ipfs/go-ipfs/plugin" fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo" ipld "github.com/ipfs/go-ipld-format" logging "github.com/ipfs/go-log" - coreiface "github.com/ipfs/interface-go-ipfs-core" opentracing "github.com/opentracing/opentracing-go" ) +var preloadPlugins []plugin.Plugin + +// Preload adds one or more plugins to the preload list. This should _only_ be called during init. +func Preload(plugins ...plugin.Plugin) { + preloadPlugins = append(preloadPlugins, plugins...) +} + var log = logging.Logger("plugin/loader") var loadPluginsFunc = func(string) ([]plugin.Plugin, error) { return nil, nil } -// PluginLoader keeps track of loaded plugins +type loaderState int + +const ( + loaderLoading loaderState = iota + loaderInitializing + loaderInitialized + loaderInjecting + loaderInjected + loaderStarting + loaderStarted + loaderClosing + loaderClosed + loaderFailed +) + +func (ls loaderState) String() string { + switch ls { + case loaderLoading: + return "Loading" + case loaderInitializing: + return "Initializing" + case loaderInitialized: + return "Initialized" + case loaderInjecting: + return "Injecting" + case loaderInjected: + return "Injected" + case loaderStarting: + return "Starting" + case loaderStarted: + return "Started" + case loaderClosing: + return "Closing" + case loaderClosed: + return "Closed" + case loaderFailed: + return "Failed" + default: + return "Unknown" + } +} + +// PluginLoader keeps track of loaded plugins. +// +// To use: +// 1. Load any desired plugins with Load and LoadDirectory. Preloaded plugins +// will automatically be loaded. +// 2. Call Initialize to run all initialization logic. +// 3. Call Inject to register the plugins. +// 4. Optionally call Start to start plugins. +// 5. Call Close to close all plugins. type PluginLoader struct { - plugins []plugin.Plugin + state loaderState + plugins map[string]plugin.Plugin + started []plugin.Plugin + config config.Plugins + repo string } // NewPluginLoader creates new plugin loader -func NewPluginLoader(pluginDir string) (*PluginLoader, error) { - plMap := make(map[string]plugin.Plugin) - for _, v := range preloadPlugins { - plMap[v.Name()] = v +func NewPluginLoader(repo string) (*PluginLoader, error) { + loader := &PluginLoader{plugins: make(map[string]plugin.Plugin, len(preloadPlugins)), repo: repo} + if repo != "" { + cfg, err := cserialize.Load(filepath.Join(repo, config.DefaultConfigFile)) + switch err { + case cserialize.ErrNotInitialized: + case nil: + loader.config = cfg.Plugins + default: + return nil, err + } } - - if pluginDir != "" { - newPls, err := loadDynamicPlugins(pluginDir) - if err != nil { + for _, v := range preloadPlugins { + if err := loader.Load(v); err != nil { return nil, err } + } - for _, pl := range newPls { - if ppl, ok := plMap[pl.Name()]; ok { - // plugin is already preloaded - return nil, fmt.Errorf( - "plugin: %s, is duplicated in version: %s, "+ - "while trying to load dynamically: %s", - ppl.Name(), ppl.Version(), pl.Version()) - } - plMap[pl.Name()] = pl - } + if err := loader.LoadDirectory(filepath.Join(repo, "plugins")); err != nil { + return nil, err } + return loader, nil +} - loader := &PluginLoader{plugins: make([]plugin.Plugin, 0, len(plMap))} +func (loader *PluginLoader) assertState(state loaderState) error { + if loader.state != state { + return fmt.Errorf("loader state must be %s, was %s", state, loader.state) + } + return nil +} - for _, v := range plMap { - loader.plugins = append(loader.plugins, v) +func (loader *PluginLoader) transition(from, to loaderState) error { + if err := loader.assertState(from); err != nil { + return err } + loader.state = to + return nil +} - return loader, nil +// Load loads a plugin into the plugin loader. +func (loader *PluginLoader) Load(pl plugin.Plugin) error { + if err := loader.assertState(loaderLoading); err != nil { + return err + } + + name := pl.Name() + if ppl, ok := loader.plugins[name]; ok { + // plugin is already loaded + return fmt.Errorf( + "plugin: %s, is duplicated in version: %s, "+ + "while trying to load dynamically: %s", + name, ppl.Version(), pl.Version()) + } + if loader.config.Plugins[name].Disabled { + log.Infof("not loading disabled plugin %s", name) + return nil + } + loader.plugins[name] = pl + return nil +} + +// LoadDirectory loads a directory of plugins into the plugin loader. +func (loader *PluginLoader) LoadDirectory(pluginDir string) error { + if err := loader.assertState(loaderLoading); err != nil { + return err + } + newPls, err := loadDynamicPlugins(pluginDir) + if err != nil { + return err + } + + for _, pl := range newPls { + if err := loader.Load(pl); err != nil { + return err + } + } + return nil } func loadDynamicPlugins(pluginDir string) ([]plugin.Plugin, error) { @@ -74,65 +187,102 @@ func loadDynamicPlugins(pluginDir string) ([]plugin.Plugin, error) { // Initialize initializes all loaded plugins func (loader *PluginLoader) Initialize() error { - for _, p := range loader.plugins { - err := p.Init() + if err := loader.transition(loaderLoading, loaderInitializing); err != nil { + return err + } + for name, p := range loader.plugins { + err := p.Init(&plugin.Environment{ + Repo: loader.repo, + Config: loader.config.Plugins[name].Config, + }) if err != nil { + loader.state = loaderFailed return err } } - return nil + return loader.transition(loaderInitializing, loaderInitialized) } // Inject hooks all the plugins into the appropriate subsystems. func (loader *PluginLoader) Inject() error { + if err := loader.transition(loaderInitialized, loaderInjecting); err != nil { + return err + } + for _, pl := range loader.plugins { if pl, ok := pl.(plugin.PluginIPLD); ok { err := injectIPLDPlugin(pl) if err != nil { + loader.state = loaderFailed return err } } if pl, ok := pl.(plugin.PluginTracer); ok { err := injectTracerPlugin(pl) if err != nil { + loader.state = loaderFailed return err } } if pl, ok := pl.(plugin.PluginDatastore); ok { err := injectDatastorePlugin(pl) if err != nil { + loader.state = loaderFailed return err } } } - return nil + + return loader.transition(loaderInjecting, loaderInjected) } // Start starts all long-running plugins. -func (loader *PluginLoader) Start(iface coreiface.CoreAPI) error { - for i, pl := range loader.plugins { +func (loader *PluginLoader) Start(node *core.IpfsNode) error { + if err := loader.transition(loaderInjected, loaderStarting); err != nil { + return err + } + iface, err := coreapi.NewCoreAPI(node) + if err != nil { + return err + } + for _, pl := range loader.plugins { if pl, ok := pl.(plugin.PluginDaemon); ok { err := pl.Start(iface) if err != nil { - _ = closePlugins(loader.plugins[i:]) + _ = loader.Close() return err } + loader.started = append(loader.started, pl) + } + if pl, ok := pl.(plugin.PluginDaemonInternal); ok { + err := pl.Start(node) + if err != nil { + _ = loader.Close() + return err + } + loader.started = append(loader.started, pl) } } - return nil + + return loader.transition(loaderStarting, loaderStarted) } // StopDaemon stops all long-running plugins. func (loader *PluginLoader) Close() error { - return closePlugins(loader.plugins) -} + switch loader.state { + case loaderClosing, loaderFailed, loaderClosed: + // nothing to do. + return nil + } + loader.state = loaderClosing -func closePlugins(plugins []plugin.Plugin) error { var errs []string - for _, pl := range plugins { - if pl, ok := pl.(plugin.PluginDaemon); ok { - err := pl.Close() + started := loader.started + loader.started = nil + for _, pl := range started { + if closer, ok := pl.(io.Closer); ok { + err := closer.Close() if err != nil { errs = append(errs, fmt.Sprintf( "error closing plugin %s: %s", @@ -143,8 +293,10 @@ func closePlugins(plugins []plugin.Plugin) error { } } if errs != nil { + loader.state = loaderFailed return fmt.Errorf(strings.Join(errs, "\n")) } + loader.state = loaderClosed return nil } diff --git a/plugin/loader/preload.go b/plugin/loader/preload.go index 730f3538e74..2c6d512bf8c 100644 --- a/plugin/loader/preload.go +++ b/plugin/loader/preload.go @@ -1,7 +1,6 @@ package loader import ( - "github.com/ipfs/go-ipfs/plugin" pluginbadgerds "github.com/ipfs/go-ipfs/plugin/plugins/badgerds" pluginflatfs "github.com/ipfs/go-ipfs/plugin/plugins/flatfs" pluginipldgit "github.com/ipfs/go-ipfs/plugin/plugins/git" @@ -12,9 +11,9 @@ import ( // This file is being generated as part of plugin build process // To change it, modify the plugin/loader/preload.sh -var preloadPlugins = []plugin.Plugin{ - pluginipldgit.Plugins[0], - pluginbadgerds.Plugins[0], - pluginflatfs.Plugins[0], - pluginlevelds.Plugins[0], +func init() { + Preload(pluginipldgit.Plugins...) + Preload(pluginbadgerds.Plugins...) + Preload(pluginflatfs.Plugins...) + Preload(pluginlevelds.Plugins...) } diff --git a/plugin/loader/preload.sh b/plugin/loader/preload.sh index 5d000d0a33f..30ba8b73e4b 100755 --- a/plugin/loader/preload.sh +++ b/plugin/loader/preload.sh @@ -4,13 +4,17 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" to_preload() { awk 'NF' "$DIR/preload_list" | sed '/^#/d' + if [[ -n "$IPFS_PLUGINS" ]]; then + for plugin in $IPFS_PLUGINS; do + echo "$plugin github.com/ipfs/go-ipfs/plugin/plugins/$plugin *" + done + fi } cat < 0 { + busyCounter++ + + // sleep a bit to give the system a chance to catch up with logging. + select { + case <-time.After(time.Duration(busyCounter) * time.Second): + case <-ctx.Done(): + return + } + + // drain 1/8th of the backlog backlog so we + // don't immediately run into this situation + // again. + loop: + for i := 0; i < busyDropAmount; i++ { + select { + case <-pl.events: + dropped++ + default: + break loop + } + } + + // Add in any events we've dropped in the mean-time. + dropped += atomic.SwapUint64(&pl.droppedCount, 0) + + // Report that we've dropped events. + dlog.Error("dropped events", zap.Uint64("count", dropped)) + } else { + busyCounter = 0 + } + + var e plEvent + select { + case <-ctx.Done(): + return + case e = <-pl.events: + } + + peerID := zap.String("peer", e.peer.Pretty()) + + switch e.kind { + case eventConnect: + dlog.Info("connected", peerID) + case eventIdentify: + agent, err := node.Peerstore.Get(e.peer, "AgentVersion") + switch err { + case nil: + case peerstore.ErrNotFound: + continue + default: + dlog.Error("failed to get agent version", zap.Error(err)) + continue + } + + agentS, ok := agent.(string) + if !ok { + continue + } + dlog.Info("identified", peerID, zap.String("agent", agentS)) + } + } +} + +func (pl *peerLogPlugin) emit(evt eventType, p peer.ID) { + select { + case pl.events <- plEvent{kind: evt, peer: p}: + default: + atomic.AddUint64(&pl.droppedCount, 1) + } +} + +func (pl *peerLogPlugin) Start(node *core.IpfsNode) error { + // Ensure logs from this plugin get printed regardless of global IPFS_LOGGING value + if err := logging.SetLogLevel("plugin/peerlog", "info"); err != nil { + return fmt.Errorf("failed to set log level: %w", err) + } + + sub, err := node.PeerHost.EventBus().Subscribe(new(event.EvtPeerIdentificationCompleted)) + if err != nil { + return fmt.Errorf("failed to subscribe to identify notifications") + } + + var notifee network.NotifyBundle + notifee.ConnectedF = func(net network.Network, conn network.Conn) { + pl.emit(eventConnect, conn.RemotePeer()) + } + node.PeerHost.Network().Notify(¬ifee) + + go func() { + defer sub.Close() + for e := range sub.Out() { + switch e := e.(type) { + case event.EvtPeerIdentificationCompleted: + pl.emit(eventIdentify, e.Peer) + } + } + }() + + go pl.collectEvents(node) + + return nil +} + +func (*peerLogPlugin) Close() error { + return nil +} diff --git a/plugin/tracer.go b/plugin/tracer.go index 2f1d8f814ca..b6b56939d44 100644 --- a/plugin/tracer.go +++ b/plugin/tracer.go @@ -7,5 +7,6 @@ import ( // PluginTracer is an interface that can be implemented to add a tracer type PluginTracer interface { Plugin + InitTracer() (opentracing.Tracer, error) } diff --git a/provider/offline.go b/provider/offline.go deleted file mode 100644 index 0c91ed2af77..00000000000 --- a/provider/offline.go +++ /dev/null @@ -1,20 +0,0 @@ -package provider - -import "github.com/ipfs/go-cid" - -type offlineProvider struct{} - -// NewOfflineProvider creates a Provider that does nothing -func NewOfflineProvider() Provider { - return &offlineProvider{} -} - -func (op *offlineProvider) Run() {} - -func (op *offlineProvider) Provide(cid cid.Cid) error { - return nil -} - -func (op *offlineProvider) Close() error { - return nil -} diff --git a/provider/provider.go b/provider/provider.go deleted file mode 100644 index 67c5c6b6b92..00000000000 --- a/provider/provider.go +++ /dev/null @@ -1,79 +0,0 @@ -// Package provider implements structures and methods to provide blocks, -// keep track of which blocks are provided, and to allow those blocks to -// be reprovided. -package provider - -import ( - "context" - "github.com/ipfs/go-cid" - logging "github.com/ipfs/go-log" - "github.com/libp2p/go-libp2p-routing" -) - -var log = logging.Logger("provider") - -const provideOutgoingWorkerLimit = 8 - -// Provider announces blocks to the network -type Provider interface { - // Run is used to begin processing the provider work - Run() - // Provide takes a cid and makes an attempt to announce it to the network - Provide(cid.Cid) error - // Close stops the provider - Close() error -} - -type provider struct { - ctx context.Context - // the CIDs for which provide announcements should be made - queue *Queue - // used to announce providing to the network - contentRouting routing.ContentRouting -} - -// NewProvider creates a provider that announces blocks to the network using a content router -func NewProvider(ctx context.Context, queue *Queue, contentRouting routing.ContentRouting) Provider { - return &provider{ - ctx: ctx, - queue: queue, - contentRouting: contentRouting, - } -} - -// Close stops the provider -func (p *provider) Close() error { - p.queue.Close() - return nil -} - -// Start workers to handle provide requests. -func (p *provider) Run() { - p.handleAnnouncements() -} - -// Provide the given cid using specified strategy. -func (p *provider) Provide(root cid.Cid) error { - p.queue.Enqueue(root) - return nil -} - -// Handle all outgoing cids by providing (announcing) them -func (p *provider) handleAnnouncements() { - for workers := 0; workers < provideOutgoingWorkerLimit; workers++ { - go func() { - for p.ctx.Err() == nil { - select { - case <-p.ctx.Done(): - return - case c := <-p.queue.Dequeue(): - log.Info("announce - start - ", c) - if err := p.contentRouting.Provide(p.ctx, c, true); err != nil { - log.Warningf("Unable to provide entry: %s, %s", c, err) - } - log.Info("announce - end - ", c) - } - } - }() - } -} diff --git a/provider/provider_test.go b/provider/provider_test.go deleted file mode 100644 index 7ef007b03a7..00000000000 --- a/provider/provider_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package provider - -import ( - "context" - "math/rand" - "testing" - "time" - - cid "github.com/ipfs/go-cid" - datastore "github.com/ipfs/go-datastore" - sync "github.com/ipfs/go-datastore/sync" - blocksutil "github.com/ipfs/go-ipfs-blocksutil" - pstore "github.com/libp2p/go-libp2p-peerstore" -) - -var blockGenerator = blocksutil.NewBlockGenerator() - -type mockRouting struct { - provided chan cid.Cid -} - -func (r *mockRouting) Provide(ctx context.Context, cid cid.Cid, recursive bool) error { - r.provided <- cid - return nil -} - -func (r *mockRouting) FindProvidersAsync(ctx context.Context, cid cid.Cid, timeout int) <-chan pstore.PeerInfo { - return nil -} - -func mockContentRouting() *mockRouting { - r := mockRouting{} - r.provided = make(chan cid.Cid) - return &r -} - -func TestAnnouncement(t *testing.T) { - ctx := context.Background() - defer ctx.Done() - - ds := sync.MutexWrap(datastore.NewMapDatastore()) - queue, err := NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - r := mockContentRouting() - - provider := NewProvider(ctx, queue, r) - provider.Run() - - cids := cid.NewSet() - - for i := 0; i < 100; i++ { - c := blockGenerator.Next().Cid() - cids.Add(c) - } - - go func() { - for _, c := range cids.Keys() { - err = provider.Provide(c) - // A little goroutine stirring to exercise some different states - r := rand.Intn(10) - time.Sleep(time.Microsecond * time.Duration(r)) - } - }() - - for cids.Len() > 0 { - select { - case cp := <-r.provided: - if !cids.Has(cp) { - t.Fatal("Wrong CID provided") - } - cids.Remove(cp) - case <-time.After(time.Second * 5): - t.Fatal("Timeout waiting for cids to be provided.") - } - } -} diff --git a/provider/queue.go b/provider/queue.go deleted file mode 100644 index 8fdfca81521..00000000000 --- a/provider/queue.go +++ /dev/null @@ -1,208 +0,0 @@ -package provider - -import ( - "context" - "fmt" - "strconv" - "strings" - - cid "github.com/ipfs/go-cid" - datastore "github.com/ipfs/go-datastore" - namespace "github.com/ipfs/go-datastore/namespace" - query "github.com/ipfs/go-datastore/query" -) - -// Queue provides a durable, FIFO interface to the datastore for storing cids -// -// Durability just means that cids in the process of being provided when a -// crash or shutdown occurs will still be in the queue when the node is -// brought back online. -type Queue struct { - // used to differentiate queues in datastore - // e.g. provider vs reprovider - name string - ctx context.Context - tail uint64 - head uint64 - ds datastore.Datastore // Must be threadsafe - dequeue chan cid.Cid - enqueue chan cid.Cid - close context.CancelFunc - closed chan struct{} -} - -// NewQueue creates a queue for cids -func NewQueue(ctx context.Context, name string, ds datastore.Datastore) (*Queue, error) { - namespaced := namespace.Wrap(ds, datastore.NewKey("/"+name+"/queue/")) - head, tail, err := getQueueHeadTail(ctx, namespaced) - if err != nil { - return nil, err - } - cancelCtx, cancel := context.WithCancel(ctx) - q := &Queue{ - name: name, - ctx: cancelCtx, - head: head, - tail: tail, - ds: namespaced, - dequeue: make(chan cid.Cid), - enqueue: make(chan cid.Cid), - close: cancel, - closed: make(chan struct{}, 1), - } - q.work() - return q, nil -} - -// Close stops the queue -func (q *Queue) Close() error { - q.close() - <-q.closed - return nil -} - -// Enqueue puts a cid in the queue -func (q *Queue) Enqueue(cid cid.Cid) { - select { - case q.enqueue <- cid: - case <-q.ctx.Done(): - } -} - -// Dequeue returns a channel that if listened to will remove entries from the queue -func (q *Queue) Dequeue() <-chan cid.Cid { - return q.dequeue -} - -// Look for next Cid in the queue and return it. Skip over gaps and mangled data -func (q *Queue) nextEntry() (datastore.Key, cid.Cid) { - for { - if q.head >= q.tail { - return datastore.Key{}, cid.Undef - } - - key := q.queueKey(q.head) - value, err := q.ds.Get(key) - - if err != nil { - if err == datastore.ErrNotFound { - log.Warningf("Error missing entry in queue: %s", key) - } else { - log.Errorf("Error fetching from queue: %s", err) - } - q.head++ // move on - continue - } - - c, err := cid.Parse(value) - if err != nil { - log.Warningf("Error marshalling Cid from queue: ", err) - q.head++ - err = q.ds.Delete(key) - if err != nil { - log.Warningf("Provider queue failed to delete: %s", key) - } - continue - } - - return key, c - } -} - -// Run dequeues and enqueues when available. -func (q *Queue) work() { - go func() { - var k datastore.Key = datastore.Key{} - var c cid.Cid = cid.Undef - - defer func() { - close(q.closed) - }() - - for { - if c == cid.Undef { - k, c = q.nextEntry() - } - - // If c != cid.Undef set dequeue and attempt write, otherwise wait for enqueue - var dequeue chan cid.Cid - if c != cid.Undef { - dequeue = q.dequeue - } - - select { - case toQueue := <-q.enqueue: - nextKey := q.queueKey(q.tail) - - if err := q.ds.Put(nextKey, toQueue.Bytes()); err != nil { - log.Errorf("Failed to enqueue cid: %s", err) - continue - } - - q.tail++ - case dequeue <- c: - err := q.ds.Delete(k) - - if err != nil { - log.Errorf("Failed to delete queued cid %s with key %s: %s", c, k, err) - continue - } - c = cid.Undef - q.head++ - case <-q.ctx.Done(): - return - } - } - }() -} - -func (q *Queue) queueKey(id uint64) datastore.Key { - s := fmt.Sprintf("%016X", id) - return datastore.NewKey(s) -} - -func getQueueHeadTail(ctx context.Context, datastore datastore.Datastore) (uint64, uint64, error) { - head, err := getQueueHead(datastore) - if err != nil { - return 0, 0, err - } - tail, err := getQueueTail(datastore) - if err != nil { - return 0, 0, err - } - return head, tail, nil -} - -func getQueueHead(ds datastore.Datastore) (uint64, error) { - return getFirstIDByOrder(ds, query.OrderByKey{}) -} - -func getQueueTail(ds datastore.Datastore) (uint64, error) { - tail, err := getFirstIDByOrder(ds, query.OrderByKeyDescending{}) - if err != nil { - return 0, err - } - if tail > 0 { - tail++ - } - return tail, nil -} - -func getFirstIDByOrder(ds datastore.Datastore, order query.Order) (uint64, error) { - q := query.Query{Orders: []query.Order{order}} - results, err := ds.Query(q) - if err != nil { - return 0, err - } - defer results.Close() - r, ok := results.NextSync() - if !ok { - return 0, nil - } - trimmed := strings.TrimPrefix(r.Key, "/") - id, err := strconv.ParseUint(trimmed, 16, 64) - if err != nil { - return 0, err - } - return id, nil -} diff --git a/provider/queue_test.go b/provider/queue_test.go deleted file mode 100644 index e151478d9f3..00000000000 --- a/provider/queue_test.go +++ /dev/null @@ -1,158 +0,0 @@ -package provider - -import ( - "context" - "testing" - "time" - - cid "github.com/ipfs/go-cid" - datastore "github.com/ipfs/go-datastore" - sync "github.com/ipfs/go-datastore/sync" -) - -func makeCids(n int) []cid.Cid { - cids := make([]cid.Cid, 0, n) - for i := 0; i < n; i++ { - c := blockGenerator.Next().Cid() - cids = append(cids, c) - } - return cids -} - -func assertOrdered(cids []cid.Cid, q *Queue, t *testing.T) { - for _, c := range cids { - select { - case dequeued := <-q.dequeue: - if c != dequeued { - t.Fatalf("Error in ordering of CIDs retrieved from queue. Expected: %s, got: %s", c, dequeued) - } - - case <-time.After(time.Second * 1): - t.Fatal("Timeout waiting for cids to be provided.") - } - } -} - -func TestBasicOperation(t *testing.T) { - ctx := context.Background() - defer ctx.Done() - - ds := sync.MutexWrap(datastore.NewMapDatastore()) - queue, err := NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - cids := makeCids(10) - - for _, c := range cids { - queue.Enqueue(c) - } - - assertOrdered(cids, queue, t) -} - -func TestSparseDatastore(t *testing.T) { - ctx := context.Background() - defer ctx.Done() - - ds := sync.MutexWrap(datastore.NewMapDatastore()) - queue, err := NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - cids := makeCids(10) - for _, c := range cids { - queue.Enqueue(c) - } - - // remove entries in the middle - err = queue.ds.Delete(queue.queueKey(5)) - if err != nil { - t.Fatal(err) - } - - err = queue.ds.Delete(queue.queueKey(6)) - if err != nil { - t.Fatal(err) - } - - expected := append(cids[:5], cids[7:]...) - assertOrdered(expected, queue, t) -} - -func TestMangledData(t *testing.T) { - ctx := context.Background() - defer ctx.Done() - - ds := sync.MutexWrap(datastore.NewMapDatastore()) - queue, err := NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - cids := makeCids(10) - for _, c := range cids { - queue.Enqueue(c) - } - - // remove entries in the middle - err = queue.ds.Put(queue.queueKey(5), []byte("borked")) - if err != nil { - t.Fatal(err) - } - - expected := append(cids[:5], cids[6:]...) - assertOrdered(expected, queue, t) -} - -func TestInitialization(t *testing.T) { - ctx := context.Background() - defer ctx.Done() - - ds := sync.MutexWrap(datastore.NewMapDatastore()) - queue, err := NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - cids := makeCids(10) - for _, c := range cids { - queue.Enqueue(c) - } - - assertOrdered(cids[:5], queue, t) - - // make a new queue, same data - queue, err = NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - assertOrdered(cids[5:], queue, t) -} - -func TestInitializationWithManyCids(t *testing.T) { - ctx := context.Background() - defer ctx.Done() - - ds := sync.MutexWrap(datastore.NewMapDatastore()) - queue, err := NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - cids := makeCids(25) - for _, c := range cids { - queue.Enqueue(c) - } - - // make a new queue, same data - queue, err = NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - assertOrdered(cids, queue, t) -} diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index d35c97140c5..a14e96ff25c 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -11,7 +11,7 @@ import ( "strings" "sync" - filestore "github.com/ipfs/go-ipfs/filestore" + filestore "github.com/ipfs/go-filestore" keystore "github.com/ipfs/go-ipfs/keystore" repo "github.com/ipfs/go-ipfs/repo" "github.com/ipfs/go-ipfs/repo/common" @@ -36,7 +36,7 @@ const LockFile = "repo.lock" var log = logging.Logger("fsrepo") // version number that we are currently expecting to see -var RepoVersion = 7 +var RepoVersion = 9 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.` @@ -403,7 +403,7 @@ func (r *FSRepo) openDatastore() error { return fmt.Errorf("required Datastore.Spec entry missing from config file") } if r.config.Datastore.NoSync { - log.Warning("NoSync is now deprecated in favor of datastore specific settings. If you want to disable fsync on flatfs set 'sync' to false. See https://github.com/ipfs/go-ipfs/blob/master/docs/datastores.md#flatfs.") + log.Warn("NoSync is now deprecated in favor of datastore specific settings. If you want to disable fsync on flatfs set 'sync' to false. See https://github.com/ipfs/go-ipfs/blob/master/docs/datastores.md#flatfs.") } dsc, err := AnyDatastoreConfig(r.config.Datastore.Spec) @@ -457,7 +457,7 @@ func (r *FSRepo) Close() error { err := os.Remove(filepath.Join(r.path, apiFile)) if err != nil && !os.IsNotExist(err) { - log.Warning("error removing api file: ", err) + log.Warn("error removing api file: ", err) } if err := r.ds.Close(); err != nil { diff --git a/repo/fsrepo/migrations/migrations.go b/repo/fsrepo/migrations/migrations.go index de71de60d9d..bc6a4bf34cc 100644 --- a/repo/fsrepo/migrations/migrations.go +++ b/repo/fsrepo/migrations/migrations.go @@ -15,7 +15,7 @@ import ( "strings" ) -var DistPath = "https://ipfs.io/ipfs/QmZLYJBVBK8nqc5JTHp6CZU1v9Ja3MvGrkCe61PfCecc6E" +var DistPath = "https://ipfs.io/ipfs/QmUgfXycSjF9R8F4Tyauaz6LZ4bj5nbksg54G9GdF4fit6" func init() { if dist := os.Getenv("IPFS_DIST_PATH"); dist != "" { @@ -116,7 +116,7 @@ func verifyMigrationSupportsVersion(fsrbin string, vn int) error { return nil } - return fmt.Errorf("migrations binary doesnt support version %d: %s", vn, fsrbin) + return fmt.Errorf("migrations binary doesn't support version %d: %s", vn, fsrbin) } func migrationsVersion(bin string) (int, error) { @@ -163,13 +163,13 @@ func GetLatestVersion(ipfspath, dist string) (string, error) { } } if latest == "" { - return "", fmt.Errorf("couldnt find a non dev version in the list") + return "", fmt.Errorf("couldn't find a non dev version in the list") } return vs[len(vs)-1], nil } func httpGet(url string) (*http.Response, error) { - req, err := http.NewRequest("GET", url, nil) + req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { return nil, fmt.Errorf("http.NewRequest error: %s", err) } diff --git a/repo/mock.go b/repo/mock.go index 78ec9073b4b..f39fe6f1795 100644 --- a/repo/mock.go +++ b/repo/mock.go @@ -3,7 +3,7 @@ package repo import ( "errors" - filestore "github.com/ipfs/go-ipfs/filestore" + filestore "github.com/ipfs/go-filestore" keystore "github.com/ipfs/go-ipfs/keystore" config "github.com/ipfs/go-ipfs-config" @@ -45,7 +45,7 @@ func (m *Mock) Datastore() Datastore { return m.D } func (m *Mock) GetStorageUsage() (uint64, error) { return 0, nil } -func (m *Mock) Close() error { return errTODO } +func (m *Mock) Close() error { return m.D.Close() } func (m *Mock) SetAPIAddr(addr ma.Multiaddr) error { return errTODO } diff --git a/repo/onlyone.go b/repo/onlyone.go index 860c166bf24..f24717c2b9c 100644 --- a/repo/onlyone.go +++ b/repo/onlyone.go @@ -12,7 +12,7 @@ type OnlyOne struct { } // Open a Repo identified by key. If Repo is not already open, the -// open function is called, and the result is remember for further +// open function is called, and the result is remembered for further // use. // // Key must be comparable, or Open will panic. Make sure to pick keys diff --git a/repo/repo.go b/repo/repo.go index ffb024afae7..5c2557c6a82 100644 --- a/repo/repo.go +++ b/repo/repo.go @@ -4,7 +4,7 @@ import ( "errors" "io" - filestore "github.com/ipfs/go-ipfs/filestore" + filestore "github.com/ipfs/go-filestore" keystore "github.com/ipfs/go-ipfs/keystore" ds "github.com/ipfs/go-datastore" diff --git a/reprovide/providers.go b/reprovide/providers.go deleted file mode 100644 index bef56a0b720..00000000000 --- a/reprovide/providers.go +++ /dev/null @@ -1,75 +0,0 @@ -package reprovide - -import ( - "context" - - pin "github.com/ipfs/go-ipfs/pin" - - cid "github.com/ipfs/go-cid" - cidutil "github.com/ipfs/go-cidutil" - blocks "github.com/ipfs/go-ipfs-blockstore" - ipld "github.com/ipfs/go-ipld-format" - merkledag "github.com/ipfs/go-merkledag" -) - -// NewBlockstoreProvider returns key provider using bstore.AllKeysChan -func NewBlockstoreProvider(bstore blocks.Blockstore) KeyChanFunc { - return func(ctx context.Context) (<-chan cid.Cid, error) { - return bstore.AllKeysChan(ctx) - } -} - -// NewPinnedProvider returns provider supplying pinned keys -func NewPinnedProvider(onlyRoots bool) func(pinning pin.Pinner, dag ipld.DAGService) KeyChanFunc { - return func(pinning pin.Pinner, dag ipld.DAGService) KeyChanFunc { - return func(ctx context.Context) (<-chan cid.Cid, error) { - set, err := pinSet(ctx, pinning, dag, onlyRoots) - if err != nil { - return nil, err - } - - outCh := make(chan cid.Cid) - go func() { - defer close(outCh) - for c := range set.New { - select { - case <-ctx.Done(): - return - case outCh <- c: - } - } - - }() - - return outCh, nil - } - } -} - -func pinSet(ctx context.Context, pinning pin.Pinner, dag ipld.DAGService, onlyRoots bool) (*cidutil.StreamingSet, error) { - set := cidutil.NewStreamingSet() - - go func() { - ctx, cancel := context.WithCancel(ctx) - defer cancel() - defer close(set.New) - - for _, key := range pinning.DirectKeys() { - set.Visitor(ctx)(key) - } - - for _, key := range pinning.RecursiveKeys() { - set.Visitor(ctx)(key) - - if !onlyRoots { - err := merkledag.EnumerateChildren(ctx, merkledag.GetLinksWithDAG(dag), key, set.Visitor(ctx)) - if err != nil { - log.Errorf("reprovide indirect pins: %s", err) - return - } - } - } - }() - - return set, nil -} diff --git a/reprovide/reprovide.go b/reprovide/reprovide.go deleted file mode 100644 index 1a6f5bad3f0..00000000000 --- a/reprovide/reprovide.go +++ /dev/null @@ -1,159 +0,0 @@ -package reprovide - -import ( - "context" - "errors" - "fmt" - "time" - - "github.com/cenkalti/backoff" - "github.com/ipfs/go-cid" - logging "github.com/ipfs/go-log" - "github.com/ipfs/go-verifcid" - "github.com/jbenet/goprocess" - goprocessctx "github.com/jbenet/goprocess/context" - routing "github.com/libp2p/go-libp2p-routing" -) - -var log = logging.Logger("reprovider") - -// KeyChanFunc is function streaming CIDs to pass to content routing -type KeyChanFunc func(context.Context) (<-chan cid.Cid, error) -type doneFunc func(error) - -type Reprovider struct { - ctx context.Context - trigger chan doneFunc - closing chan struct{} - - // The routing system to provide values through - rsys routing.ContentRouting - - keyProvider KeyChanFunc - tick time.Duration -} - -// NewReprovider creates new Reprovider instance. -func NewReprovider(ctx context.Context, tick time.Duration, rsys routing.ContentRouting, keyProvider KeyChanFunc) *Reprovider { - return &Reprovider{ - ctx: ctx, - trigger: make(chan doneFunc), - closing: make(chan struct{}), - - rsys: rsys, - keyProvider: keyProvider, - tick: tick, - } -} - -// Run re-provides keys with 'tick' interval or when triggered -func (rp *Reprovider) Run(proc goprocess.Process) { - ctx := goprocessctx.WithProcessClosing(rp.ctx, proc) - defer close(rp.closing) - - // dont reprovide immediately. - // may have just started the daemon and shutting it down immediately. - // probability( up another minute | uptime ) increases with uptime. - after := time.After(time.Minute) - var done doneFunc - for { - if rp.tick == 0 { - after = make(chan time.Time) - } - - select { - case <-ctx.Done(): - return - case done = <-rp.trigger: - case <-after: - } - - // 'mute' the trigger channel so when `ipfs bitswap reprovide` is called - // a 'reprovider is already running' error is returned - unmute := rp.muteTrigger() - - err := rp.reprovide(ctx) - if err != nil { - log.Debug(err) - } - - if done != nil { - done(err) - } - - unmute() - - after = time.After(rp.tick) - } -} - -// reprovide registers all keys given by rp.keyProvider to libp2p content routing -func (rp *Reprovider) reprovide(ctx context.Context) error { - keychan, err := rp.keyProvider(ctx) - if err != nil { - return fmt.Errorf("failed to get key chan: %s", err) - } - for c := range keychan { - // hash security - if err := verifcid.ValidateCid(c); err != nil { - log.Errorf("insecure hash in reprovider, %s (%s)", c, err) - continue - } - op := func() error { - err := rp.rsys.Provide(ctx, c, true) - if err != nil { - log.Debugf("Failed to provide key: %s", err) - } - return err - } - - // TODO: this backoff library does not respect our context, we should - // eventually work contexts into it. low priority. - err := backoff.Retry(op, backoff.NewExponentialBackOff()) - if err != nil { - log.Debugf("Providing failed after number of retries: %s", err) - return err - } - } - return nil -} - -// Trigger starts reprovision process in rp.Run and waits for it -func (rp *Reprovider) Trigger(ctx context.Context) error { - progressCtx, done := context.WithCancel(ctx) - - var err error - df := func(e error) { - err = e - done() - } - - select { - case <-rp.closing: - return errors.New("reprovider is closed") - case <-rp.ctx.Done(): - return rp.ctx.Err() - case <-ctx.Done(): - return ctx.Err() - case rp.trigger <- df: - <-progressCtx.Done() - return err - } -} - -func (rp *Reprovider) muteTrigger() context.CancelFunc { - ctx, cf := context.WithCancel(rp.ctx) - go func() { - defer cf() - for { - select { - case <-ctx.Done(): - return - case done := <-rp.trigger: - done(fmt.Errorf("reprovider is already running")) - } - } - }() - - return cf -} diff --git a/reprovide/reprovide_test.go b/reprovide/reprovide_test.go deleted file mode 100644 index b9e9738b440..00000000000 --- a/reprovide/reprovide_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package reprovide - -import ( - "context" - "testing" - - blocks "github.com/ipfs/go-block-format" - ds "github.com/ipfs/go-datastore" - dssync "github.com/ipfs/go-datastore/sync" - blockstore "github.com/ipfs/go-ipfs-blockstore" - mock "github.com/ipfs/go-ipfs-routing/mock" - pstore "github.com/libp2p/go-libp2p-peerstore" - "github.com/libp2p/go-testutil" -) - -func TestReprovide(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - mrserv := mock.NewServer() - - idA := testutil.RandIdentityOrFatal(t) - idB := testutil.RandIdentityOrFatal(t) - - clA := mrserv.Client(idA) - clB := mrserv.Client(idB) - - bstore := blockstore.NewBlockstore(dssync.MutexWrap(ds.NewMapDatastore())) - - blk := blocks.NewBlock([]byte("this is a test")) - err := bstore.Put(blk) - if err != nil { - t.Fatal(err) - } - - keyProvider := NewBlockstoreProvider(bstore) - reprov := NewReprovider(ctx, 0, clA, keyProvider) - err = reprov.reprovide(ctx) - if err != nil { - t.Fatal(err) - } - - var providers []pstore.PeerInfo - maxProvs := 100 - - provChan := clB.FindProvidersAsync(ctx, blk.Cid(), maxProvs) - for p := range provChan { - providers = append(providers, p) - } - - if len(providers) == 0 { - t.Fatal("Should have gotten a provider") - } - - if providers[0].ID != idA.ID() { - t.Fatal("Somehow got the wrong peer back as a provider.") - } -} diff --git a/tar/format.go b/tar/format.go index 02fb4b2cd33..2bbf7298fd1 100644 --- a/tar/format.go +++ b/tar/format.go @@ -8,8 +8,8 @@ import ( "io" "strings" - "github.com/ipfs/go-ipfs/dagutils" dag "github.com/ipfs/go-merkledag" + "github.com/ipfs/go-merkledag/dagutils" path "github.com/ipfs/go-path" importer "github.com/ipfs/go-unixfs/importer" uio "github.com/ipfs/go-unixfs/io" diff --git a/test/3nodetest/Makefile b/test/3nodetest/GNUmakefile similarity index 100% rename from test/3nodetest/Makefile rename to test/3nodetest/GNUmakefile diff --git a/test/3nodetest/bootstrap/Dockerfile b/test/3nodetest/bootstrap/Dockerfile index 3fd42f5671d..ed8ac9ffa52 100644 --- a/test/3nodetest/bootstrap/Dockerfile +++ b/test/3nodetest/bootstrap/Dockerfile @@ -1,6 +1,6 @@ FROM zaqwsx_ipfs-test-img -RUN ipfs init -b=1024 +RUN ipfs init -b=2048 ADD . /tmp/id RUN mv -f /tmp/id/config /root/.ipfs/config RUN ipfs id diff --git a/test/3nodetest/client/Dockerfile b/test/3nodetest/client/Dockerfile index c2ac8d725c4..d4e1ffa36d4 100644 --- a/test/3nodetest/client/Dockerfile +++ b/test/3nodetest/client/Dockerfile @@ -1,6 +1,6 @@ FROM zaqwsx_ipfs-test-img -RUN ipfs init -b=1024 +RUN ipfs init -b=2048 ADD . /tmp/id RUN mv -f /tmp/id/config /root/.ipfs/config RUN ipfs id diff --git a/test/3nodetest/client/run.sh b/test/3nodetest/client/run.sh index 7a34d7bbc0b..f3bb966e849 100644 --- a/test/3nodetest/client/run.sh +++ b/test/3nodetest/client/run.sh @@ -1,4 +1,4 @@ -ipfs bootstrap add /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/ipfs/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE +ipfs bootstrap add /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/p2p/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE ipfs bootstrap # list bootstrap nodes for debugging echo "3nodetest> starting client daemon" diff --git a/test/3nodetest/run-test-on-img.sh b/test/3nodetest/run-test-on-img.sh index 73b1935ac0f..ada96edf0be 100755 --- a/test/3nodetest/run-test-on-img.sh +++ b/test/3nodetest/run-test-on-img.sh @@ -9,7 +9,7 @@ fi # {data, server, client, bootstrap} tag=zaqwsx_ipfs-test-img -# could use set -v, but i dont want to see the comments... +# could use set -v, but i don't want to see the comments... img=$(docker images | grep $1 | awk '{print $3}') echo "using docker image: $img ($1)" diff --git a/test/3nodetest/server/Dockerfile b/test/3nodetest/server/Dockerfile index bced683546c..935d2e1b022 100644 --- a/test/3nodetest/server/Dockerfile +++ b/test/3nodetest/server/Dockerfile @@ -1,6 +1,6 @@ FROM zaqwsx_ipfs-test-img -RUN ipfs init -b=1024 +RUN ipfs init -b=2048 ADD . /tmp/test RUN mv -f /tmp/test/config /root/.ipfs/config RUN ipfs id diff --git a/test/3nodetest/server/run.sh b/test/3nodetest/server/run.sh index 325ae3c3c6c..dfe586310ea 100644 --- a/test/3nodetest/server/run.sh +++ b/test/3nodetest/server/run.sh @@ -1,5 +1,5 @@ # must be connected to bootstrap node -ipfs bootstrap add /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/ipfs/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE +ipfs bootstrap add /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/p2p/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE ipfs bootstrap # list bootstrap nodes for debugging # wait for daemon to start/bootstrap @@ -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/ipfs/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE +# TODO instead of bootrapping: 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 dbd092891fa..727a87aea2f 100644 --- a/test/bench/bench_cli_ipfs_add/main.go +++ b/test/bench/bench_cli_ipfs_add/main.go @@ -65,7 +65,7 @@ func benchmarkAdd(amount int64) (*testing.BenchmarkResult, error) { } } - initCmd := exec.Command("ipfs", "init", "-b=1024") + initCmd := exec.Command("ipfs", "init", "-b=2048") setupCmd(initCmd) if err := initCmd.Run(); err != nil { benchmarkError = err diff --git a/test/bench/offline_add/main.go b/test/bench/offline_add/main.go index 74597686364..94e8cac23ba 100644 --- a/test/bench/offline_add/main.go +++ b/test/bench/offline_add/main.go @@ -49,7 +49,7 @@ func benchmarkAdd(amount int64) (*testing.BenchmarkResult, error) { cmd.Env = env } - cmd := exec.Command("ipfs", "init", "-b=1024") + cmd := exec.Command("ipfs", "init", "-b=2048") setupCmd(cmd) if err := cmd.Run(); err != nil { b.Fatal(err) diff --git a/test/bin/Rules.mk b/test/bin/Rules.mk index 88eaa6ae92c..b01ec7dd042 100644 --- a/test/bin/Rules.mk +++ b/test/bin/Rules.mk @@ -18,6 +18,11 @@ $(d)/go-sleep: github.com/ipfs/go-ipfs/test/dependencies/go-sleep $(go-build-testdep) TGTS_$(d) += $(d)/go-sleep +.PHONY: github.com/ipfs/go-ipfs/test/dependencies/graphsync-get +$(d)/graphsync-get: github.com/ipfs/go-ipfs/test/dependencies/graphsync-get + $(go-build-testdep) +TGTS_$(d) += $(d)/graphsync-get + .PHONY: github.com/ipfs/go-ipfs/test/dependencies/go-timeout $(d)/go-timeout: github.com/ipfs/go-ipfs/test/dependencies/go-timeout $(go-build-testdep) diff --git a/test/dependencies/Makefile b/test/dependencies/GNUmakefile similarity index 100% rename from test/dependencies/Makefile rename to test/dependencies/GNUmakefile diff --git a/test/dependencies/go.mod b/test/dependencies/go.mod index b456e7d1a68..9c33af08235 100644 --- a/test/dependencies/go.mod +++ b/test/dependencies/go.mod @@ -5,17 +5,26 @@ go 1.13 require ( github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd github.com/golangci/golangci-lint v1.18.0 + github.com/ipfs/go-blockservice v0.1.2 + github.com/ipfs/go-cid v0.0.5 github.com/ipfs/go-cidutil v0.0.2 - github.com/ipfs/go-log v0.0.1 - github.com/ipfs/hang-fds v0.0.1 + github.com/ipfs/go-datastore v0.4.4 + github.com/ipfs/go-graphsync v0.0.4 + github.com/ipfs/go-ipfs-blockstore v1.0.0 + github.com/ipfs/go-ipfs-exchange-offline v0.0.1 + github.com/ipfs/go-log v1.0.2 + github.com/ipfs/go-merkledag v0.3.1 + github.com/ipfs/go-unixfs v0.2.4 + github.com/ipfs/hang-fds v0.0.2 github.com/ipfs/iptb v1.4.0 - github.com/ipfs/iptb-plugins v0.2.0 + github.com/ipfs/iptb-plugins v0.2.2 + github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785 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.0.4 - github.com/multiformats/go-multiaddr-net v0.0.1 - github.com/multiformats/go-multihash v0.0.7 - github.com/ultraware/funlen v0.0.2 // indirect - golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89 // indirect + github.com/libp2p/go-libp2p v0.5.2 + github.com/libp2p/go-libp2p-core v0.3.1 + github.com/multiformats/go-multiaddr v0.2.0 + github.com/multiformats/go-multiaddr-net v0.1.2 + github.com/multiformats/go-multihash v0.0.13 gotest.tools/gotestsum v0.3.5 ) diff --git a/test/dependencies/go.sum b/test/dependencies/go.sum index 616c4afba53..f4ea381a1ad 100644 --- a/test/dependencies/go.sum +++ b/test/dependencies/go.sum @@ -6,19 +6,27 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= 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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenPeeDeeP/depguard v1.0.0 h1:k9QF73nrHT3nPLz3lu6G5s+3Hi8Je36ODr1F5gjAXXM= github.com/OpenPeeDeeP/depguard v1.0.0/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/Stebalien/go-bitfield v0.0.1 h1:X3kbSSPUaJK60wV2hjOPZwmpljr6VGCqdq4cBLhbQBo= +github.com/Stebalien/go-bitfield v0.0.1/go.mod h1:GNjFpasyUVkHMsfEOk8EFLJ9syQ6SI+XWrX9Wf2XH0s= github.com/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/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 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/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q= github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8 h1:mOg8/RgDSHTQ1R0IR+LMDuW4TDShPv+JzYHuR4GLoNA= +github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -27,7 +35,6 @@ github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVa github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -35,16 +42,19 @@ 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 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +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/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= @@ -89,7 +99,12 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.0.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= @@ -98,6 +113,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 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= @@ -135,10 +152,18 @@ github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSW github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 h1:JVnpOZS+qxli+rgVl98ILOXVNbW+kb5wcxeGx8ShUIw= github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gxed/go-shellwords v1.0.3 h1:2TP32H4TAklZUdz84oj95BJhVnIrRasyx2j1cqH5K38= @@ -150,6 +175,9 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= 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= @@ -160,32 +188,119 @@ github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7 github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/ipfs/bbloom v0.0.1/go.mod h1:oqo8CVWsJFMOZqTglBG4wydCE4IQA/G2/SEofB0rjUI= +github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= +github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= +github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= +github.com/ipfs/go-bitswap v0.1.2 h1:IkhOPiifc6b2LWTi/vp8TXwNT0eGCsizI1JFbZ08IQQ= +github.com/ipfs/go-bitswap v0.1.2/go.mod h1:qxSWS4NXGs7jQ6zQvoPY3+NmOfHHG47mhkiLzBpJQIs= +github.com/ipfs/go-bitswap v0.1.3 h1:jAl9Z/TYObpGeGATUemnOZ7RYb0F/kzNVlhcYZesz+0= +github.com/ipfs/go-bitswap v0.1.3/go.mod h1:YEQlFy0kkxops5Vy+OxWdRSEZIoS7I7KDIwoa5Chkps= +github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= +github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= +github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= +github.com/ipfs/go-blockservice v0.1.0 h1:dh2i7xjMbCtf0ZSMyQAF2qpV/pEEmM7yVpQ00+gik6U= +github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= +github.com/ipfs/go-blockservice v0.1.2 h1:fqFeeu1EG0lGVrqUo+BVJv7LZV31I4ZsyNthCOMAJRc= +github.com/ipfs/go-blockservice v0.1.2/go.mod h1:t+411r7psEUhLueM8C7aPA7cxCclv4O3VsUVxt9kz2I= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.2 h1:tuuKaZPU1M6HcejsO3AcYWW8sZ8MTvyxfc4uqB4eFE8= github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= +github.com/ipfs/go-cid v0.0.5 h1:o0Ix8e/ql7Zb5UVUJEUfjsWCIY8t48++9lR8qi6oiJU= +github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= github.com/ipfs/go-cidutil v0.0.2 h1:CNOboQf1t7Qp0nuNh8QMmhJs0+Q//bRL1axtCnIB1Yo= github.com/ipfs/go-cidutil v0.0.2/go.mod h1:ewllrvrxG6AMYStla3GD7Cqn+XYSLqjK0vc+086tB6s= github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-datastore v0.0.5 h1:q3OfiOZV5rlsK1H5V8benjeUApRfMGs4Mrhmr6NriQo= github.com/ipfs/go-datastore v0.0.5/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= +github.com/ipfs/go-datastore v0.3.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= +github.com/ipfs/go-datastore v0.4.1 h1:W4ZfzyhNi3xmuU5dQhjfuRn/wFuqEE1KnOmmQiOevEY= +github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= +github.com/ipfs/go-datastore v0.4.4 h1:rjvQ9+muFaJ+QZ7dN5B1MSDNQ0JVZKkkES/rMZmA8X8= +github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= +github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= -github.com/ipfs/go-ipfs-config v0.0.6 h1:jzK9Tl8S0oWBir3F5ObtGgnHRPdqQ0MYiCmwXtV3Ps4= -github.com/ipfs/go-ipfs-config v0.0.6/go.mod h1:IGkVTacurWv9WFKc7IBPjHGM/7hi6+PEClqUb/l2BIM= +github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= +github.com/ipfs/go-graphsync v0.0.4 h1:iF98+J8pcqvEb48IM0TemqeGARsCDtwQ73P9ejMZIuU= +github.com/ipfs/go-graphsync v0.0.4/go.mod h1:6UACBjfOXEa8rQL3Q/JpZpWS0nZDCLx134WUkjrmFpQ= +github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= +github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= +github.com/ipfs/go-ipfs-blockstore v1.0.0 h1:pmFp5sFYsYVvMOp9X01AK3s85usVcLvkBTRsN6SnfUA= +github.com/ipfs/go-ipfs-blockstore v1.0.0/go.mod h1:knLVdhVU9L7CC4T+T4nvGdeUIPAXlnd9zmXfp+9MIjU= +github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= +github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk= +github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE27SEw= +github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= +github.com/ipfs/go-ipfs-config v0.0.11 h1:5/4nas2CQXiKr2/MLxU24GDGTBvtstQIQezuk7ltOQQ= +github.com/ipfs/go-ipfs-config v0.0.11/go.mod h1:wveA8UT5ywN26oKStByzmz1CO6cXwLKKM6Jn/Hfw08I= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= +github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= +github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= +github.com/ipfs/go-ipfs-ds-help v0.0.1/go.mod h1:gtP9xRaZXqIQRh1HRpp595KbBEdgqWFxefeVKOV8sxo= +github.com/ipfs/go-ipfs-ds-help v1.0.0 h1:bEQ8hMGs80h0sR8O4tfDgV6B01aaF9qeTrujrTLYV3g= +github.com/ipfs/go-ipfs-ds-help v1.0.0/go.mod h1:ujAbkeIgkKAWtxxNkoZHWLCyk5JpPoKnGyCcsoF6ueE= +github.com/ipfs/go-ipfs-exchange-interface v0.0.1 h1:LJXIo9W7CAmugqI+uofioIpRb6rY30GUu7G6LUfpMvM= +github.com/ipfs/go-ipfs-exchange-interface v0.0.1/go.mod h1:c8MwfHjtQjPoDyiy9cFquVtVHkO9b9Ob3FG91qJnWCM= +github.com/ipfs/go-ipfs-exchange-offline v0.0.1 h1:P56jYKZF7lDDOLx5SotVh5KFxoY6C81I1NSHW1FxGew= +github.com/ipfs/go-ipfs-exchange-offline v0.0.1/go.mod h1:WhHSFCVYX36H/anEKQboAzpUws3x7UeEGkzQc3iNkM0= +github.com/ipfs/go-ipfs-files v0.0.3/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= +github.com/ipfs/go-ipfs-files v0.0.4 h1:WzRCivcybUQch/Qh6v8LBRhKtRsjnwyiuOV09mK7mrE= +github.com/ipfs/go-ipfs-files v0.0.4/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= +github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= +github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= +github.com/ipfs/go-ipfs-pq v0.0.1 h1:zgUotX8dcAB/w/HidJh1zzc1yFq6Vm8J7T2F4itj/RU= +github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= +github.com/ipfs/go-ipfs-routing v0.1.0 h1:gAJTT1cEeeLj6/DlLX6t+NxD9fQe2ymTO6qWRDI/HQQ= +github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50= github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= +github.com/ipfs/go-ipld-cbor v0.0.2 h1:amzFztBQQQ69UA5+f7JRfoXF/z2l//MGfEDHVkS20+s= +github.com/ipfs/go-ipld-cbor v0.0.2/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc= +github.com/ipfs/go-ipld-cbor v0.0.3 h1:ENsxvybwkmke7Z/QJOmeJfoguj6GH3Y0YOaGrfy9Q0I= +github.com/ipfs/go-ipld-cbor v0.0.3/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc= +github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms= +github.com/ipfs/go-ipld-format v0.0.2 h1:OVAGlyYT6JPZ0pEfGntFPS40lfrDmaDbQwNHEY2G9Zs= +github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k= github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= +github.com/ipfs/go-log v1.0.2 h1:s19ZwJxH8rPWzypjcDpqPLIyV7BnbLqvpli3iZoqYK0= +github.com/ipfs/go-log v1.0.2/go.mod h1:1MNjMxe0u6xvJZgeqbJ8vdo2TKaGwZ1a0Bpza+sr2Sk= +github.com/ipfs/go-log/v2 v2.0.2 h1:xguurydRdfKMJjKyxNXNU8lYP0VZH1NUwJRwUorjuEw= +github.com/ipfs/go-log/v2 v2.0.2/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= +github.com/ipfs/go-merkledag v0.2.3 h1:aMdkK9G1hEeNvn3VXfiEMLY0iJnbiQQUHnM0HFJREsE= +github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= +github.com/ipfs/go-merkledag v0.3.1 h1:3UqWINBEr3/N+r6OwgFXAddDP/8zpQX/8J7IGVOCqRQ= +github.com/ipfs/go-merkledag v0.3.1/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= +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.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= +github.com/ipfs/go-peertaskqueue v0.1.1 h1:+gPjbI+V3NktXZOqJA1kzbms2pYmhjgQQal0MzZrOAY= +github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= -github.com/ipfs/hang-fds v0.0.1 h1:KGAxiGtJPT3THVRNT6yxgpdFPeX4ZemUjENOt6NlOn4= -github.com/ipfs/hang-fds v0.0.1/go.mod h1:U4JNbzwTpk/qP2Ms4VgrZ4HcgJGVosBJqMXvwe4udSY= +github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb h1:tmWYgjltxwM7PDmFJgWgLuy5qx24csUvRoIiO+F/zQ4= +github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb/go.mod h1:IwAAgul1UQIcNZzKPYZWOCijryFBeCV79cNubPzol+k= +github.com/ipfs/go-unixfs v0.2.4 h1:6NwppOXefWIyysZ4LR/qUBPvXd5//8J3jiMdvpbw6Lo= +github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= +github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= +github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= +github.com/ipfs/hang-fds v0.0.2 h1:ffZPd+OFbKpfjNAoBCI+G7okTQKd7oS1jCEDm2Kzm4c= +github.com/ipfs/hang-fds v0.0.2/go.mod h1:Ajpp/qR2orKbv5LsZmotGRASTcH38MwcIG5vTlZ9y8k= 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.2.0 h1:HJUvew9ZJweCW71YeblvNui07pZtyiZnuUzrk49ol9Q= -github.com/ipfs/iptb-plugins v0.2.0/go.mod h1:J2wpKQKaLa9eQC8sQtSkjdjbUfdQEAHXqnbj86f55gI= +github.com/ipfs/iptb-plugins v0.2.2 h1:HleRKMeex/jmQrmNG36v51M3eZO5j9BhFplBPGs0qGQ= +github.com/ipfs/iptb-plugins v0.2.2/go.mod h1:QXMbtIWZ+jRsW8a4h13qAKU7jcM7qaittO8wOsTP0Rs= +github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785 h1:fASnkvtR+SmB2y453RxmDD3Uvd4LonVUgFGk9JoDaZs= +github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= +github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5 h1:lSip43rAdyGA+yRQuy6ju0ucZkWpYc1F2CTQtZTVW/4= +github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU= github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= @@ -207,9 +322,15 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v0.0.0-20161130080628-0de1eaf82fa3/go.mod h1:jxZFDH7ILpTPQTk+E2s+z4CUas9lVNjIuKR4c5/zKgM= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -222,6 +343,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGi 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.0-20180514024734-4a0ed625a78b h1:wxtKgYHEncAU00muMD06dzLiahtGM1eouRNOzVV7tdQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= +github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d h1:68u9r4wEvL3gYg2jvAOgROwZ3H+Y3hIDk4tbbmIjcYQ= +github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -237,33 +360,61 @@ github.com/libp2p/go-conn-security-multistream v0.1.0 h1:aqGmto+ttL/uJgX0JtQI0tD github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= github.com/libp2p/go-eventbus v0.0.2 h1:L9eslON8FjFBJlyUs9fyEZKnxSqZd2AMDUNldPrqmZI= github.com/libp2p/go-eventbus v0.0.2/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk= +github.com/libp2p/go-eventbus v0.0.3 h1:4sB0NrwnWr6qGeq2RWUp/JG1wNajf6gyILInId72hrw= +github.com/libp2p/go-eventbus v0.0.3/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk= +github.com/libp2p/go-eventbus v0.1.0 h1:mlawomSAjjkk97QnYiEmHsLu7E136+2oCWSHRUvMfzQ= +github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= +github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM= +github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM= -github.com/libp2p/go-libp2p v0.3.0 h1:XhYEJKmIdi4U4Zbie/ym9k6lqgg3PHM2stGS/cOUDWk= -github.com/libp2p/go-libp2p v0.3.0/go.mod h1:J7DPB1+zB5VLc8v/kKSD8+u2cbyIGI0Dh/Pf3Wprt+0= +github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8= +github.com/libp2p/go-libp2p v0.2.1/go.mod h1:HZbtEOrgZN4F1fGZVvkV+930Wx3DkqlpBlO8dIoZWds= +github.com/libp2p/go-libp2p v0.3.1/go.mod h1:e6bwxbdYH1HqWTz8faTChKGR0BjPc8p+6SyP8GTTR7Y= +github.com/libp2p/go-libp2p v0.4.0/go.mod h1:9EsEIf9p2UDuwtPd0DwJsAl0qXVxgAnuDGRvHbfATfI= +github.com/libp2p/go-libp2p v0.5.2 h1:fjQUTyB7x/4XgO31OEWkJ5uFeHRgpoExlf0rXz5BO8k= +github.com/libp2p/go-libp2p v0.5.2/go.mod h1:o2r6AcpNl1eNGoiWhRtPji03NYOvZumeQ6u+X6gSxnM= github.com/libp2p/go-libp2p-autonat v0.1.0 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= +github.com/libp2p/go-libp2p-autonat v0.1.1 h1:WLBZcIRsjZlWdAZj9CiBSvU2wQXoUOiS1Zk1tM7DTJI= +github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= github.com/libp2p/go-libp2p-autonat-svc v0.1.0/go.mod h1:fqi8Obl/z3R4PFVLm8xFtZ6PBL9MlV/xumymRFkKq5A= github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= github.com/libp2p/go-libp2p-blankhost v0.1.3 h1:0KycuXvPDhmehw0ASsg+s1o3IfXgCUDqfzAl94KEBOg= github.com/libp2p/go-libp2p-blankhost v0.1.3/go.mod h1:KML1//wiKR8vuuJO0y3LUd1uLv+tlkGTAr3jC0S5cLg= +github.com/libp2p/go-libp2p-blankhost v0.1.4 h1:I96SWjR4rK9irDHcHq3XHN6hawCRTPUADzkJacgZLvk= +github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU= github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= github.com/libp2p/go-libp2p-circuit v0.1.1 h1:eopfG9fAg6rEHWQO1TSrLosXDgYbbbu/RTva/tBANus= github.com/libp2p/go-libp2p-circuit v0.1.1/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= -github.com/libp2p/go-libp2p-connmgr v0.1.0/go.mod h1:wZxh8veAmU5qdrfJ0ZBLcU8oJe9L82ciVP/fl1VHjXk= +github.com/libp2p/go-libp2p-circuit v0.1.3/go.mod h1:Xqh2TjSy8DD5iV2cCOMzdynd6h8OTBGoV1AWbWor3qM= +github.com/libp2p/go-libp2p-circuit v0.1.4 h1:Phzbmrg3BkVzbqd4ZZ149JxCuUWu2wZcXf/Kr6hZJj8= +github.com/libp2p/go-libp2p-circuit v0.1.4/go.mod h1:CY67BrEjKNDhdTk8UgBX1Y/H5c3xkAcs3gnksxY7osU= +github.com/libp2p/go-libp2p-connmgr v0.1.1/go.mod h1:wZxh8veAmU5qdrfJ0ZBLcU8oJe9L82ciVP/fl1VHjXk= github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= +github.com/libp2p/go-libp2p-core v0.0.2/go.mod h1:9dAcntw/n46XycV4RnlBq3BpgrmyUi9LuoTNdPrbUco= github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE= github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= github.com/libp2p/go-libp2p-core v0.0.6/go.mod h1:0d9xmaYAVY5qmbp/fcgxHT3ZJsLjYeYPMJAUKpaCHrE= +github.com/libp2p/go-libp2p-core v0.0.9/go.mod h1:0d9xmaYAVY5qmbp/fcgxHT3ZJsLjYeYPMJAUKpaCHrE= github.com/libp2p/go-libp2p-core v0.2.0 h1:ycFtuNwtZBAJSxzaHbyv6NjG3Yj5Nmra1csHaQ3zwaw= github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= +github.com/libp2p/go-libp2p-core v0.2.3/go.mod h1:GqhyQqyIAPsxFYXHMjfXgMv03lxsvM0mFzuYA9Ib42A= +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-core v0.3.1 h1:hEnSDjScfjYvPHoTgZhC4F62M8K1x1Oco/BY0RZ1N3s= +github.com/libp2p/go-libp2p-core v0.3.1/go.mod h1:thvWy0hvaSBhnVBaW37BvzgVV68OUhgJJLAa6almrII= +github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= -github.com/libp2p/go-libp2p-daemon v0.2.0/go.mod h1:1hlzu8xFRi+fkC1N+zvhSgznGZGo9HxpJtSrj3X5HQw= +github.com/libp2p/go-libp2p-daemon v0.2.2/go.mod h1:kyrpsLB2JeNYR2rvXSVWyY0iZuRIMhqzWR3im9BV6NQ= github.com/libp2p/go-libp2p-discovery v0.1.0 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6SrqMymQhmvs= github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g= -github.com/libp2p/go-libp2p-kad-dht v0.1.0/go.mod h1:EiH74cOsCxcu2Yh1XxQMpf1uHcLNm/hYEJBOIRlzHNE= -github.com/libp2p/go-libp2p-kbucket v0.2.0/go.mod h1:JNymBToym3QXKBMKGy3m29+xprg0EVr/GJFHxFEdgh8= +github.com/libp2p/go-libp2p-discovery v0.2.0 h1:1p3YSOq7VsgaL+xVHPi8XAmtGyas6D2J6rWBEfz/aiY= +github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg= +github.com/libp2p/go-libp2p-kad-dht v0.2.1/go.mod h1:k7ONOlup7HKzQ68dE6lSnp07cdxdkmnRa+6B4Fh9/w0= +github.com/libp2p/go-libp2p-kbucket v0.2.1/go.mod h1:/Rtu8tqbJ4WQ2KTCOMJhggMukOLNLNPY1EtEWWLxUvc= github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= @@ -271,26 +422,43 @@ github.com/libp2p/go-libp2p-mplex v0.2.1 h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8 github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= github.com/libp2p/go-libp2p-nat v0.0.4 h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2wwmyw= github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= +github.com/libp2p/go-libp2p-nat v0.0.5 h1:/mH8pXFVKleflDL1YwqMg27W9GD8kjEx7NY0P6eGc98= +github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= +github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ= github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= +github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY= github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= +github.com/libp2p/go-libp2p-peerstore v0.1.2/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= github.com/libp2p/go-libp2p-peerstore v0.1.3 h1:wMgajt1uM2tMiqf4M+4qWKVyyFc8SfA+84VV9glZq1M= github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= -github.com/libp2p/go-libp2p-pubsub v0.1.0/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q= -github.com/libp2p/go-libp2p-quic-transport v0.1.0/go.mod h1:1oh6y4f8/lDX42jIGlhXO95ox3Y1XMLdffb7zde29Y8= +github.com/libp2p/go-libp2p-peerstore v0.1.4 h1:d23fvq5oYMJ/lkkbO4oTwBp/JP+I/1m5gZJobNXCE/k= +github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs= +github.com/libp2p/go-libp2p-pubsub v0.1.1/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q= +github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU= +github.com/libp2p/go-libp2p-record v0.1.0 h1:wHwBGbFzymoIl69BpgwIu0O6ta3TXGcMPvHUAcodzRc= github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q= +github.com/libp2p/go-libp2p-record v0.1.1 h1:ZJK2bHXYUBqObHX+rHLSNrM3M8fmJUlUHrodDPPATmY= +github.com/libp2p/go-libp2p-record v0.1.1/go.mod h1:VRgKajOyMVgP/F0L5g3kH7SVskp17vFi2xheb5uMJtg= github.com/libp2p/go-libp2p-routing v0.1.0/go.mod h1:zfLhI1RI8RLEzmEaaPwzonRvXeeSHddONWkcTcB54nE= github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= +github.com/libp2p/go-libp2p-secio v0.1.1/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= github.com/libp2p/go-libp2p-secio v0.2.0 h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXYwAWqHng= github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= +github.com/libp2p/go-libp2p-secio v0.2.1 h1:eNWbJTdyPA7NxhP7J3c5lT97DC5d+u+IldkgCYFTPVA= +github.com/libp2p/go-libp2p-secio v0.2.1/go.mod h1:cWtZpILJqkqrSkiYcDBh5lA3wbT2Q+hz3rJQq3iftD8= github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= -github.com/libp2p/go-libp2p-swarm v0.2.0 h1:gUqj9WYFC9mQ6khEtO5EjfaAtevwBMxsXRARbi6lAiI= -github.com/libp2p/go-libp2p-swarm v0.2.0/go.mod h1:x07b4zkMFo2EvgPV2bMTlNmdQc8i+74Jjio7xGvsTgU= +github.com/libp2p/go-libp2p-swarm v0.1.1/go.mod h1:4NVJaLwq/dr5kEq79Jo6pMin7ZFwLx73ln1FTefR91Q= +github.com/libp2p/go-libp2p-swarm v0.2.1/go.mod h1:x07b4zkMFo2EvgPV2bMTlNmdQc8i+74Jjio7xGvsTgU= +github.com/libp2p/go-libp2p-swarm v0.2.2 h1:T4hUpgEs2r371PweU3DuH7EOmBIdTBCwWs+FLcgx3bQ= +github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU= github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.1.0 h1:WaFRj/t3HdMZGNZqnU2pS7pDRBmMeoDx7/HDNpeyT9U= github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= +github.com/libp2p/go-libp2p-testing v0.1.1 h1:U03z3HnGI7Ni8Xx6ONVZvUFOAzWYmolWf5W5jAOPNmU= +github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= @@ -303,10 +471,17 @@ github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTW github.com/libp2p/go-mplex v0.1.0 h1:/nBTy5+1yRyY82YaO6HXQRnO5IAGsXTjEJaR3LdTPc0= github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.3/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA= github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-nat v0.0.3 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI= github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI= +github.com/libp2p/go-nat v0.0.4 h1:KbizNnq8YIf7+Hn7+VFL/xE0eDrkPru2zIO9NMwL8UQ= +github.com/libp2p/go-nat v0.0.4/go.mod h1:Nmw50VAvKuk38jUBcmNh6p9lUJLoODbJRvYAa/+KSDo= +github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= +github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.4 h1:d27YZvLoTyMhIN4njrkr8zMDOM4lfpHIp6A+TK9fovg= +github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4= @@ -316,13 +491,19 @@ github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROm github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc= github.com/libp2p/go-tcp-transport v0.1.0 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o= github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= +github.com/libp2p/go-tcp-transport v0.1.1 h1:yGlqURmqgNA2fvzjSgZNlHcsd/IulAnKM8Ncu+vlqnw= +github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= +github.com/libp2p/go-testutil v0.1.0/go.mod h1:81b2n5HypcVyrCg/MJx4Wgfp/VHojytjVe/gLzZ2Ehc= github.com/libp2p/go-ws-transport v0.1.0 h1:F+0OvvdmPTDsVc4AjPHjV7L7Pk1B7D5QwtDcKE2oag4= github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo= +github.com/libp2p/go-ws-transport v0.1.2/go.mod h1:dsh2Ld8F+XNmzpkaAijmg5Is+e9l6/1tK/6VFOdN69Y= +github.com/libp2p/go-ws-transport v0.2.0 h1:MJCw2OrPA9+76YNRvdo1wMnSOxb9Bivj6sVFY1Xrj6w= +github.com/libp2p/go-ws-transport v0.2.0/go.mod h1:9BHJz/4Q5A9ludYWKoGCFC5gUElzlHoKzu0yY9p/klM= github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI= github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/lucas-clemente/quic-go v0.11.1/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= +github.com/lucas-clemente/quic-go v0.11.2/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -331,10 +512,14 @@ github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwm github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= 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= @@ -345,6 +530,10 @@ github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+ github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM= github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -352,37 +541,65 @@ github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzO github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= 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= +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/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc= +github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.2.0 h1:lR52sFwcTCuQb6bTfnXF6zA2XfyYvyd+5a9qECv/J90= +github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr-dns v0.0.3 h1:P19q/k9jwmtgh+qXFkKfgFM7rCg/9l5AVqh7VNxSXhs= +github.com/multiformats/go-multiaddr-dns v0.0.3/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr-dns v0.1.0/go.mod h1:01k2RAqtoXIuPa3DCavAE9/6jc6nM0H3EgZyfUhN2oY= +github.com/multiformats/go-multiaddr-dns v0.2.0 h1:YWJoIDwLePniH7OU5hBnDZV6SWuvJqJ0YtN6pLeH9zA= +github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= github.com/multiformats/go-multiaddr-fmt v0.0.1 h1:5YjeOIzbX8OTKVaN72aOzGIYW7PnrZrnkDyOfAWRSMA= github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= +github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= +github.com/multiformats/go-multiaddr-net v0.1.1/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= +github.com/multiformats/go-multiaddr-net v0.1.2 h1:P7zcBH9FRETdPkDrylcXVjQLQ2t1JQtNItZULWNWgeg= +github.com/multiformats/go-multiaddr-net v0.1.2/go.mod h1:QsWt3XK/3hwvNxZJp92iMQKME1qHfpYmyIjFVsSOY6Y= github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= -github.com/multiformats/go-multihash v0.0.7 h1:uoqoE03rGJdlQEPq2EAc6UeSbo4L7mZyeAAoqNalf54= -github.com/multiformats/go-multihash v0.0.7/go.mod h1:XuKXPp8VHcTygube3OWZC+aZrA+H1IhmjoCDtJc7PXM= +github.com/multiformats/go-multihash v0.0.6/go.mod h1:XuKXPp8VHcTygube3OWZC+aZrA+H1IhmjoCDtJc7PXM= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.13 h1:06x+mk/zj1FoMsgNejLpy6QTvJqlSt/BhLEy87zidlc= +github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= +github.com/multiformats/go-multistream v0.1.1 h1:JlAdpIFhBhGRLxe9W6Om0w++Gd6KMWoFPZL/dEnm9nI= +github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= +github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg= +github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nbutton23/zxcvbn-go v0.0.0-20160627004424-a22cb81b2ecd/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663 h1:Ri1EhipkbhWsffPJ3IPlrb4SkTOPa2PfRXp3jchBczw= github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -395,6 +612,8 @@ github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -403,17 +622,22 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.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/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= +github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14 h1:2m16U/rLwVaRdz7ANkHtHTodP3zTP3N451MADg64x5k= +github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= 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/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= @@ -425,6 +649,13 @@ github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOms github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8= +github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= +github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 h1:N8Bg45zpk/UcpNGnfJt2y/3lRWASHNTUET8owPYCgYI= +github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= github.com/sourcegraph/go-diff v0.5.1 h1:gO6i5zugwzo1RVTvgvfwCOSVegNuvnNi6bAD1QCmkHs= github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= @@ -432,7 +663,6 @@ github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQ github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -459,29 +689,37 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec h1:AmoEvWAO3nDx1MEcMzPh+GzOOIA5Znpv6++c7bePPY0= github.com/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ultraware/funlen v0.0.1 h1:UeC9tpM4wNWzUJfan8z9sFE4QCzjjzlCZmuJN+aOkH0= github.com/ultraware/funlen v0.0.1/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= -github.com/ultraware/funlen v0.0.2 h1:Av96YVBwwNSe4MLR7iI/BIa3VyI7/djnto/pK3Uxbdo= -github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= github.com/valyala/quicktemplate v1.1.1/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= +github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830 h1:8kxMKmKzXXL4Ru1nyhvdms/JjWt+3YLpvRb/bAjO/y0= +github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= 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-ctrlnet v0.0.0-20180313164037-f564fbbdaa95/go.mod h1:SJqKCCPXRfBFCwXjfNT/skfsceF7+MBFLI2OrvuRA7g= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= +github.com/whyrusleeping/go-logging v0.0.1/go.mod h1:lDPYj54zutzG1XYfHAhcc7oNXEburHQBn+Iqd4yS4vE= github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f h1:M/lL30eFZTKnomXY6huvM6G0+gVquFNf6mxghaWlFUg= github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8= github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg59EbA= github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= @@ -489,6 +727,17 @@ github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7V github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= +go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180426230345-b49d69b5da94/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -504,9 +753,15 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -519,8 +774,14 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/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-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-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 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= @@ -532,22 +793,34 @@ golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5h 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-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190524122548-abf6ff778158/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e h1:D5TXcfTk7xF7hvieo4QErS3qqCB4teTffacDWr7CI+0= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20170915040203-e531a2a1c15f/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/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-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -557,23 +830,26 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190909030654-5b82db07426d h1:PhtdWYteEBebOX7KXm4qkIAVSUTHQ883/2hRB92r9lk= golang.org/x/tools v0.0.0-20190909030654-5b82db07426d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89 h1:WiVZGyzQN7gPNLRkkpsNX3jC0Jx5j9GxadCZW/8eXw0= -golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 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-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 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= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= diff --git a/test/dependencies/graphsync-get/graphsync-get.go b/test/dependencies/graphsync-get/graphsync-get.go new file mode 100644 index 00000000000..7c6c380deb3 --- /dev/null +++ b/test/dependencies/graphsync-get/graphsync-get.go @@ -0,0 +1,130 @@ +package main + +import ( + "context" + "fmt" + "io" + "log" + "os" + + "github.com/ipfs/go-blockservice" + "github.com/ipfs/go-cid" + "github.com/ipfs/go-datastore" + dssync "github.com/ipfs/go-datastore/sync" + "github.com/ipfs/go-graphsync" + gsimpl "github.com/ipfs/go-graphsync/impl" + "github.com/ipfs/go-graphsync/ipldbridge" + "github.com/ipfs/go-graphsync/network" + "github.com/ipfs/go-graphsync/storeutil" + "github.com/ipfs/go-ipfs-blockstore" + "github.com/ipfs/go-ipfs-exchange-offline" + "github.com/ipfs/go-merkledag" + uio "github.com/ipfs/go-unixfs/io" + "github.com/ipld/go-ipld-prime" + ipldfree "github.com/ipld/go-ipld-prime/impl/free" + cidlink "github.com/ipld/go-ipld-prime/linking/cid" + ipldselector "github.com/ipld/go-ipld-prime/traversal/selector" + "github.com/ipld/go-ipld-prime/traversal/selector/builder" + "github.com/libp2p/go-libp2p" + "github.com/libp2p/go-libp2p-core/host" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/multiformats/go-multiaddr" +) + +func newGraphsync(ctx context.Context, p2p host.Host, bs blockstore.Blockstore) (graphsync.GraphExchange, error) { + network := network.NewFromLibp2pHost(p2p) + ipldBridge := ipldbridge.NewIPLDBridge() + return gsimpl.New(ctx, + network, ipldBridge, + storeutil.LoaderForBlockstore(bs), + storeutil.StorerForBlockstore(bs), + ), nil +} + +var selectAll ipld.Node = func() ipld.Node { + ssb := builder.NewSelectorSpecBuilder(ipldfree.NodeBuilder()) + return ssb.ExploreRecursive( + ipldselector.RecursionLimitDepth(100), // default max + ssb.ExploreAll(ssb.ExploreRecursiveEdge()), + ).Node() +}() + +func fetch(ctx context.Context, gs graphsync.GraphExchange, p peer.ID, c cid.Cid) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + resps, errs := gs.Request(ctx, p, cidlink.Link{Cid: c}, selectAll) + for { + select { + case <-ctx.Done(): + return ctx.Err() + case _, ok := <-resps: + if !ok { + resps = nil + } + case err, ok := <-errs: + if !ok { + // done. + return nil + } + if err != nil { + return fmt.Errorf("got an unexpected error: %s", err) + } + } + } +} + +func main() { + if len(os.Args) != 3 { + log.Fatalf("expected a multiaddr and a CID, got %d args", len(os.Args)-1) + } + addr, err := multiaddr.NewMultiaddr(os.Args[1]) + if err != nil { + log.Fatalf("failed to multiaddr '%q': %s", os.Args[1], err) + } + ai, err := peer.AddrInfoFromP2pAddr(addr) + if err != nil { + log.Fatal(err) + } + + target, err := cid.Decode(os.Args[2]) + if err != nil { + log.Fatalf("failed to decode CID '%q': %s", os.Args[2], err) + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + p2p, err := libp2p.New(ctx, libp2p.NoListenAddrs) + if err != nil { + log.Fatal(err) + } + err = p2p.Connect(ctx, *ai) + if err != nil { + log.Fatal(err) + } + + bs := blockstore.NewBlockstore(dssync.MutexWrap(datastore.NewMapDatastore())) + gs, err := newGraphsync(ctx, p2p, bs) + if err != nil { + log.Fatal("failed to start", err) + } + err = fetch(ctx, gs, ai.ID, target) + if err != nil { + log.Fatal(err) + } + + dag := merkledag.NewDAGService(blockservice.New(bs, offline.Exchange(bs))) + root, err := dag.Get(ctx, target) + if err != nil { + log.Fatal(err) + } + reader, err := uio.NewDagReader(ctx, root, dag) + if err != nil { + log.Fatal(err) + } + _, err = io.Copy(os.Stdout, reader) + if err != nil { + log.Fatal(err) + } +} diff --git a/test/dependencies/ma-pipe-unidir/main.go b/test/dependencies/ma-pipe-unidir/main.go index 03617e618ee..db77f5fbae4 100644 --- a/test/dependencies/ma-pipe-unidir/main.go +++ b/test/dependencies/ma-pipe-unidir/main.go @@ -43,16 +43,6 @@ func app() int { return 1 } - if len(opts.PidFile) > 0 { - data := []byte(strconv.Itoa(os.Getpid())) - err := ioutil.WriteFile(opts.PidFile, data, 0644) - if err != nil { - return 1 - } - - defer os.Remove(opts.PidFile) - } - maddr, err := ma.NewMultiaddr(addr) if err != nil { return 1 @@ -66,6 +56,16 @@ func app() int { return 1 } + if len(opts.PidFile) > 0 { + data := []byte(strconv.Itoa(os.Getpid())) + err := ioutil.WriteFile(opts.PidFile, data, 0644) + if err != nil { + return 1 + } + + defer os.Remove(opts.PidFile) + } + conn, err = listener.Accept() if err != nil { return 1 @@ -76,6 +76,17 @@ func app() int { if err != nil { return 1 } + + if len(opts.PidFile) > 0 { + data := []byte(strconv.Itoa(os.Getpid())) + err := ioutil.WriteFile(opts.PidFile, data, 0644) + if err != nil { + return 1 + } + + defer os.Remove(opts.PidFile) + } + } defer conn.Close() diff --git a/test/dependencies/pollEndpoint/main.go b/test/dependencies/pollEndpoint/main.go index 67a5e2be0d5..7eadcd3f702 100644 --- a/test/dependencies/pollEndpoint/main.go +++ b/test/dependencies/pollEndpoint/main.go @@ -3,10 +3,6 @@ package main import ( "flag" - "fmt" - "io/ioutil" - "net/http" - "net/url" "os" "time" @@ -16,11 +12,10 @@ import ( ) var ( - host = flag.String("host", "/ip4/127.0.0.1/tcp/5001", "the multiaddr host to dial on") - endpoint = flag.String("ep", "/version", "which http endpoint path to hit") - tries = flag.Int("tries", 10, "how many tries to make before failing") - timeout = flag.Duration("tout", time.Second, "how long to wait between attempts") - verbose = flag.Bool("v", false, "verbose logging") + host = flag.String("host", "/ip4/127.0.0.1/tcp/5001", "the multiaddr host to dial on") + tries = flag.Int("tries", 10, "how many tries to make before failing") + timeout = flag.Duration("tout", time.Second, "how long to wait between attempts") + verbose = flag.Bool("v", false, "verbose logging") ) var log = logging.Logger("pollEndpoint") @@ -33,37 +28,23 @@ func main() { if err != nil { log.Fatal("NewMultiaddr() failed: ", err) } - p := addr.Protocols() - if len(p) < 2 { - log.Fatal("need two protocols in host flag (/ip/tcp): ", addr) - } - _, host, err := manet.DialArgs(addr) - if err != nil { - log.Fatal("manet.DialArgs() failed: ", err) - } if *verbose { // lower log level logging.SetDebugLogging() } - // construct url to dial - var u url.URL - u.Scheme = "http" - u.Host = host - u.Path = *endpoint - // show what we got start := time.Now() - log.Debugf("starting at %s, tries: %d, timeout: %s, url: %s", start, *tries, *timeout, u) + log.Debugf("starting at %s, tries: %d, timeout: %s, addr: %s", start, *tries, *timeout, addr) for *tries > 0 { - - err := checkOK(http.Get(u.String())) + c, err := manet.Dial(addr) if err == nil { log.Debugf("ok - endpoint reachable with %d tries remaining, took %s", *tries, time.Since(start)) + c.Close() os.Exit(0) } - log.Debug("get failed: ", err) + log.Debug("connect failed: ", err) time.Sleep(*timeout) *tries-- } @@ -71,18 +52,3 @@ func main() { log.Error("failed.") os.Exit(1) } - -func checkOK(resp *http.Response, err error) error { - if err == nil { // request worked - defer resp.Body.Close() - if resp.StatusCode == http.StatusOK { - return nil - } - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - fmt.Fprintf(os.Stderr, "pollEndpoint: ioutil.ReadAll() Error: %s", err) - } - return fmt.Errorf("response not OK. %d %s %q", resp.StatusCode, resp.Status, string(body)) - } - return err -} diff --git a/test/integration/Makefile b/test/integration/GNUmakefile similarity index 100% rename from test/integration/Makefile rename to test/integration/GNUmakefile diff --git a/test/integration/addcat_test.go b/test/integration/addcat_test.go index 98e6936ee82..eebc1f63f76 100644 --- a/test/integration/addcat_test.go +++ b/test/integration/addcat_test.go @@ -11,18 +11,17 @@ import ( "testing" "time" + files "github.com/ipfs/go-ipfs-files" "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/core/bootstrap" "github.com/ipfs/go-ipfs/core/coreapi" mock "github.com/ipfs/go-ipfs/core/mock" "github.com/ipfs/go-ipfs/thirdparty/unit" - - files "github.com/ipfs/go-ipfs-files" logging "github.com/ipfs/go-log" random "github.com/jbenet/go-random" - pstore "github.com/libp2p/go-libp2p-peerstore" + peer "github.com/libp2p/go-libp2p-core/peer" + testutil "github.com/libp2p/go-libp2p-testing/net" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" - testutil "github.com/libp2p/go-testutil" ) var log = logging.Logger("epictest") @@ -138,8 +137,8 @@ func DirectAddCat(data []byte, conf testutil.LatencyConfig) error { return err } - bs1 := []pstore.PeerInfo{adder.Peerstore.PeerInfo(adder.Identity)} - bs2 := []pstore.PeerInfo{catter.Peerstore.PeerInfo(catter.Identity)} + bs1 := []peer.AddrInfo{adder.Peerstore.PeerInfo(adder.Identity)} + bs2 := []peer.AddrInfo{catter.Peerstore.PeerInfo(catter.Identity)} if err := catter.Bootstrap(bootstrap.BootstrapConfigWithPeers(bs1)); err != nil { return err diff --git a/test/integration/bench_cat_test.go b/test/integration/bench_cat_test.go index a40fcfe37b1..6115b5b54dd 100644 --- a/test/integration/bench_cat_test.go +++ b/test/integration/bench_cat_test.go @@ -8,16 +8,15 @@ import ( "math" "testing" + files "github.com/ipfs/go-ipfs-files" "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/core/bootstrap" "github.com/ipfs/go-ipfs/core/coreapi" mock "github.com/ipfs/go-ipfs/core/mock" "github.com/ipfs/go-ipfs/thirdparty/unit" - - files "github.com/ipfs/go-ipfs-files" - pstore "github.com/libp2p/go-libp2p-peerstore" + peer "github.com/libp2p/go-libp2p-core/peer" + testutil "github.com/libp2p/go-libp2p-testing/net" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" - testutil "github.com/libp2p/go-testutil" ) func BenchmarkCat1MB(b *testing.B) { benchmarkVarCat(b, unit.MB*1) } @@ -81,8 +80,8 @@ func benchCat(b *testing.B, data []byte, conf testutil.LatencyConfig) error { return err } - bs1 := []pstore.PeerInfo{adder.Peerstore.PeerInfo(adder.Identity)} - bs2 := []pstore.PeerInfo{catter.Peerstore.PeerInfo(catter.Identity)} + bs1 := []peer.AddrInfo{adder.Peerstore.PeerInfo(adder.Identity)} + bs2 := []peer.AddrInfo{catter.Peerstore.PeerInfo(catter.Identity)} if err := catter.Bootstrap(bootstrap.BootstrapConfigWithPeers(bs1)); err != nil { return err diff --git a/test/integration/bench_test.go b/test/integration/bench_test.go index 78e78eb57d0..bc5a22ea91d 100644 --- a/test/integration/bench_test.go +++ b/test/integration/bench_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/ipfs/go-ipfs/thirdparty/unit" - testutil "github.com/libp2p/go-testutil" + testutil "github.com/libp2p/go-libp2p-testing/net" ) func benchmarkAddCat(numBytes int64, conf testutil.LatencyConfig, b *testing.B) { diff --git a/test/integration/three_legged_cat_test.go b/test/integration/three_legged_cat_test.go index 1fc0e7bf253..eb82d00083a 100644 --- a/test/integration/three_legged_cat_test.go +++ b/test/integration/three_legged_cat_test.go @@ -9,16 +9,15 @@ import ( "testing" "time" - core "github.com/ipfs/go-ipfs/core" bootstrap2 "github.com/ipfs/go-ipfs/core/bootstrap" "github.com/ipfs/go-ipfs/core/coreapi" mock "github.com/ipfs/go-ipfs/core/mock" "github.com/ipfs/go-ipfs/thirdparty/unit" files "github.com/ipfs/go-ipfs-files" - pstore "github.com/libp2p/go-libp2p-peerstore" + peer "github.com/libp2p/go-libp2p-core/peer" + testutil "github.com/libp2p/go-libp2p-testing/net" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" - testutil "github.com/libp2p/go-testutil" ) func TestThreeLeggedCatTransfer(t *testing.T) { @@ -76,28 +75,19 @@ func RunThreeLeggedCat(data []byte, conf testutil.LatencyConfig) error { Bandwidth: math.MaxInt32, }) - bootstrap, err := core.NewNode(ctx, &core.BuildCfg{ - Online: true, - Host: mock.MockHostOption(mn), - }) + bootstrap, err := mock.MockPublicNode(ctx, mn) if err != nil { return err } defer bootstrap.Close() - adder, err := core.NewNode(ctx, &core.BuildCfg{ - Online: true, - Host: mock.MockHostOption(mn), - }) + adder, err := mock.MockPublicNode(ctx, mn) if err != nil { return err } defer adder.Close() - catter, err := core.NewNode(ctx, &core.BuildCfg{ - Online: true, - Host: mock.MockHostOption(mn), - }) + catter, err := mock.MockPublicNode(ctx, mn) if err != nil { return err } @@ -119,7 +109,7 @@ func RunThreeLeggedCat(data []byte, conf testutil.LatencyConfig) error { } bis := bootstrap.Peerstore.PeerInfo(bootstrap.PeerHost.ID()) - bcfg := bootstrap2.BootstrapConfigWithPeers([]pstore.PeerInfo{bis}) + bcfg := bootstrap2.BootstrapConfigWithPeers([]peer.AddrInfo{bis}) if err := adder.Bootstrap(bcfg); err != nil { return err } diff --git a/test/integration/wan_lan_dht_test.go b/test/integration/wan_lan_dht_test.go new file mode 100644 index 00000000000..1cea5d831b0 --- /dev/null +++ b/test/integration/wan_lan_dht_test.go @@ -0,0 +1,277 @@ +package integrationtest + +import ( + "context" + "encoding/binary" + "fmt" + "math" + "math/rand" + "net" + "testing" + "time" + + "github.com/ipfs/go-cid" + "github.com/ipfs/go-ipfs/core" + mock "github.com/ipfs/go-ipfs/core/mock" + libp2p2 "github.com/ipfs/go-ipfs/core/node/libp2p" + + corenet "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/peerstore" + testutil "github.com/libp2p/go-libp2p-testing/net" + mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" + + ma "github.com/multiformats/go-multiaddr" +) + +func TestDHTConnectivityFast(t *testing.T) { + conf := testutil.LatencyConfig{ + NetworkLatency: 0, + RoutingLatency: 0, + BlockstoreLatency: 0, + } + if err := RunDHTConnectivity(conf, 5); err != nil { + t.Fatal(err) + } +} + +func TestDHTConnectivitySlowNetwork(t *testing.T) { + SkipUnlessEpic(t) + conf := testutil.LatencyConfig{NetworkLatency: 400 * time.Millisecond} + if err := RunDHTConnectivity(conf, 5); err != nil { + t.Fatal(err) + } +} + +func TestDHTConnectivitySlowRouting(t *testing.T) { + SkipUnlessEpic(t) + conf := testutil.LatencyConfig{RoutingLatency: 400 * time.Millisecond} + if err := RunDHTConnectivity(conf, 5); err != nil { + t.Fatal(err) + } +} + +var wanPrefix = net.ParseIP("2000::") +var lanPrefix = net.ParseIP("fe80::") + +func makeAddr(n uint32, wan bool) ma.Multiaddr { + var ip net.IP + if wan { + ip = append(net.IP{}, wanPrefix...) + } else { + ip = append(net.IP{}, lanPrefix...) + } + + binary.LittleEndian.PutUint32(ip[12:], n) + addr, _ := ma.NewMultiaddr(fmt.Sprintf("/ip6/%s/tcp/4242", ip)) + return addr +} + +func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // create network + mn := mocknet.New(ctx) + mn.SetLinkDefaults(mocknet.LinkOptions{ + Latency: conf.NetworkLatency, + Bandwidth: math.MaxInt32, + }) + + testPeer, err := core.NewNode(ctx, &core.BuildCfg{ + Online: true, + Host: mock.MockHostOption(mn), + }) + if err != nil { + return err + } + defer testPeer.Close() + + wanPeers := []*core.IpfsNode{} + lanPeers := []*core.IpfsNode{} + + connectionContext, connCtxCancel := context.WithTimeout(ctx, 15*time.Second) + defer connCtxCancel() + for i := 0; i < numPeers; i++ { + wanPeer, err := core.NewNode(ctx, &core.BuildCfg{ + Online: true, + Routing: libp2p2.DHTServerOption, + Host: mock.MockHostOption(mn), + }) + if err != nil { + return err + } + defer wanPeer.Close() + wanAddr := makeAddr(uint32(i), true) + wanPeer.Peerstore.AddAddr(wanPeer.Identity, wanAddr, peerstore.PermanentAddrTTL) + for _, p := range wanPeers { + _, _ = mn.LinkPeers(p.Identity, wanPeer.Identity) + _ = wanPeer.PeerHost.Connect(connectionContext, p.Peerstore.PeerInfo(p.Identity)) + } + wanPeers = append(wanPeers, wanPeer) + + lanPeer, err := core.NewNode(ctx, &core.BuildCfg{ + Online: true, + Host: mock.MockHostOption(mn), + }) + if err != nil { + return err + } + defer lanPeer.Close() + lanAddr := makeAddr(uint32(i), false) + lanPeer.Peerstore.AddAddr(lanPeer.Identity, lanAddr, peerstore.PermanentAddrTTL) + for _, p := range lanPeers { + _, _ = mn.LinkPeers(p.Identity, lanPeer.Identity) + _ = lanPeer.PeerHost.Connect(connectionContext, p.Peerstore.PeerInfo(p.Identity)) + } + lanPeers = append(lanPeers, lanPeer) + } + connCtxCancel() + + // Add interfaces / addresses to test peer. + wanAddr := makeAddr(0, true) + testPeer.Peerstore.AddAddr(testPeer.Identity, wanAddr, peerstore.PermanentAddrTTL) + lanAddr := makeAddr(0, false) + testPeer.Peerstore.AddAddr(testPeer.Identity, lanAddr, peerstore.PermanentAddrTTL) + + // The test peer is connected to one lan peer. + for _, p := range lanPeers { + if _, err := mn.LinkPeers(testPeer.Identity, p.Identity); err != nil { + return err + } + } + err = testPeer.PeerHost.Connect(ctx, lanPeers[0].Peerstore.PeerInfo(lanPeers[0].Identity)) + if err != nil { + return err + } + + startupCtx, startupCancel := context.WithTimeout(ctx, time.Second*60) +StartupWait: + for { + select { + case err := <-testPeer.DHT.LAN.RefreshRoutingTable(): + if err != nil { + fmt.Printf("Error refreshing routing table: %v\n", err) + } + if testPeer.DHT.LAN.RoutingTable() == nil || + testPeer.DHT.LAN.RoutingTable().Size() == 0 || + err != nil { + time.Sleep(100 * time.Millisecond) + continue + } + break StartupWait + case <-startupCtx.Done(): + startupCancel() + return fmt.Errorf("expected faster dht bootstrap") + } + } + startupCancel() + + // choose a lan peer and validate lan DHT is functioning. + i := rand.Intn(len(lanPeers)) + if testPeer.PeerHost.Network().Connectedness(lanPeers[i].Identity) == corenet.Connected { + i = (i + 1) % len(lanPeers) + if testPeer.PeerHost.Network().Connectedness(lanPeers[i].Identity) == corenet.Connected { + _ = testPeer.PeerHost.Network().ClosePeer(lanPeers[i].Identity) + testPeer.PeerHost.Peerstore().ClearAddrs(lanPeers[i].Identity) + } + } + // That peer will provide a new CID, and we'll validate the test node can find it. + provideCid := cid.NewCidV1(cid.Raw, []byte("Lan Provide Record")) + provideCtx, cancel := context.WithTimeout(ctx, time.Second) + defer cancel() + if err := lanPeers[i].DHT.Provide(provideCtx, provideCid, true); err != nil { + return err + } + provChan := testPeer.DHT.FindProvidersAsync(provideCtx, provideCid, 0) + prov, ok := <-provChan + if !ok || prov.ID == "" { + return fmt.Errorf("Expected provider. stream closed early") + } + if prov.ID != lanPeers[i].Identity { + return fmt.Errorf("Unexpected lan peer provided record") + } + + // Now, connect with a wan peer. + for _, p := range wanPeers { + if _, err := mn.LinkPeers(testPeer.Identity, p.Identity); err != nil { + return err + } + } + + err = testPeer.PeerHost.Connect(ctx, wanPeers[0].Peerstore.PeerInfo(wanPeers[0].Identity)) + if err != nil { + return err + } + + startupCtx, startupCancel = context.WithTimeout(ctx, time.Second*60) +WanStartupWait: + for { + select { + case err := <-testPeer.DHT.WAN.RefreshRoutingTable(): + //if err != nil { + // fmt.Printf("Error refreshing routing table: %v\n", err) + //} + if testPeer.DHT.WAN.RoutingTable() == nil || + testPeer.DHT.WAN.RoutingTable().Size() == 0 || + err != nil { + time.Sleep(100 * time.Millisecond) + continue + } + break WanStartupWait + case <-startupCtx.Done(): + startupCancel() + return fmt.Errorf("expected faster wan dht bootstrap") + } + } + startupCancel() + + // choose a wan peer and validate wan DHT is functioning. + i = rand.Intn(len(wanPeers)) + if testPeer.PeerHost.Network().Connectedness(wanPeers[i].Identity) == corenet.Connected { + i = (i + 1) % len(wanPeers) + if testPeer.PeerHost.Network().Connectedness(wanPeers[i].Identity) == corenet.Connected { + _ = testPeer.PeerHost.Network().ClosePeer(wanPeers[i].Identity) + testPeer.PeerHost.Peerstore().ClearAddrs(wanPeers[i].Identity) + } + } + + // That peer will provide a new CID, and we'll validate the test node can find it. + wanCid := cid.NewCidV1(cid.Raw, []byte("Wan Provide Record")) + wanProvideCtx, cancel := context.WithTimeout(ctx, time.Second) + defer cancel() + if err := wanPeers[i].DHT.Provide(wanProvideCtx, wanCid, true); err != nil { + return err + } + provChan = testPeer.DHT.FindProvidersAsync(wanProvideCtx, wanCid, 0) + prov, ok = <-provChan + if !ok || prov.ID == "" { + return fmt.Errorf("Expected one provider, closed early") + } + if prov.ID != wanPeers[i].Identity { + return fmt.Errorf("Unexpected lan peer provided record") + } + + // Finally, re-share the lan provided cid from a wan peer and expect a merged result. + i = rand.Intn(len(wanPeers)) + if testPeer.PeerHost.Network().Connectedness(wanPeers[i].Identity) == corenet.Connected { + _ = testPeer.PeerHost.Network().ClosePeer(wanPeers[i].Identity) + testPeer.PeerHost.Peerstore().ClearAddrs(wanPeers[i].Identity) + } + + provideCtx, cancel = context.WithTimeout(ctx, time.Second) + defer cancel() + if err := wanPeers[i].DHT.Provide(provideCtx, provideCid, true); err != nil { + return err + } + provChan = testPeer.DHT.FindProvidersAsync(provideCtx, provideCid, 0) + prov, ok = <-provChan + if !ok { + return fmt.Errorf("Expected two providers, got 0") + } + prov, ok = <-provChan + if !ok { + return fmt.Errorf("Expected two providers, got 1") + } + + return nil +} diff --git a/test/ipfs-test-lib.sh b/test/ipfs-test-lib.sh index 9cd99c2e761..38c62d33177 100644 --- a/test/ipfs-test-lib.sh +++ b/test/ipfs-test-lib.sh @@ -9,7 +9,7 @@ shellquote() { _space='' for _arg do - # On Mac OS, sed adds a newline character. + # On macOS, sed adds a newline character. # With a printf wrapper the extra newline is removed. printf "$_space'%s'" "$(printf "%s" "$_arg" | sed -e "s/'/'\\\\''/g;")" _space=' ' diff --git a/test/sharness/Makefile b/test/sharness/GNUmakefile similarity index 100% rename from test/sharness/Makefile rename to test/sharness/GNUmakefile diff --git a/test/sharness/README.md b/test/sharness/README.md index 2df09b52d92..16cb508c137 100644 --- a/test/sharness/README.md +++ b/test/sharness/README.md @@ -52,7 +52,7 @@ directory. Please do not change anything in the "lib/sharness" directory. If you really need some changes in sharness, please fork it from -[its cannonical repo](https://github.com/mlafeldt/sharness/) and +[its canonical repo](https://github.com/mlafeldt/sharness/) and send pull requests there. ## Writing Tests @@ -107,7 +107,7 @@ test_expect_success "'ipfs add --help' succeeds" ' # other tests here... -# dont forget to kill the daemon!! +# don't forget to kill the daemon!! test_kill_ipfs_daemon ``` @@ -126,6 +126,6 @@ test_mount_ipfs # tests mounted here -# dont forget to kill the daemon!! +# don't forget to kill the daemon!! test_kill_ipfs_daemon ``` diff --git a/test/sharness/Rules.mk b/test/sharness/Rules.mk index c6d6dd83aaf..49e41824c3f 100644 --- a/test/sharness/Rules.mk +++ b/test/sharness/Rules.mk @@ -7,7 +7,7 @@ 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 \ test/bin/go-timeout test/bin/hang-fds test/bin/ma-pipe-unidir \ - test/bin/cid-fmt + test/bin/cid-fmt test/bin/graphsync-get DEPS_$(d) += cmd/ipfs/ipfs DEPS_$(d) += $(d)/clean-test-results DEPS_$(d) += $(SHARNESS_$(d)) diff --git a/test/sharness/lib/iptb-lib.sh b/test/sharness/lib/iptb-lib.sh index 6ee8fbd8b01..ab612ada7f2 100644 --- a/test/sharness/lib/iptb-lib.sh +++ b/test/sharness/lib/iptb-lib.sh @@ -14,7 +14,7 @@ ipfsi() { check_has_connection() { node="$1" ipfsi "$node" swarm peers >"swarm_peers_$node" && - grep "ipfs" "swarm_peers_$node" >/dev/null + grep "p2p" "swarm_peers_$node" >/dev/null } iptb() { @@ -44,7 +44,7 @@ startup_cluster() { ' fi - test_expect_success "connect nodes to eachother" ' + test_expect_success "connect nodes to each other" ' iptb connect [1-$bound] 0 ' diff --git a/test/sharness/lib/test-lib-hashes.sh b/test/sharness/lib/test-lib-hashes.sh index a8a3631e4b5..dbe8491ce80 100644 --- a/test/sharness/lib/test-lib-hashes.sh +++ b/test/sharness/lib/test-lib-hashes.sh @@ -1,5 +1,5 @@ # this file defines several useful hashes used across the test codebase. # thus they can be defined + changed in one place -HASH_WELCOME_DOCS="QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv" +HASH_WELCOME_DOCS="QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc" HASH_EMPTY_DIR="QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn" diff --git a/test/sharness/lib/test-lib.sh b/test/sharness/lib/test-lib.sh index f9ebae81e4c..69766579a71 100644 --- a/test/sharness/lib/test-lib.sh +++ b/test/sharness/lib/test-lib.sh @@ -41,6 +41,47 @@ SHARNESS_LIB="lib/sharness/sharness.sh" # Please put go-ipfs specific shell functions below +### +# BEGIN Check for pre-existing daemon being stuck +### +wait_prev_cleanup_tick_secs=1 +wait_prev_cleanup_max_secs=5 +cur_test_pwd="$(pwd)" + +while true ; do + echo -n > stuck_cwd_list + + lsof -c ipfs -Ffn 2>/dev/null | grep -A1 '^fcwd$' | grep '^n' | cut -b 2- | while read -r pwd_of_stuck ; do + case "$pwd_of_stuck" in + "$cur_test_pwd"*) + echo "$pwd_of_stuck" >> stuck_cwd_list + ;; + *) + ;; + esac + done + + test -s stuck_cwd_list || break + + test "$wait_prev_cleanup_max_secs" -le 0 && break + + echo "Daemons still running, waiting for ${wait_prev_cleanup_max_secs}s" + sleep $wait_prev_cleanup_tick_secs + + wait_prev_cleanup_max_secs="$(( $wait_prev_cleanup_max_secs - $wait_prev_cleanup_tick_secs ))" +done + +if test -s stuck_cwd_list ; then + test_expect_success "ipfs daemon (s)seems to be running with CWDs of +$(cat stuck_cwd_list) +Almost certainly a leftover from a prior test, ABORTING" 'false' + + test_done +fi +### +# END Check for pre-existing daemon being stuck +### + # Make sure the ipfs path is set, also set in test_init_ipfs but that # is not always used. export IPFS_PATH="$(pwd)/.ipfs" @@ -52,9 +93,13 @@ TEST_OS="$(uname -s | tr '[a-z]' '[A-Z]')" # grab + output options test "$TEST_NO_FUSE" != 1 && test_set_prereq FUSE test "$TEST_EXPENSIVE" = 1 && test_set_prereq EXPENSIVE -test "$TEST_NO_DOCKER" != 1 && type docker >/dev/null 2>&1 && test_set_prereq DOCKER +test "$TEST_NO_DOCKER" != 1 && type docker >/dev/null 2>&1 && groups | egrep "\bdocker\b" && test_set_prereq DOCKER test "$TEST_NO_PLUGIN" != 1 && test "$TEST_OS" = "LINUX" && test_set_prereq PLUGIN +# this may not be available, skip a few dependent tests +type socat >/dev/null 2>&1 && test_set_prereq SOCAT + + # Set a prereq as error messages are often different on Windows/Cygwin expr "$TEST_OS" : "CYGWIN_NT" >/dev/null || test_set_prereq STD_ERR_MSG @@ -148,7 +193,7 @@ test_init_ipfs() { test_expect_success "ipfs init succeeds" ' export IPFS_PATH="$(pwd)/.ipfs" && - ipfs init --profile=test -b=1024 > /dev/null + ipfs init --profile=test -b=2048 > /dev/null ' test_expect_success "prepare config -- mounting" ' @@ -212,12 +257,12 @@ test_set_address_vars() { test_launch_ipfs_daemon() { - args="$@" + args=("$@") test "$TEST_ULIMIT_PRESET" != 1 && ulimit -n 2048 test_expect_success "'ipfs daemon' succeeds" ' - ipfs daemon $args >actual_daemon 2>daemon_err & + ipfs daemon "${args[@]}" >actual_daemon 2>daemon_err & IPFS_PID=$! ' @@ -230,7 +275,7 @@ test_launch_ipfs_daemon() { # we say the daemon is ready when the API server is ready. test_expect_success "'ipfs daemon' is ready" ' - pollEndpoint -ep=/version -host=$API_MADDR -v -tout=1s -tries=60 2>poll_apierr > poll_apiout || + pollEndpoint -host=$API_MADDR -v -tout=1s -tries=60 2>poll_apierr > poll_apiout || test_fsh cat actual_daemon || test_fsh cat daemon_err || test_fsh cat poll_apierr || test_fsh cat poll_apiout ' } @@ -398,30 +443,6 @@ file_size() { $_STAT "$1" } -directory_size() { - local total=0 - local fsize=0 - local res=0 - find "$1" -type f | ( while read fname; do - fsize=$(file_size "$fname") - res=$? - if ! test $res -eq 0; then - if ! test -e "$fname"; then - continue; - fi - echo "failed to get filesize" >&2 - return $res - fi - total=$(expr "$total" + "$fsize") - res=$? - if ! test $res -eq 0; then - echo "filesize not a number: $fsize" >&2 - return $res - fi - done - echo "$total" ) # do not remove this subshell -} - test_check_peerid() { peeridlen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && test "$peeridlen" = "46" || { @@ -437,3 +458,24 @@ convert_tcp_maddr() { port_from_maddr() { echo $1 | awk -F'/' '{ print $NF }' } + +findprovs_empty() { + test_expect_success 'findprovs '$1' succeeds' ' + ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut + ' + + test_expect_success "findprovs $1 output is empty" ' + test_must_be_empty findprovsOut + ' +} + +findprovs_expect() { + test_expect_success 'findprovs '$1' succeeds' ' + ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut && + echo '$2' > expected + ' + + test_expect_success "findprovs $1 output looks good" ' + test_cmp findprovsOut expected + ' +} diff --git a/test/sharness/t0001-tests-work.sh b/test/sharness/t0001-tests-work.sh new file mode 100755 index 00000000000..6394fed77d6 --- /dev/null +++ b/test/sharness/t0001-tests-work.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +test_description="Test sharness tests are correctly written" + +. lib/test-lib.sh + +for file in $(find .. -maxdepth 1 -name 't*.sh' -type f); do + test_expect_success "test in $file finishes" ' + grep -q "^test_done\b" "$file" + ' + + test_expect_success "test in $file has a description" ' + grep -q "^test_description=" "$file" + ' + + # We have some tests that manually kill. + case "$(basename "$file")" in + t0060-daemon.sh|t0023-shutdown.sh) continue ;; + esac + + test_expect_success "test in $file has matching ipfs start/stop" ' + awk "/^ *[^#]*test_launch_ipfs_daemon/ { if (count != 0) { exit(1) }; count++ } /^ *[^#]*test_kill_ipfs_daemon/ { if (count != 1) { exit(1) }; count-- } END { exit(count) }" "$file" + ' +done + +test_done diff --git a/test/sharness/t0010-basic-commands.sh b/test/sharness/t0010-basic-commands.sh index d483adfd7c9..289c3ddc09f 100755 --- a/test/sharness/t0010-basic-commands.sh +++ b/test/sharness/t0010-basic-commands.sh @@ -45,8 +45,9 @@ test_expect_success "ipfs version deps succeeds" ' ipfs version deps >deps.txt ' -test_expect_success "ipfs version deps output looks good" ' +test_expect_success "ipfs version deps output looks good ( set \$GOIPFSTEST_SKIP_LOCAL_DEVTREE_DEPS_CHECK to skip this test )" ' head -1 deps.txt | grep "go-ipfs@(devel)" && + [[ "$GOIPFSTEST_SKIP_LOCAL_DEVTREE_DEPS_CHECK" == "1" ]] || [[ $(tail -n +2 deps.txt | egrep -v -c "^[^ @]+@v[^ @]+( => [^ @]+@v[^ @]+)?$") -eq 0 ]] || test_fsh cat deps.txt ' @@ -66,9 +67,9 @@ test_expect_success "All sub-commands accept help" ' while read -r cmd do ${cmd:0:4} help ${cmd:5} >/dev/null || - { echo "$cmd doesnt accept --help"; echo 1 > fail; } + { echo "$cmd does not accept --help"; echo 1 > fail; } echo stuff | $cmd --help >/dev/null || - { echo "$cmd doesnt accept --help when using stdin"; echo 1 > fail; } + { echo "$cmd does not accept --help when using stdin"; echo 1 > fail; } done /dev/null || - { echo "$cmd doesnt accept --help"; echo 1 > fail; } + { echo "$cmd does not accept --help"; echo 1 > fail; } echo stuff | $cmd --help >/dev/null || - { echo "$cmd doesnt accept --help when using stdin"; echo 1 > fail; } + { echo "$cmd does not accept --help when using stdin"; echo 1 > fail; } done actual_init ' @@ -114,7 +114,7 @@ test_expect_success "'ipfs init --empty-repo' output looks good" ' test_cmp expected actual_init ' -test_expect_success "Welcome readme doesn't exists" ' +test_expect_success "Welcome readme doesn't exist" ' test_must_fail ipfs cat /ipfs/$HASH_WELCOME_DOCS/readme ' @@ -128,14 +128,14 @@ test_expect_success "clean up ipfs dir" ' # test init profiles test_expect_success "'ipfs init --profile' with invalid profile fails" ' - BITS="1024" && + BITS="2048" && test_must_fail ipfs init --bits="$BITS" --profile=nonexistent_profile 2> invalid_profile_out EXPECT="Error: invalid configuration profile: nonexistent_profile" && grep "$EXPECT" invalid_profile_out ' test_expect_success "'ipfs init --profile' succeeds" ' - BITS="1024" && + BITS="2048" && ipfs init --bits="$BITS" --profile=server ' @@ -149,7 +149,7 @@ test_expect_success "clean up ipfs dir" ' ' test_expect_success "'ipfs init --profile=test' succeeds" ' - BITS="1024" && + BITS="2048" && ipfs init --bits="$BITS" --profile=test ' @@ -163,12 +163,26 @@ test_expect_success "'ipfs config Addresses.API' looks good" ' test $(cat actual_config) = "/ip4/127.0.0.1/tcp/0" ' +test_expect_success "ipfs init from existing config succeeds" ' + export ORIG_PATH=$IPFS_PATH + export IPFS_PATH=$(pwd)/.ipfs-clone + + ipfs init "$ORIG_PATH/config" && + ipfs config Addresses.API > actual_config && + test $(cat actual_config) = "/ip4/127.0.0.1/tcp/0" +' + +test_expect_success "clean up ipfs clone dir and reset IPFS_PATH" ' + rm -rf "$IPFS_PATH" && + export IPFS_PATH=$ORIG_PATH +' + test_expect_success "clean up ipfs dir" ' rm -rf "$IPFS_PATH" ' test_expect_success "'ipfs init --profile=lowpower' succeeds" ' - BITS="1024" && + BITS="2048" && ipfs init --bits="$BITS" --profile=lowpower ' diff --git a/test/sharness/t0025-datastores.sh b/test/sharness/t0025-datastores.sh index 21100e5ae31..63290d9fb01 100755 --- a/test/sharness/t0025-datastores.sh +++ b/test/sharness/t0025-datastores.sh @@ -5,7 +5,7 @@ test_description="Test non-standard datastores" . lib/test-lib.sh test_expect_success "'ipfs init --profile=badgerds' succeeds" ' - BITS="1024" && + BITS="2048" && ipfs init --bits="$BITS" --profile=badgerds ' diff --git a/test/sharness/t0026-id.sh b/test/sharness/t0026-id.sh new file mode 100755 index 00000000000..124c1117b6a --- /dev/null +++ b/test/sharness/t0026-id.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +test_description="Test to make sure our identity information looks sane" + +. lib/test-lib.sh + +test_init_ipfs + +test_id_compute_agent() { + AGENT_VERSION="$(ipfs version --number)" || return 1 + AGENT_COMMIT="$(ipfs version --number --commit)" || return 1 + if test "$AGENT_COMMIT" = "$AGENT_VERSION"; then + AGENT_COMMIT="" + else + AGENT_COMMIT="${AGENT_COMMIT##$AGENT_VERSION-}" + fi + echo "go-ipfs/$AGENT_VERSION/$AGENT_COMMIT" +} + +test_expect_success "checking AgentVersion" ' + test_id_compute_agent > expected-agent-version && + ipfs id -f "\n" > actual-agent-version && + test_cmp expected-agent-version actual-agent-version +' + +test_expect_success "checking ProtocolVersion" ' + echo "ipfs/0.1.0" > expected-protocol-version && + ipfs id -f "\n" > actual-protocol-version && + test_cmp expected-protocol-version actual-protocol-version +' + +test_expect_success "checking ID" ' + ipfs config Identity.PeerID > expected-id && + ipfs id -f "\n" > actual-id && + test_cmp expected-id actual-id +' + +test_done diff --git a/test/sharness/t0030-mount.sh b/test/sharness/t0030-mount.sh index 9f17f478bff..4282083eec6 100755 --- a/test/sharness/t0030-mount.sh +++ b/test/sharness/t0030-mount.sh @@ -8,7 +8,7 @@ test_description="Test mount command" . lib/test-lib.sh -# if in travis CI, dont test mount (no fuse) +# if in travis CI, don't test mount (no fuse) if ! test_have_prereq FUSE; then skip_all='skipping mount tests, fuse not available' diff --git a/test/sharness/t0031-mount-publish.sh b/test/sharness/t0031-mount-publish.sh index c37c1161dd1..bfb1e030845 100755 --- a/test/sharness/t0031-mount-publish.sh +++ b/test/sharness/t0031-mount-publish.sh @@ -5,7 +5,7 @@ test_description="Test mount command in conjunction with publishing" # imports . lib/test-lib.sh -# if in travis CI, dont test mount (no fuse) +# if in travis CI, don't test mount (no fuse) if ! test_have_prereq FUSE; then skip_all='skipping mount tests, fuse not available' diff --git a/test/sharness/t0040-add-and-cat.sh b/test/sharness/t0040-add-and-cat.sh index 0d7c98f7169..365626bb76e 100755 --- a/test/sharness/t0040-add-and-cat.sh +++ b/test/sharness/t0040-add-and-cat.sh @@ -13,7 +13,7 @@ test_add_cat_file() { ipfs add --help 2> add_help_err1 > /dev/null ' - test_expect_success "stdin reading message doesnt show up" ' + test_expect_success "stdin reading message doesn't show up" ' test_expect_code 1 grep "ipfs: Reading from" add_help_err1 && test_expect_code 1 grep "send Ctrl-d to stop." add_help_err1 ' @@ -22,7 +22,7 @@ test_add_cat_file() { ipfs help add 2> add_help_err2 > /dev/null ' - test_expect_success "stdin reading message doesnt show up" ' + test_expect_success "stdin reading message doesn't show up" ' test_expect_code 1 grep "ipfs: Reading from" add_help_err2 && test_expect_code 1 grep "send Ctrl-d to stop." add_help_err2 ' @@ -83,7 +83,7 @@ test_add_cat_file() { test_cmp expected actual ' - test_expect_success "ipfs cat from negitive offset should fail" ' + test_expect_success "ipfs cat from negative offset should fail" ' test_expect_code 1 ipfs cat --offset -102 "$HASH" > actual ' @@ -132,7 +132,7 @@ test_add_cat_file() { test_cmp expected actual ' - test_expect_success "ipfs cat with negitive length should fail" ' + test_expect_success "ipfs cat with negative length should fail" ' test_expect_code 1 ipfs cat --length -102 "$HASH" > actual ' @@ -193,6 +193,16 @@ test_add_cat_file() { test_expect_code 1 ipfs add -Q --chunker rabin-12-512-1024 mountdir/hello.txt ' + test_expect_success "ipfs add --chunker buzhash succeeds" ' + ipfs add --chunker buzhash mountdir/hello.txt >actual + ' + + test_expect_success "ipfs add --chunker buzhash output looks good" ' + HASH="QmVr26fY1tKyspEJBniVhqxQeEjhF78XerGiqWAwraVLQH" && + echo "added $HASH hello.txt" >expected && + test_cmp expected actual + ' + test_expect_success "ipfs add on hidden file succeeds" ' echo "Hello Worlds!" >mountdir/.hello.txt && ipfs add mountdir/.hello.txt >actual @@ -494,15 +504,15 @@ test_add_cat_expensive() { } test_add_named_pipe() { - err_prefix=$1 - test_expect_success "useful error message when adding a named pipe" ' - mkfifo named-pipe && - test_expect_code 1 ipfs add named-pipe 2>actual && - STAT=$(generic_stat named-pipe) && - rm named-pipe && - grep "Error: unrecognized file type for named-pipe: $STAT" actual && - grep USAGE actual && - grep "ipfs add" actual + test_expect_success "Adding named pipes explicitly works" ' + mkfifo named-pipe1 && + ( echo foo > named-pipe1 & echo "added $( echo foo | ipfs add -nq ) named-pipe1" > expected_named_pipes_add ) && + mkfifo named-pipe2 && + ( echo bar > named-pipe2 & echo "added $( echo bar | ipfs add -nq ) named-pipe2" >> expected_named_pipes_add ) && + ipfs add -n named-pipe1 named-pipe2 >actual_pipe_add && + rm named-pipe1 && + rm named-pipe2 && + test_cmp expected_named_pipes_add actual_pipe_add ' test_expect_success "useful error message when recursively adding a named pipe" ' @@ -510,7 +520,7 @@ test_add_named_pipe() { mkfifo named-pipe-dir/named-pipe && STAT=$(generic_stat named-pipe-dir/named-pipe) && test_expect_code 1 ipfs add -r named-pipe-dir 2>actual && - printf "Error:$err_prefix unrecognized file type for named-pipe-dir/named-pipe: $STAT\n" >expected && + printf "Error: unrecognized file type for named-pipe-dir/named-pipe: $STAT\n" >expected && rm named-pipe-dir/named-pipe && rmdir named-pipe-dir && test_cmp expected actual @@ -778,11 +788,11 @@ test_add_cat_5MB '--cid-version=1 --raw-leaves=false' "bafybeieyifrgpjn3yengthr7 # 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 funtion +# encoded with the blake2b-256 hash function test_add_cat_5MB '--hash=blake2b-256' "bafykbzacebnmjcl4sn37b3ehtibvf263oun2w6idghenrvlpehq5w5jqyvhjo" # the specified hash represents the leaf nodes stored as protoful nodes and -# encoded with the blake2b-256 hash funtion +# encoded with the blake2b-256 hash function test_add_cat_5MB '--hash=blake2b-256 --raw-leaves=false' "bafykbzaceaxiiykzgpbhnzlecffqm3zbuvhujyvxe5scltksyafagkyw4rjn2" test_add_cat_expensive "" "QmU9SWAPPmNEKZB8umYMmjYvN7VyHqABNvdA6GUi4MMEz3" @@ -793,10 +803,10 @@ test_add_cat_expensive "--cid-version=1" "bafybeidkj5ecbhrqmzrcee2rw7qwsx24z3364 # 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 funtion +# encoded with the blake2b-256 hash function test_add_cat_expensive '--hash=blake2b-256' "bafykbzaceb26fnq5hz5iopzamcb4yqykya5x6a4nvzdmcyuu4rj2akzs3z7r6" -test_add_named_pipe " Post http://$API_ADDR/api/v0/add?chunker=size-262144&encoding=json&hash=sha2-256&inline-limit=32&pin=true&progress=true&recursive=true&stream-channels=true:" +test_add_named_pipe test_add_pwd_is_symlink @@ -827,7 +837,7 @@ test_expect_success "ipfs cat file fails" ' test_must_fail ipfs cat $(cat oh_hash) ' -test_add_named_pipe "" +test_add_named_pipe test_add_pwd_is_symlink diff --git a/test/sharness/t0042-add-skip.sh b/test/sharness/t0042-add-skip.sh index 1bdea660779..9da78163c45 100755 --- a/test/sharness/t0042-add-skip.sh +++ b/test/sharness/t0042-add-skip.sh @@ -12,6 +12,7 @@ test_add_skip() { test_expect_success "'ipfs add -r' with hidden file succeeds" ' mkdir -p mountdir/planets/.asteroids && + echo "mars.txt" >mountdir/planets/.gitignore && echo "Hello Mars" >mountdir/planets/mars.txt && echo "Hello Venus" >mountdir/planets/venus.txt && echo "Hello Pluto" >mountdir/planets/.pluto.txt && @@ -39,11 +40,44 @@ EOF added QmcAREBcjgnUpKfyFmUGnfajA1NQS5ydqRp7WfqZ6JF8Dx planets/.asteroids/ceres.txt added QmZ5eaLybJ5GUZBNwy24AA9EEDTDpA4B8qXnuN3cGxu2uF planets/.asteroids/pallas.txt added QmaowqjedBkUrMUXgzt9c2ZnAJncM9jpJtkFfgdFstGr5a planets/.charon.txt +added QmPHrRjTH8FskN3C2iv6BLekDT94o23KSL2u5qLqQqGhVH planets/.gitignore added QmU4zFD5eJtRBsWC63AvpozM9Atiadg9kPVTuTrnCYJiNF planets/.pluto.txt added QmZy3khu7qf696i5HtkgL2NotsCZ8wzvNZJ1eUdA5n8KaV planets/mars.txt added QmQnv4m3Q5512zgVtpbJ9z85osQrzZzGRn934AGh6iVEXz planets/venus.txt added Qmf6rbs5GF85anDuoxpSAdtuZPM9D2Yt3HngzjUVSQ7kDV planets/.asteroids -added QmetajtFdmzhWYodAsZoVZSiqpeJDAiaw2NwbM3xcWcpDj planets +added QmczhHaXyb3bc9APMxe4MXbr87V5YDLKLaw3DZX3fK7HrK planets +EOF + test_cmp expected actual + ' + + test_expect_success "'ipfs add -r --ignore-rules-path=.gitignore --hidden' succeeds" ' + (cd mountdir/planets && ipfs add -r --ignore-rules-path=.gitignore --hidden .) > actual + ' + + test_expect_success "'ipfs add -r --ignore-rules-path=.gitignore --hidden' did not include mars.txt file" ' + cat >expected <<-\EOF && +added QmcAREBcjgnUpKfyFmUGnfajA1NQS5ydqRp7WfqZ6JF8Dx planets/.asteroids/ceres.txt +added QmZ5eaLybJ5GUZBNwy24AA9EEDTDpA4B8qXnuN3cGxu2uF planets/.asteroids/pallas.txt +added QmaowqjedBkUrMUXgzt9c2ZnAJncM9jpJtkFfgdFstGr5a planets/.charon.txt +added QmPHrRjTH8FskN3C2iv6BLekDT94o23KSL2u5qLqQqGhVH planets/.gitignore +added QmU4zFD5eJtRBsWC63AvpozM9Atiadg9kPVTuTrnCYJiNF planets/.pluto.txt +added QmQnv4m3Q5512zgVtpbJ9z85osQrzZzGRn934AGh6iVEXz planets/venus.txt +added Qmf6rbs5GF85anDuoxpSAdtuZPM9D2Yt3HngzjUVSQ7kDV planets/.asteroids +added QmaRsiaCYvc65RqHVAcv2tqyjZgQYgvaNqW1tQGsjfy4N5 planets +EOF + test_cmp expected actual + ' + + test_expect_success "'ipfs add -r --ignore-rules-path=.gitignore --ignore .asteroids --ignore venus.txt --hidden' succeeds" ' + (cd mountdir/planets && ipfs add -r --ignore-rules-path=.gitignore --ignore .asteroids --ignore venus.txt --hidden .) > actual + ' + + test_expect_success "'ipfs add -r --ignore-rules-path=.gitignore --ignore .asteroids --ignore venus.txt --hidden' did not include ignored files" ' + cat >expected <<-\EOF && +added QmaowqjedBkUrMUXgzt9c2ZnAJncM9jpJtkFfgdFstGr5a planets/.charon.txt +added QmPHrRjTH8FskN3C2iv6BLekDT94o23KSL2u5qLqQqGhVH planets/.gitignore +added QmU4zFD5eJtRBsWC63AvpozM9Atiadg9kPVTuTrnCYJiNF planets/.pluto.txt +added QmemuMahjSh7eYLY3hbz2q8sqMPnbQzBQeUdosqNiWChE6 planets EOF test_cmp expected actual ' diff --git a/test/sharness/t0050-block.sh b/test/sharness/t0050-block.sh index 7092d4cb87e..70639f623e9 100755 --- a/test/sharness/t0050-block.sh +++ b/test/sharness/t0050-block.sh @@ -11,6 +11,7 @@ test_description="Test block command" test_init_ipfs HASH="QmRKqGMAM6EZngbpjSqrvYzq5Qd8b1bSWymjSUY9zQSNDk" +HASHB="QmdnpnsaEj69isdw5sNzp3h3HkaDz7xKq7BmvFFBzNr5e7" # # "block put tests" @@ -26,6 +27,18 @@ test_expect_success "'ipfs block put' output looks good" ' test_cmp expected_out actual_out ' +test_expect_success "'ipfs block put' with 2 files succeeds" ' + echo "Hello Mars!" > a && + echo "Hello Venus!" > b && + ipfs block put a b >actual_out +' + +test_expect_success "'ipfs block put' output looks good" ' + echo "$HASH" >expected_out && + echo "$HASHB" >>expected_out && + test_cmp expected_out actual_out +' + # # "block get" tests # @@ -215,7 +228,7 @@ test_expect_success "can read block with different hash" ' # Misc tests # -test_expect_success "'ipfs block stat' with nothing from stdin doesnt crash" ' +test_expect_success "'ipfs block stat' with nothing from stdin doesn't crash" ' test_expect_code 1 ipfs block stat < /dev/null 2> stat_out ' diff --git a/test/sharness/t0051-object.sh b/test/sharness/t0051-object.sh index 4f8e7e12d0f..173148de0c5 100755 --- a/test/sharness/t0051-object.sh +++ b/test/sharness/t0051-object.sh @@ -206,7 +206,7 @@ test_object_cmd() { test_cmp expected actual ' - test_expect_success "after gc, objects still acessible" ' + test_expect_success "after gc, objects still accessible" ' ipfs repo gc > /dev/null && ipfs refs -r --timeout=2s $HASH > /dev/null ' @@ -419,19 +419,19 @@ test_object_cmd() { test_object_content_type() { test_expect_success "'ipfs object get --encoding=protobuf' returns the correct content type" ' - curl -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=protobuf" | grep -q "^Content-Type: application/protobuf" + 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 -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=json" | grep -q "^Content-Type: application/json" + 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 -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=text" | grep -q "^Content-Type: text/plain" + 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 -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=xml" | grep -q "^Content-Type: application/xml" + curl -X POST -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=xml" | grep -q "^Content-Type: application/xml" ' } diff --git a/test/sharness/t0053-dag.sh b/test/sharness/t0053-dag.sh index f31024420b1..de35a58fd1c 100755 --- a/test/sharness/t0053-dag.sh +++ b/test/sharness/t0053-dag.sh @@ -97,7 +97,7 @@ test_dag_cmd() { ipfs pin add $EXPHASH ' - test_expect_success "after gc, objects still acessible" ' + test_expect_success "after gc, objects still accessible" ' ipfs repo gc > /dev/null && ipfs refs -r --timeout=2s $EXPHASH > /dev/null ' @@ -110,7 +110,7 @@ test_dag_cmd() { grep "{\"/\":\"" ipld_obj_out > /dev/null ' - test_expect_success "retreived object hashes back correctly" ' + test_expect_success "retrieved object hashes back correctly" ' IPLDHASH2=$(cat ipld_obj_out | ipfs dag put) && test "$IPLDHASH" = "$IPLDHASH2" ' @@ -153,7 +153,7 @@ test_dag_cmd() { PINHASH=$(printf {\"foo\":\"bar\"} | ipfs dag put --pin=true) ' - test_expect_success "after gc, objects still acessible" ' + test_expect_success "after gc, objects still accessible" ' ipfs repo gc > /dev/null && ipfs refs -r --timeout=2s $PINHASH > /dev/null ' diff --git a/test/sharness/t0054-dag-car-import-export-data/README.md b/test/sharness/t0054-dag-car-import-export-data/README.md new file mode 100644 index 00000000000..77679af390f --- /dev/null +++ b/test/sharness/t0054-dag-car-import-export-data/README.md @@ -0,0 +1,24 @@ +# Dataset description/sources + +- lotus_testnet_export_256_multiroot.car + - Export of the first 256 block of the testnet chain, with 3 tipset roots. Exported from Lotus by @traviperson on 2019-03-18 + + +- lotus_devnet_genesis.car + - Source: https://github.com/filecoin-project/lotus/blob/v0.2.10/build/genesis/devnet.car + +- lotus_testnet_export_128.car + - Export of the first 128 block of the testnet chain, exported from Lotus by @traviperson on 2019-03-24 + + +- lotus_devnet_genesis_shuffled_noroots.car +- lotus_testnet_export_128_shuffled_noroots.car + - versions of the above with an **empty** root array, and having all blocks shuffled + +- lotus_devnet_genesis_shuffled_nulroot.car +- lotus_testnet_export_128_shuffled_nulroot.car + - versions identical to the above, but with a single "empty-block" root each ( in order to work around go-car not following the current "roots can be empty" spec ) + +- combined_naked_roots_genesis_and_128.car + - only the roots of `lotus_devnet_genesis.car` and `lotus_testnet_export_128.car`, to to be used in combination with the root-less parts to validate "transactional" pinning + diff --git a/test/sharness/t0054-dag-car-import-export-data/test_dataset_car_v0.tar.xz b/test/sharness/t0054-dag-car-import-export-data/test_dataset_car_v0.tar.xz new file mode 100644 index 00000000000..34eb36dd1ca Binary files /dev/null and b/test/sharness/t0054-dag-car-import-export-data/test_dataset_car_v0.tar.xz differ diff --git a/test/sharness/t0054-dag-car-import-export.sh b/test/sharness/t0054-dag-car-import-export.sh new file mode 100755 index 00000000000..450591ff792 --- /dev/null +++ b/test/sharness/t0054-dag-car-import-export.sh @@ -0,0 +1,204 @@ +#!/usr/bin/env bash +# + +test_description="Test car file import/export functionality" + +. lib/test-lib.sh +export -f ipfsi + +set -o pipefail + +tar -C ../t0054-dag-car-import-export-data/ --strip-components=1 -Jxf ../t0054-dag-car-import-export-data/test_dataset_car_v0.tar.xz +tab=$'\t' + +test_cmp_sorted() { + # use test_cmp to dump out the unsorted file contents as a diff + [[ "$( sort "$1" | sha256sum )" == "$( sort "$2" | sha256sum )" ]] \ + || test_cmp "$1" "$2" +} +export -f test_cmp_sorted + +reset_blockstore() { + node=$1 + + ipfsi "$node" pin ls --quiet --type=recursive | ipfsi "$node" pin rm &>/dev/null + ipfsi "$node" repo gc &>/dev/null + + test_expect_success "pinlist empty" ' + [[ -z "$( ipfsi $node pin ls )" ]] + ' + test_expect_success "nothing left to gc" ' + [[ -z "$( ipfsi $node repo gc )" ]] + ' +} + +# hammer with concurrent gc to ensure nothing clashes +do_import() { + node="$1"; shift + ( + touch spin.gc + + while [[ -e spin.gc ]]; do ipfsi "$node" repo gc &>/dev/null; done & + while [[ -e spin.gc ]]; do ipfsi "$node" repo gc &>/dev/null; done & + + ipfsi "$node" dag import "$@" 2>&1 && ipfsi "$node" repo verify &>/dev/null + result=$? + + rm -f spin.gc &>/dev/null + wait || true # work around possible trigger of a bash bug on overloaded circleci + exit $result + ) +} + +run_online_imp_exp_tests() { + + reset_blockstore 0 + reset_blockstore 1 + + cat > basic_import_expected <naked_root_import_json_expected < basic_import_actual + ' + + test_expect_success "basic import output as expected" ' + test_cmp_sorted basic_import_expected basic_import_actual + ' + + test_expect_success "basic fetch+export 1" ' + ipfsi 1 dag export bafy2bzaced4ueelaegfs5fqu4tzsh6ywbbpfk3cxppupmxfdhbpbhzawfw5oy > reexported_testnet_128.car + ' + test_expect_success "export of shuffled testnet export identical to canonical original" ' + test_cmp reexported_testnet_128.car ../t0054-dag-car-import-export-data/lotus_testnet_export_128.car + ' + + test_expect_success "basic fetch+export 2" ' + ipfsi 1 dag export bafy2bzaceaxm23epjsmh75yvzcecsrbavlmkcxnva66bkdebdcnyw3bjrc74u > reexported_devnet_genesis.car + ' + test_expect_success "export of shuffled devnet export identical to canonical original" ' + test_cmp reexported_devnet_genesis.car ../t0054-dag-car-import-export-data/lotus_devnet_genesis.car + ' + + test_expect_success "pinlist on node1 still empty" ' + [[ -z "$( ipfsi 1 pin ls )" ]] + ' + + test_expect_success "import/pin naked roots only, relying on local blockstore having all the data" ' + ipfsi 1 dag import --enc=json ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \ + > naked_import_result_json_actual + ' + + test_expect_success "naked import output as expected" ' + test_cmp_sorted naked_root_import_json_expected naked_import_result_json_actual + ' + + reset_blockstore 0 + reset_blockstore 1 + + mkfifo pipe_testnet + mkfifo pipe_devnet + + test_expect_success "fifo import" ' + ( + cat ../t0054-dag-car-import-export-data/lotus_testnet_export_128_shuffled_nulroot.car > pipe_testnet & + cat ../t0054-dag-car-import-export-data/lotus_devnet_genesis_shuffled_nulroot.car > pipe_devnet & + + do_import 0 \ + pipe_testnet \ + pipe_devnet \ + ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \ + > basic_fifo_import_actual + result=$? + + wait || true # work around possible trigger of a bash bug on overloaded circleci + exit "$result" + ) + ' + + test_expect_success "remove fifos" ' + rm pipe_testnet pipe_devnet + ' + + test_expect_success "fifo-import output as expected" ' + test_cmp_sorted basic_import_expected basic_fifo_import_actual + ' +} + + +test_expect_success "set up testbed" ' + iptb testbed create -type localipfs -count 2 -force -init +' +startup_cluster 2 + +run_online_imp_exp_tests + +test_expect_success "shut down nodes" ' + iptb stop && iptb_wait_stop +' + + +# We want to just init the repo, without using a daemon for stuff below +test_init_ipfs + + +test_expect_success "basic offline export of 'getting started' dag works" ' + ipfs dag export "$HASH_WELCOME_DOCS" >/dev/null +' + + +echo "Error: merkledag: not found (currently offline, perhaps retry after attaching to the network)" > offline_fetch_error_expected +test_expect_success "basic offline export of nonexistent cid" ' + ! ipfs dag export QmYwAPJXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 2> offline_fetch_error_actual >/dev/null +' +test_expect_success "correct error" ' + test_cmp_sorted offline_fetch_error_expected offline_fetch_error_actual +' + + +cat >multiroot_import_json_expected < multiroot_import_json_actual +' +test_expect_success "multiroot import expected output" ' + test_cmp_sorted multiroot_import_json_expected multiroot_import_json_actual +' + + +test_expect_success "pin-less import works" ' + ipfs dag import --enc=json --pin-roots=false \ + ../t0054-dag-car-import-export-data/lotus_devnet_genesis.car \ + ../t0054-dag-car-import-export-data/lotus_testnet_export_128.car \ + > no-pin_import_actual +' +test_expect_success "expected silence on --pin-roots=false" ' + test_cmp /dev/null no-pin_import_actual +' + + +test_expect_success "naked root import works" ' + ipfs dag import --enc=json ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \ + > naked_root_import_json_actual +' +test_expect_success "naked root import expected output" ' + test_cmp_sorted naked_root_import_json_expected naked_root_import_json_actual +' + +test_done diff --git a/test/sharness/t0060-daemon.sh b/test/sharness/t0060-daemon.sh index 6f2445b3d9a..c2f11a10c7b 100755 --- a/test/sharness/t0060-daemon.sh +++ b/test/sharness/t0060-daemon.sh @@ -8,6 +8,39 @@ test_description="Test daemon command" . lib/test-lib.sh +test_expect_success "create badger config" ' + ipfs init --profile=badgerds,test > /dev/null && + cp "$IPFS_PATH/config" init-config +' + +test_expect_success "cleanup repo" ' + rm -rf "$IPFS_PATH" +' + +test_launch_ipfs_daemon --init --init-config="$(pwd)/init-config" --init-profile=test +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 Addresses > orig_addrs +' + +test_expect_success "cleanup repo" ' + rm -rf "$IPFS_PATH" +' + +test_launch_ipfs_daemon --init --init-config="$(pwd)/init-config" --init-profile=test,randomports +test_kill_ipfs_daemon + +test_expect_success "daemon initialization with existing config + profiles works" ' + ipfs config Addresses >new_addrs && + test_expect_code 1 diff -q new_addrs orig_addrs +' + +test_expect_success "cleanup repo" ' + rm -rf "$IPFS_PATH" +' test_init_ipfs test_launch_ipfs_daemon @@ -32,11 +65,11 @@ test_expect_success "ipfs peer id looks good" ' # this is for checking SetAllowedOrigins race condition for the api and gateway # See https://github.com/ipfs/go-ipfs/pull/1966 test_expect_success "ipfs API works with the correct allowed origin port" ' - curl -s -X GET -H "Origin:http://localhost:$API_PORT" -I "http://$API_ADDR/api/v0/version" + curl -s -X POST -H "Origin:http://localhost:$API_PORT" -I "http://$API_ADDR/api/v0/version" ' test_expect_success "ipfs gateway works with the correct allowed origin port" ' - curl -s -X GET -H "Origin:http://localhost:$GWAY_PORT" -I "http://$GWAY_ADDR/api/v0/version" + 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" ' @@ -75,8 +108,9 @@ test_expect_success "ipfs version deps succeeds" ' ipfs version deps >deps.txt ' -test_expect_success "ipfs version deps output looks good" ' +test_expect_success "ipfs version deps output looks good ( set \$GOIPFSTEST_SKIP_LOCAL_DEVTREE_DEPS_CHECK to skip this test )" ' head -1 deps.txt | grep "go-ipfs@(devel)" && + [[ "$GOIPFSTEST_SKIP_LOCAL_DEVTREE_DEPS_CHECK" == "1" ]] || [[ $(tail -n +2 deps.txt | egrep -v -c "^[^ @]+@v[^ @]+( => [^ @]+@v[^ @]+)?$") -eq 0 ]] || test_fsh cat deps.txt ' @@ -91,13 +125,8 @@ test_expect_success "ipfs help output looks good" ' test_fsh cat help.txt ' -# netcat (nc) is needed for the following test -test_expect_success "socat is available" ' - type socat >/dev/null -' - # check transport is encrypted -test_expect_success "transport should be encrypted" ' +test_expect_success SOCAT "transport should be encrypted ( needs socat )" ' socat - tcp:localhost:$SWARM_PORT,connect-timeout=1 > swarmnc < ../t0060-data/mss-ls && grep -q "/secio" swarmnc && test_must_fail grep -q "/plaintext/1.0.0" swarmnc || @@ -105,7 +134,7 @@ test_expect_success "transport should be encrypted" ' ' test_expect_success "output from streaming commands works" ' - test_expect_code 28 curl -m 5 http://localhost:$API_PORT/api/v0/stats/bw\?poll=true > statsout + test_expect_code 28 curl -X POST -m 5 http://localhost:$API_PORT/api/v0/stats/bw\?poll=true > statsout ' test_expect_success "output looks good" ' @@ -133,7 +162,7 @@ test_expect_success "'ipfs daemon' should be able to run with a pipe attached to ' test_expect_success "daemon with pipe eventually becomes live" ' - pollEndpoint -host='$API_MADDR' -ep=/version -v -tout=1s -tries=10 >stdin_poll_apiout 2>stdin_poll_apierr && + pollEndpoint -host='$API_MADDR' -v -tout=1s -tries=10 >stdin_poll_apiout 2>stdin_poll_apierr && test_kill_repeat_10_sec $DAEMON_PID || test_fsh cat stdin_daemon_out || test_fsh cat stdin_daemon_err || test_fsh cat stdin_poll_apiout || test_fsh cat stdin_poll_apierr ' @@ -155,7 +184,7 @@ test_expect_success "daemon actually can handle 2048 file descriptors" ' hang-fds -hold=2s 2000 '$API_MADDR' > /dev/null ' -test_expect_success "daemon didnt throw any errors" ' +test_expect_success "daemon didn't throw any errors" ' test_expect_code 1 grep "too many open files" daemon_err ' diff --git a/test/sharness/t0061-daemon-opts.sh b/test/sharness/t0061-daemon-opts.sh index 227d4fa30dc..7d5cf7fe7b6 100755 --- a/test/sharness/t0061-daemon-opts.sh +++ b/test/sharness/t0061-daemon-opts.sh @@ -17,7 +17,7 @@ gwyaddr=$GWAY_ADDR apiaddr=$API_ADDR # Odd. this fails here, but the inverse works on t0060-daemon. -test_expect_success 'transport should be unencrypted' ' +test_expect_success SOCAT 'transport should be unencrypted ( needs socat )' ' socat - tcp:localhost:$SWARM_PORT,connect-timeout=1 > swarmnc < ../t0060-data/mss-ls && grep -q -v "/secio" swarmnc && grep -q "/plaintext" swarmnc || diff --git a/test/sharness/t0062-daemon-api.sh b/test/sharness/t0062-daemon-api.sh index b4c7eccdb51..3eb31b1c731 100755 --- a/test/sharness/t0062-daemon-api.sh +++ b/test/sharness/t0062-daemon-api.sh @@ -32,7 +32,7 @@ test_client_must_fail() { opts="$@" echo "OPTS = " $opts test_expect_success "client should fail $state" ' - echo "Error: cannot connect to the api. Is the deamon running? To run as a standalone CLI command remove the api file in \`\$IPFS_PATH/api\`" >expected_err && + echo "Error: cannot connect to the api. Is the daemon running? To run as a standalone CLI command remove the api file in \`\$IPFS_PATH/api\`" >expected_err && test_must_fail ipfs id -f="" $opts >actual 2>actual_err && test_cmp expected_err actual_err ' @@ -66,7 +66,7 @@ test_client_suite() { # first, test things without daemon, without /api file # with no daemon, everything should fail -# (using unreachable because API_MADDR doesnt get set until daemon start) +# (using unreachable because API_MADDR doesn't get set until daemon start) test_client_suite "(daemon off, no --api, no /api file)" false false "$api_unreachable" "$api_other" diff --git a/test/sharness/t0064-api-file.sh b/test/sharness/t0064-api-file.sh new file mode 100755 index 00000000000..97c1a7b239c --- /dev/null +++ b/test/sharness/t0064-api-file.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +# +# MIT Licensed; see the LICENSE file in this repository. +# + +test_description="Test api file" + +. lib/test-lib.sh + +test_init_ipfs + + +test_launch_ipfs_daemon +test_kill_ipfs_daemon + +test_expect_success "version always works" ' + ipfs version >/dev/null +' + +test_expect_success "swarm peers fails when offline" ' + test_must_fail ipfs swarm peers >/dev/null +' + +test_expect_success "swarm peers fails when offline and API specified" ' + test_must_fail ipfs swarm peers --api="$API_MADDR" >/dev/null +' + +test_expect_success "pin ls succeeds when offline" ' + ipfs pin ls >/dev/null +' + +test_expect_success "pin ls fails when offline and API specified" ' + test_must_fail ipfs pin ls --api="$API_MADDR" >/dev/null +' + +test_expect_success "id succeeds when offline" ' + ipfs id >/dev/null +' + +test_expect_success "id fails when offline API specified" ' + test_must_fail ipfs id --api="$API_MADDR" >/dev/null +' + +test_expect_success "create API file" ' + echo "$API_MADDR" > "$IPFS_PATH/api" +' + +test_expect_success "version always works" ' + ipfs version >/dev/null +' + +test_expect_success "id succeeds when offline and API file exists" ' + ipfs id >/dev/null +' + +test_expect_success "pin ls succeeds when offline and API file exists" ' + ipfs pin ls >/dev/null +' + +test_launch_ipfs_daemon + +test_expect_success "version always works" ' + ipfs version >/dev/null +' + +test_expect_success "id succeeds when online" ' + ipfs id >/dev/null +' + +test_expect_success "swarm peers succeeds when online" ' + ipfs swarm peers >/dev/null +' + +test_expect_success "pin ls succeeds when online" ' + ipfs pin ls >/dev/null +' + +test_expect_success "remove API file when daemon is running" ' + rm "$IPFS_PATH/api" +' + +test_expect_success "version always works" ' + ipfs version >/dev/null +' + +test_expect_success "swarm peers fails when the API file is missing" ' + test_must_fail ipfs swarm peers >/dev/null +' + +test_expect_success "id fails when daemon is running but API file is missing (locks repo)" ' + test_must_fail ipfs pin ls >/dev/null +' + +test_expect_success "pin ls fails when daemon is running but API file is missing (locks repo)" ' + test_must_fail ipfs pin ls >/dev/null +' + +test_kill_ipfs_daemon + +test_done diff --git a/test/sharness/t0067-unix-api.sh b/test/sharness/t0067-unix-api.sh new file mode 100755 index 00000000000..4f1e34ca4af --- /dev/null +++ b/test/sharness/t0067-unix-api.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# +# MIT Licensed; see the LICENSE file in this repository. +# + +test_description="Test unix API transport" + +. lib/test-lib.sh + +test_init_ipfs + +# We can't use the trash dir as the full name must be longer less than 108 bytes +# long (because that's the max unix domain socket path length). +SOCKDIR="$(mktemp -d "${TMPDIR:-/tmp}/unix-api-sharness.XXXXXX")" + +test_expect_success "configure" ' + peerid=$(ipfs config Identity.PeerID) && + ipfs config Addresses.API "/unix/$SOCKDIR/sock" +' + +test_launch_ipfs_daemon + +test_expect_success "client works" ' + printf "$peerid" >expected && + ipfs --api="/unix/$SOCKDIR/sock" id -f="" >actual && + test_cmp expected actual +' + +test_kill_ipfs_daemon +test_done diff --git a/test/sharness/t0080-repo.sh b/test/sharness/t0080-repo.sh index 2882e8721ca..4e0d4800f72 100755 --- a/test/sharness/t0080-repo.sh +++ b/test/sharness/t0080-repo.sh @@ -33,7 +33,7 @@ test_expect_success "'ipfs repo gc' looks good (patch root)" ' grep -v "removed $HASH" gc_out_actual ' -test_expect_success "'ipfs repo gc' doesnt remove file" ' +test_expect_success "'ipfs repo gc' doesn't remove file" ' ipfs cat "$HASH" >out && test_cmp out afile ' @@ -50,8 +50,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 && - expected="$(directory_size "$IPFS_PATH/blocks")" && - find "$IPFS_PATH/blocks" -type f && + find "$IPFS_PATH/blocks" -type f -name "*.data" | sort -u > expected_blocks && hash=$(ipfs add -q gcfile) && ipfs pin rm -r $hash && ipfs repo gc @@ -60,9 +59,8 @@ test_expect_success "ipfs repo gc fully reverse ipfs add (part 1)" ' test_kill_ipfs_daemon test_expect_success "ipfs repo gc fully reverse ipfs add (part 2)" ' - actual=$(directory_size "$IPFS_PATH/blocks") && - { test "$actual" -eq "$expected" || test_fsh echo "$actual != $expected"; } && - { test "$actual" -gt "0" || test_fsh echo "not($actual > 0)"; } + find "$IPFS_PATH/blocks" -type f -name "*.data" | sort -u > actual_blocks && + test_cmp expected_blocks actual_blocks ' test_launch_ipfs_daemon --offline @@ -249,10 +247,10 @@ test_expect_success "'ipfs repo stat --human' succeeds" ' test_expect_success "repo stats --human came out correct" ' grep "RepoPath" repo-stats-human && - grep -P "RepoSize:\s*([0-9]*[.])?[0-9]+\s+?(B|kB|MB|GB|TB|PB|EB)" repo-stats-human && + grep -E "RepoSize:\s*([0-9]*[.])?[0-9]+\s+?(B|kB|MB|GB|TB|PB|EB)" repo-stats-human && grep "NumObjects" repo-stats-human && grep "Version" repo-stats-human && - grep -P "StorageMax:\s*([0-9]*[.])?[0-9]+\s+?(B|kB|MB|GB|TB|PB|EB)" repo-stats-human || + grep -E "StorageMax:\s*([0-9]*[.])?[0-9]+\s+?(B|kB|MB|GB|TB|PB|EB)" repo-stats-human || test_fsh cat repo-stats-human ' diff --git a/test/sharness/t0083-repo-fsck.sh b/test/sharness/t0083-repo-fsck.sh deleted file mode 100755 index fe567840cd5..00000000000 --- a/test/sharness/t0083-repo-fsck.sh +++ /dev/null @@ -1,190 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2016 Mike Pfister -# MIT Licensed; see the LICENSE file in this repository. -# - -test_description="Test ipfs repo fsck operations" - -. lib/test-lib.sh - -test_init_ipfs - -############################# -# Test without daemon running -############################# -# NOTE: if api file isn't present we can assume the daemon isn't running - -# Try with all lock files present: repo.lock, api, and datastore/LOCK with -# repo.lock and datastore/LOCK being empty -test_expect_success "'ipfs repo fsck' succeeds with no daemon running empty -repo.lock" ' - mkdir -p $IPFS_PATH && - mkdir -p $IPFS_PATH/datastore && - touch $IPFS_PATH/datastore/LOCK && - touch $IPFS_PATH/repo.lock && - printf "/ip4/127.0.0.1/tcp/5001" > "$IPFS_PATH/api" && - ipfs repo fsck > fsck_out_actual1 -' -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual1 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -# Try with all lock files present: repo.lock, api, and datastore/LOCK with -# repo.lock is non-zero TODO: this test is broken until we find consensus on the -# non-zero repo.lock issue -test_expect_success "'ipfs repo fsck' succeeds with no daemon running non-zero -repo.lock" ' - mkdir -p "$IPFS_PATH" && - printf ":D" > "$IPFS_PATH/repo.lock" && - touch "$IPFS_PATH/datastore/LOCK" && - ipfs repo fsck > fsck_out_actual1b -' -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual1b -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -######################## -# Test for partial locks -######################## - -# Try with locks api and datastore/LOCK -test_expect_success "'ipfs repo fsck' succeeds partial lock" ' - printf "/ip4/127.0.0.1/tcp/5001" > "$IPFS_PATH/api" && - touch $IPFS_PATH/datastore/LOCK && - ipfs repo fsck > fsck_out_actual2 -' - -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual2 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -# Try with locks api and repo.lock -test_expect_success "'ipfs repo fsck' succeeds partial lock" ' - printf "/ip4/127.0.0.1/tcp/5001" > "$IPFS_PATH/api" && - touch $IPFS_PATH/repo.lock && - ipfs repo fsck > fsck_out_actual3 -' - -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual3 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -# Try with locks repo.lock and datastore -test_expect_success "'ipfs repo fsck' succeeds partial lock" ' - touch $IPFS_PATH/repo.lock && - touch $IPFS_PATH/datastore/LOCK && - ipfs repo fsck > fsck_out_actual4 -' - -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual4 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -####################### -# Test for single locks -####################### - -# Try with single locks repo.lock -test_expect_success "'ipfs repo fsck' succeeds partial lock" ' - touch $IPFS_PATH/repo.lock && - ipfs repo fsck > fsck_out_actual5 -' -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual5 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -# Try with single locks datastore/LOCK -test_expect_success "'ipfs repo fsck' succeeds partial lock" ' - touch $IPFS_PATH/datastore/LOCK && - ipfs repo fsck > fsck_out_actual6 -' -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual6 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -# Try with single lock api -test_expect_success "'ipfs repo fsck' succeeds partial lock" ' - printf "/ip4/127.0.0.1/tcp/5001" > "$IPFS_PATH/api" && - ipfs repo fsck > fsck_out_actual7 -' - -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual7 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -########################## -# Test with daemon running -########################## - -test_launch_ipfs_daemon - -# Daemon is running -> command doesn't run -test_expect_success "'ipfs repo fsck' fails with daemon running" ' - ! (ipfs repo fsck 2>fsck_out_actual8 ) - -' - -test_expect_success "'ipfs repo fsck' output looks good with daemon" ' - grep "Error: ipfs daemon is running" fsck_out_actual8 -' - -test_kill_ipfs_daemon - -test_done diff --git a/test/sharness/t0085-pins.sh b/test/sharness/t0085-pins.sh index 6428e099d2f..e05f7dedbbd 100755 --- a/test/sharness/t0085-pins.sh +++ b/test/sharness/t0085-pins.sh @@ -10,8 +10,9 @@ test_description="Test ipfs pinning operations" test_pins() { - EXTRA_ARGS=$1 - BASE=$2 + PIN_ARGS="$1" + LS_ARGS="$2" + BASE=$3 if [ -n "$BASE" ]; then BASE_ARGS="--cid-base=$BASE" fi @@ -44,11 +45,11 @@ test_pins() { ' fi - test_expect_success "'ipfs pin add $EXTRA_ARGS' via stdin" ' - cat hashes | ipfs pin add $EXTRA_ARGS $BASE_ARGS | tee actual + test_expect_success "'ipfs pin add $PIN_ARGS' via stdin" ' + cat hashes | ipfs pin add $PIN_ARGS $BASE_ARGS | tee actual ' - test_expect_success "'ipfs pin add $EXTRA_ARGS' output looks good" ' + test_expect_success "'ipfs pin add $PIN_ARGS' output looks good" ' sed -e "s/^/pinned /; s/$/ recursively/" hashes > expected && test_cmp expected actual ' @@ -69,8 +70,8 @@ test_pins() { test_should_contain "$HASH_G ok" verify_out ' - test_expect_success "ipfs pin ls $BASE_ARGS works" ' - ipfs pin ls $BASE_ARGS > ls_out && + test_expect_success "ipfs pin ls $LS_ARGS $BASE_ARGS works" ' + ipfs pin ls $LS_ARGS $BASE_ARGS > ls_out && test_should_contain "$HASH_A" ls_out && test_should_contain "$HASH_B" ls_out && test_should_contain "$HASH_C" ls_out && @@ -80,9 +81,9 @@ test_pins() { test_should_contain "$HASH_G" ls_out ' - test_expect_success "test pin ls $BASE_ARGS hash" ' + test_expect_success "test pin ls $LS_ARGS $BASE_ARGS hash" ' echo $HASH_B | test_must_fail grep /ipfs && # just to be sure - ipfs pin ls $BASE_ARGS $HASH_B > ls_hash_out && + ipfs pin ls $LS_ARGS $BASE_ARGS $HASH_B > ls_hash_out && echo "$HASH_B recursive" > ls_hash_exp && test_cmp ls_hash_exp ls_hash_out ' @@ -93,11 +94,11 @@ test_pins() { test_expect_success "test pin update" ' ipfs pin add "$HASH_A" && - ipfs pin ls $BASE_ARGS | tee before_update && + ipfs pin ls $LS_ARGS $BASE_ARGS | tee before_update && test_should_contain "$HASH_A" before_update && test_must_fail grep -q "$HASH_B" before_update && ipfs pin update --unpin=true "$HASH_A" "$HASH_B" && - ipfs pin ls $BASE_ARGS > after_update && + ipfs pin ls $LS_ARGS $BASE_ARGS > after_update && test_must_fail grep -q "$HASH_A" after_update && test_should_contain "$HASH_B" after_update && ipfs pin update --unpin=true "$HASH_B" "$HASH_B" && @@ -110,20 +111,20 @@ test_pins() { RANDOM_HASH=Qme8uX5n9hn15pw9p6WcVKoziyyC9LXv4LEgvsmKMULjnV test_pins_error_reporting() { - EXTRA_ARGS=$1 + PIN_ARGS=$1 - test_expect_success "'ipfs pin add $EXTRA_ARGS' on non-existent hash should fail" ' - test_must_fail ipfs pin add $EXTRA_ARGS $RANDOM_HASH 2> err && + test_expect_success "'ipfs pin add $PIN_ARGS' on non-existent hash should fail" ' + test_must_fail ipfs pin add $PIN_ARGS $RANDOM_HASH 2> err && grep -q "not found" err ' } test_pin_dag_init() { - EXTRA_ARGS=$1 + PIN_ARGS=$1 - test_expect_success "'ipfs add $EXTRA_ARGS --pin=false' 1MB file" ' + test_expect_success "'ipfs add $PIN_ARGS --pin=false' 1MB file" ' random 1048576 56 > afile && - HASH=`ipfs add $EXTRA_ARGS --pin=false -q afile` + HASH=`ipfs add $PIN_ARGS --pin=false -q afile` ' } @@ -165,9 +166,11 @@ test_pin_progress() { test_init_ipfs -test_pins -test_pins --progress -test_pins '' base32 +test_pins '' '' '' +test_pins --progress '' '' +test_pins --progress --stream '' +test_pins '' '' base32 +test_pins '' --stream base32 test_pins_error_reporting test_pins_error_reporting --progress @@ -179,9 +182,11 @@ test_pin_progress test_launch_ipfs_daemon --offline -test_pins -test_pins --progress -test_pins '' base32 +test_pins '' '' '' +test_pins --progress '' '' +test_pins --progress --stream '' +test_pins '' '' base32 +test_pins '' --stream base32 test_pins_error_reporting test_pins_error_reporting --progress diff --git a/test/sharness/t0087-repo-robust-gc.sh b/test/sharness/t0087-repo-robust-gc.sh index 9038e9c5b00..6da96af6c44 100755 --- a/test/sharness/t0087-repo-robust-gc.sh +++ b/test/sharness/t0087-repo-robust-gc.sh @@ -35,7 +35,7 @@ test_gc_robust_part1() { test_must_fail ipfs cat $HASH1 ' - test_expect_success "'ipfs repo gc' should still be be fine" ' + test_expect_success "'ipfs repo gc' should still be fine" ' ipfs repo gc ' diff --git a/test/sharness/t0090-get.sh b/test/sharness/t0090-get.sh index e19d5506d9c..dd173dc7f62 100755 --- a/test/sharness/t0090-get.sh +++ b/test/sharness/t0090-get.sh @@ -156,7 +156,7 @@ test_get_cmd() { } test_get_fail() { - test_expect_success "create an object that has unresolveable links" ' + 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" } EOF @@ -184,7 +184,7 @@ test_launch_ipfs_daemon test_get_cmd test_expect_success "empty request to get doesn't panic and returns error" ' - curl "http://$API_ADDR/api/v0/get" > curl_out || true && + curl -X POST "http://$API_ADDR/api/v0/get" > curl_out || true && grep "argument \"ipfs-path\" is required" curl_out ' test_kill_ipfs_daemon diff --git a/test/sharness/t0095-refs.sh b/test/sharness/t0095-refs.sh index d363d043f8c..99dc361c79c 100755 --- a/test/sharness/t0095-refs.sh +++ b/test/sharness/t0095-refs.sh @@ -182,4 +182,6 @@ test_refs_output '' 'cat' test_refs_output '--cid-base=base32' 'ipfs cid base32' +test_kill_ipfs_daemon + test_done diff --git a/test/sharness/t0100-name.sh b/test/sharness/t0100-name.sh index e03f1553cf9..96d2ce5ea82 100755 --- a/test/sharness/t0100-name.sh +++ b/test/sharness/t0100-name.sh @@ -195,7 +195,7 @@ test_expect_success "resolve output looks good" ' ' test_expect_success "empty request to name publish doesn't panic and returns error" ' - curl "http://$API_ADDR/api/v0/name/publish" > curl_out || true && + curl -X POST "http://$API_ADDR/api/v0/name/publish" > curl_out || true && grep "argument \"ipfs-path\" is required" curl_out ' diff --git a/test/sharness/t0110-gateway.sh b/test/sharness/t0110-gateway.sh index 68172cb5655..2a1f58c71a4 100755 --- a/test/sharness/t0110-gateway.sh +++ b/test/sharness/t0110-gateway.sh @@ -64,7 +64,7 @@ test_expect_success "GET IPFS directory file output looks good" ' test_cmp dir/test actual ' -test_expect_success "GET IPFS non existent file returns code expected (404)" ' +test_expect_success "GET IPFS nonexistent file returns code expected (404)" ' test_curl_resp_http_code "http://127.0.0.1:$port/ipfs/$HASH2/pleaseDontAddMe" "HTTP/1.1 404 Not Found" ' @@ -104,7 +104,7 @@ test_expect_success "log output looks good" ' ' test_expect_success "GET /api/v0/version succeeds" ' - curl -v "http://127.0.0.1:$apiport/api/v0/version" 2> version_out + curl -X POST -v "http://127.0.0.1:$apiport/api/v0/version" 2> version_out ' test_expect_success "output only has one transfer encoding header" ' @@ -250,7 +250,7 @@ test_expect_success "try fetching not present ipns key from node 0" ' test_expect_code 22 curl -f "http://127.0.0.1:$GWPORT/ipns/$PEERID_1" ' -test_expect_success "try fetching present key from from node 0" ' +test_expect_success "try fetching present key from node 0" ' BAR=$(echo "bar" | ipfsi 0 add -Q) && curl -f "http://127.0.0.1:$GWPORT/ipfs/$BAR" ' diff --git a/test/sharness/t0111-gateway-writeable.sh b/test/sharness/t0111-gateway-writeable.sh index 71775d5d1e4..6708b91a6db 100755 --- a/test/sharness/t0111-gateway-writeable.sh +++ b/test/sharness/t0111-gateway-writeable.sh @@ -30,7 +30,7 @@ test_launch_ipfs_daemon port=$GWAY_PORT test_expect_success "ipfs daemon up" ' - pollEndpoint -host $GWAY_MADDR -ep=/version -v -tout=1s -tries=60 2>poll_apierr > poll_apiout || + pollEndpoint -host $GWAY_MADDR -v -tout=1s -tries=60 2>poll_apierr > poll_apiout || test_fsh cat poll_apierr || test_fsh cat poll_apiout ' @@ -41,7 +41,7 @@ test_expect_success "HTTP gateway gives access to sample file" ' test_expect_success "HTTP POST file gives Hash" ' echo "$RANDOM" >infile && - URL="http://localhost:$port/ipfs/" && + URL="http://127.0.0.1:$port/ipfs/" && curl -svX POST --data-binary @infile "$URL" 2>curl_post.out && grep "HTTP/1.1 201 Created" curl_post.out && LOCATION=$(grep Location curl_post.out) && @@ -49,22 +49,18 @@ test_expect_success "HTTP POST file gives Hash" ' ' test_expect_success "We can HTTP GET file just created" ' - URL="http://localhost:${port}${HASH}" && + URL="http://127.0.0.1:${port}${HASH}" && curl -so outfile "$URL" && test_cmp infile outfile ' -test_expect_success "HTTP PUT empty directory" ' - URL="http://localhost:$port/ipfs/$HASH_EMPTY_DIR/" && - echo "PUT $URL" && - curl -svX PUT "$URL" 2>curl_putEmpty.out && - cat curl_putEmpty.out && - grep "Ipfs-Hash: $HASH_EMPTY_DIR" curl_putEmpty.out && - grep "Location: /ipfs/$HASH_EMPTY_DIR" curl_putEmpty.out && - grep "HTTP/1.1 201 Created" curl_putEmpty.out +test_expect_success "We got the correct hash" ' + ADD_HASH="/ipfs/$(ipfs add -q infile)" && + test "x$ADD_HASH" = "x$HASH" || test_fsh echo "$ADD_HASH != $HASH" ' test_expect_success "HTTP GET empty directory" ' + URL="http://127.0.0.1:$port/ipfs/$HASH_EMPTY_DIR/" && echo "GET $URL" && curl -so outfile "$URL" 2>curl_getEmpty.out && grep "Index of /ipfs/$HASH_EMPTY_DIR/" outfile @@ -72,7 +68,7 @@ test_expect_success "HTTP GET empty directory" ' test_expect_success "HTTP PUT file to construct a hierarchy" ' echo "$RANDOM" >infile && - URL="http://localhost:$port/ipfs/$HASH_EMPTY_DIR/test.txt" && + URL="http://127.0.0.1:$port/ipfs/$HASH_EMPTY_DIR/test.txt" && echo "PUT $URL" && curl -svX PUT --data-binary @infile "$URL" 2>curl_put.out && grep "HTTP/1.1 201 Created" curl_put.out && @@ -81,7 +77,7 @@ test_expect_success "HTTP PUT file to construct a hierarchy" ' ' test_expect_success "We can HTTP GET file just created" ' - URL="http://localhost:$port/ipfs/$HASH/test.txt" && + URL="http://127.0.0.1:$port/ipfs/$HASH/test.txt" && echo "GET $URL" && curl -so outfile "$URL" && test_cmp infile outfile @@ -89,7 +85,7 @@ test_expect_success "We can HTTP GET file just created" ' test_expect_success "HTTP PUT file to append to existing hierarchy" ' echo "$RANDOM" >infile2 && - URL="http://localhost:$port/ipfs/$HASH/test/test.txt" && + URL="http://127.0.0.1:$port/ipfs/$HASH/test/test.txt" && echo "PUT $URL" && curl -svX PUT --data-binary @infile2 "$URL" 2>curl_putAgain.out && grep "HTTP/1.1 201 Created" curl_putAgain.out && @@ -99,12 +95,38 @@ test_expect_success "HTTP PUT file to append to existing hierarchy" ' test_expect_success "We can HTTP GET file just updated" ' - URL="http://localhost:$port/ipfs/$HASH/test/test.txt" && + URL="http://127.0.0.1:$port/ipfs/$HASH/test/test.txt" && echo "GET $URL" && curl -svo outfile2 "$URL" 2>curl_getAgain.out && test_cmp infile2 outfile2 ' +test_expect_success "HTTP PUT to replace a directory" ' + echo "$RANDOM" >infile3 && + URL="http://127.0.0.1:$port/ipfs/$HASH/test" && + echo "PUT $URL" && + curl -svX PUT --data-binary @infile3 "$URL" 2>curl_putOverDirectory.out && + grep "HTTP/1.1 201 Created" curl_putOverDirectory.out && + LOCATION=$(grep Location curl_putOverDirectory.out) && + HASH=$(expr "$LOCATION" : "< Location: /ipfs/\(.*\)/test") +' + +test_expect_success "We can HTTP GET file just put over a directory" ' + URL="http://127.0.0.1:$port/ipfs/$HASH/test" && + echo "GET $URL" && + curl -svo outfile3 "$URL" 2>curl_getOverDirectory.out && + test_cmp infile3 outfile3 +' + +test_expect_success "HTTP PUT to /ipns fails" ' + PEERID=`ipfs id --format=""` && + URL="http://127.0.0.1:$port/ipns/$PEERID/test.txt" && + echo "PUT $URL" && + curl -svX PUT --data-binary @infile1 "$URL" 2>curl_putIpns.out && + grep "HTTP/1.1 400 Bad Request" curl_putIpns.out +' + + test_kill_ipfs_daemon test_done diff --git a/test/sharness/t0113-gateway-symlink.sh b/test/sharness/t0113-gateway-symlink.sh new file mode 100755 index 00000000000..d1f94bde7e9 --- /dev/null +++ b/test/sharness/t0113-gateway-symlink.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# +# Copyright (c) Protocol Labs + +test_description="Test symlink support on the HTTP gateway" + +. lib/test-lib.sh + +test_init_ipfs +test_launch_ipfs_daemon + + +test_expect_success "Create a test directory with symlinks" ' + mkdir testfiles && + echo "content" > testfiles/foo && + ln -s foo testfiles/bar && + test_cmp testfiles/foo testfiles/bar +' + +test_expect_success "Add the test directory" ' + HASH=$(ipfs add -Qr testfiles) +' + +test_expect_success "Test the directory listing" ' + curl "$GWAY_ADDR/ipfs/$HASH" > list_response && + test_should_contain ">foo<" list_response && + test_should_contain ">bar<" list_response +' + +test_expect_success "Test the symlink" ' + curl "$GWAY_ADDR/ipfs/$HASH/bar" > bar_actual && + echo -n "foo" > bar_expected && + test_cmp bar_expected bar_actual +' + +test_kill_ipfs_daemon + +test_done diff --git a/test/sharness/t0114-gateway-subdomains.sh b/test/sharness/t0114-gateway-subdomains.sh new file mode 100755 index 00000000000..8b5133259af --- /dev/null +++ b/test/sharness/t0114-gateway-subdomains.sh @@ -0,0 +1,672 @@ +#!/usr/bin/env bash +# +# Copyright (c) Protocol Labs + +test_description="Test subdomain support on the HTTP gateway" + + +. lib/test-lib.sh + +## ============================================================================ +## Helpers specific to subdomain tests +## ============================================================================ + +# Helper that tests gateway response over direct HTTP +# and in all supported HTTP proxy modes +test_localhost_gateway_response_should_contain() { + local label="$1" + local expected="$3" + + # explicit "Host: $hostname" header to match browser behavior + # and also make tests independent from DNS + local host=$(echo $2 | cut -d'/' -f3 | cut -d':' -f1) + local hostname=$(echo $2 | cut -d'/' -f3 | cut -d':' -f1,2) + + # Proxy is the same as HTTP Gateway, we use raw IP and port to be sure + local proxy="http://127.0.0.1:$GWAY_PORT" + + # Create a raw URL version with IP to ensure hostname from Host header is used + # (removes false-positives, Host header is used for passing hostname already) + local url="$2" + local rawurl=$(echo "$url" | sed "s/$hostname/127.0.0.1:$GWAY_PORT/") + + #echo "hostname: $hostname" + #echo "url before: $url" + #echo "url after: $rawurl" + + # regular HTTP request + # (hostname in Host header, raw IP in URL) + test_expect_success "$label (direct HTTP)" " + curl -H \"Host: $hostname\" -sD - \"$rawurl\" > response && + test_should_contain \"$expected\" response + " + + # HTTP proxy + # (hostname is passed via URL) + # Note: proxy client should not care, but curl does DNS lookup + # for some reason anyway, so we pass static DNS mapping + test_expect_success "$label (HTTP proxy)" " + curl -x $proxy --resolve $hostname:127.0.0.1 -sD - \"$url\" > response && + test_should_contain \"$expected\" response + " + + # HTTP proxy 1.0 + # (repeating proxy test with older spec, just to be sure) + test_expect_success "$label (HTTP proxy 1.0)" " + curl --proxy1.0 $proxy --resolve $hostname:127.0.0.1 -sD - \"$url\" > response && + test_should_contain \"$expected\" response + " + + # HTTP proxy tunneling (CONNECT) + # https://tools.ietf.org/html/rfc7231#section-4.3.6 + # In HTTP/1.x, the pseudo-method CONNECT + # can be used to convert an HTTP connection into a tunnel to a remote host + test_expect_success "$label (HTTP proxy tunneling)" " + curl --proxytunnel -x $proxy -H \"Host: $hostname\" -sD - \"$rawurl\" > response && + test_should_contain \"$expected\" response + " +} + +# Helper that checks gateway response for specific hostname in Host header +test_hostname_gateway_response_should_contain() { + local label="$1" + local hostname="$2" + local url="$3" + local rawurl=$(echo "$url" | sed "s/$hostname/127.0.0.1:$GWAY_PORT/") + local expected="$4" + test_expect_success "$label" " + curl -H \"Host: $hostname\" -sD - \"$rawurl\" > response && + test_should_contain \"$expected\" response + " +} + +## ============================================================================ +## Start IPFS Node and prepare test CIDs +## ============================================================================ + +test_init_ipfs +test_launch_ipfs_daemon --offline + +# CIDv0to1 is necessary because raw-leaves are enabled by default during +# "ipfs add" with CIDv1 and disabled with CIDv0 +test_expect_success "Add test text file" ' + CID_VAL="hello" + CIDv1=$(echo $CID_VAL | ipfs add --cid-version 1 -Q) + CIDv0=$(echo $CID_VAL | ipfs add --cid-version 0 -Q) + CIDv0to1=$(echo "$CIDv0" | ipfs cid base32) +' + +test_expect_success "Add the test directory" ' + mkdir -p testdirlisting/subdir1/subdir2 && + echo "hello" > testdirlisting/hello && + echo "subdir2-bar" > testdirlisting/subdir1/subdir2/bar && + mkdir -p testdirlisting/api && + mkdir -p testdirlisting/ipfs && + echo "I am a txt file" > testdirlisting/api/file.txt && + echo "I am a txt file" > testdirlisting/ipfs/file.txt && + DIR_CID=$(ipfs add -Qr --cid-version 1 testdirlisting) +' + +test_expect_success "Publish test text file to IPNS" ' + PEERID=$(ipfs id --format="") + IPNS_IDv0=$(echo "$PEERID" | ipfs cid format -v 0) + IPNS_IDv1=$(echo "$PEERID" | ipfs cid format -v 1 --codec libp2p-key -b base32) + IPNS_IDv1_DAGPB=$(echo "$IPNS_IDv0" | ipfs cid format -v 1 -b base32) + test_check_peerid "${PEERID}" && + ipfs name publish --allow-offline -Q "/ipfs/$CIDv1" > name_publish_out && + ipfs name resolve "$PEERID" > output && + printf "/ipfs/%s\n" "$CIDv1" > expected2 && + test_cmp expected2 output +' + + +# ensure we start with empty Gateway.PublicGateways +test_expect_success 'start daemon with empty config for Gateway.PublicGateways' ' + test_kill_ipfs_daemon && + ipfs config --json Gateway.PublicGateways "{}" && + test_launch_ipfs_daemon --offline +' + +## ============================================================================ +## Test path-based requests to a local gateway with default config +## (forced redirects to http://*.localhost) +## ============================================================================ + +# /ipfs/ + +# IP remains old school path-based gateway + +test_localhost_gateway_response_should_contain \ + "request for 127.0.0.1/ipfs/{CID} stays on path" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1" \ + "$CID_VAL" + +# 'localhost' hostname is used for subdomains, and should not return +# payload directly, but redirect to URL with proper origin isolation + +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{CIDv1} returns HTTP 301 Moved Permanently" \ + "http://localhost:$GWAY_PORT/ipfs/$CIDv1" \ + "301 Moved Permanently" + +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{CIDv1} returns Location HTTP header for subdomain redirect in browsers" \ + "http://localhost:$GWAY_PORT/ipfs/$CIDv1" \ + "Location: http://$CIDv1.ipfs.localhost:$GWAY_PORT/" + +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{DIR_CID} returns HTTP 301 Moved Permanently" \ + "http://localhost:$GWAY_PORT/ipfs/$DIR_CID" \ + "301 Moved Permanently" + +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{DIR_CID} returns Location HTTP header for subdomain redirect in browsers" \ + "http://localhost:$GWAY_PORT/ipfs/$DIR_CID/" \ + "Location: http://$DIR_CID.ipfs.localhost:$GWAY_PORT/" + +# Responses to the root domain of subdomain gateway hostname should Clear-Site-Data +# https://github.com/ipfs/go-ipfs/issues/6975#issuecomment-597472477 +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{CIDv1} returns Clear-Site-Data header to purge Origin cookies and storage" \ + "http://localhost:$GWAY_PORT/ipfs/$CIDv1" \ + 'Clear-Site-Data: \"cookies\", \"storage\"' + +# We return body with HTTP 301 so existing cli scripts that use path-based +# gateway do not break (curl doesn't auto-redirect without passing -L; wget +# does not span across hostnames by default) +# Context: https://github.com/ipfs/go-ipfs/issues/6975 +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{CIDv1} includes valid payload in body for CLI tools like curl" \ + "http://localhost:$GWAY_PORT/ipfs/$CIDv1" \ + "$CID_VAL" + +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{CIDv0} redirects to CIDv1 representation in subdomain" \ + "http://localhost:$GWAY_PORT/ipfs/$CIDv0" \ + "Location: http://${CIDv0to1}.ipfs.localhost:$GWAY_PORT/" + +# /ipns/ + +test_localhost_gateway_response_should_contain \ + "request for localhost/ipns/{CIDv0} redirects to CIDv1 with libp2p-key multicodec in subdomain" \ + "http://localhost:$GWAY_PORT/ipns/$IPNS_IDv0" \ + "Location: http://${IPNS_IDv1}.ipns.localhost:$GWAY_PORT/" + +# /ipns/ + +test_localhost_gateway_response_should_contain \ + "request for localhost/ipns/{fqdn} redirects to DNSLink in subdomain" \ + "http://localhost:$GWAY_PORT/ipns/en.wikipedia-on-ipfs.org/wiki" \ + "Location: http://en.wikipedia-on-ipfs.org.ipns.localhost:$GWAY_PORT/wiki" + +# 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) +## ============================================================================ + +# {CID}.ipfs.localhost + +test_localhost_gateway_response_should_contain \ + "request for {CID}.ipfs.localhost should return expected payload" \ + "http://${CIDv1}.ipfs.localhost:$GWAY_PORT" \ + "$CID_VAL" + +# ensure /ipfs/ namespace is not mounted on subdomain +test_localhost_gateway_response_should_contain \ + "request for {CID}.ipfs.localhost/ipfs/{CID} should return HTTP 404" \ + "http://${CIDv1}.ipfs.localhost:$GWAY_PORT/ipfs/$CIDv1" \ + "404 Not Found" + +# ensure requests to /ipfs/* are not blocked, if content root has such subdirectory +test_localhost_gateway_response_should_contain \ + "request for {CID}.ipfs.localhost/ipfs/file.txt should return data from a file in CID content root" \ + "http://${DIR_CID}.ipfs.localhost:$GWAY_PORT/ipfs/file.txt" \ + "I am a txt file" + +# {CID}.ipfs.localhost/sub/dir (Directory Listing) +DIR_HOSTNAME="${DIR_CID}.ipfs.localhost:$GWAY_PORT" + +test_expect_success "valid file and subdirectory paths in directory listing at {cid}.ipfs.localhost" ' + curl -s --resolve $DIR_HOSTNAME:127.0.0.1 "http://$DIR_HOSTNAME" > list_response && + test_should_contain "hello" list_response && + test_should_contain "subdir1" list_response +' + +test_expect_success "valid parent directory path in directory listing at {cid}.ipfs.localhost/sub/dir" ' + curl -s --resolve $DIR_HOSTNAME:127.0.0.1 "http://$DIR_HOSTNAME/subdir1/subdir2/" > list_response && + test_should_contain ".." list_response && + test_should_contain "bar" list_response +' + +test_expect_success "request for deep path resource at {cid}.ipfs.localhost/sub/dir/file" ' + curl -s --resolve $DIR_HOSTNAME:127.0.0.1 "http://$DIR_HOSTNAME/subdir1/subdir2/bar" > list_response && + test_should_contain "subdir2-bar" list_response +' + +# *.ipns.localhost + +# .ipns.localhost + +test_localhost_gateway_response_should_contain \ + "request for {CIDv1-libp2p-key}.ipns.localhost returns expected payload" \ + "http://${IPNS_IDv1}.ipns.localhost:$GWAY_PORT" \ + "$CID_VAL" + +test_localhost_gateway_response_should_contain \ + "request for {CIDv1-dag-pb}.ipns.localhost redirects to CID with libp2p-key multicodec" \ + "http://${IPNS_IDv1_DAGPB}.ipns.localhost:$GWAY_PORT" \ + "Location: http://${IPNS_IDv1}.ipns.localhost:$GWAY_PORT/" + +# .ipns.localhost + +# DNSLink test requires a daemon in online mode with precached /ipns/ mapping +test_kill_ipfs_daemon +DNSLINK_FQDN="dnslink-test.example.com" +export IPFS_NS_MAP="$DNSLINK_FQDN:/ipfs/$CIDv1" +test_launch_ipfs_daemon + +test_localhost_gateway_response_should_contain \ + "request for {dnslink}.ipns.localhost returns expected payload" \ + "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 subdomain-based requests with a custom hostname config +## (origin per content root at http://*.example.com) +## ============================================================================ + +# set explicit subdomain gateway config for the hostname +ipfs config --json Gateway.PublicGateways '{ + "example.com": { + "UseSubdomains": true, + "Paths": ["/ipfs", "/ipns", "/api"] + } +}' || exit 1 +# restart daemon to apply config changes +test_kill_ipfs_daemon +test_launch_ipfs_daemon --offline + + +# example.com/ip(f|n)s/* +# ============================================================================= + +# path requests to the root hostname should redirect +# to a subdomain URL with proper origin isolation + +test_hostname_gateway_response_should_contain \ + "request for example.com/ipfs/{CIDv1} produces redirect to {CIDv1}.ipfs.example.com" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1" \ + "Location: http://$CIDv1.ipfs.example.com/" + +# error message should include original CID +# (and it should be case-sensitive, as we can't assume everyone uses base32) +test_hostname_gateway_response_should_contain \ + "request for example.com/ipfs/{InvalidCID} produces useful error before redirect" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/QmInvalidCID" \ + 'invalid path \"/ipfs/QmInvalidCID\"' + +test_hostname_gateway_response_should_contain \ + "request for example.com/ipfs/{CIDv0} produces redirect to {CIDv1}.ipfs.example.com" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv0" \ + "Location: http://${CIDv0to1}.ipfs.example.com/" + +# Support X-Forwarded-Proto +test_expect_success "request for http://example.com/ipfs/{CID} with X-Forwarded-Proto: https produces redirect to HTTPS URL" " + curl -H \"X-Forwarded-Proto: https\" -H \"Host: example.com\" -sD - \"http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1\" > response && + test_should_contain \"Location: https://$CIDv1.ipfs.example.com/\" response +" + + + +# example.com/ipns/ + +test_hostname_gateway_response_should_contain \ + "request for example.com/ipns/{CIDv0} redirects to CIDv1 with libp2p-key multicodec in subdomain" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipns/$IPNS_IDv0" \ + "Location: http://${IPNS_IDv1}.ipns.example.com/" + +# example.com/ipns/ + +test_hostname_gateway_response_should_contain \ + "request for example.com/ipns/{fqdn} redirects to DNSLink in subdomain" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipns/en.wikipedia-on-ipfs.org/wiki" \ + "Location: http://en.wikipedia-on-ipfs.org.ipns.example.com/wiki" + +# *.ipfs.example.com: subdomain requests made with custom FQDN in Host header + +test_hostname_gateway_response_should_contain \ + "request for {CID}.ipfs.example.com should return expected payload" \ + "${CIDv1}.ipfs.example.com" \ + "http://127.0.0.1:$GWAY_PORT/" \ + "$CID_VAL" + +test_hostname_gateway_response_should_contain \ + "request for {CID}.ipfs.example.com/ipfs/{CID} should return HTTP 404" \ + "${CIDv1}.ipfs.example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1" \ + "404 Not Found" + +# {CID}.ipfs.example.com/sub/dir (Directory Listing) +DIR_FQDN="${DIR_CID}.ipfs.example.com" + +test_expect_success "valid file and directory paths in directory listing at {cid}.ipfs.example.com" ' + curl -s -H "Host: $DIR_FQDN" http://127.0.0.1:$GWAY_PORT > list_response && + test_should_contain "hello" list_response && + test_should_contain "subdir1" list_response +' + +test_expect_success "valid parent directory path in directory listing at {cid}.ipfs.example.com/sub/dir" ' + curl -s -H "Host: $DIR_FQDN" http://127.0.0.1:$GWAY_PORT/subdir1/subdir2/ > list_response && + test_should_contain ".." list_response && + test_should_contain "bar" list_response +' + +test_expect_success "request for deep path resource {cid}.ipfs.example.com/sub/dir/file" ' + curl -s -H "Host: $DIR_FQDN" http://127.0.0.1:$GWAY_PORT/subdir1/subdir2/bar > list_response && + test_should_contain "subdir2-bar" list_response +' + +# *.ipns.example.com +# ============================================================================ + +# .ipns.example.com + +test_hostname_gateway_response_should_contain \ + "request for {CIDv1-libp2p-key}.ipns.example.com returns expected payload" \ + "${IPNS_IDv1}.ipns.example.com" \ + "http://127.0.0.1:$GWAY_PORT" \ + "$CID_VAL" + +test_hostname_gateway_response_should_contain \ + "request for {CIDv1-dag-pb}.ipns.localhost redirects to CID with libp2p-key multicodec" \ + "${IPNS_IDv1_DAGPB}.ipns.example.com" \ + "http://127.0.0.1:$GWAY_PORT" \ + "Location: http://${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 --offline + +# 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) +# ============================================================================ + +# DNSLink test requires a daemon in online mode with precached /ipns/ mapping +test_kill_ipfs_daemon +DNSLINK_FQDN="dnslink-subdomain-gw-test.example.org" +export IPFS_NS_MAP="$DNSLINK_FQDN:/ipfs/$CIDv1" +test_launch_ipfs_daemon + +test_hostname_gateway_response_should_contain \ + "request for {dnslink}.ipns.example.com returns expected payload" \ + "$DNSLINK_FQDN.ipns.example.com" \ + "http://127.0.0.1:$GWAY_PORT" \ + "$CID_VAL" + +# Disable selected Paths for the subdomain gateway hostname +# ============================================================================= + +# disable /ipns for the hostname by not whitelisting it +ipfs config --json Gateway.PublicGateways '{ + "example.com": { + "UseSubdomains": true, + "Paths": ["/ipfs"] + } +}' || exit 1 +# restart daemon to apply config changes +test_kill_ipfs_daemon +test_launch_ipfs_daemon --offline + +# refuse requests to Paths that were not explicitly whitelisted for the hostname +test_hostname_gateway_response_should_contain \ + "request for *.ipns.example.com returns HTTP 404 Not Found when /ipns is not on Paths whitelist" \ + "${IPNS_IDv1}.ipns.example.com" \ + "http://127.0.0.1:$GWAY_PORT" \ + "404 Not Found" + + +## ============================================================================ +## Test path-based requests with a custom hostname config +## ============================================================================ + +# set explicit subdomain gateway config for the hostname +ipfs config --json Gateway.PublicGateways '{ + "example.com": { + "UseSubdomains": false, + "Paths": ["/ipfs"] + } +}' || exit 1 + +# restart daemon to apply config changes +test_kill_ipfs_daemon +test_launch_ipfs_daemon --offline + +# example.com/ip(f|n)s/* smoke-tests +# ============================================================================= + +# confirm path gateway works for /ipfs +test_hostname_gateway_response_should_contain \ + "request for example.com/ipfs/{CIDv1} returns expected payload" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1" \ + "$CID_VAL" + +# refuse subdomain requests on path gateway +# (we don't want false sense of security) +test_hostname_gateway_response_should_contain \ + "request for {CID}.ipfs.example.com/ipfs/{CID} should return HTTP 404 Not Found" \ + "${CIDv1}.ipfs.example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1" \ + "404 Not Found" + +# refuse requests to Paths that were not explicitly whitelisted for the hostname +test_hostname_gateway_response_should_contain \ + "request for example.com/ipns/ returns HTTP 404 Not Found when /ipns is not on Paths whitelist" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipns/$IPNS_IDv1" \ + "404 Not Found" + +## ============================================================================ +## Test DNSLink requests with a custom PublicGateway (hostname config) +## (DNSLink site at http://dnslink-test.example.com) +## ============================================================================ + +test_kill_ipfs_daemon + +# disable wildcard DNSLink gateway +# and enable it on specific NSLink hostname +ipfs config --json Gateway.NoDNSLink true && \ +ipfs config --json Gateway.PublicGateways '{ + "dnslink-enabled-on-fqdn.example.org": { + "NoDNSLink": false, + "UseSubdomains": false, + "Paths": ["/ipfs"] + }, + "only-dnslink-enabled-on-fqdn.example.org": { + "NoDNSLink": false, + "UseSubdomains": false, + "Paths": [] + }, + "dnslink-disabled-on-fqdn.example.com": { + "NoDNSLink": true, + "UseSubdomains": false, + "Paths": [] + } +}' || exit 1 + +# DNSLink test requires a daemon in online mode with precached /ipns/ mapping +DNSLINK_FQDN="dnslink-enabled-on-fqdn.example.org" +ONLY_DNSLINK_FQDN="only-dnslink-enabled-on-fqdn.example.org" +NO_DNSLINK_FQDN="dnslink-disabled-on-fqdn.example.com" +export IPFS_NS_MAP="$DNSLINK_FQDN:/ipfs/$CIDv1,$ONLY_DNSLINK_FQDN:/ipfs/$DIR_CID" + +# restart daemon to apply config changes +test_launch_ipfs_daemon + +# make sure test setup is valid (fail if CoreAPI is unable to resolve) +test_expect_success "spoofed DNSLink record resolves in cli" " + ipfs resolve /ipns/$DNSLINK_FQDN > result && + test_should_contain \"$CIDv1\" result && + ipfs cat /ipns/$DNSLINK_FQDN > result && + test_should_contain \"$CID_VAL\" result +" + +# DNSLink enabled + +test_hostname_gateway_response_should_contain \ + "request for http://{dnslink-fqdn}/ PublicGateway returns expected payload" \ + "$DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/" \ + "$CID_VAL" + +test_hostname_gateway_response_should_contain \ + "request for {dnslink-fqdn}/ipfs/{cid} returns expected payload when /ipfs is on Paths whitelist" \ + "$DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1" \ + "$CID_VAL" + +# Test for a fun edge case: DNSLink-only gateway without /ipfs/ namespace +# mounted, and with subdirectory named "ipfs" ¯\_(ツ)_/¯ +test_hostname_gateway_response_should_contain \ + "request for {dnslink-fqdn}/ipfs/file.txt returns data from content root when /ipfs in not on Paths whitelist" \ + "$ONLY_DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/file.txt" \ + "I am a txt file" + +test_hostname_gateway_response_should_contain \ + "request for {dnslink-fqdn}/ipns/{peerid} returns 404 when path is not whitelisted" \ + "$DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/ipns/$IPNS_IDv0" \ + "404 Not Found" + +# DNSLink disabled + +test_hostname_gateway_response_should_contain \ + "request for http://{dnslink-fqdn}/ returns 404 when NoDNSLink=true" \ + "$NO_DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/" \ + "404 Not Found" + +test_hostname_gateway_response_should_contain \ + "request for {dnslink-fqdn}/ipfs/{cid} returns 404 when path is not whitelisted" \ + "$NO_DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv0" \ + "404 Not Found" + + +## ============================================================================ +## Test wildcard DNSLink (any hostname, with default config) +## ============================================================================ + +test_kill_ipfs_daemon + +# enable wildcard DNSLink gateway (any value in Host header) +# and remove custom PublicGateways +ipfs config --json Gateway.NoDNSLink false && \ +ipfs config --json Gateway.PublicGateways '{}' || exit 1 + +# DNSLink test requires a daemon in online mode with precached /ipns/ mapping +DNSLINK_FQDN="wildcard-dnslink-not-in-config.example.com" +export IPFS_NS_MAP="$DNSLINK_FQDN:/ipfs/$CIDv1" + +# restart daemon to apply config changes +test_launch_ipfs_daemon + +# make sure test setup is valid (fail if CoreAPI is unable to resolve) +test_expect_success "spoofed DNSLink record resolves in cli" " + ipfs resolve /ipns/$DNSLINK_FQDN > result && + test_should_contain \"$CIDv1\" result && + ipfs cat /ipns/$DNSLINK_FQDN > result && + test_should_contain \"$CID_VAL\" result +" + +# gateway test +test_hostname_gateway_response_should_contain \ + "request for http://{dnslink-fqdn}/ (wildcard) returns expected payload" \ + "$DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/" \ + "$CID_VAL" + +# ============================================================================= +# ensure we end with empty Gateway.PublicGateways +ipfs config --json Gateway.PublicGateways '{}' +test_kill_ipfs_daemon + +test_done diff --git a/test/sharness/t0120-bootstrap.sh b/test/sharness/t0120-bootstrap.sh index 2314a02a2ab..538c5bde0ef 100755 --- a/test/sharness/t0120-bootstrap.sh +++ b/test/sharness/t0120-bootstrap.sh @@ -5,19 +5,11 @@ # # changing the bootstrap peers will require changing it in two places :) -BP1="/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN" -BP2="/dnsaddr/bootstrap.libp2p.io/ipfs/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa" -BP3="/dnsaddr/bootstrap.libp2p.io/ipfs/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb" -BP4="/dnsaddr/bootstrap.libp2p.io/ipfs/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt" -BP5="/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ" -BP6="/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM" -BP7="/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64" -BP8="/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu" -BP9="/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd" -BP10="/ip6/2400:6180:0:d0::151:6001/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu" -BP11="/ip6/2604:a880:1:20::203:d001/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM" -BP12="/ip6/2604:a880:800:10::4a:5001/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64" -BP13="/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd" +BP1="/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN" +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" test_description="Test ipfs repo operations" @@ -99,18 +91,10 @@ test_bootstrap_cmd() { echo "added $BP3" >>add2_expected && echo "added $BP4" >>add2_expected && echo "added $BP5" >>add2_expected && - echo "added $BP6" >>add2_expected && - echo "added $BP7" >>add2_expected && - echo "added $BP8" >>add2_expected && - echo "added $BP9" >>add2_expected && - echo "added $BP10" >>add2_expected && - echo "added $BP11" >>add2_expected && - echo "added $BP12" >>add2_expected && - echo "added $BP13" >>add2_expected && test_cmp add2_expected add2_actual ' - test_bootstrap_list_cmd $BP1 $BP2 $BP3 $BP4 $BP5 $BP6 $BP7 $BP8 $BP9 $BP10 $BP11 $BP12 $BP13 $BP14 $BP15 $BP16 $BP17 + test_bootstrap_list_cmd $BP1 $BP2 $BP3 $BP4 $BP5 test_expect_success "'ipfs bootstrap rm --all' succeeds" ' ipfs bootstrap rm --all >rm2_actual @@ -122,14 +106,6 @@ test_bootstrap_cmd() { echo "removed $BP3" >>rm2_expected && echo "removed $BP4" >>rm2_expected && echo "removed $BP5" >>rm2_expected && - echo "removed $BP6" >>rm2_expected && - echo "removed $BP7" >>rm2_expected && - echo "removed $BP8" >>rm2_expected && - echo "removed $BP9" >>rm2_expected && - echo "removed $BP10" >>rm2_expected && - echo "removed $BP11" >>rm2_expected && - echo "removed $BP12" >>rm2_expected && - echo "removed $BP13" >>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 e7c7d0105b6..16dcbdb2f09 100755 --- a/test/sharness/t0121-bootstrap-iptb.sh +++ b/test/sharness/t0121-bootstrap-iptb.sh @@ -38,11 +38,11 @@ betterwait() { } test_expect_success "bring down iptb nodes" ' - PID0=$(cat "$IPTB_ROOT/benches/default/0/daemon.pid") && - PID1=$(cat "$IPTB_ROOT/benches/default/1/daemon.pid") && - PID2=$(cat "$IPTB_ROOT/benches/default/2/daemon.pid") && - PID3=$(cat "$IPTB_ROOT/benches/default/3/daemon.pid") && - PID4=$(cat "$IPTB_ROOT/benches/default/4/daemon.pid") && + PID0=$(cat "$IPTB_ROOT/testbeds/default/0/daemon.pid") && + PID1=$(cat "$IPTB_ROOT/testbeds/default/1/daemon.pid") && + PID2=$(cat "$IPTB_ROOT/testbeds/default/2/daemon.pid") && + PID3=$(cat "$IPTB_ROOT/testbeds/default/3/daemon.pid") && + PID4=$(cat "$IPTB_ROOT/testbeds/default/4/daemon.pid") && iptb stop && # TODO: add --wait flag to iptb stop betterwait $PID0 betterwait $PID1 @@ -58,7 +58,7 @@ test_expect_success "reset iptb nodes" ' test_expect_success "set bootstrap addrs" ' bsn_peer_id=$(ipfs id -f "") && - BADDR="/ip4/127.0.0.1/tcp/$SWARM_PORT/ipfs/$bsn_peer_id" && + BADDR="/ip4/127.0.0.1/tcp/$SWARM_PORT/p2p/$bsn_peer_id" && ipfsi 0 bootstrap add $BADDR && ipfsi 1 bootstrap add $BADDR && ipfsi 2 bootstrap add $BADDR && diff --git a/test/sharness/t0130-multinode.sh b/test/sharness/t0130-multinode.sh index 1c732db7a7b..e0a27b66600 100755 --- a/test/sharness/t0130-multinode.sh +++ b/test/sharness/t0130-multinode.sh @@ -80,7 +80,7 @@ run_advanced_test() { test_expect_success "shut down nodes" ' iptb stop && iptb_wait_stop || - test_fsh tail -n +1 .iptb/benches/default/*/daemon.std* + test_fsh tail -n +1 .iptb/testbeds/default/*/daemon.std* ' } diff --git a/test/sharness/t0131-multinode-client-routing.sh b/test/sharness/t0131-multinode-client-routing.sh index e96f230cd66..b62c9790b9c 100755 --- a/test/sharness/t0131-multinode-client-routing.sh +++ b/test/sharness/t0131-multinode-client-routing.sh @@ -60,7 +60,7 @@ test_expect_success "add a file on a node in client mode" ' FILE_HASH=$(ipfsi 8 add -q filea) ' -test_expect_success "retrieve that file on a client mode node" ' +test_expect_success "retrieve that file on a node in client mode" ' check_file_fetch 9 $FILE_HASH filea ' diff --git a/test/sharness/t0140-swarm.sh b/test/sharness/t0140-swarm.sh index a5c1dadda7d..77e2af1b00f 100755 --- a/test/sharness/t0140-swarm.sh +++ b/test/sharness/t0140-swarm.sh @@ -38,9 +38,9 @@ test_expect_success "output looks good" ' grep PublicKey output ' -addr="/ip4/127.0.0.1/tcp/9898/ipfs/QmUWKoHbjsqsSMesRC2Zoscs8edyFz6F77auBB1YBBhgpX" +addr="/ip4/127.0.0.1/tcp/9898/p2p/QmUWKoHbjsqsSMesRC2Zoscs8edyFz6F77auBB1YBBhgpX" -test_expect_success "cant trigger a dial backoff with swarm connect" ' +test_expect_success "can't trigger a dial backoff with swarm connect" ' test_expect_code 1 ipfs swarm connect $addr 2> connect_out test_expect_code 1 ipfs swarm connect $addr 2>> connect_out test_expect_code 1 ipfs swarm connect $addr 2>> connect_out @@ -105,13 +105,13 @@ startup_cluster 2 test_expect_success "disconnect work without specifying a transport address" ' [ $(ipfsi 0 swarm peers | wc -l) -eq 1 ] && - ipfsi 0 swarm disconnect "/ipfs/$(iptb attr get 1 id)" && + ipfsi 0 swarm disconnect "/p2p/$(iptb attr get 1 id)" && [ $(ipfsi 0 swarm peers | wc -l) -eq 0 ] ' test_expect_success "connect work without specifying a transport address" ' [ $(ipfsi 0 swarm peers | wc -l) -eq 0 ] && - ipfsi 0 swarm connect "/ipfs/$(iptb attr get 1 id)" && + ipfsi 0 swarm connect "/p2p/$(iptb attr get 1 id)" && [ $(ipfsi 0 swarm peers | wc -l) -eq 1 ] ' diff --git a/test/sharness/t0142-testfilter.sh b/test/sharness/t0142-testfilter.sh new file mode 100755 index 00000000000..0b46e2c9556 --- /dev/null +++ b/test/sharness/t0142-testfilter.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2020 Protocol Labs +# MIT/Apache-2.0 Licensed; see the LICENSE file in this repository. +# + +test_description="Test swarm filters are effective" + +AF="/ip4/127.0.0.0/ipcidr/24" + +. lib/test-lib.sh + +NUM_NODES=3 + +test_expect_success "set up testbed" ' + iptb testbed create -type localipfs -count $NUM_NODES -force -init +' + +test_expect_success 'filter 127.0.0.0/24 on node 1' ' + ipfsi 1 config --json Swarm.AddrFilters "[\"$AF\"]" +' + +for i in $(seq 0 $(( NUM_NODES - 1 ))); do + test_expect_success 'enable quic for node $i' ' + echo "$i" + ipfsi $i config --json Experimental.QUIC true + ' + + test_expect_success "change IP for node $i" ' + ipfsi $i config --json "Addresses.Swarm" \ + "[\"/ip4/127.0.$i.1/tcp/0\",\"/ip4/127.0.$i.1/udp/0/quic\",\"/ip4/127.0.$i.1/tcp/0/ws\"]" + ' +done + +test_expect_success 'start cluster' ' + iptb start --wait +' + +test_expect_success 'connecting 1 to 0 fails' ' + test_must_fail iptb connect 1 0 +' + +test_expect_success 'connecting 0 to 1 fails' ' + test_must_fail iptb connect 1 0 +' + +test_expect_success 'connecting 2 to 0 succeeds' ' + iptb connect 2 0 +' + +test_expect_success 'connecting 1 to 0 with dns addrs fails' ' + ipfsi 0 id -f "" | sed "s|^/ip4/127.0.0.1/|/dns4/localhost/|" > addrs && + test_must_fail ipfsi 1 swarm connect $(cat addrs) +' + + +test_expect_success 'stopping cluster' ' + iptb stop +' + +test_done diff --git a/test/sharness/t0160-resolve.sh b/test/sharness/t0160-resolve.sh index 87740685644..1524ed8d28e 100755 --- a/test/sharness/t0160-resolve.sh +++ b/test/sharness/t0160-resolve.sh @@ -116,6 +116,15 @@ test_resolve_cmd_b32() { test_resolve_setup_name "self" "/ipfs/$c_hash_b32" test_resolve "/ipns/$self_hash" "/ipfs/$c_hash_b32" --cid-base=base32 + + # peer ID represented as CIDv1 require libp2p-key multicodec + # https://github.com/libp2p/specs/blob/master/RFC/0001-text-peerid-cid.md + local self_hash_b32protobuf=$(echo $self_hash | ipfs cid format -v 1 -b b --codec protobuf) + local self_hash_b32libp2pkey=$(echo $self_hash | ipfs cid format -v 1 -b b --codec libp2p-key) + test_expect_success "resolve of /ipns/{cidv1} with multicodec other than libp2p-key returns a meaningful error" ' + test_expect_code 1 ipfs resolve /ipns/$self_hash_b32protobuf 2>cidcodec_error && + grep "Error: peer ID represented as CIDv1 require libp2p-key multicodec: retry with /ipns/$self_hash_b32libp2pkey" cidcodec_error + ' } @@ -144,17 +153,24 @@ test_resolve_cmd_fail() { test_resolve "/ipld/$dag_hash/i/j" "/ipld/$dag_hash/i/j" test_resolve "/ipld/$dag_hash/i" "/ipld/$dag_hash/i" + # At the moment, publishing _fails_ because we fail to put to the DHT. + # However, resolving succeeds because we resolve the record we put to our own + # node. + # + # We should find a nice way to truly support offline publishing. But this + # behavior isn't terrible. + test_resolve_setup_name_fail "self" "/ipfs/$a_hash" - test_resolve_fail "/ipns/$self_hash" "/ipfs/$a_hash" - test_resolve_fail "/ipns/$self_hash/b" "/ipfs/$b_hash" - test_resolve_fail "/ipns/$self_hash/b/c" "/ipfs/$c_hash" + test_resolve "/ipns/$self_hash" "/ipfs/$a_hash" + test_resolve "/ipns/$self_hash/b" "/ipfs/$b_hash" + test_resolve "/ipns/$self_hash/b/c" "/ipfs/$c_hash" test_resolve_setup_name_fail "self" "/ipfs/$b_hash" - test_resolve_fail "/ipns/$self_hash" "/ipfs/$b_hash" - test_resolve_fail "/ipns/$self_hash/c" "/ipfs/$c_hash" + test_resolve "/ipns/$self_hash" "/ipfs/$b_hash" + test_resolve "/ipns/$self_hash/c" "/ipfs/$c_hash" test_resolve_setup_name_fail "self" "/ipfs/$c_hash" - test_resolve_fail "/ipns/$self_hash" "/ipfs/$c_hash" + test_resolve "/ipns/$self_hash" "/ipfs/$c_hash" } # should work offline diff --git a/test/sharness/t0170-dht.sh b/test/sharness/t0170-dht.sh index d2956fea191..e76b8586089 100755 --- a/test/sharness/t0170-dht.sh +++ b/test/sharness/t0170-dht.sh @@ -4,9 +4,6 @@ test_description="Test dht command" . lib/test-lib.sh -TEST_DHT_VALUE="foobar" -TEST_DHT_PATH="/pk/QmbWTwYGcmdyK9CYfNBcfs9nhZs17a6FQ4Y8oea278xx41" - test_dht() { NUM_NODES=5 @@ -29,38 +26,35 @@ test_dht() { test_cmp actual expected ' - # ipfs dht put - test_expect_success 'put with good keys' ' - ipfsi 0 dht put "$TEST_DHT_PATH" "$TEST_DHT_VALUE" | sort >putted && - [ -s putted ] || - test_fsh cat putted - ' - - test_expect_success 'put round trips' ' - echo -n "$TEST_DHT_VALUE" >expected && - ipfsi 0 dht get "$TEST_DHT_PATH" >actual && - test_cmp actual expected - ' - # ipfs dht get - test_expect_success 'get with good keys' ' + test_expect_success 'get with good keys works' ' HASH="$(echo "hello world" | ipfsi 2 add -q)" && ipfsi 2 name publish "/ipfs/$HASH" && - ipfsi 1 dht get "/ipns/$PEERID_2" | grep -aq "/ipfs/$HASH" + ipfsi 1 dht get "/ipns/$PEERID_2" >get_result + ' + + test_expect_success 'get with good keys contains the right value' ' + cat get_result | grep -aq "/ipfs/$HASH" + ' + + test_expect_success 'put round trips (#3124)' ' + ipfsi 0 dht put "/ipns/$PEERID_2" get_result | sort >putted && + [ -s putted ] || + test_fsh cat putted ' test_expect_success 'put with bad keys fails (issue #5113)' ' - ipfsi 0 dht put "foo" "bar" >putted - ipfsi 0 dht put "/pk/foo" "bar" >>putted - ipfsi 0 dht put "/ipns/foo" "bar" >>putted + ipfsi 0 dht put "foo" <<putted + ipfsi 0 dht put "/pk/foo" <<>putted + ipfsi 0 dht put "/ipns/foo" <<>putted [ ! -s putted ] || test_fsh cat putted ' test_expect_success 'put with bad keys returns error (issue #4611)' ' - test_must_fail ipfsi 0 dht put "foo" "bar" && - test_must_fail ipfsi 0 dht put "/pk/foo" "bar" && - test_must_fail ipfsi 0 dht put "/ipns/foo" "bar" + test_must_fail ipfsi 0 dht put "foo" << - ## We query 3 different keys, to statisically lower the chance that the queryer - ## turns out to be the closest to what a key hashes to. - # TODO: flaky. tracked by https://github.com/ipfs/go-ipfs/issues/2620 - test_expect_success 'query' ' - ipfsi 3 dht query "$(echo banana | ipfsi 3 add -q)" >actual && - ipfsi 3 dht query "$(echo apple | ipfsi 3 add -q)" >>actual && - ipfsi 3 dht query "$(echo pear | ipfsi 3 add -q)" >>actual && - PEERS=$(wc -l actual | cut -d '"'"' '"'"' -f 1) && - [ -s actual ] || - test_might_fail test_fsh cat actual + # + # We test all nodes. 4 nodes should see the same peer ID, one node (the + # closest) should see a different one. + + for i in $(test_seq 0 4); do + test_expect_success "query from $i" ' + ipfsi "$i" dht query "$HASH" | head -1 >closest-$i + ' + done + + test_expect_success "collecting results" ' + cat closest-* | sort | uniq -c | sed -e "s/ *\([0-9]\+\) .*/\1/g" | sort -g > actual && + echo 1 > expected && + echo 4 >> expected + ' + + test_expect_success "checking results" ' + test_cmp actual expected ' test_expect_success 'stop iptb' ' @@ -101,7 +103,7 @@ test_dht() { test_expect_success "dht commands fail when offline" ' test_must_fail ipfsi 0 dht findprovs "$HASH" 2>err_findprovs && test_must_fail ipfsi 0 dht findpeer "$HASH" 2>err_findpeer && - test_must_fail ipfsi 0 dht put "$TEST_DHT_PATH" "$TEST_DHT_VALUE" 2>err_put && + test_must_fail ipfsi 0 dht put "/ipns/$PEERID_2" "get_result" 2>err_put && test_should_contain "this command must be run in online mode" err_findprovs && test_should_contain "this command must be run in online mode" err_findpeer && test_should_contain "this command must be run in online mode" err_put diff --git a/test/sharness/t0175-provider.sh b/test/sharness/t0175-provider.sh new file mode 100755 index 00000000000..364df60e91e --- /dev/null +++ b/test/sharness/t0175-provider.sh @@ -0,0 +1,34 @@ +#!/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=$(echo "foo" | 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 index 2df63fdfc0a..c9401558551 100755 --- a/test/sharness/t0175-reprovider.sh +++ b/test/sharness/t0175-reprovider.sh @@ -16,34 +16,13 @@ init_strategy() { PEERID_1=$(iptb attr get 1 id) ' - test_expect_success 'use pinning startegy for reprovider' ' + test_expect_success 'use pinning strategy for reprovider' ' ipfsi 0 config Reprovider.Strategy '$1' ' startup_cluster ${NUM_NODES} } -findprovs_empty() { - test_expect_success 'findprovs '$1' succeeds' ' - ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut - ' - - test_expect_success "findprovs $1 output is empty" ' - test_must_be_empty findprovsOut - ' -} - -findprovs_expect() { - test_expect_success 'findprovs '$1' succeeds' ' - ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut && - echo '$2' > expected - ' - - test_expect_success "findprovs $1 output looks good" ' - test_cmp findprovsOut expected - ' -} - reprovide() { test_expect_success 'reprovide' ' # TODO: this hangs, though only after reprovision was done diff --git a/test/sharness/t0175-strategic-provider.sh b/test/sharness/t0175-strategic-provider.sh new file mode 100755 index 00000000000..7bad38838b6 --- /dev/null +++ b/test/sharness/t0175-strategic-provider.sh @@ -0,0 +1,34 @@ +#!/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=$(echo "foo" | ipfsi 0 add -q) +' + +findprovs_empty '$HASH_0' + +test_expect_success 'stop node 1' ' + iptb stop +' + +test_done diff --git a/test/sharness/t0180-p2p.sh b/test/sharness/t0180-p2p.sh index eaeed65b66f..236f2ac9f33 100755 --- a/test/sharness/t0180-p2p.sh +++ b/test/sharness/t0180-p2p.sh @@ -22,10 +22,10 @@ test_expect_success 'peer ids' ' ' check_test_ports() { test_expect_success "test ports are closed" ' - (! (netstat -lnp | grep "LISTEN" | grep ":10101 ")) && - (! (netstat -lnp | grep "LISTEN" | grep ":10102 "))&& - (! (netstat -lnp | grep "LISTEN" | grep ":10103 ")) && - (! (netstat -lnp | grep "LISTEN" | grep ":10104 ")) + (! (netstat -aln | grep "LISTEN" | grep -E "[.:]10101 ")) && + (! (netstat -aln | grep "LISTEN" | grep -E "[.:]10102 ")) && + (! (netstat -aln | grep "LISTEN" | grep -E "[.:]10103 ")) && + (! (netstat -aln | grep "LISTEN" | grep -E "[.:]10104 ")) ' } check_test_ports @@ -75,16 +75,16 @@ test_server_to_client() { spawn_sending_server -test_expect_success 'S->C(/ipfs/peerID) Setup client side' ' - ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10102 /ipfs/${PEERID_0} 2>&1 > dialer-stdouterr.log +test_expect_success 'S->C(/p2p/peerID) Setup client side' ' + ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10102 /p2p/${PEERID_0} 2>&1 > dialer-stdouterr.log ' -test_expect_success 'S->C Setup(dnsaddr/addr/ipfs/peerID) client side' ' - ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10103 /dnsaddr/bootstrap.libp2p.io/ipfs/${PEERID_0} 2>&1 > dialer-stdouterr.log +test_expect_success 'S->C Setup(dnsaddr/addr/p2p/peerID) client side' ' + ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10103 /dnsaddr/bootstrap.libp2p.io/p2p/${PEERID_0} 2>&1 > dialer-stdouterr.log ' test_expect_success 'S->C Setup(dnsaddr/addr) client side' ' - ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10104 /dnsaddr/bootstrap.libp2p.io/ 2>&1 > dialer-stdouterr.log + ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10104 /dnsaddr/cluster.ipfs.io 2>&1 > dialer-stdouterr.log ' @@ -126,7 +126,7 @@ test_expect_success 'C->S Spawn receiving server' ' ' test_expect_success 'C->S Setup client side' ' - ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10102 /ipfs/${PEERID_0} 2>&1 > dialer-stdouterr.log + ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10102 /p2p/${PEERID_0} 2>&1 > dialer-stdouterr.log ' test_expect_success 'C->S Connect and receive data' ' @@ -155,7 +155,7 @@ test_expect_success "cannot accept 0 port in 'ipfs p2p listen'" ' ' test_expect_success "'ipfs p2p forward' accept 0 port" ' - ipfsi 2 p2p forward /x/p2p-test/0 /ip4/127.0.0.1/tcp/0 /ipfs/$PEERID_0 + ipfsi 2 p2p forward /x/p2p-test/0 /ip4/127.0.0.1/tcp/0 /p2p/$PEERID_0 ' test_expect_success "'ipfs p2p ls' output looks good" ' @@ -168,7 +168,7 @@ test_expect_success "'ipfs p2p ls' output looks good" ' # Listing streams test_expect_success "'ipfs p2p ls' succeeds" ' - echo "/x/p2p-test /ipfs/$PEERID_0 /ip4/127.0.0.1/tcp/10101" > expected && + echo "/x/p2p-test /p2p/$PEERID_0 /ip4/127.0.0.1/tcp/10101" > expected && ipfsi 0 p2p ls > actual ' @@ -190,7 +190,7 @@ check_test_ports test_expect_success "Setup: Idle stream" ' ma-pipe-unidir --listen --pidFile=listener.pid recv /ip4/127.0.0.1/tcp/10101 & - ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10102 /ipfs/$PEERID_0 && + ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10102 /p2p/$PEERID_0 && ma-pipe-unidir --pidFile=client.pid recv /ip4/127.0.0.1/tcp/10102 & test_wait_for_file 30 100ms listener.pid && @@ -199,7 +199,7 @@ test_expect_success "Setup: Idle stream" ' ' test_expect_success "'ipfs p2p stream ls' succeeds" ' - echo "3 /x/p2p-test /ipfs/$PEERID_1 /ip4/127.0.0.1/tcp/10101" > expected + echo "3 /x/p2p-test /p2p/$PEERID_1 /ip4/127.0.0.1/tcp/10101" > expected ipfsi 0 p2p stream ls > actual ' @@ -232,7 +232,7 @@ test_expect_success "Setup: Idle stream(2)" ' ma-pipe-unidir --listen --pidFile=listener.pid recv /ip4/127.0.0.1/tcp/10101 & ipfsi 0 p2p listen /x/p2p-test2 /ip4/127.0.0.1/tcp/10101 2>&1 > listener-stdouterr.log && - ipfsi 1 p2p forward /x/p2p-test2 /ip4/127.0.0.1/tcp/10102 /ipfs/$PEERID_0 2>&1 > dialer-stdouterr.log && + ipfsi 1 p2p forward /x/p2p-test2 /ip4/127.0.0.1/tcp/10102 /p2p/$PEERID_0 2>&1 > dialer-stdouterr.log && ma-pipe-unidir --pidFile=client.pid recv /ip4/127.0.0.1/tcp/10102 & test_wait_for_file 30 100ms listener.pid && @@ -241,7 +241,7 @@ test_expect_success "Setup: Idle stream(2)" ' ' test_expect_success "'ipfs p2p stream ls' succeeds(2)" ' - echo "4 /x/p2p-test2 /ipfs/$PEERID_1 /ip4/127.0.0.1/tcp/10101" > expected + echo "4 /x/p2p-test2 /p2p/$PEERID_1 /ip4/127.0.0.1/tcp/10101" > expected ipfsi 0 p2p stream ls > actual test_cmp expected actual ' @@ -283,8 +283,8 @@ test_expect_success "'ipfs p2p close' closes by target addr" ' test_expect_success "'ipfs p2p close' closes right listeners" ' ipfsi 0 p2p listen /x/p2p-test /ip4/127.0.0.1/tcp/10101 && - ipfsi 0 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10101 /ipfs/$PEERID_1 && - echo "/x/p2p-test /ipfs/$PEERID_0 /ip4/127.0.0.1/tcp/10101" > expected && + ipfsi 0 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10101 /p2p/$PEERID_1 && + echo "/x/p2p-test /p2p/$PEERID_0 /ip4/127.0.0.1/tcp/10101" > expected && ipfsi 0 p2p close -l /ip4/127.0.0.1/tcp/10101 && ipfsi 0 p2p ls > actual && @@ -294,7 +294,7 @@ test_expect_success "'ipfs p2p close' closes right listeners" ' check_test_ports test_expect_success "'ipfs p2p close' closes by listen addr" ' - ipfsi 0 p2p close -l /ipfs/$PEERID_0 && + ipfsi 0 p2p close -l /p2p/$PEERID_0 && ipfsi 0 p2p ls > actual && test_must_be_empty actual ' @@ -313,7 +313,7 @@ test_expect_success 'C->S Spawn receiving server' ' ' test_expect_success 'C->S Setup client side' ' - ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10102 /ipfs/${PEERID_0} 2>&1 > dialer-stdouterr.log + ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10102 /p2p/${PEERID_0} 2>&1 > dialer-stdouterr.log ' test_expect_success 'C->S Connect and receive data' ' @@ -358,7 +358,7 @@ test_expect_success 'start p2p listener on custom proto' ' spawn_sending_server test_expect_success 'S->C Setup client side (custom proto)' ' - ipfsi 1 p2p forward --allow-custom-protocol /p2p-test /ip4/127.0.0.1/tcp/10102 /ipfs/${PEERID_0} 2>&1 > dialer-stdouterr.log + ipfsi 1 p2p forward --allow-custom-protocol /p2p-test /ip4/127.0.0.1/tcp/10102 /p2p/${PEERID_0} 2>&1 > dialer-stdouterr.log ' test_server_to_client diff --git a/test/sharness/t0180-pubsub.sh b/test/sharness/t0180-pubsub.sh index 9efdc4d1f90..abffd2d77c2 100755 --- a/test/sharness/t0180-pubsub.sh +++ b/test/sharness/t0180-pubsub.sh @@ -10,6 +10,10 @@ test_expect_success 'init iptb' ' iptb testbed create -type localipfs -count $NUM_NODES -init ' +test_expect_success 'disable the DHT' ' + iptb run -- ipfs config Routing.Type none +' + run_pubsub_tests() { test_expect_success 'peer ids' ' PEERID_0=$(iptb attr get 0 id) && diff --git a/test/sharness/t0181-private-network.sh b/test/sharness/t0181-private-network.sh index 6a0efd4c2ba..dfb4be2031b 100755 --- a/test/sharness/t0181-private-network.sh +++ b/test/sharness/t0181-private-network.sh @@ -26,7 +26,7 @@ test_expect_success "daemon output incudes info about the reason" ' pnet_key() { echo '/key/swarm/psk/1.0.0/' echo '/bin/' - random 16 + random 32 } pnet_key > "${IPFS_PATH}/swarm.key" @@ -132,4 +132,6 @@ test_expect_success "stop testbed" ' iptb stop ' +test_kill_ipfs_daemon + test_done diff --git a/test/sharness/t0182-circuit-relay.sh b/test/sharness/t0182-circuit-relay.sh index 4f480ebef64..3dd12ed68fa 100755 --- a/test/sharness/t0182-circuit-relay.sh +++ b/test/sharness/t0182-circuit-relay.sh @@ -44,7 +44,7 @@ test_expect_success 'peer ids' ' ' test_expect_success 'connect A <-Relay-> B' ' - ipfsi 0 swarm connect /p2p-circuit/ipfs/$PEERID_2 > peers_out + ipfsi 0 swarm connect /p2p/$PEERID_1/p2p-circuit/p2p/$PEERID_2 > peers_out ' test_expect_success 'output looks good' ' @@ -53,15 +53,13 @@ test_expect_success 'output looks good' ' ' test_expect_success 'peers for A look good' ' - ipfsi 0 swarm peers | grep p2p-circuit > peers_out && - echo "/ipfs/$PEERID_1/p2p-circuit/ipfs/$PEERID_2" > peers_exp && - test_cmp peers_exp peers_out + ipfsi 0 swarm peers > peers_out && + test_should_contain "/p2p/$PEERID_1/p2p-circuit/p2p/$PEERID_2$" peers_out ' test_expect_success 'peers for B look good' ' - ipfsi 2 swarm peers | grep p2p-circuit > peers_out && - echo "/ipfs/$PEERID_1/p2p-circuit/ipfs/$PEERID_0" > peers_exp && - test_cmp peers_exp peers_out + ipfsi 2 swarm peers > peers_out && + test_should_contain "/p2p/$PEERID_1/p2p-circuit/p2p/$PEERID_0$" peers_out ' test_expect_success 'add an object in A' ' diff --git a/test/sharness/t0183-namesys-pubsub.sh b/test/sharness/t0183-namesys-pubsub.sh index b4bbbc8413c..1026b47e7c8 100755 --- a/test/sharness/t0183-namesys-pubsub.sh +++ b/test/sharness/t0183-namesys-pubsub.sh @@ -41,7 +41,7 @@ test_expect_success 'check subscriptions' ' test_cmp expected subs2 ' -test_expect_success 'add an obect on publisher node' ' +test_expect_success 'add an object on publisher node' ' echo "ipns is super fun" > file && HASH_FILE=$(ipfsi 0 add -q file) ' diff --git a/test/sharness/t0184-http-proxy-over-p2p.sh b/test/sharness/t0184-http-proxy-over-p2p.sh index d647273f07c..06a3b9ccb18 100755 --- a/test/sharness/t0184-http-proxy-over-p2p.sh +++ b/test/sharness/t0184-http-proxy-over-p2p.sh @@ -3,6 +3,12 @@ test_description="Test http proxy over p2p" . lib/test-lib.sh + +if ! test_have_prereq SOCAT; then + skip_all="skipping '$test_description': socat is not available" + test_done +fi + WEB_SERVE_PORT=5099 IPFS_GATEWAY_PORT=5199 SENDER_GATEWAY="http://127.0.0.1:$IPFS_GATEWAY_PORT" @@ -138,10 +144,19 @@ test_expect_success 'configure nodes' ' iptb testbed create -type localipfs -count 2 -force -init && ipfsi 0 config --json Experimental.Libp2pStreamMounting true && ipfsi 1 config --json Experimental.Libp2pStreamMounting true && - ipfsi 0 config --json Experimental.P2pHttpProxy true + ipfsi 0 config --json Experimental.P2pHttpProxy true && ipfsi 0 config --json Addresses.Gateway "[\"/ip4/127.0.0.1/tcp/$IPFS_GATEWAY_PORT\"]" ' +test_expect_success 'configure a subdomain gateway with /p2p/ path whitelisted' " + ipfsi 0 config --json Gateway.PublicGateways '{ + \"example.com\": { + \"UseSubdomains\": true, + \"Paths\": [\"/p2p/\"] + } + }' +" + test_expect_success 'start and connect nodes' ' iptb start -wait && iptb connect 0 1 ' @@ -163,7 +178,7 @@ test_expect_success 'start http server' ' start_http_server ' -test_expect_success 'handle proxy http request propogates error response from remote' ' +test_expect_success 'handle proxy http request propagates error response from remote' ' serve_content "SORRY GUYS, I LOST IT" "404 Not Found" && curl_send_proxy_request_and_check_response 404 "SORRY GUYS, I LOST IT" ' @@ -200,6 +215,30 @@ test_expect_success 'handle multipart/form-data http request' ' curl_send_multipart_form_request 200 ' +# subdomain gateway at *.p2p.example.com requires PeerdID in base32 +RECEIVER_ID_CIDv1=$( ipfs cid format -v 1 -b b --codec libp2p-key -- $RECEIVER_ID) + +# OK: $peerid.p2p.example.com/http/index.txt +test_expect_success "handle http request to a subdomain gateway" ' + serve_content "SUBDOMAIN PROVIDES ORIGIN ISOLATION PER RECEIVER_ID" && + curl -H "Host: $RECEIVER_ID_CIDv1.p2p.example.com" -sD - $SENDER_GATEWAY/http/index.txt > p2p_response && + test_should_contain "SUBDOMAIN PROVIDES ORIGIN ISOLATION PER RECEIVER_ID" p2p_response +' + +# FAIL: $peerid.p2p.example.com/p2p/$peerid/http/index.txt +test_expect_success "handle invalid http request to a subdomain gateway" ' + serve_content "SUBDOMAIN DOES NOT SUPPORT FULL /p2p/ PATH" && + curl -H "Host: $RECEIVER_ID_CIDv1.p2p.example.com" -sD - $SENDER_GATEWAY/p2p/$RECEIVER_ID/http/index.txt > p2p_response && + test_should_contain "400 Bad Request" p2p_response +' + +# REDIRECT: example.com/p2p/$peerid/http/index.txt → $peerid.p2p.example.com/http/index.txt +test_expect_success "redirect http path request to subdomain gateway" ' + serve_content "SUBDOMAIN ROOT REDIRECTS /p2p/ PATH TO SUBDOMAIN" && + curl -H "Host: example.com" -sD - $SENDER_GATEWAY/p2p/$RECEIVER_ID/http/index.txt > p2p_response && + test_should_contain "Location: http://$RECEIVER_ID_CIDv1.p2p.example.com/http/index.txt" p2p_response +' + test_expect_success 'stop http server' ' teardown_remote_server ' diff --git a/test/sharness/t0185-autonat.sh b/test/sharness/t0185-autonat.sh new file mode 100755 index 00000000000..9cde1ad5cbd --- /dev/null +++ b/test/sharness/t0185-autonat.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +test_description="Test autonat" + +. lib/test-lib.sh + +# NOTE: This is currently a really dumb test just to make sure this service +# starts. We need better tests but testing AutoNAT without public IP addresses +# is tricky. + +test_init_ipfs + +test_expect_success "enable autonat" ' + ipfs config AutoNAT.ServiceMode enabled +' + +test_launch_ipfs_daemon + +test_kill_ipfs_daemon + +test_expect_success "enable autonat" ' + ipfs config AutoNAT.ServiceMode disabled +' + +test_launch_ipfs_daemon + +test_kill_ipfs_daemon + +test_done diff --git a/test/sharness/t0221-graphsync.sh b/test/sharness/t0221-graphsync.sh new file mode 100755 index 00000000000..771ff4f8c89 --- /dev/null +++ b/test/sharness/t0221-graphsync.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +test_description="Test fetching from graphsync." + +# imports +. lib/test-lib.sh + +test_init_ipfs + +test_expect_success 'configuring ipfs' ' + ipfs config --json Experimental.GraphsyncEnabled true +' + +test_expect_success 'add content' ' + HASH=$(random 1000000 | ipfs add -q) +' + +test_launch_ipfs_daemon + +test_expect_success 'get addrs' ' + ADDR="$(ipfs id --format="" | head -1)" +' + +test_expect_success 'fetch' ' + graphsync-get "$ADDR" "$HASH" > result +' + +test_expect_success 'check' ' + ipfs add -q < result > hash_actual && + echo "$HASH" > hash_expected && + test_cmp hash_expected hash_actual +' + +test_kill_ipfs_daemon +test_done diff --git a/test/sharness/t0230-channel-streaming-http-content-type.sh b/test/sharness/t0230-channel-streaming-http-content-type.sh index deffffa2c2f..34ef57771fb 100755 --- a/test/sharness/t0230-channel-streaming-http-content-type.sh +++ b/test/sharness/t0230-channel-streaming-http-content-type.sh @@ -16,7 +16,7 @@ test_ls_cmd() { mkdir -p testdir && echo "hello test" >testdir/test.txt && ipfs add -r testdir && - curl -i "http://$API_ADDR/api/v0/refs?arg=QmTcJAn3JP8ZMAKS6WS75q8sbTyojWKbxcUHgLYGWur4Ym&stream-channels=true&encoding=text" >actual_output + curl -X POST -i "http://$API_ADDR/api/v0/refs?arg=QmTcJAn3JP8ZMAKS6WS75q8sbTyojWKbxcUHgLYGWur4Ym&stream-channels=true&encoding=text" >actual_output ' test_expect_success "Text encoded channel-streaming command output looks good" ' @@ -39,7 +39,7 @@ test_ls_cmd() { mkdir -p testdir && echo "hello test" >testdir/test.txt && ipfs add -r testdir && - curl -i "http://$API_ADDR/api/v0/refs?arg=QmTcJAn3JP8ZMAKS6WS75q8sbTyojWKbxcUHgLYGWur4Ym&stream-channels=true&encoding=json" >actual_output + curl -X POST -i "http://$API_ADDR/api/v0/refs?arg=QmTcJAn3JP8ZMAKS6WS75q8sbTyojWKbxcUHgLYGWur4Ym&stream-channels=true&encoding=json" >actual_output ' test_expect_success "JSON encoded channel-streaming command output looks good" ' diff --git a/test/sharness/t0235-cli-request.sh b/test/sharness/t0235-cli-request.sh index 24bccd4d5e9..3d50a2e62bf 100755 --- a/test/sharness/t0235-cli-request.sh +++ b/test/sharness/t0235-cli-request.sh @@ -8,6 +8,12 @@ test_description="test http requests made by cli" . lib/test-lib.sh +if ! test_have_prereq SOCAT; then + skip_all="skipping '$test_description': socat is not available" + test_done +fi + + test_init_ipfs test_expect_success "start nc" ' diff --git a/test/sharness/t0236-cli-api-dns-resolve.sh b/test/sharness/t0236-cli-api-dns-resolve.sh index 1beefed0996..eddbc93da49 100755 --- a/test/sharness/t0236-cli-api-dns-resolve.sh +++ b/test/sharness/t0236-cli-api-dns-resolve.sh @@ -8,6 +8,11 @@ test_description="test dns resolution of api endpoint by cli" . lib/test-lib.sh +if ! test_have_prereq SOCAT; then + skip_all="skipping '$test_description': socat is not available" + test_done +fi + test_init_ipfs test_expect_success "start nc" ' diff --git a/test/sharness/t0250-files-api.sh b/test/sharness/t0250-files-api.sh index d26b89042a6..5c146b550e0 100755 --- a/test/sharness/t0250-files-api.sh +++ b/test/sharness/t0250-files-api.sh @@ -202,6 +202,12 @@ test_files_api() { test_cmp ls_l_expected ls_l_actual ' + test_expect_success "file has correct hash and size listed with --long" ' + echo "file1 $FILE1 4" > ls_l_expected && + ipfs files ls --long /cats/file1 > ls_l_actual && + test_cmp ls_l_expected ls_l_actual + ' + test_expect_success "file has correct hash and size listed with -l --cid-base=base32" ' echo "file1 `cid-fmt -v 1 -b base32 %s $FILE1` 4" > ls_l_expected && ipfs files ls --cid-base=base32 -l /cats/file1 > ls_l_actual && @@ -436,10 +442,10 @@ test_files_api() { test_expect_success "file hash correct $EXTRA" ' echo $FILE_HASH > filehash_expected && ipfs files stat --hash /cats/ipfs > filehash && - test_cmp filehash_expected filehash + test_cmp filehash_expected filehash ' - test_expect_success "cant write to negative offset $EXTRA" ' + test_expect_success "can't write to negative offset $EXTRA" ' test_expect_code 1 ipfs files write $ARGS $RAW_LEAVES --offset -1 /cats/ipfs < output ' @@ -677,6 +683,14 @@ test_files_api() { ipfs files rm --force /forcibly-dir && verify_dir_contents / ' + + test_expect_success "remove nonexistant path forcibly" ' + ipfs files rm --force /nonexistant + ' + + test_expect_success "remove deeply nonexistant path forcibly" ' + ipfs files rm --force /deeply/nonexistant + ' } # test offline and online diff --git a/test/sharness/t0270-filestore.sh b/test/sharness/t0270-filestore.sh index 200305493bc..a8ca939a501 100755 --- a/test/sharness/t0270-filestore.sh +++ b/test/sharness/t0270-filestore.sh @@ -48,7 +48,7 @@ test_filestore_adds() { assert_repo_size_less_than 1000000 - test_expect_success "normal add with fscache doesnt duplicate data" ' + test_expect_success "normal add with fscache doesn't duplicate data" ' ipfs add --raw-leaves --fscache -r -q somedir > /dev/null ' diff --git a/test/sharness/t0272-urlstore.sh b/test/sharness/t0272-urlstore.sh index 5464c8ad584..a2c4867f659 100755 --- a/test/sharness/t0272-urlstore.sh +++ b/test/sharness/t0272-urlstore.sh @@ -28,7 +28,7 @@ test_urlstore() { test_launch_ipfs_daemon --offline - test_expect_success "make sure files can be retrived via the gateway" ' + test_expect_success "make sure files can be retrieved via the gateway" ' curl http://127.0.0.1:$GWAY_PORT/ipfs/$HASH1a -o file1.actual && test_cmp file1 file1.actual && curl http://127.0.0.1:$GWAY_PORT/ipfs/$HASH2a -o file2.actual && @@ -125,7 +125,7 @@ EOF test_cmp verify_expect_2 verify_actual_2 ' - test_expect_success "files can not be retrieved via the urlstore" ' + test_expect_success "files cannot be retrieved via the urlstore" ' test_must_fail ipfs cat $HASH1 > /dev/null && test_must_fail ipfs cat $HASH2 > /dev/null ' @@ -164,7 +164,7 @@ EOF test_kill_ipfs_daemon - test_expect_success "files can not be retrieved via the urlstore" ' + test_expect_success "files cannot be retrieved via the urlstore" ' test_must_fail ipfs cat $HASH1 > /dev/null && test_must_fail ipfs cat $HASH2 > /dev/null && test_must_fail ipfs cat $HASH3 > /dev/null diff --git a/test/sharness/t0280-plugin-data/example.go b/test/sharness/t0280-plugin-data/example.go new file mode 100644 index 00000000000..87b96249ad2 --- /dev/null +++ b/test/sharness/t0280-plugin-data/example.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "os" + + "github.com/ipfs/go-ipfs/plugin" +) + +var Plugins = []plugin.Plugin{ + &testPlugin{}, +} + +var _ = Plugins // used + +type testPlugin struct{} + +func (*testPlugin) Name() string { + return "test-plugin" +} + +func (*testPlugin) Version() string { + return "0.1.0" +} + +func (*testPlugin) Init(env *plugin.Environment) error { + fmt.Fprintf(os.Stderr, "testplugin %s\n", env.Repo) + fmt.Fprintf(os.Stderr, "testplugin %v\n", env.Config) + return nil +} diff --git a/test/sharness/t0280-plugin-git.sh b/test/sharness/t0280-plugin-git.sh index f5948fbb63d..e7bc0642742 100755 --- a/test/sharness/t0280-plugin-git.sh +++ b/test/sharness/t0280-plugin-git.sh @@ -21,7 +21,7 @@ test_dag_git() { ' test_expect_success "successfully get added objects" ' - cat hashes | xargs -i ipfs dag get -- {} > /dev/null + cat hashes | xargs -I {} ipfs dag get -- {} > /dev/null ' test_expect_success "path traversals work" ' diff --git a/test/sharness/t0280-plugin.sh b/test/sharness/t0280-plugin.sh index b739a7834bc..a0709ef1b2b 100755 --- a/test/sharness/t0280-plugin.sh +++ b/test/sharness/t0280-plugin.sh @@ -8,6 +8,12 @@ test_description="Test plugin loading" . lib/test-lib.sh +if ! test_have_prereq PLUGIN; then + skip_all='skipping plugin tests, plugins not available' + + test_done +fi + test_init_ipfs test_expect_success "ipfs id succeeds" ' @@ -28,4 +34,59 @@ test_expect_success "cleanup bad plugin" ' rm "$IPFS_PATH/plugins/foo.so" ' +test_expect_success "install test plugin" ' + go build \ + -asmflags=all="-trimpath=${GOPATH}" -gcflags=all="-trimpath=${GOPATH}" \ + -buildmode=plugin -o "$IPFS_PATH/plugins/example.so" ../t0280-plugin-data/example.go && + chmod +x "$IPFS_PATH/plugins/example.so" +' + +test_plugin() { + local loads="$1" + local repo="$2" + local config="$3" + + rm -f id_raw_output id_output id_output_expected + + test_expect_success "id runs" ' + ipfs id 2>id_raw_output >/dev/null + ' + + test_expect_success "filter test plugin output" ' + sed -ne "s/^testplugin //p" id_raw_output >id_output + ' + + if [ "$loads" != "true" ]; then + test_expect_success "plugin doesn't load" ' + test_must_be_empty id_output + ' + else + test_expect_success "plugin produces the correct output" ' + echo "$repo" >id_output_expected && + echo "$config" >>id_output_expected && + test_cmp id_output id_output_expected + ' + fi +} + +test_plugin true "$IPFS_PATH" "" + +test_expect_success "disable the plugin" ' + ipfs config --json Plugins.Plugins.test-plugin.Disabled true +' + +test_plugin false + +test_expect_success "re-enable the plugin" ' + ipfs config --json Plugins.Plugins.test-plugin.Disabled false +' + +test_plugin true "$IPFS_PATH" "" + +test_expect_success "configure the plugin" ' + ipfs config Plugins.Plugins.test-plugin.Config foobar +' + +test_plugin true "$IPFS_PATH" "foobar" + test_done diff --git a/test/sharness/t0290-cid.sh b/test/sharness/t0290-cid.sh index 5cf27f1c1a9..0659df2a20a 100755 --- a/test/sharness/t0290-cid.sh +++ b/test/sharness/t0290-cid.sh @@ -10,6 +10,10 @@ CIDv0="QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv" CIDv1="zdj7WZAAFKPvYPPzyJLso2hhxo8a7ZACFQ4DvvfrNXTHidofr" CIDb32="bafybeibxm2nsadl3fnxv2sxcxmxaco2jl53wpeorjdzidjwf5aqdg7wa6u" +CIDbase="QmYNmQKp6SuaVrpgWRsPTgCQCnpxUYGq76YEKBXuj2N4H6" +CIDb32pb="bafybeievd6mwe6vcwnkwo3eizs3h7w3a34opszbyfxziqdxguhjw7imdve" +CIDb32raw="bafkreievd6mwe6vcwnkwo3eizs3h7w3a34opszbyfxziqdxguhjw7imdve" + test_expect_success "cid base32 works" ' echo $CIDb32 > expected && ipfs cid base32 $CIDv0 > actual1 && @@ -26,6 +30,12 @@ test_expect_success "cid format -v 1 -b base58btc" ' test_cmp expected actual2 ' +test_expect_success "cid format -v 0" ' + echo $CIDv0 > expected && + ipfs cid format -v 0 $CIDb32 > actual && + test_cmp expected actual +' + cat < various_cids QmZZRTyhDpL5Jgift1cHbAhexeE1m2Hw8x8g7rTcPahDvo QmPhk6cJkRcFfZCdYam4c9MKYjFG9V29LswUnbrFNhtk2S @@ -228,4 +238,17 @@ test_expect_success "cid hashes --numeric" ' test_cmp hashes_expect actual ' +test_expect_success "cid format -c raw" ' + echo $CIDb32raw > expected && + ipfs cid format --codec raw -b base32 $CIDb32pb > actual && + test_cmp actual expected +' + +test_expect_success "cid format -c protobuf -v 0" ' + echo $CIDbase > expected && + ipfs cid format --codec protobuf -v 0 $CIDb32raw > actual && + test_cmp actual expected +' + + test_done diff --git a/test/sharness/t0300-docker-image.sh b/test/sharness/t0300-docker-image.sh index 741f8885a49..3d8f573f2f5 100755 --- a/test/sharness/t0300-docker-image.sh +++ b/test/sharness/t0300-docker-image.sh @@ -23,10 +23,6 @@ test_expect_success "'docker --version' output looks good" ' egrep "^Docker version" actual ' -test_expect_success "current user is in the 'docker' group" ' - groups | egrep "\bdocker\b" -' - TEST_TRASH_DIR=$(pwd) TEST_SCRIPTS_DIR=$(dirname "$TEST_TRASH_DIR") TEST_TESTS_DIR=$(dirname "$TEST_SCRIPTS_DIR") diff --git a/test/sharness/t0301-docker-migrate.sh b/test/sharness/t0301-docker-migrate.sh index 76776920210..4f47310d181 100755 --- a/test/sharness/t0301-docker-migrate.sh +++ b/test/sharness/t0301-docker-migrate.sh @@ -10,11 +10,16 @@ test_description="Test docker image migration" # if in travis CI on OSX, docker is not available if ! test_have_prereq DOCKER; then - skip_all='skipping docker tests, docker not available' + skip_all='skipping '$test_description', docker not available' test_done fi +if ! test_have_prereq SOCAT; then + skip_all="skipping '$test_description': socat is not available" + test_done +fi + TEST_TRASH_DIR=$(pwd) TEST_SCRIPTS_DIR=$(dirname "$TEST_TRASH_DIR") TEST_TESTS_DIR=$(dirname "$TEST_SCRIPTS_DIR") @@ -39,7 +44,7 @@ test_expect_success "setup http response" ' ' pretend_server() { - socat tcp-listen:17233,fork,bind=127.0.0.1,reuseaddr 'SYSTEM:cat cers_resp'!!STDERR & + socat tcp-listen:17233,fork,bind=127.0.0.1,reuseaddr 'SYSTEM:cat vers_resp'!!STDERR & } test_expect_success "startup fake dists server" ' diff --git a/test/sharness/t0410-api-add.sh b/test/sharness/t0410-api-add.sh index 6481e9ef686..da81f8332ec 100755 --- a/test/sharness/t0410-api-add.sh +++ b/test/sharness/t0410-api-add.sh @@ -10,7 +10,7 @@ test_description="Test API add command" test_init_ipfs -# Verify that that API add command returns size +# Verify that the API add command returns size test_launch_ipfs_daemon test_expect_success "API Add response includes size field" ' diff --git a/test/sharness/t0600-issues-and-regressions-online.sh b/test/sharness/t0600-issues-and-regressions-online.sh index 1abf87170d9..947b5610ab0 100755 --- a/test/sharness/t0600-issues-and-regressions-online.sh +++ b/test/sharness/t0600-issues-and-regressions-online.sh @@ -11,16 +11,16 @@ test_launch_ipfs_daemon # Tests go here test_expect_success "commands command with flag flags works via HTTP API - #2301" ' - curl "http://$API_ADDR/api/v0/commands?flags" | grep "verbose" + curl -X POST "http://$API_ADDR/api/v0/commands?flags" | grep "verbose" ' test_expect_success "ipfs refs local over HTTP API returns NDJOSN not flat - #2803" ' echo "Hello World" | ipfs add && - curl "http://$API_ADDR/api/v0/refs/local" | grep "Ref" | grep "Err" + curl -X POST "http://$API_ADDR/api/v0/refs/local" | grep "Ref" | grep "Err" ' -test_expect_success "args expecting stdin dont crash when not given" ' - curl "$API_ADDR/api/v0/bootstrap/add" > result +test_expect_success "args expecting stdin don't crash when not given" ' + curl -X POST "$API_ADDR/api/v0/bootstrap/add" > result ' test_expect_success "no panic traces on daemon" ' @@ -28,25 +28,25 @@ test_expect_success "no panic traces on daemon" ' ' test_expect_success "metrics work" ' - curl "$API_ADDR/debug/metrics/prometheus" > pro_data && + curl -X POST "$API_ADDR/debug/metrics/prometheus" > pro_data && grep "ipfs_bs_cache_arc_hits_total" < pro_data || test_fsh cat pro_data ' test_expect_success "pin add api looks right - #3753" ' HASH=$(echo "foo" | ipfs add -q) && - curl "http://$API_ADDR/api/v0/pin/add/$HASH" > pinadd_out && + curl -X POST "http://$API_ADDR/api/v0/pin/add/$HASH" > pinadd_out && echo "{\"Pins\":[\"QmYNmQKp6SuaVrpgWRsPTgCQCnpxUYGq76YEKBXuj2N4H6\"]}" > pinadd_exp && test_cmp pinadd_out pinadd_exp ' test_expect_success "pin add api looks right - #3753" ' - curl "http://$API_ADDR/api/v0/pin/rm/$HASH" > pinrm_out && + curl -X POST "http://$API_ADDR/api/v0/pin/rm/$HASH" > pinrm_out && echo "{\"Pins\":[\"QmYNmQKp6SuaVrpgWRsPTgCQCnpxUYGq76YEKBXuj2N4H6\"]}" > pinrm_exp && test_cmp pinrm_out pinrm_exp ' -test_expect_success "no daemon crash on improper file argument - #4003" ' +test_expect_success SOCAT "no daemon crash on improper file argument - #4003 ( test needs socat )" ' FNC=$(echo $API_ADDR | awk -F: '\''{ printf "%s:%s", $1, $2 }'\'') && printf "POST /api/v0/add?pin=true HTTP/1.1\r\nHost: $API_ADDR\r\nContent-Type: multipart/form-data; boundary=Pyw9xQLtiLPE6XcI\r\nContent-Length: 22\r\n\r\n\r\n--Pyw9xQLtiLPE6XcI\r\n" | socat STDIO tcp-connect:$FNC | grep -m1 "500 Internal Server Error" ' diff --git a/test/sharness_test_coverage_helper.sh b/test/sharness_test_coverage_helper.sh index 99bcb7dbf25..56f784d315c 100755 --- a/test/sharness_test_coverage_helper.sh +++ b/test/sharness_test_coverage_helper.sh @@ -170,7 +170,7 @@ do done # The following will allow us to check that -# we are properly excuding enough stuff using: +# we are properly excluding enough stuff using: # diff -u ipfs_cmd_result.txt cmd_found.txt log "Get all the line commands that matched" CMD_FOUND="$TMPDIR/cmd_found.txt" diff --git a/thirdparty/README.md b/thirdparty/README.md index 554a07febd3..a68b51c5dfe 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -1,5 +1,5 @@ thirdparty consists of Golang packages that contain no go-ipfs dependencies and may be vendored ipfs/go-ipfs at a later date. -packages in under this directory _must not_ import packages under +packages under this directory _must not_ import packages under `ipfs/go-ipfs` that are not also under `thirdparty`. diff --git a/thirdparty/notifier/notifier.go b/thirdparty/notifier/notifier.go index be44b04f340..60bf6da3a6b 100644 --- a/thirdparty/notifier/notifier.go +++ b/thirdparty/notifier/notifier.go @@ -1,5 +1,5 @@ // Package notifier provides a simple notification dispatcher -// meant to be embedded in larger structres who wish to allow +// meant to be embedded in larger structures who wish to allow // clients to sign up for event notifications. package notifier diff --git a/version.go b/version.go index 43a09929579..49bfdcacecd 100644 --- a/version.go +++ b/version.go @@ -4,6 +4,11 @@ package ipfs var CurrentCommit string // CurrentVersionNumber is the current application's version literal -const CurrentVersionNumber = "0.4.23" +const CurrentVersionNumber = "0.5.0" const ApiVersion = "/go-ipfs/" + CurrentVersionNumber + "/" + +// UserAgent is the libp2p user agent used by go-ipfs. +// +// Note: This will end in `/` when no commit is available. This is expected. +var UserAgent = "go-ipfs/" + CurrentVersionNumber + "/" + CurrentCommit