From 3db9551f7948809e6f9104651412557fbde08af0 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Fri, 19 Feb 2021 00:33:43 +0100 Subject: [PATCH] Extract the namesys and the keystore submodules Namesys is a very useful submodule. Given a ValueStore and a Datastore it can resolve and publish /ipns/ paths. This functionality does not need to be sequestered inside go-ipfs as it can and should be used without IPFS, for example, for implementing lightweight IPNS publishing services or for resolving /ipns/ paths. "keystore" extraction was necessary, as there is a dependency to it in namesys. Keystore is also a useful module by itself within the stack. Fixes #6537 --- cmd/ipfs/init.go | 2 +- core/commands/dht_test.go | 2 +- core/commands/dns.go | 2 +- core/commands/name/ipns.go | 2 +- core/commands/resolve.go | 2 +- core/core.go | 4 +- core/coreapi/coreapi.go | 2 +- core/coreapi/name.go | 4 +- core/coreapi/path.go | 2 +- core/coreapi/test/api_test.go | 2 +- core/corehttp/gateway_test.go | 2 +- core/corehttp/hostname.go | 2 +- core/node/ipns.go | 4 +- fuse/ipns/common.go | 2 +- go.mod | 8 +- go.sum | 96 ++++++- keystore/keystore.go | 189 -------------- keystore/keystore_test.go | 278 -------------------- keystore/memkeystore.go | 64 ----- keystore/memkeystore_test.go | 99 -------- namesys/base.go | 120 --------- namesys/cache.go | 62 ----- namesys/dns.go | 159 ------------ namesys/dns_test.go | 172 ------------- namesys/interface.go | 106 -------- namesys/ipns_resolver_validation_test.go | 206 --------------- namesys/namesys.go | 238 ----------------- namesys/namesys_test.go | 169 ------------- namesys/proquint.go | 32 --- namesys/publisher.go | 309 ----------------------- namesys/publisher_test.go | 155 ------------ namesys/republisher/repub.go | 168 ------------ namesys/republisher/repub_test.go | 245 ------------------ namesys/resolve/resolve.go | 52 ---- namesys/resolve_test.go | 123 --------- namesys/routing.go | 148 ----------- repo/fsrepo/fsrepo.go | 2 +- repo/mock.go | 2 +- repo/repo.go | 2 +- 39 files changed, 114 insertions(+), 3124 deletions(-) delete mode 100644 keystore/keystore.go delete mode 100644 keystore/keystore_test.go delete mode 100644 keystore/memkeystore.go delete mode 100644 keystore/memkeystore_test.go delete mode 100644 namesys/base.go delete mode 100644 namesys/cache.go delete mode 100644 namesys/dns.go delete mode 100644 namesys/dns_test.go delete mode 100644 namesys/interface.go delete mode 100644 namesys/ipns_resolver_validation_test.go delete mode 100644 namesys/namesys.go delete mode 100644 namesys/namesys_test.go delete mode 100644 namesys/proquint.go delete mode 100644 namesys/publisher.go delete mode 100644 namesys/publisher_test.go delete mode 100644 namesys/republisher/repub.go delete mode 100644 namesys/republisher/repub_test.go delete mode 100644 namesys/resolve/resolve.go delete mode 100644 namesys/resolve_test.go delete mode 100644 namesys/routing.go diff --git a/cmd/ipfs/init.go b/cmd/ipfs/init.go index f419604f2e3..fe252e8cbf4 100644 --- a/cmd/ipfs/init.go +++ b/cmd/ipfs/init.go @@ -14,8 +14,8 @@ import ( oldcmds "github.com/ipfs/go-ipfs/commands" core "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/core/commands" - namesys "github.com/ipfs/go-ipfs/namesys" fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo" + namesys "github.com/ipfs/go-namesys" cmds "github.com/ipfs/go-ipfs-cmds" config "github.com/ipfs/go-ipfs-config" diff --git a/core/commands/dht_test.go b/core/commands/dht_test.go index b32190a12e0..4c31a4b5c7b 100644 --- a/core/commands/dht_test.go +++ b/core/commands/dht_test.go @@ -3,7 +3,7 @@ package commands import ( "testing" - "github.com/ipfs/go-ipfs/namesys" + "github.com/ipfs/go-namesys" ipns "github.com/ipfs/go-ipns" "github.com/libp2p/go-libp2p-core/test" diff --git a/core/commands/dns.go b/core/commands/dns.go index d5dea4cf1d6..43c5f3d78bf 100644 --- a/core/commands/dns.go +++ b/core/commands/dns.go @@ -6,7 +6,7 @@ import ( cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" ncmd "github.com/ipfs/go-ipfs/core/commands/name" - namesys "github.com/ipfs/go-ipfs/namesys" + namesys "github.com/ipfs/go-namesys" nsopts "github.com/ipfs/interface-go-ipfs-core/options/namesys" cmds "github.com/ipfs/go-ipfs-cmds" diff --git a/core/commands/name/ipns.go b/core/commands/name/ipns.go index 57cf68b2ae5..885c469247a 100644 --- a/core/commands/name/ipns.go +++ b/core/commands/name/ipns.go @@ -8,7 +8,7 @@ import ( "time" cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" - namesys "github.com/ipfs/go-ipfs/namesys" + namesys "github.com/ipfs/go-namesys" cmds "github.com/ipfs/go-ipfs-cmds" logging "github.com/ipfs/go-log" diff --git a/core/commands/resolve.go b/core/commands/resolve.go index 63d17504807..fb87d1c02aa 100644 --- a/core/commands/resolve.go +++ b/core/commands/resolve.go @@ -9,7 +9,7 @@ import ( cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" ncmd "github.com/ipfs/go-ipfs/core/commands/name" - ns "github.com/ipfs/go-ipfs/namesys" + ns "github.com/ipfs/go-namesys" cidenc "github.com/ipfs/go-cidutil/cidenc" cmds "github.com/ipfs/go-ipfs-cmds" diff --git a/core/core.go b/core/core.go index d422a1aa80c..7c8737a6a41 100644 --- a/core/core.go +++ b/core/core.go @@ -45,11 +45,11 @@ import ( "github.com/ipfs/go-ipfs/core/node" "github.com/ipfs/go-ipfs/core/node/libp2p" "github.com/ipfs/go-ipfs/fuse/mount" - "github.com/ipfs/go-ipfs/namesys" - ipnsrp "github.com/ipfs/go-ipfs/namesys/republisher" "github.com/ipfs/go-ipfs/p2p" "github.com/ipfs/go-ipfs/peering" "github.com/ipfs/go-ipfs/repo" + "github.com/ipfs/go-namesys" + ipnsrp "github.com/ipfs/go-namesys/republisher" ) var log = logging.Logger("core") diff --git a/core/coreapi/coreapi.go b/core/coreapi/coreapi.go index 5b638826b45..672b426456f 100644 --- a/core/coreapi/coreapi.go +++ b/core/coreapi/coreapi.go @@ -39,8 +39,8 @@ import ( "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/core/node" - "github.com/ipfs/go-ipfs/namesys" "github.com/ipfs/go-ipfs/repo" + "github.com/ipfs/go-namesys" ) type CoreAPI struct { diff --git a/core/coreapi/name.go b/core/coreapi/name.go index c9c3dedf36e..babb7c4a8b7 100644 --- a/core/coreapi/name.go +++ b/core/coreapi/name.go @@ -6,8 +6,8 @@ import ( "strings" "time" - "github.com/ipfs/go-ipfs/keystore" - "github.com/ipfs/go-ipfs/namesys" + "github.com/ipfs/go-ipfs-keystore" + "github.com/ipfs/go-namesys" ipath "github.com/ipfs/go-path" coreiface "github.com/ipfs/interface-go-ipfs-core" diff --git a/core/coreapi/path.go b/core/coreapi/path.go index 314d1b5fd55..598f5d11581 100644 --- a/core/coreapi/path.go +++ b/core/coreapi/path.go @@ -5,7 +5,7 @@ import ( "fmt" gopath "path" - "github.com/ipfs/go-ipfs/namesys/resolve" + "github.com/ipfs/go-namesys/resolve" "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" diff --git a/core/coreapi/test/api_test.go b/core/coreapi/test/api_test.go index 153a8c7cf31..e5ccb62dd6f 100644 --- a/core/coreapi/test/api_test.go +++ b/core/coreapi/test/api_test.go @@ -9,12 +9,12 @@ import ( "testing" "github.com/ipfs/go-filestore" + "github.com/ipfs/go-ipfs-keystore" "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/core/node/libp2p" - "github.com/ipfs/go-ipfs/keystore" "github.com/ipfs/go-ipfs/repo" "github.com/ipfs/go-datastore" diff --git a/core/corehttp/gateway_test.go b/core/corehttp/gateway_test.go index a05e456ab6c..053c22f9a8d 100644 --- a/core/corehttp/gateway_test.go +++ b/core/corehttp/gateway_test.go @@ -14,8 +14,8 @@ import ( version "github.com/ipfs/go-ipfs" core "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/core/coreapi" - namesys "github.com/ipfs/go-ipfs/namesys" repo "github.com/ipfs/go-ipfs/repo" + namesys "github.com/ipfs/go-namesys" datastore "github.com/ipfs/go-datastore" syncds "github.com/ipfs/go-datastore/sync" diff --git a/core/corehttp/hostname.go b/core/corehttp/hostname.go index da133f7abe1..6d2955e49c4 100644 --- a/core/corehttp/hostname.go +++ b/core/corehttp/hostname.go @@ -12,7 +12,7 @@ import ( cid "github.com/ipfs/go-cid" core "github.com/ipfs/go-ipfs/core" coreapi "github.com/ipfs/go-ipfs/core/coreapi" - namesys "github.com/ipfs/go-ipfs/namesys" + namesys "github.com/ipfs/go-namesys" isd "github.com/jbenet/go-is-domain" "github.com/libp2p/go-libp2p-core/peer" mbase "github.com/multiformats/go-multibase" diff --git a/core/node/ipns.go b/core/node/ipns.go index 11769d97f92..4b2c1738923 100644 --- a/core/node/ipns.go +++ b/core/node/ipns.go @@ -11,9 +11,9 @@ import ( "github.com/libp2p/go-libp2p-core/routing" "github.com/libp2p/go-libp2p-record" - "github.com/ipfs/go-ipfs/namesys" - "github.com/ipfs/go-ipfs/namesys/republisher" "github.com/ipfs/go-ipfs/repo" + "github.com/ipfs/go-namesys" + "github.com/ipfs/go-namesys/republisher" ) const DefaultIpnsCacheSize = 128 diff --git a/fuse/ipns/common.go b/fuse/ipns/common.go index 48129a92e98..1b810eaa990 100644 --- a/fuse/ipns/common.go +++ b/fuse/ipns/common.go @@ -4,7 +4,7 @@ import ( "context" "github.com/ipfs/go-ipfs/core" - nsys "github.com/ipfs/go-ipfs/namesys" + nsys "github.com/ipfs/go-namesys" path "github.com/ipfs/go-path" ft "github.com/ipfs/go-unixfs" ci "github.com/libp2p/go-libp2p-core/crypto" diff --git a/go.mod b/go.mod index 9178cca5fe0..8a0d5e11b62 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ require ( bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc contrib.go.opencensus.io/exporter/prometheus v0.2.0 github.com/blang/semver/v4 v4.0.0 - github.com/bren2010/proquint v0.0.0-20201027163346-95122a84635f github.com/cheggaaa/pb v1.0.29 github.com/coreos/go-systemd/v22 v22.1.0 github.com/dustin/go-humanize v1.0.0 @@ -12,9 +11,7 @@ require ( github.com/fsnotify/fsnotify v1.4.9 github.com/gabriel-vasile/mimetype v1.1.2 github.com/go-bindata/go-bindata/v3 v3.1.3 - github.com/gogo/protobuf v1.3.2 github.com/hashicorp/go-multierror v1.1.0 - github.com/hashicorp/golang-lru v0.5.4 github.com/ipfs/go-bitswap v0.3.3 github.com/ipfs/go-block-format v0.0.3 github.com/ipfs/go-blockservice v0.1.4 @@ -33,10 +30,10 @@ require ( github.com/ipfs/go-ipfs-chunker v0.0.5 github.com/ipfs/go-ipfs-cmds v0.6.0 github.com/ipfs/go-ipfs-config v0.12.0 - 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.8 + github.com/ipfs/go-ipfs-keystore v0.0.2 github.com/ipfs/go-ipfs-pinner v0.1.1 github.com/ipfs/go-ipfs-posinfo v0.0.1 github.com/ipfs/go-ipfs-provider v0.4.3 @@ -51,6 +48,7 @@ require ( github.com/ipfs/go-metrics-interface v0.0.1 github.com/ipfs/go-metrics-prometheus v0.0.2 github.com/ipfs/go-mfs v0.1.2 + github.com/ipfs/go-namesys v0.0.1 github.com/ipfs/go-path v0.0.9 github.com/ipfs/go-pinning-service-http-client v0.1.0 github.com/ipfs/go-unixfs v0.2.4 @@ -86,7 +84,6 @@ require ( github.com/libp2p/go-tcp-transport v0.2.1 github.com/libp2p/go-ws-transport v0.4.0 github.com/lucas-clemente/quic-go v0.19.3 - github.com/mattn/go-runewidth v0.0.9 // indirect github.com/mitchellh/go-homedir v1.1.0 github.com/multiformats/go-multiaddr v0.3.1 github.com/multiformats/go-multiaddr-dns v0.2.0 @@ -97,7 +94,6 @@ require ( github.com/prometheus/client_golang v1.9.0 github.com/stretchr/testify v1.7.0 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-20201201191210-20a61371de5b diff --git a/go.sum b/go.sum index 273db1cd0dc..b30a5ac5e5b 100644 --- a/go.sum +++ b/go.sum @@ -40,6 +40,7 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/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/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= @@ -73,11 +74,13 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +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/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= 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-20201027163346-95122a84635f h1:aYq2dAS53HXEmxlI9AAggLbqJS4DML1/H0+r59TH/vw= -github.com/bren2010/proquint v0.0.0-20201027163346-95122a84635f/go.mod h1:Jbj8eKecMNwf0KFI75skSUZqMB4UCRcndUScVBTWyUI= +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/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= @@ -171,6 +174,7 @@ github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:Jp github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/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/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNpjmVH56sVtS/RfclBAYocb4as= github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ= @@ -181,6 +185,7 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2 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/gabriel-vasile/mimetype v1.1.1/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To= github.com/gabriel-vasile/mimetype v1.1.2 h1:gaPnPcNor5aZSVCJVSGipcpbgMWiAAj9z182ocSGbHU= github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -285,6 +290,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpg github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824/go.mod h1:OiEWyHgK+CWrmOlVquHaIK1vhpUJydC9m0Je6mhaiNE= github.com/hannahhoward/cbor-gen-for v0.0.0-20200817222906-ea96cece81f1/go.mod h1:jvfsLIxk0fY/2BKSQ1xf2406AKA5dwMmKKv0ADcOfN8= github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e h1:3YKHER4nmd7b5qy5t0GWDTwSn4OyRgfAXSmo6VnryBY= github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e/go.mod h1:I8h3MITA53gN9OnWGCgaMa0JWVRdXthWw4M3CPM54OY= @@ -316,6 +322,7 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp 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/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= @@ -325,17 +332,20 @@ github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod 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.0.3/go.mod h1:jadAZYsP/tcRMl47ZhFxhaNuDQoXawT8iHMg+iFoQbg= 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.20/go.mod h1:C7TwBgHnu89Q8sHsTJP7IhUqF9XYLe71P4tT5adgmYo= github.com/ipfs/go-bitswap v0.3.3 h1:CrTO3OiOYFBcdliw074/C7T2QYHEOsPClgvR6RIYcO4= github.com/ipfs/go-bitswap v0.3.3/go.mod h1:AyWWfN3moBzQX0banEtfKOfbXb3ZeoOeXnZGNPV9S6w= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= github.com/ipfs/go-block-format v0.0.3 h1:r8t66QstRp/pd/or4dpnbVfXT5Gt7lOqRvC+/dDTpMc= github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= +github.com/ipfs/go-blockservice v0.0.3/go.mod h1:/NNihwTi6V2Yr6g8wBI+BSwPuURpBRMtYNGrlxZ8KuI= 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= @@ -371,6 +381,7 @@ github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaH github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= +github.com/ipfs/go-ds-badger v0.2.4/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= github.com/ipfs/go-ds-badger v0.2.6 h1:Hy8jw4rifxtRDrqpvC1yh36oIyE37KDzsUzlHUPOFiU= github.com/ipfs/go-ds-badger v0.2.6/go.mod h1:02rnztVKA4aZwDuaRPTf8mpqcKmXP7mLl6JPxd14JHA= github.com/ipfs/go-ds-flatfs v0.4.5 h1:4QceuKEbH+HVZ2ZommstJMi3o3II+dWS3IhLaD7IGHs= @@ -386,8 +397,10 @@ github.com/ipfs/go-filestore v0.0.3 h1:MhZ1jT5K3NewZwim6rS/akcJLm1xM+r6nz6foeB9E github.com/ipfs/go-filestore v0.0.3/go.mod h1:dvXRykFzyyXN2CdNlRGzDAkXMDPyI+D7JE066SiKLSE= github.com/ipfs/go-fs-lock v0.0.6 h1:sn3TWwNVQqSeNjlWy6zQ1uUGAZrV3hPOyEA6y1/N2a0= github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM= +github.com/ipfs/go-graphsync v0.1.1/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= github.com/ipfs/go-graphsync v0.7.0 h1:ZdyU2otZYPjcvduAPwVjCdijmkPtHI1mm1VyZbRQ5KI= github.com/ipfs/go-graphsync v0.7.0/go.mod h1:YRQg0TyvD2HzFansAZdMcUFBJ8zIJ4K+32kNdnHfHZc= +github.com/ipfs/go-ipfs v0.7.0/go.mod h1:4UNBZMgbAZ6/+xUZDlMkGxMFPiu1RB67+TaNVvKV7ZQ= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= github.com/ipfs/go-ipfs-blockstore v0.1.4 h1:2SGI6U1B44aODevza8Rde3+dY30Pb+lbcObe1LETxOQ= @@ -397,8 +410,10 @@ github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtL github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8= github.com/ipfs/go-ipfs-chunker v0.0.5/go.mod h1:jhgdF8vxRHycr00k13FM8Y0E+6BoalYeobXmUyTreP8= +github.com/ipfs/go-ipfs-cmds v0.4.0/go.mod h1:ZgYiWVnCk43ChwoH8hAmI1IRbuVtq3GSTHwtRB/Kqhk= github.com/ipfs/go-ipfs-cmds v0.6.0 h1:yAxdowQZzoFKjcLI08sXVNnqVj3jnABbf9smrPQmBsw= github.com/ipfs/go-ipfs-cmds v0.6.0/go.mod h1:ZgYiWVnCk43ChwoH8hAmI1IRbuVtq3GSTHwtRB/Kqhk= +github.com/ipfs/go-ipfs-config v0.9.0/go.mod h1:GQUxqb0NfkZmEU92PxqqqLVVFTLpoGGUlBaTyDaAqrE= github.com/ipfs/go-ipfs-config v0.12.0 h1:wxqN3ohBlis1EkhkzIKuF+XLx4YNn9rNpiSOYw3DFZc= github.com/ipfs/go-ipfs-config v0.12.0/go.mod h1:Ei/FLgHGTdPyqCPK0oPCwGTe8VSnsjJjx7HZqUb6Ry0= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= @@ -411,9 +426,14 @@ github.com/ipfs/go-ipfs-exchange-interface v0.0.1 h1:LJXIo9W7CAmugqI+uofioIpRb6r 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/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= github.com/ipfs/go-ipfs-files v0.0.3/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-keystore v0.0.2 h1:Fa9xg9IFD1VbiZtrNLzsD0GuELVHUFXCWF64kCPfEXU= +github.com/ipfs/go-ipfs-keystore v0.0.2/go.mod h1:H49tRmibOEs7gLMgbOsjC4dqh1u5e0R/SWuc2ScfgSo= +github.com/ipfs/go-ipfs-pinner v0.0.4/go.mod h1:s4kFZWLWGDudN8Jyd/GTpt222A12C2snA2+OTdy/7p8= github.com/ipfs/go-ipfs-pinner v0.1.1 h1:iJd1gwILGQJSZhhI0jn6yFOLg34Ua7fdKcB6mXp6k/M= github.com/ipfs/go-ipfs-pinner v0.1.1/go.mod h1:EzyyaWCWeZJ/he9cDBH6QrEkSuRqTRWMmCoyNkylTTg= github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= @@ -429,6 +449,7 @@ github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42 github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= +github.com/ipfs/go-ipld-cbor v0.0.1/go.mod h1:RXHr8s4k0NE0TKhnrxqZC9M888QfsBN9rhS5NjfKzY8= github.com/ipfs/go-ipld-cbor v0.0.2/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc= github.com/ipfs/go-ipld-cbor v0.0.3/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc= github.com/ipfs/go-ipld-cbor v0.0.4/go.mod h1:BkCduEx3XBCO6t2Sfo5BaHzuok7hbhdMm9Oh8B2Ftq4= @@ -454,6 +475,7 @@ github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBW github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= github.com/ipfs/go-log/v2 v2.1.1 h1:G4TtqN+V9y9HY9TA6BwbCVyyBZ2B9MbCjR2MtGx8FR0= github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= +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/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= @@ -467,7 +489,11 @@ github.com/ipfs/go-metrics-prometheus v0.0.2 h1:9i2iljLg12S78OhC6UAiXi176xvQGiZa github.com/ipfs/go-metrics-prometheus v0.0.2/go.mod h1:ELLU99AQQNi+zX6GCGm2lAgnzdSH3u5UVlCdqSXnEks= github.com/ipfs/go-mfs v0.1.2 h1:DlelNSmH+yz/Riy0RjPKlooPg0KML4lXGdLw7uZkfAg= github.com/ipfs/go-mfs v0.1.2/go.mod h1:T1QBiZPEpkPLzDqEJLNnbK55BVKVlNi2a+gVm4diFo0= +github.com/ipfs/go-namesys v0.0.1 h1:HmhgHDA2hyfVtFtbvPR92IdmKbUFRmlbU0Lv1IwmDas= +github.com/ipfs/go-namesys v0.0.1/go.mod h1:I33kVZixNRWXe5FN1mpWBXsAeJj0t+kxcVDgbIkgE2E= +github.com/ipfs/go-path v0.0.3/go.mod h1:zIRQUez3LuQIU25zFjC2hpBTHimWx7VK5bjZgRLbbdo= github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd2Sno= +github.com/ipfs/go-path v0.0.8/go.mod h1:VpDkSBKQ9EFQOUgi54Tq/O/tGi8n1RfYNks13M3DEs8= github.com/ipfs/go-path v0.0.9 h1:BIi831cNED8YnIlIKo9y1SI3u+E+FwQQD+rIIw8PwFA= github.com/ipfs/go-path v0.0.9/go.mod h1:VpDkSBKQ9EFQOUgi54Tq/O/tGi8n1RfYNks13M3DEs8= github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP1MX6Kd+aN+rMQ= @@ -477,19 +503,25 @@ github.com/ipfs/go-peertaskqueue v0.2.0 h1:2cSr7exUGKYyDeUyQ7P/nHPs9P7Ht/B+ROrpN github.com/ipfs/go-peertaskqueue v0.2.0/go.mod h1:5/eNrBEbtSKWCG+kQK8K8fGNixoYUnr+P7jivavs9lY= github.com/ipfs/go-pinning-service-http-client v0.1.0 h1:Au0P4NglL5JfzhNSZHlZ1qra+IcJyO3RWMd9EYCwqSY= github.com/ipfs/go-pinning-service-http-client v0.1.0/go.mod h1:tcCKmlkWWH9JUUkKs8CrOZBanacNc1dmKLfjlyXAMu4= +github.com/ipfs/go-unixfs v0.0.4/go.mod h1:eIo/p9ADu/MFOuyxzwU+Th8D6xoxU//r590vUpWyfz8= github.com/ipfs/go-unixfs v0.1.0/go.mod h1:lysk5ELhOso8+Fed9U1QTGey2ocsfaZ18h0NCO2Fj9s= 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.3.0/go.mod h1:Tihp8zxGpUeE3Tokr94L6zWZZdkRQvG5TL6i9MuNE+s= github.com/ipfs/interface-go-ipfs-core v0.4.0 h1:+mUiamyHIwedqP8ZgbCIwpy40oX7QcXUbo4CZOeJVJg= github.com/ipfs/interface-go-ipfs-core v0.4.0/go.mod h1:UJBcU6iNennuI05amq3FQ7g0JHUkibHFAfhfUIy927o= +github.com/ipld/go-car v0.1.1-0.20200429200904-c222d793c339/go.mod h1:eajxljm6I8o3LitnFeVEmucwZmz7+yLSiKce9yYMefg= github.com/ipld/go-car v0.2.0 h1:WwP83IdXdEuaW4fkCj+DWmdWygcFXpixramvItqFo1A= github.com/ipld/go-car v0.2.0/go.mod h1:pPb7hzVBHBoRqU3GkPy1d6FZKQoGQ56yd3MyPGzZ0Xs= +github.com/ipld/go-ipld-prime v0.0.2-0.20200428162820-8b59dc292b8e/go.mod h1:uVIwe/u0H4VdKv3kaN1ck7uCb6yD9cFLS9/ELyXbsw8= github.com/ipld/go-ipld-prime v0.7.0 h1:eigF1ZpaL1prbsKYVMqPLoPJqD/pzkQOe2j1uzvVg7w= github.com/ipld/go-ipld-prime v0.7.0/go.mod h1:0xEgdD6MKbZ1vF0GC+YcR/C4SQCAlRuOjIJ2i0HxqzM= +github.com/ipld/go-ipld-prime-proto v0.0.0-20200428191222-c1ffdadc01e1/go.mod h1:OAV6xBmuTLsPZ+epzKkPB1e25FHk/vCtyatkdHcArLs= github.com/ipld/go-ipld-prime-proto v0.1.1 h1:EX4yWYaIqSLwtVE30nxEcZDcvsWDtx1vImSG+XCJebY= github.com/ipld/go-ipld-prime-proto v0.1.1/go.mod h1:cI9NwYAUKCLUwqufoUjChISxuTEkaY2yvNYCRCuhRck= +github.com/jackpal/gateway v1.0.4/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= @@ -556,6 +588,7 @@ github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoR github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= github.com/libp2p/go-conn-security v0.0.1/go.mod h1:bGmu51N0KU9IEjX7kl2PQjgZa40JQWnayTvNMgD/vyk= +github.com/libp2p/go-conn-security-multistream v0.0.1/go.mod h1:nc9vud7inQ+d6SO0I/6dSWrdMnHnzZNHeyUQqrAJulE= github.com/libp2p/go-conn-security-multistream v0.0.2/go.mod h1:nc9vud7inQ+d6SO0I/6dSWrdMnHnzZNHeyUQqrAJulE= github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= github.com/libp2p/go-conn-security-multistream v0.2.0 h1:uNiDjS58vrvJTg9jO6bySd1rMKejieG7v45ekqHbZ1M= @@ -567,35 +600,45 @@ github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZ 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/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.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM= github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8= +github.com/libp2p/go-libp2p v0.6.0/go.mod h1:mfKWI7Soz3ABX+XEBR61lGbg+ewyMtJHVt043oWeqwg= github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZkfEI5sT54= github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= +github.com/libp2p/go-libp2p v0.8.3/go.mod h1:EsH1A+8yoWK+L4iKcbPYu6MPluZ+CHWI9El8cTaefiM= +github.com/libp2p/go-libp2p v0.11.0/go.mod h1:3/ogJDXsbbepEfqtZKBR/DedzxJXCeK17t2Z9RE9bEE= github.com/libp2p/go-libp2p v0.12.0/go.mod h1:FpHZrfC1q7nA8jitvdjKBDF31hguaC676g/nT9PgQM0= github.com/libp2p/go-libp2p v0.13.0 h1:tDdrXARSghmusdm0nf1U/4M8aj8Rr0V2IzQOXmbzQ3s= github.com/libp2p/go-libp2p v0.13.0/go.mod h1:pM0beYdACRfHO1WcJlp65WXyG2A6NqYM+t2DTVAJxMo= github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052 h1:BM7aaOF7RpmNn9+9g6uTjGJ0cTzWr5j9i9IKeun2M8U= github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= +github.com/libp2p/go-libp2p-autonat v0.0.2/go.mod h1:fs71q5Xk+pdnKU014o2iq1RhMs9/PMaG5zXRFNnIIT4= github.com/libp2p/go-libp2p-autonat v0.0.6/go.mod h1:uZneLdOkZHro35xIhpbtTzLlgYturpu4J5+0cZK3MqE= github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= github.com/libp2p/go-libp2p-autonat v0.2.1/go.mod h1:MWtAhV5Ko1l6QBsHQNSuM6b1sRkXrpk0/LqCr+vCVxI= github.com/libp2p/go-libp2p-autonat v0.2.2/go.mod h1:HsM62HkqZmHR2k1xgX34WuWDzk/nBwNHoeyyT4IWV6A= +github.com/libp2p/go-libp2p-autonat v0.3.2/go.mod h1:0OzOi1/cVc7UcxfOddemYD5vzEqi4fwRbnZcJGLi68U= github.com/libp2p/go-libp2p-autonat v0.4.0 h1:3y8XQbpr+ssX8QfZUHekjHCYK64sj6/4hnf/awD4+Ug= github.com/libp2p/go-libp2p-autonat v0.4.0/go.mod h1:YxaJlpr81FhdOv3W3BTconZPfhaYivRdf53g+S2wobk= github.com/libp2p/go-libp2p-blankhost v0.0.1/go.mod h1:Ibpbw/7cPPYwFb7PACIWdvxxv0t0XCCI10t7czjAjTc= github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU= +github.com/libp2p/go-libp2p-blankhost v0.1.6/go.mod h1:jONCAJqEP+Z8T6EQviGL4JsQcLx1LgTGtVqFNY8EMfQ= github.com/libp2p/go-libp2p-blankhost v0.2.0 h1:3EsGAi0CBGcZ33GwRuXEYJLLPoVWyXJ1bcJzAJjINkk= github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= +github.com/libp2p/go-libp2p-circuit v0.0.1/go.mod h1:Dqm0s/BiV63j8EEAs8hr1H5HudqvCAeXxDyic59lCwE= github.com/libp2p/go-libp2p-circuit v0.0.9/go.mod h1:uU+IBvEQzCu953/ps7bYzC/D/R0Ho2A9LfKVVCatlqU= github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= github.com/libp2p/go-libp2p-circuit v0.1.4/go.mod h1:CY67BrEjKNDhdTk8UgBX1Y/H5c3xkAcs3gnksxY7osU= github.com/libp2p/go-libp2p-circuit v0.2.1/go.mod h1:BXPwYDN5A8z4OEY9sOfr2DUQMLQvKt/6oku45YUmjIo= +github.com/libp2p/go-libp2p-circuit v0.2.2/go.mod h1:nkG3iE01tR3FoQ2nMm06IUrCpCyJp1Eo4A1xYdpjfs4= +github.com/libp2p/go-libp2p-circuit v0.3.1/go.mod h1:8RMIlivu1+RxhebipJwFDA45DasLx+kkrp4IlJj53F4= github.com/libp2p/go-libp2p-circuit v0.4.0 h1:eqQ3sEYkGTtybWgr6JLqJY6QLtPWRErvFjFDfAOO1wc= github.com/libp2p/go-libp2p-circuit v0.4.0/go.mod h1:t/ktoFIUzM6uLQ+o1G6NuBl2ANhBKN9Bc8jRIk31MoA= github.com/libp2p/go-libp2p-connmgr v0.2.4 h1:TMS0vc0TCBomtQJyWr7fYxcVYYhx+q/2gF++G5Jkl/w= @@ -613,6 +656,7 @@ github.com/libp2p/go-libp2p-core v0.3.1/go.mod h1:thvWy0hvaSBhnVBaW37BvzgVV68OUh github.com/libp2p/go-libp2p-core v0.4.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= github.com/libp2p/go-libp2p-core v0.5.1/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= +github.com/libp2p/go-libp2p-core v0.5.2/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= github.com/libp2p/go-libp2p-core v0.5.3/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= github.com/libp2p/go-libp2p-core v0.5.4/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= github.com/libp2p/go-libp2p-core v0.5.5/go.mod h1:vj3awlOr9+GMZJFH9s4mpt9RHHgGqeHCopzbYKZdRjM= @@ -628,22 +672,27 @@ github.com/libp2p/go-libp2p-core v0.8.5/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJB github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE= github.com/libp2p/go-libp2p-crypto v0.0.2/go.mod h1:eETI5OUfBnvARGOHrJz2eWNyTUxEGZnBxMcbUjfIj4I= github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= +github.com/libp2p/go-libp2p-discovery v0.0.1/go.mod h1:ZkkF9xIFRLA1xCc7bstYFkd80gBGK8Fc1JqGoU2i+zI= github.com/libp2p/go-libp2p-discovery v0.0.5/go.mod h1:YtF20GUxjgoKZ4zmXj8j3Nb2TUSBHFlOCetzYdbZL5I= github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g= github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg= github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw= +github.com/libp2p/go-libp2p-discovery v0.4.0/go.mod h1:bZ0aJSrFc/eX2llP0ryhb1kpgkPyTo23SJ5b7UQCMh4= github.com/libp2p/go-libp2p-discovery v0.5.0 h1:Qfl+e5+lfDgwdrXdu4YNCWyEo3fWuP+WgN9mN0iWviQ= github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= +github.com/libp2p/go-libp2p-gostream v0.2.1/go.mod h1:1Mjp3LDmkqICe5tH9yLVNCqFaRTy6OwBvuJV6j1b9Nk= github.com/libp2p/go-libp2p-gostream v0.3.0 h1:rnas//vRdHYCr7bjraZJISPwZV8OGMjeX5k5fN5Ax44= github.com/libp2p/go-libp2p-gostream v0.3.0/go.mod h1:pLBQu8db7vBMNINGsAwLL/ZCE8wng5V1FThoaE5rNjc= github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= github.com/libp2p/go-libp2p-host v0.0.3/go.mod h1:Y/qPyA6C8j2coYyos1dfRm0I8+nvd4TGrDGt4tA7JR8= +github.com/libp2p/go-libp2p-http v0.1.5/go.mod h1:2YfPjsQxUlBGFQl2u461unkQ7ukwiSs7NX2eSslOJiU= github.com/libp2p/go-libp2p-http v0.2.0 h1:GYeVd+RZzkRa8XFLITqOpcrIQG6KbFLPJqII6HHBHzY= github.com/libp2p/go-libp2p-http v0.2.0/go.mod h1:GlNKFqDZHe25LVy2CvnZKx75/jLtMaD3VxZV6N39X7E= github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= github.com/libp2p/go-libp2p-interface-connmgr v0.0.4/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= github.com/libp2p/go-libp2p-interface-connmgr v0.0.5/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= github.com/libp2p/go-libp2p-interface-pnet v0.0.1/go.mod h1:el9jHpQAXK5dnTpKA4yfCNBZXvrzdOU75zz+C6ryp3k= +github.com/libp2p/go-libp2p-kad-dht v0.9.0/go.mod h1:LEKcCFHxnvypOPaqZ0m6h0fLQ9Y8t1iZMOg7a0aQDD4= github.com/libp2p/go-libp2p-kad-dht v0.11.1 h1:FsriVQhOUZpCotWIjyFSjEDNJmUzuMma/RyyTDZanwc= github.com/libp2p/go-libp2p-kad-dht v0.11.1/go.mod h1:5ojtR2acDPqh/jXf5orWy8YGb8bHQDS+qeDcoscL/PI= github.com/libp2p/go-libp2p-kbucket v0.4.7 h1:spZAcgxifvFZHBD8tErvppbnNiKA5uokDu3CV7axu70= @@ -657,10 +706,12 @@ github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3 github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= github.com/libp2p/go-libp2p-mplex v0.2.2/go.mod h1:74S9eum0tVQdAfFiKxAyKzNdSuLqw5oadDq7+L/FELo= github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxWDkm+dVvjfuG3ek= +github.com/libp2p/go-libp2p-mplex v0.2.4/go.mod h1:mI7iOezdWFOisvUwaYd3IDrJ4oVmgoXK8H331ui39CE= github.com/libp2p/go-libp2p-mplex v0.3.0/go.mod h1:l9QWxRbbb5/hQMECEb908GbS9Sm2UAR2KFZKUJEynEs= github.com/libp2p/go-libp2p-mplex v0.4.0/go.mod h1:yCyWJE2sc6TBTnFpjvLuEJgTSw/u+MamvzILKdX7asw= github.com/libp2p/go-libp2p-mplex v0.4.1 h1:/pyhkP1nLwjG3OM+VuaNJkQT/Pqq73WzB3aDN3Fx1sc= github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= +github.com/libp2p/go-libp2p-nat v0.0.2/go.mod h1:QrjXQSD5Dj4IJOdEcjHRkWTSomyxRo6HnUkf/TfQpLQ= github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= github.com/libp2p/go-libp2p-nat v0.0.6 h1:wMWis3kYynCbHoyKLPBEMu4YRLltbm8Mk08HGSfvTkU= @@ -684,17 +735,23 @@ github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVd github.com/libp2p/go-libp2p-peerstore v0.2.0/go.mod h1:N2l3eVIeAitSg3Pi2ipSrJYnqhVnMNQZo9nkSCuAbnQ= github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= +github.com/libp2p/go-libp2p-peerstore v0.2.3/go.mod h1:K8ljLdFn590GMttg/luh4caB/3g0vKuY01psze0upRw= +github.com/libp2p/go-libp2p-peerstore v0.2.4/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s= github.com/libp2p/go-libp2p-peerstore v0.2.6 h1:2ACefBX23iMdJU9Ke+dcXt3w86MIryes9v7In4+Qq3U= github.com/libp2p/go-libp2p-peerstore v0.2.6/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s= 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-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= +github.com/libp2p/go-libp2p-pubsub v0.3.2/go.mod h1:Uss7/Cfz872KggNb+doCVPHeCDmXB7z500m/R8DaAUk= +github.com/libp2p/go-libp2p-pubsub v0.3.5/go.mod h1:DTMSVmZZfXodB/pvdTGrY2eHPZ9W2ev7hzTH83OKHrI= github.com/libp2p/go-libp2p-pubsub v0.4.0/go.mod h1:izkeMLvz6Ht8yAISXjx60XUQZMq9ZMe5h2ih4dLIBIQ= github.com/libp2p/go-libp2p-pubsub v0.4.1 h1:j4umIg5nyus+sqNfU+FWvb9aeYFQH/A+nDFhWj+8yy8= github.com/libp2p/go-libp2p-pubsub v0.4.1/go.mod h1:izkeMLvz6Ht8yAISXjx60XUQZMq9ZMe5h2ih4dLIBIQ= +github.com/libp2p/go-libp2p-pubsub-router v0.3.2/go.mod h1:G4MAvYzPxhoR0LEBluS9Ow+Nnr/8iDalUN+RNwVgNkY= github.com/libp2p/go-libp2p-pubsub-router v0.4.0 h1:KjzTLIOBCt0+/4wH6epTxD/Qu4Up/IyeKHlj9MhWRJI= github.com/libp2p/go-libp2p-pubsub-router v0.4.0/go.mod h1:hs0j0ugcBjMOMgJ6diOlZM2rZEId/w5Gg86E+ac4SmQ= +github.com/libp2p/go-libp2p-quic-transport v0.8.0/go.mod h1:F2FG/6Bzz0U6essUVxDzE0s9CrY4XGLbl7QEmDNvU7A= github.com/libp2p/go-libp2p-quic-transport v0.10.0 h1:koDCbWD9CCHwcHZL3/WEvP2A+e/o5/W5L3QS/2SPMA0= github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q= @@ -706,15 +763,18 @@ github.com/libp2p/go-libp2p-record v0.1.3/go.mod h1:yNUff/adKIfPnYQXgp6FQmNu3gLJ github.com/libp2p/go-libp2p-routing v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= github.com/libp2p/go-libp2p-routing-helpers v0.2.3 h1:xY61alxJ6PurSi+MXbywZpelvuU4U4p/gPTxjqCqTzY= github.com/libp2p/go-libp2p-routing-helpers v0.2.3/go.mod h1:795bh+9YeoFl99rMASoiVgHdi5bjack0N1+AFAdbvBw= +github.com/libp2p/go-libp2p-secio v0.0.1/go.mod h1:IdG6iQybdcYmbTzxp4J5dwtUEDTOvZrT0opIDVNPrJs= github.com/libp2p/go-libp2p-secio v0.0.3/go.mod h1:hS7HQ00MgLhRO/Wyu1bTX6ctJKhVpm+j2/S2A5UqYb0= github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= github.com/libp2p/go-libp2p-secio v0.2.1/go.mod h1:cWtZpILJqkqrSkiYcDBh5lA3wbT2Q+hz3rJQq3iftD8= github.com/libp2p/go-libp2p-secio v0.2.2/go.mod h1:wP3bS+m5AUnFA+OFO7Er03uO1mncHG0uVwGrwvjYlNY= +github.com/libp2p/go-libp2p-swarm v0.0.1/go.mod h1:mh+KZxkbd3lQnveQ3j2q60BM1Cw2mX36XXQqwfPOShs= github.com/libp2p/go-libp2p-swarm v0.0.6/go.mod h1:s5GZvzg9xXe8sbeESuFpjt8CJPTCa8mhEusweJqyFy8= github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU= github.com/libp2p/go-libp2p-swarm v0.2.3/go.mod h1:P2VO/EpxRyDxtChXz/VPVXyTnszHvokHKRhfkEgFKNM= +github.com/libp2p/go-libp2p-swarm v0.2.4/go.mod h1:/xIpHFPPh3wmSthtxdGbkHZ0OET1h/GGZes8Wku/M5Y= github.com/libp2p/go-libp2p-swarm v0.2.8/go.mod h1:JQKMGSth4SMqonruY0a8yjlPVIkb0mdNSwckW7OYziM= github.com/libp2p/go-libp2p-swarm v0.3.0/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= github.com/libp2p/go-libp2p-swarm v0.3.1/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= @@ -728,13 +788,16 @@ github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MB github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= +github.com/libp2p/go-libp2p-testing v0.2.0/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= github.com/libp2p/go-libp2p-testing v0.3.0/go.mod h1:efZkql4UZ7OVsEfaxNHZPzIehtsBXMrXnCfJIgDti5g= github.com/libp2p/go-libp2p-testing v0.4.0 h1:PrwHRi0IGqOwVQWR3xzgigSlhlLfxgfXgkHxr77EghQ= github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= 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/go.mod h1:StoY3sx6IqsP6XKoabsPnHCwqKXWUMWU7Rfcsubee/A= github.com/libp2p/go-libp2p-transport v0.0.5/go.mod h1:StoY3sx6IqsP6XKoabsPnHCwqKXWUMWU7Rfcsubee/A= +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/go.mod h1:RGq+tupk+oj7PzL2kn/m1w6YXxcIAYJYeI90h6BGgUc= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= github.com/libp2p/go-libp2p-transport-upgrader v0.2.0/go.mod h1:mQcrHj4asu6ArfSoMuyojOdjx73Q47cYD7s5+gZOlns= @@ -757,6 +820,7 @@ github.com/libp2p/go-maddr-filter v0.0.1/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9 github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M= github.com/libp2p/go-maddr-filter v0.1.0/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= +github.com/libp2p/go-mplex v0.0.1/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= github.com/libp2p/go-mplex v0.0.4/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= @@ -765,6 +829,7 @@ github.com/libp2p/go-mplex v0.1.2/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3 github.com/libp2p/go-mplex v0.2.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= github.com/libp2p/go-mplex v0.3.0 h1:U1T+vmCYJaEoDJPV1aq31N56hS+lJgb397GsylNSgrU= github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= +github.com/libp2p/go-msgio v0.0.1/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.3/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= @@ -786,6 +851,7 @@ github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= github.com/libp2p/go-reuseport v0.0.2 h1:XSG94b1FJfGA01BUrT82imejHQyTxO4jEWqheyCXYvU= github.com/libp2p/go-reuseport v0.0.2/go.mod h1:SPD+5RwGC7rcnzngoYC86GjPzjSywuQyMVAheVBD9nQ= +github.com/libp2p/go-reuseport-transport v0.0.1/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= github.com/libp2p/go-reuseport-transport v0.0.3/go.mod h1:Spv+MPft1exxARzP2Sruj2Wb5JSyHNncjf1Oi2dEbzM= github.com/libp2p/go-reuseport-transport v0.0.4 h1:OZGz0RB620QDGpv300n1zaOcKGGAoGVf8h9txtt/1uM= @@ -800,6 +866,7 @@ github.com/libp2p/go-stream-muxer-multistream v0.1.1/go.mod h1:zmGdfkQ1AzOECIAcc 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/go.mod h1:+E8HvC8ezEVOxIo3V5vCK9l1y/19K427vCzQ+xHKH/o= github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= @@ -808,6 +875,7 @@ github.com/libp2p/go-tcp-transport v0.2.1 h1:ExZiVQV+h+qL16fzCWtd1HSzPsqWottJ8KX github.com/libp2p/go-tcp-transport v0.2.1/go.mod h1:zskiJ70MEfWz2MKxvFB/Pv+tPIB1PpPUrHIWQ8aFw7M= github.com/libp2p/go-testutil v0.0.1/go.mod h1:iAcJc/DKJQanJ5ws2V+u5ywdL2n12X1WbbEG+Jjy69I= github.com/libp2p/go-testutil v0.1.0/go.mod h1:81b2n5HypcVyrCg/MJx4Wgfp/VHojytjVe/gLzZ2Ehc= +github.com/libp2p/go-ws-transport v0.0.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.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo= github.com/libp2p/go-ws-transport v0.2.0/go.mod h1:9BHJz/4Q5A9ludYWKoGCFC5gUElzlHoKzu0yY9p/klM= @@ -829,6 +897,7 @@ github.com/libp2p/go-yamux/v2 v2.0.0 h1:vSGhAy5u6iHBq11ZDcyHH4Blcf9xlBhT4WQDoOE9 github.com/libp2p/go-yamux/v2 v2.0.0/go.mod h1:NVWira5+sVUIU6tu1JWvaRn1dRnG+cawOJiflsAM+7U= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lucas-clemente/quic-go v0.18.0/go.mod h1:yXttHsSNxQi8AWijC/vLP+OJczXqzHSOcJrM5ITUlCg= github.com/lucas-clemente/quic-go v0.19.3 h1:eCDQqvGBB+kCTkA0XrAFtNe81FMa0/fn4QSoeAbmiF4= github.com/lucas-clemente/quic-go v0.19.3/go.mod h1:ADXpNbTQjq1hIzCpB+y/k5iz4n4z4IwqoLb94Kh5Hu8= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= @@ -836,9 +905,11 @@ github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0Q github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/marten-seemann/qpack v0.2.0/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= github.com/marten-seemann/qtls v0.10.0 h1:ECsuYUKalRL240rRD4Ri33ISb7kAQ3qGDlrrl55b2pc= github.com/marten-seemann/qtls v0.10.0/go.mod h1:UvMd1oaYDACI99/oZUYLzMCkBXQVT0aGm99sJhbT8hs= +github.com/marten-seemann/qtls-go1-15 v0.1.0/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= github.com/marten-seemann/qtls-go1-15 v0.1.1 h1:LIH6K34bPVttyXnUWixk0bzH6/N07VxbSabxn5A5gZQ= github.com/marten-seemann/qtls-go1-15 v0.1.1/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -862,6 +933,7 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1f github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.31 h1:sJFOl9BgwbYAWOGEwr61FU28pqsBNdpRBnhGXtO06Oo= @@ -925,10 +997,12 @@ github.com/multiformats/go-multiaddr-net v0.1.5/go.mod h1:ilNnaM9HbmVFqsb/qcNysj github.com/multiformats/go-multiaddr-net v0.2.0 h1:MSXRGN0mFymt6B1yo/6BPnIRpLPEnKgQNvVfCX5VDJk= github.com/multiformats/go-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= +github.com/multiformats/go-multibase v0.0.2/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= 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/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.9/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= @@ -939,6 +1013,7 @@ github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wS github.com/multiformats/go-multistream v0.0.4/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= +github.com/multiformats/go-multistream v0.1.2/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= github.com/multiformats/go-multistream v0.2.0 h1:6AuNmQVKUkRnddw2YiDjt5Elit40SFxMJkVnhmETXtU= github.com/multiformats/go-multistream v0.2.0/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= @@ -1004,6 +1079,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= +github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e h1:ZOcivgkkFRnjfoTcGsDq3UQYiBmekwLA+qg0OjyB/ls= github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -1090,6 +1166,7 @@ github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHei github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= @@ -1145,6 +1222,7 @@ github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvS github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4= github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= +github.com/whyrusleeping/cbor-gen v0.0.0-20200402171437-3d27c146c105/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= github.com/whyrusleeping/cbor-gen v0.0.0-20200710004633-5379fc63235d/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2 h1:bsUlNhdmbtlfdLVXAVfuvKQ01RnWAM09TVrJkI7NZs4= github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= @@ -1155,6 +1233,10 @@ github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= github.com/whyrusleeping/go-logging v0.0.1/go.mod h1:lDPYj54zutzG1XYfHAhcc7oNXEburHQBn+Iqd4yS4vE= github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8= +github.com/whyrusleeping/go-smux-multiplex v3.0.16+incompatible/go.mod h1:34LEDbeKFZInPUrAG+bjuJmUXONGdEFW7XL0SpTY1y4= +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/go.mod h1:6qHUzBXUbB9MXmw3AUdB52L8sEb/hScCqOdW2kj/wuI= +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/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= @@ -1163,10 +1245,12 @@ github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9 h1:Y1/FEOpaCpD2 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/go.mod h1:xxcJeBb7SIUl/Wzkz1eVKJE/CB34YNrqX2TQI6jY9zs= github.com/whyrusleeping/tar-utils v0.0.0-20201201191210-20a61371de5b h1:wA3QeTsaAXybLL2kb2cKhCAQTHgYTMwuI8lBlJSv5V8= github.com/whyrusleeping/tar-utils v0.0.0-20201201191210-20a61371de5b/go.mod h1:xT1Y5p2JR2PfSZihE0s4mjdJaRGp1waCTf5JzhQLBck= 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/go.mod h1:E8LnQQ8HKx5KD29HZFUwM1PxCOdPRzGwur1mcYhXcD8= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= @@ -1237,6 +1321,7 @@ golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= @@ -1261,6 +1346,7 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= @@ -1272,6 +1358,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +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= @@ -1327,7 +1414,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1378,11 +1464,11 @@ golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1438,6 +1524,7 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1-0.20210225150353-54dc8c5edb56 h1:g3QwFWCjsUzBtcQIcI+CYmiL/0i0BxTJjQp54GGDLEM= @@ -1523,6 +1610,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 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.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= diff --git a/keystore/keystore.go b/keystore/keystore.go deleted file mode 100644 index 9b2109ccdf2..00000000000 --- a/keystore/keystore.go +++ /dev/null @@ -1,189 +0,0 @@ -package keystore - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strings" - - base32 "encoding/base32" - - logging "github.com/ipfs/go-log" - 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 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 - // Get retrieves a key from the Keystore if it exists, and returns ErrNoSuchKey - // otherwise. - Get(string) (ci.PrivKey, error) - // Delete removes a key from the Keystore - Delete(string) error - // List returns a list of key identifier - 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 -} - -// NewFSKeystore returns a new filesystem-backed keystore. -func NewFSKeystore(dir string) (*FSKeystore, error) { - 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 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) - - if os.IsNotExist(err) { - return false, 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 { - name, err := encode(name) - if err != nil { - return err - } - - b, err := ci.MarshalPrivateKey(k) - if err != nil { - return err - } - - kp := filepath.Join(ks.dir, name) - - 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() - - _, err = fi.Write(b) - - return err -} - -// Get retrieves a key from the Keystore if it exists, and returns ErrNoSuchKey -// otherwise. -func (ks *FSKeystore) Get(name string) (ci.PrivKey, error) { - name, err := encode(name) - if err != nil { - return nil, err - } - - kp := filepath.Join(ks.dir, name) - - data, err := ioutil.ReadFile(kp) - if err != nil { - if os.IsNotExist(err) { - return nil, ErrNoSuchKey - } - return nil, err - } - - return ci.UnmarshalPrivateKey(data) -} - -// Delete removes a key from the Keystore -func (ks *FSKeystore) Delete(name string) error { - name, err := encode(name) - if err != nil { - return err - } - - kp := filepath.Join(ks.dir, name) - - return os.Remove(kp) -} - -// List return a list of key identifier -func (ks *FSKeystore) List() ([]string, error) { - dir, err := os.Open(ks.dir) - if err != nil { - return nil, err - } - - dirs, err := dir.Readdirnames(0) - if err != nil { - return nil, err - } - - list := make([]string, 0, len(dirs)) - - for _, name := range dirs { - decodedName, err := decode(name) - if err == nil { - list = append(list, decodedName) - } else { - 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 deleted file mode 100644 index 06f2fccc533..00000000000 --- a/keystore/keystore_test.go +++ /dev/null @@ -1,278 +0,0 @@ -package keystore - -import ( - "fmt" - "io/ioutil" - "math/rand" - "os" - "path/filepath" - "sort" - "testing" - - ci "github.com/libp2p/go-libp2p-core/crypto" -) - -type rr struct{} - -func (rr rr) Read(b []byte) (int, error) { - return rand.Read(b) -} - -func privKeyOrFatal(t *testing.T) ci.PrivKey { - priv, _, err := ci.GenerateEd25519Key(rr{}) - if err != nil { - t.Fatal(err) - } - return priv -} - -func TestKeystoreBasics(t *testing.T) { - tdir, err := ioutil.TempDir("", "keystore-test") - if err != nil { - t.Fatal(err) - } - - ks, err := NewFSKeystore(tdir) - if err != nil { - t.Fatal(err) - } - - l, err := ks.List() - if err != nil { - t.Fatal(err) - } - - if len(l) != 0 { - t.Fatal("expected no keys") - } - - k1 := privKeyOrFatal(t) - k2 := privKeyOrFatal(t) - k3 := privKeyOrFatal(t) - k4 := privKeyOrFatal(t) - - err = ks.Put("foo", k1) - if err != nil { - t.Fatal(err) - } - - err = ks.Put("bar", k2) - if err != nil { - t.Fatal(err) - } - - l, err = ks.List() - if err != nil { - t.Fatal(err) - } - - sort.Strings(l) - if l[0] != "bar" || l[1] != "foo" { - t.Fatal("wrong entries listed") - } - - if err := assertDirContents(tdir, []string{"foo", "bar"}); err != nil { - t.Fatal(err) - } - - err = ks.Put("foo", k3) - if err == nil { - t.Fatal("should not be able to overwrite key") - } - - if err := assertDirContents(tdir, []string{"foo", "bar"}); err != nil { - t.Fatal(err) - } - - exist, err := ks.Has("foo") - if !exist { - t.Fatal("should know it has a key named foo") - } - if err != nil { - t.Fatal(err) - } - - exist, err = ks.Has("nonexistingkey") - if exist { - t.Fatal("should know it doesn't have a key named nonexistingkey") - } - if err != nil { - t.Fatal(err) - } - - if err := ks.Delete("bar"); err != nil { - t.Fatal(err) - } - - if err := assertDirContents(tdir, []string{"foo"}); err != nil { - t.Fatal(err) - } - - if err := ks.Put("beep", k3); err != nil { - t.Fatal(err) - } - - if err := ks.Put("boop", k4); err != nil { - t.Fatal(err) - } - - if err := assertDirContents(tdir, []string{"foo", "beep", "boop"}); err != nil { - t.Fatal(err) - } - - if err := assertGetKey(ks, "foo", k1); err != nil { - t.Fatal(err) - } - - if err := assertGetKey(ks, "beep", k3); err != nil { - t.Fatal(err) - } - - if err := assertGetKey(ks, "boop", k4); err != nil { - t.Fatal(err) - } - - if err := ks.Put("..///foo/", k1); err != nil { - t.Fatal(err) - } - - if err := ks.Put("", k1); err == nil { - t.Fatal("shouldn't be able to put a key with no name") - } - - if err := ks.Put(".foo", k1); err != nil { - t.Fatal(err) - } -} - -func TestInvalidKeyFiles(t *testing.T) { - tdir, err := ioutil.TempDir("", "keystore-test") - - if err != nil { - t.Fatal(err) - } - - defer os.RemoveAll(tdir) - - ks, err := NewFSKeystore(tdir) - if err != nil { - t.Fatal(err) - } - - key := privKeyOrFatal(t) - - bytes, err := key.Bytes() - if err != nil { - t.Fatal(err) - } - - encodedName, err := encode("valid") - if err != nil { - t.Fatal(err) - } - - 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) - } - - l, err := ks.List() - if err != nil { - t.Fatal(err) - } - - sort.Strings(l) - if len(l) != 1 { - t.Fatal("wrong entry count") - } - - if l[0] != "valid" { - t.Fatal("wrong entries listed") - } - - exist, err := ks.Has("valid") - if !exist { - t.Fatal("should know it has a key named valid") - } - if err != nil { - t.Fatal(err) - } -} - -func TestNonExistingKey(t *testing.T) { - tdir, err := ioutil.TempDir("", "keystore-test") - if err != nil { - t.Fatal(err) - } - - ks, err := NewFSKeystore(tdir) - if err != nil { - t.Fatal(err) - } - - k, err := ks.Get("does-it-exist") - if err != ErrNoSuchKey { - t.Fatalf("expected: %s, got %s", ErrNoSuchKey, err) - } - if k != nil { - t.Fatalf("Get on nonexistant key should give nil") - } -} - -func TestMakeKeystoreNoDir(t *testing.T) { - _, err := NewFSKeystore("/this/is/not/a/real/dir") - if err == nil { - t.Fatal("shouldnt be able to make a keystore in a nonexistant directory") - } -} - -func assertGetKey(ks Keystore, name string, exp ci.PrivKey) error { - outK, err := ks.Get(name) - if err != nil { - return err - } - - if !outK.Equals(exp) { - return fmt.Errorf("key we got out didn't match expectation") - } - - return nil -} - -func assertDirContents(dir string, exp []string) error { - finfos, err := ioutil.ReadDir(dir) - if err != nil { - return err - } - - if len(finfos) != len(exp) { - return fmt.Errorf("expected %d directory entries", len(exp)) - } - - var names []string - for _, fi := range finfos { - decodedName, err := decode(fi.Name()) - if err != nil { - return err - } - names = append(names, decodedName) - } - - sort.Strings(names) - sort.Strings(exp) - if len(names) != len(exp) { - return fmt.Errorf("directory had wrong number of entries in it") - } - - for i, v := range names { - if v != exp[i] { - return fmt.Errorf("had wrong entry in directory") - } - } - return nil -} diff --git a/keystore/memkeystore.go b/keystore/memkeystore.go deleted file mode 100644 index 94411144d4c..00000000000 --- a/keystore/memkeystore.go +++ /dev/null @@ -1,64 +0,0 @@ -package keystore - -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. -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 exists in the Keystore -func (mk *MemKeystore) Has(name string) (bool, error) { - _, ok := mk.keys[name] - return ok, nil -} - -// Put store a key in the Keystore -func (mk *MemKeystore) Put(name string, k ci.PrivKey) error { - if name == "" { - return errors.New("key name must be at least one character") - } - - _, ok := mk.keys[name] - if ok { - return ErrKeyExists - } - - mk.keys[name] = k - return nil -} - -// Get retrieve a key from the Keystore -func (mk *MemKeystore) Get(name string) (ci.PrivKey, error) { - k, ok := mk.keys[name] - if !ok { - return nil, ErrNoSuchKey - } - - return k, nil -} - -// Delete remove a key from the Keystore -func (mk *MemKeystore) Delete(name string) error { - delete(mk.keys, name) - return nil -} - -// List return a list of key identifier -func (mk *MemKeystore) List() ([]string, error) { - out := make([]string, 0, len(mk.keys)) - for k := range mk.keys { - out = append(out, k) - } - return out, nil -} diff --git a/keystore/memkeystore_test.go b/keystore/memkeystore_test.go deleted file mode 100644 index 907cbbd0e7e..00000000000 --- a/keystore/memkeystore_test.go +++ /dev/null @@ -1,99 +0,0 @@ -package keystore - -import ( - "sort" - "testing" -) - -func TestMemKeyStoreBasics(t *testing.T) { - ks := NewMemKeystore() - - l, err := ks.List() - if err != nil { - t.Fatal(err) - } - - if len(l) != 0 { - t.Fatal("expected no keys") - } - - k1 := privKeyOrFatal(t) - k2 := privKeyOrFatal(t) - k3 := privKeyOrFatal(t) - k4 := privKeyOrFatal(t) - - err = ks.Put("foo", k1) - if err != nil { - t.Fatal(err) - } - - err = ks.Put("bar", k2) - if err != nil { - t.Fatal(err) - } - - l, err = ks.List() - if err != nil { - t.Fatal(err) - } - - sort.Strings(l) - if l[0] != "bar" || l[1] != "foo" { - t.Fatal("wrong entries listed") - } - - err = ks.Put("foo", k3) - if err == nil { - t.Fatal("should not be able to overwrite key") - } - - exist, err := ks.Has("foo") - if !exist { - t.Fatal("should know it has a key named foo") - } - if err != nil { - t.Fatal(err) - } - - exist, err = ks.Has("nonexistingkey") - if exist { - t.Fatal("should know it doesn't have a key named nonexistingkey") - } - if err != nil { - t.Fatal(err) - } - - if err := ks.Delete("bar"); err != nil { - t.Fatal(err) - } - if err := ks.Put("beep", k3); err != nil { - t.Fatal(err) - } - - if err := ks.Put("boop", k4); err != nil { - t.Fatal(err) - } - if err := assertGetKey(ks, "foo", k1); err != nil { - t.Fatal(err) - } - - if err := assertGetKey(ks, "beep", k3); err != nil { - t.Fatal(err) - } - - if err := assertGetKey(ks, "boop", k4); err != nil { - t.Fatal(err) - } - - if err := ks.Put("..///foo/", k1); err != nil { - t.Fatal(err) - } - - if err := ks.Put("", k1); err == nil { - t.Fatal("shouldn't be able to put a key with no name") - } - - if err := ks.Put(".foo", k1); err != nil { - t.Fatal(err) - } -} diff --git a/namesys/base.go b/namesys/base.go deleted file mode 100644 index 27cc38f8885..00000000000 --- a/namesys/base.go +++ /dev/null @@ -1,120 +0,0 @@ -package namesys - -import ( - "context" - "strings" - "time" - - path "github.com/ipfs/go-path" - opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" -) - -type onceResult struct { - value path.Path - ttl time.Duration - err error -} - -type resolver interface { - resolveOnceAsync(ctx context.Context, name string, options opts.ResolveOpts) <-chan onceResult -} - -// resolve is a helper for implementing Resolver.ResolveN using resolveOnce. -func resolve(ctx context.Context, r resolver, name string, options opts.ResolveOpts) (path.Path, error) { - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - err := ErrResolveFailed - var p path.Path - - resCh := resolveAsync(ctx, r, name, options) - - for res := range resCh { - p, err = res.Path, res.Err - if err != nil { - break - } - } - - return p, err -} - -func resolveAsync(ctx context.Context, r resolver, name string, options opts.ResolveOpts) <-chan Result { - resCh := r.resolveOnceAsync(ctx, name, options) - depth := options.Depth - outCh := make(chan Result, 1) - - go func() { - defer close(outCh) - var subCh <-chan Result - var cancelSub context.CancelFunc - defer func() { - if cancelSub != nil { - cancelSub() - } - }() - - for { - select { - case res, ok := <-resCh: - if !ok { - resCh = nil - break - } - - if res.err != nil { - emitResult(ctx, outCh, Result{Err: res.err}) - return - } - log.Debugf("resolved %s to %s", name, res.value.String()) - if !strings.HasPrefix(res.value.String(), ipnsPrefix) { - emitResult(ctx, outCh, Result{Path: res.value}) - break - } - - if depth == 1 { - emitResult(ctx, outCh, Result{Path: res.value, Err: ErrResolveRecursion}) - break - } - - subopts := options - if subopts.Depth > 1 { - subopts.Depth-- - } - - var subCtx context.Context - if cancelSub != nil { - // Cancel previous recursive resolve since it won't be used anyways - cancelSub() - } - subCtx, cancelSub = context.WithCancel(ctx) - _ = cancelSub - - p := strings.TrimPrefix(res.value.String(), ipnsPrefix) - subCh = resolveAsync(subCtx, r, p, subopts) - case res, ok := <-subCh: - if !ok { - subCh = nil - break - } - - // We don't bother returning here in case of context timeout as there is - // no good reason to do that, and we may still be able to emit a result - emitResult(ctx, outCh, res) - case <-ctx.Done(): - return - } - if resCh == nil && subCh == nil { - return - } - } - }() - return outCh -} - -func emitResult(ctx context.Context, outCh chan<- Result, r Result) { - select { - case outCh <- r: - case <-ctx.Done(): - } -} diff --git a/namesys/cache.go b/namesys/cache.go deleted file mode 100644 index b2b1f43a8d8..00000000000 --- a/namesys/cache.go +++ /dev/null @@ -1,62 +0,0 @@ -package namesys - -import ( - "time" - - path "github.com/ipfs/go-path" -) - -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 - } - - ientry, ok := ns.cache.Get(name) - if !ok { - return "", false - } - - entry, ok := ientry.(cacheEntry) - if !ok { - // should never happen, purely for sanity - log.Panicf("unexpected type %T in cache for %q.", ientry, name) - } - - if time.Now().Before(entry.eol) { - return entry.val, true - } - - ns.cache.Remove(name) - - return "", false -} - -func (ns *mpns) cacheSet(name string, val path.Path, ttl time.Duration) { - if ns.cache == nil || ttl <= 0 { - return - } - ns.cache.Add(name, cacheEntry{ - val: val, - eol: time.Now().Add(ttl), - }) -} - -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 deleted file mode 100644 index 738612f46b2..00000000000 --- a/namesys/dns.go +++ /dev/null @@ -1,159 +0,0 @@ -package namesys - -import ( - "context" - "errors" - "fmt" - "net" - "strings" - - path "github.com/ipfs/go-path" - opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" - 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 -type DNSResolver struct { - lookupTXT LookupTXTFunc - // TODO: maybe some sort of caching? - // cache would need a timeout -} - -// NewDNSResolver constructs a name resolver using DNS TXT records. -func NewDNSResolver() *DNSResolver { - return &DNSResolver{lookupTXT: net.LookupTXT} -} - -// Resolve implements Resolver. -func (r *DNSResolver) Resolve(ctx context.Context, name string, options ...opts.ResolveOpt) (path.Path, error) { - return resolve(ctx, r, name, opts.ProcessOpts(options)) -} - -// ResolveAsync implements Resolver. -func (r *DNSResolver) ResolveAsync(ctx context.Context, name string, options ...opts.ResolveOpt) <-chan Result { - return resolveAsync(ctx, r, name, opts.ProcessOpts(options)) -} - -type lookupRes struct { - path path.Path - error error -} - -// resolveOnce implements resolver. -// TXT records for a given domain name should contain a b58 -// encoded multihash. -func (r *DNSResolver) resolveOnceAsync(ctx context.Context, name string, options opts.ResolveOpts) <-chan onceResult { - var fqdn string - out := make(chan onceResult, 1) - segments := strings.SplitN(name, "/", 2) - domain := segments[0] - - if !isd.IsDomain(domain) { - out <- onceResult{err: fmt.Errorf("not a valid domain name: %s", domain)} - close(out) - return out - } - log.Debugf("DNSResolver resolving %s", domain) - - if strings.HasSuffix(domain, ".") { - fqdn = domain - } else { - 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) - - subChan := make(chan lookupRes, 1) - go workDomain(r, "_dnslink."+fqdn, subChan) - - appendPath := func(p path.Path) (path.Path, error) { - if len(segments) > 1 { - return path.FromSegments("", strings.TrimRight(p.String(), "/"), segments[1]) - } - return p, nil - } - - go func() { - defer close(out) - for { - select { - case subRes, ok := <-subChan: - if !ok { - subChan = nil - break - } - if subRes.error == nil { - p, err := appendPath(subRes.path) - emitOnceResult(ctx, out, onceResult{value: p, err: err}) - return - } - case rootRes, ok := <-rootChan: - if !ok { - rootChan = nil - break - } - if rootRes.error == nil { - p, err := appendPath(rootRes.path) - emitOnceResult(ctx, out, onceResult{value: p, err: err}) - } - case <-ctx.Done(): - return - } - if subChan == nil && rootChan == nil { - return - } - } - }() - - return out -} - -func workDomain(r *DNSResolver, name string, res chan lookupRes) { - defer close(res) - - txt, err := r.lookupTXT(name) - if err != nil { - // Error is != nil - res <- lookupRes{"", err} - return - } - - for _, t := range txt { - p, err := parseEntry(t) - if err == nil { - res <- lookupRes{p, nil} - return - } - } - res <- lookupRes{"", ErrResolveFailed} -} - -func parseEntry(txt string) (path.Path, error) { - p, err := path.ParseCidToPath(txt) // bare IPFS multihashes - if err == nil { - return p, nil - } - - return tryParseDnsLink(txt) -} - -func tryParseDnsLink(txt string) (path.Path, error) { - parts := strings.SplitN(txt, "=", 2) - if len(parts) == 2 && parts[0] == "dnslink" { - return path.ParsePath(parts[1]) - } - - return "", errors.New("not a valid dnslink entry") -} diff --git a/namesys/dns_test.go b/namesys/dns_test.go deleted file mode 100644 index 5a0e2a7d2ff..00000000000 --- a/namesys/dns_test.go +++ /dev/null @@ -1,172 +0,0 @@ -package namesys - -import ( - "fmt" - "testing" - - opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" -) - -type mockDNS struct { - entries map[string][]string -} - -func (m *mockDNS) lookupTXT(name string) (txt []string, err error) { - txt, ok := m.entries[name] - if !ok { - return nil, fmt.Errorf("no TXT entry for %s", name) - } - return txt, nil -} - -func TestDnsEntryParsing(t *testing.T) { - - goodEntries := []string{ - "QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", - "dnslink=/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/foo", - "dnslink=/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/bar", - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/foo/bar/baz", - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/foo/bar/baz/", - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", - } - - badEntries := []string{ - "QmYhE8xgFCjGcz6PHgnvJz5NOTCORRECT", - "quux=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", - "dnslink=", - "dnslink=/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/foo", - "dnslink=ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/bar", - } - - for _, e := range goodEntries { - _, err := parseEntry(e) - if err != nil { - t.Log("expected entry to parse correctly!") - t.Log(e) - t.Fatal(err) - } - } - - for _, e := range badEntries { - _, err := parseEntry(e) - if err == nil { - t.Log("expected entry parse to fail!") - t.Fatal(err) - } - } -} - -func newMockDNS() *mockDNS { - return &mockDNS{ - entries: map[string][]string{ - "multihash.example.com.": { - "dnslink=QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", - }, - "ipfs.example.com.": { - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", - }, - "_dnslink.dipfs.example.com.": { - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", - }, - "dns1.example.com.": { - "dnslink=/ipns/ipfs.example.com", - }, - "dns2.example.com.": { - "dnslink=/ipns/dns1.example.com", - }, - "multi.example.com.": { - "some stuff", - "dnslink=/ipns/dns1.example.com", - "masked dnslink=/ipns/example.invalid", - }, - "equals.example.com.": { - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/=equals", - }, - "loop1.example.com.": { - "dnslink=/ipns/loop2.example.com", - }, - "loop2.example.com.": { - "dnslink=/ipns/loop1.example.com", - }, - "_dnslink.dloop1.example.com.": { - "dnslink=/ipns/loop2.example.com", - }, - "_dnslink.dloop2.example.com.": { - "dnslink=/ipns/loop1.example.com", - }, - "bad.example.com.": { - "dnslink=", - }, - "withsegment.example.com.": { - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment", - }, - "withrecsegment.example.com.": { - "dnslink=/ipns/withsegment.example.com/subsub", - }, - "withtrailing.example.com.": { - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/", - }, - "withtrailingrec.example.com.": { - "dnslink=/ipns/withtrailing.example.com/segment/", - }, - "double.example.com.": { - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", - }, - "_dnslink.double.example.com.": { - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", - }, - "double.conflict.com.": { - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", - }, - "_dnslink.conflict.example.com.": { - "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjE", - }, - "fqdn.example.com.": { - "dnslink=/ipfs/QmYvMB9yrsSf7RKBghkfwmHJkzJhW2ZgVwq3LxBXXPasFr", - }, - "www.wealdtech.eth.link.": { - "dnslink=/ipns/ipfs.example.com", - }, - }, - } -} - -func TestDNSResolution(t *testing.T) { - mock := newMockDNS() - r := &DNSResolver{lookupTXT: mock.lookupTXT} - testResolution(t, r, "multihash.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil) - testResolution(t, r, "ipfs.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil) - testResolution(t, r, "dipfs.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil) - testResolution(t, r, "dns1.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil) - testResolution(t, r, "dns1.example.com", 1, "/ipns/ipfs.example.com", ErrResolveRecursion) - testResolution(t, r, "dns2.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil) - testResolution(t, r, "dns2.example.com", 1, "/ipns/dns1.example.com", ErrResolveRecursion) - testResolution(t, r, "dns2.example.com", 2, "/ipns/ipfs.example.com", ErrResolveRecursion) - testResolution(t, r, "multi.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil) - testResolution(t, r, "multi.example.com", 1, "/ipns/dns1.example.com", ErrResolveRecursion) - testResolution(t, r, "multi.example.com", 2, "/ipns/ipfs.example.com", ErrResolveRecursion) - testResolution(t, r, "equals.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/=equals", nil) - testResolution(t, r, "loop1.example.com", 1, "/ipns/loop2.example.com", ErrResolveRecursion) - testResolution(t, r, "loop1.example.com", 2, "/ipns/loop1.example.com", ErrResolveRecursion) - testResolution(t, r, "loop1.example.com", 3, "/ipns/loop2.example.com", ErrResolveRecursion) - testResolution(t, r, "loop1.example.com", opts.DefaultDepthLimit, "/ipns/loop1.example.com", ErrResolveRecursion) - testResolution(t, r, "dloop1.example.com", 1, "/ipns/loop2.example.com", ErrResolveRecursion) - testResolution(t, r, "dloop1.example.com", 2, "/ipns/loop1.example.com", ErrResolveRecursion) - testResolution(t, r, "dloop1.example.com", 3, "/ipns/loop2.example.com", ErrResolveRecursion) - testResolution(t, r, "dloop1.example.com", opts.DefaultDepthLimit, "/ipns/loop1.example.com", ErrResolveRecursion) - testResolution(t, r, "bad.example.com", opts.DefaultDepthLimit, "", ErrResolveFailed) - testResolution(t, r, "withsegment.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment", nil) - testResolution(t, r, "withrecsegment.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment/subsub", nil) - testResolution(t, r, "withsegment.example.com/test1", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment/test1", nil) - testResolution(t, r, "withrecsegment.example.com/test2", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment/subsub/test2", nil) - testResolution(t, r, "withrecsegment.example.com/test3/", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment/subsub/test3/", nil) - testResolution(t, r, "withtrailingrec.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment/", nil) - 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 deleted file mode 100644 index ecd80943be8..00000000000 --- a/namesys/interface.go +++ /dev/null @@ -1,106 +0,0 @@ -/* -Package namesys implements resolvers and publishers for the IPFS -naming system (IPNS). - -The core of IPFS is an immutable, content-addressable Merkle graph. -That works well for many use cases, but doesn't allow you to answer -questions like "what is Alice's current homepage?". The mutable name -system allows Alice to publish information like: - - The current homepage for alice.example.com is - /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj - -or: - - The current homepage for node - QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy - is - /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj - -The mutable name system also allows users to resolve those references -to find the immutable IPFS object currently referenced by a given -mutable name. - -For command-line bindings to this functionality, see: - - ipfs name - ipfs dns - ipfs resolve -*/ -package namesys - -import ( - "errors" - "time" - - context "context" - - path "github.com/ipfs/go-path" - opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" - ci "github.com/libp2p/go-libp2p-core/crypto" -) - -// ErrResolveFailed signals an error when attempting to resolve. -var ErrResolveFailed = errors.New("could not resolve name") - -// ErrResolveRecursion signals a recursion-depth limit. -var ErrResolveRecursion = errors.New( - "could not resolve name (recursion limit exceeded)") - -// ErrPublishFailed signals an error when attempting to publish. -var ErrPublishFailed = errors.New("could not publish name") - -// Namesys represents a cohesive name publishing and resolving system. -// -// Publishing a name is the process of establishing a mapping, a key-value -// pair, according to naming rules and databases. -// -// Resolving a name is the process of looking up the value associated with the -// key (name). -type NameSystem interface { - Resolver - Publisher -} - -// Result is the return type for Resolver.ResolveAsync. -type Result struct { - Path path.Path - Err error -} - -// Resolver is an object capable of resolving names. -type Resolver interface { - - // Resolve performs a recursive lookup, returning the dereferenced - // path. For example, if ipfs.io has a DNS TXT record pointing to - // /ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy - // and there is a DHT IPNS entry for - // QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy - // -> /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj - // then - // Resolve(ctx, "/ipns/ipfs.io") - // will resolve both names, returning - // /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj - // - // There is a default depth-limit to avoid infinite recursion. Most - // users will be fine with this default limit, but if you need to - // adjust the limit you can specify it as an option. - Resolve(ctx context.Context, name string, options ...opts.ResolveOpt) (value path.Path, err error) - - // ResolveAsync performs recursive name lookup, like Resolve, but it returns - // entries as they are discovered in the DHT. Each returned result is guaranteed - // to be "better" (which usually means newer) than the previous one. - ResolveAsync(ctx context.Context, name string, options ...opts.ResolveOpt) <-chan Result -} - -// Publisher is an object capable of publishing particular names. -type Publisher interface { - - // Publish establishes a name-value mapping. - // TODO make this not PrivKey specific. - Publish(ctx context.Context, name ci.PrivKey, value path.Path) error - - // TODO: to be replaced by a more generic 'PublishWithValidity' type - // call once the records spec is implemented - PublishWithEOL(ctx context.Context, name ci.PrivKey, value path.Path, eol time.Time) error -} diff --git a/namesys/ipns_resolver_validation_test.go b/namesys/ipns_resolver_validation_test.go deleted file mode 100644 index 5dbfabf9cd3..00000000000 --- a/namesys/ipns_resolver_validation_test.go +++ /dev/null @@ -1,206 +0,0 @@ -package namesys - -import ( - "context" - "testing" - "time" - - ds "github.com/ipfs/go-datastore" - dssync "github.com/ipfs/go-datastore/sync" - mockrouting "github.com/ipfs/go-ipfs-routing/mock" - offline "github.com/ipfs/go-ipfs-routing/offline" - ipns "github.com/ipfs/go-ipns" - ipns_pb "github.com/ipfs/go-ipns/pb" - path "github.com/ipfs/go-path" - opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" - 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" - testutil "github.com/libp2p/go-libp2p-testing/net" -) - -func TestResolverValidation(t *testing.T) { - t.Run("RSA", - func(t *testing.T) { - testResolverValidation(t, ci.RSA) - }) - t.Run("Ed25519", - func(t *testing.T) { - testResolverValidation(t, ci.Ed25519) - }) - t.Run("ECDSA", - func(t *testing.T) { - testResolverValidation(t, ci.ECDSA) - }) - t.Run("Secp256k1", - func(t *testing.T) { - testResolverValidation(t, ci.Secp256k1) - }) -} - -func testResolverValidation(t *testing.T, keyType int) { - ctx := context.Background() - rid := testutil.RandIdentityOrFatal(t) - dstore := dssync.MutexWrap(ds.NewMapDatastore()) - peerstore := pstoremem.NewPeerstore() - - vstore := newMockValueStore(rid, dstore, peerstore) - resolver := NewIpnsResolver(vstore) - - nvVstore := offline.NewOfflineRouter(dstore, mockrouting.MockValidator{}) - - // Create entry with expiry in one hour - priv, id, _, ipnsDHTPath := genKeys(t, keyType) - ts := time.Now() - p := []byte("/ipfs/QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG") - entry, err := createIPNSRecordWithEmbeddedPublicKey(priv, p, 1, ts.Add(time.Hour)) - if err != nil { - t.Fatal(err) - } - - // Publish entry - err = PublishEntry(ctx, vstore, ipnsDHTPath, entry) - if err != nil { - t.Fatal(err) - } - - // Resolve entry - resp, err := resolve(ctx, resolver, id.Pretty(), opts.DefaultResolveOpts()) - if err != nil { - t.Fatal(err) - } - if resp != path.Path(p) { - t.Fatalf("Mismatch between published path %s and resolved path %s", p, resp) - } - // Create expired entry - expiredEntry, err := createIPNSRecordWithEmbeddedPublicKey(priv, p, 1, ts.Add(-1*time.Hour)) - if err != nil { - t.Fatal(err) - } - - // Publish entry - err = PublishEntry(ctx, nvVstore, ipnsDHTPath, expiredEntry) - if err != nil { - t.Fatal(err) - } - - // Record should fail validation because entry is expired - _, err = resolve(ctx, resolver, id.Pretty(), opts.DefaultResolveOpts()) - if err == nil { - t.Fatal("ValidateIpnsRecord should have returned error") - } - - // Create IPNS record path with a different private key - priv2, id2, _, ipnsDHTPath2 := genKeys(t, keyType) - - // Publish entry - err = PublishEntry(ctx, nvVstore, ipnsDHTPath2, entry) - if err != nil { - t.Fatal(err) - } - - // Record should fail validation because public key defined by - // ipns path doesn't match record signature - _, err = resolve(ctx, resolver, id2.Pretty(), opts.DefaultResolveOpts()) - if err == nil { - t.Fatal("ValidateIpnsRecord should have failed signature verification") - } - - // Try embedding the incorrect private key inside the entry - if err := ipns.EmbedPublicKey(priv2.GetPublic(), entry); err != nil { - t.Fatal(err) - } - - // Publish entry - err = PublishEntry(ctx, nvVstore, ipnsDHTPath2, entry) - if err != nil { - t.Fatal(err) - } - - // Record should fail validation because public key defined by - // ipns path doesn't match record signature - _, err = resolve(ctx, resolver, id2.Pretty(), opts.DefaultResolveOpts()) - if err == nil { - t.Fatal("ValidateIpnsRecord should have failed signature verification") - } -} - -func genKeys(t *testing.T, keyType int) (ci.PrivKey, peer.ID, string, string) { - bits := 0 - if keyType == ci.RSA { - bits = 2048 - } - - sk, pk, err := test.RandTestKeyPair(keyType, bits) - if err != nil { - t.Fatal(err) - } - id, err := peer.IDFromPublicKey(pk) - if err != nil { - t.Fatal(err) - } - return sk, id, PkKeyForID(id), ipns.RecordKey(id) -} - -func createIPNSRecordWithEmbeddedPublicKey(sk ci.PrivKey, val []byte, seq uint64, eol time.Time) (*ipns_pb.IpnsEntry, error) { - entry, err := ipns.Create(sk, val, seq, eol) - if err != nil { - return nil, err - } - if err := ipns.EmbedPublicKey(sk.GetPublic(), entry); err != nil { - return nil, err - } - - return entry, nil -} - -type mockValueStore struct { - r routing.ValueStore - kbook pstore.KeyBook -} - -func newMockValueStore(id testutil.Identity, dstore ds.Datastore, kbook pstore.KeyBook) *mockValueStore { - return &mockValueStore{ - r: offline.NewOfflineRouter(dstore, record.NamespacedValidator{ - "ipns": ipns.Validator{KeyBook: kbook}, - "pk": record.PublicKeyValidator{}, - }), - kbook: kbook, - } -} - -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 ...routing.Option) (<-chan []byte, error) { - return m.r.SearchValue(ctx, k, opts...) -} - -func (m *mockValueStore) GetPublicKey(ctx context.Context, p peer.ID) (ci.PubKey, error) { - pk := m.kbook.PubKey(p) - if pk != nil { - return pk, nil - } - - pkkey := routing.KeyForPublicKey(p) - val, err := m.GetValue(ctx, pkkey) - if err != nil { - return nil, err - } - - pk, err = ci.UnmarshalPublicKey(val) - if err != nil { - return nil, err - } - - return pk, m.kbook.AddPubKey(p, pk) -} - -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 deleted file mode 100644 index 760d04c1788..00000000000 --- a/namesys/namesys.go +++ /dev/null @@ -1,238 +0,0 @@ -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-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. -// -// Uses several Resolvers: -// (a) IPFS routing naming: SFS-like PKI names. -// (b) dns domains: resolves using links in DNS TXT records -// (c) proquints: interprets string as the raw byte data. -// -// It can only publish to: (a) IPFS routing naming. -// -type mpns struct { - dnsResolver, proquintResolver, ipnsResolver resolver - ipnsPublisher Publisher - - 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 - 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. -func (ns *mpns) Resolve(ctx context.Context, name string, options ...opts.ResolveOpt) (path.Path, error) { - if strings.HasPrefix(name, "/ipfs/") { - return path.ParsePath(name) - } - - if !strings.HasPrefix(name, "/") { - return path.ParsePath("/ipfs/" + name) - } - - return resolve(ctx, ns, name, opts.ProcessOpts(options)) -} - -func (ns *mpns) ResolveAsync(ctx context.Context, name string, options ...opts.ResolveOpt) <-chan Result { - if strings.HasPrefix(name, "/ipfs/") { - p, err := path.ParsePath(name) - res := make(chan Result, 1) - res <- Result{p, err} - close(res) - return res - } - - if !strings.HasPrefix(name, "/") { - p, err := path.ParsePath("/ipfs/" + name) - res := make(chan Result, 1) - res <- Result{p, err} - close(res) - return res - } - - return resolveAsync(ctx, ns, name, opts.ProcessOpts(options)) -} - -// resolveOnce implements resolver. -func (ns *mpns) resolveOnceAsync(ctx context.Context, name string, options opts.ResolveOpts) <-chan onceResult { - out := make(chan onceResult, 1) - - if !strings.HasPrefix(name, ipnsPrefix) { - name = ipnsPrefix + name - } - segments := strings.SplitN(name, "/", 4) - if len(segments) < 3 || segments[0] != "" { - log.Debugf("invalid name syntax for %s", name) - out <- onceResult{err: ErrResolveFailed} - close(out) - return out - } - - key := segments[2] - - // Resolver selection: - // 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 - ipnsKey, 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 - } - } - - cacheKey := key - if err == nil { - cacheKey = string(ipnsKey) - } - - if p, ok := ns.cacheGet(cacheKey); ok { - var err error - if len(segments) > 3 { - p, err = path.FromSegments("", strings.TrimRight(p.String(), "/"), segments[3]) - } - - out <- onceResult{value: p, err: err} - close(out) - return out - } - - if err == nil { - res = ns.ipnsResolver - } else if isd.IsDomain(key) { - res = ns.dnsResolver - } else { - res = ns.proquintResolver - } - - resCh := res.resolveOnceAsync(ctx, key, options) - var best onceResult - go func() { - defer close(out) - for { - select { - case res, ok := <-resCh: - if !ok { - if best != (onceResult{}) { - ns.cacheSet(cacheKey, best.value, best.ttl) - } - return - } - if res.err == nil { - best = res - } - p := res.value - err := res.err - ttl := res.ttl - - // Attach rest of the path - if len(segments) > 3 { - p, err = path.FromSegments("", strings.TrimRight(p.String(), "/"), segments[3]) - } - - emitOnceResult(ctx, out, onceResult{value: p, ttl: ttl, err: err}) - case <-ctx.Done(): - return - } - } - }() - - return out -} - -func emitOnceResult(ctx context.Context, outCh chan<- onceResult, r onceResult) { - select { - case outCh <- r: - case <-ctx.Done(): - } -} - -// Publish implements Publisher -func (ns *mpns) Publish(ctx context.Context, name ci.PrivKey, value path.Path) error { - return ns.PublishWithEOL(ctx, name, value, time.Now().Add(DefaultRecordEOL)) -} - -func (ns *mpns) PublishWithEOL(ctx context.Context, name ci.PrivKey, value path.Path, eol time.Time) error { - id, err := peer.IDFromPrivateKey(name) - if err != nil { - 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(string(id)) - return err - } - ttl := DefaultResolverCacheTTL - if setTTL, ok := checkCtxTTL(ctx); ok { - ttl = setTTL - } - if ttEol := time.Until(eol); ttEol < ttl { - ttl = ttEol - } - ns.cacheSet(string(id), value, ttl) - return nil -} diff --git a/namesys/namesys_test.go b/namesys/namesys_test.go deleted file mode 100644 index cc0ca69590c..00000000000 --- a/namesys/namesys_test.go +++ /dev/null @@ -1,169 +0,0 @@ -package namesys - -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" - unixfs "github.com/ipfs/go-unixfs" - opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" - 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" -) - -type mockResolver struct { - entries map[string]string -} - -func testResolution(t *testing.T, resolver Resolver, name string, depth uint, expected string, expError error) { - t.Helper() - p, err := resolver.Resolve(context.Background(), name, opts.Depth(depth)) - if err != expError { - t.Fatal(fmt.Errorf( - "expected %s with a depth of %d to have a '%s' error, but got '%s'", - name, depth, expError, err)) - } - if p.String() != expected { - t.Fatal(fmt.Errorf( - "%s with depth %d resolved to %s != %s", - name, depth, p.String(), expected)) - } -} - -func (r *mockResolver) resolveOnceAsync(ctx context.Context, name string, options opts.ResolveOpts) <-chan onceResult { - p, err := path.ParsePath(r.entries[name]) - out := make(chan onceResult, 1) - out <- onceResult{value: p, err: err} - close(out) - return out -} - -func mockResolverOne() *mockResolver { - return &mockResolver{ - entries: map[string]string{ - "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 - }, - } -} - -func mockResolverTwo() *mockResolver { - return &mockResolver{ - entries: map[string]string{ - "ipfs.io": "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", - }, - } -} - -func TestNamesysResolution(t *testing.T) { - r := &mpns{ - ipnsResolver: mockResolverOne(), - dnsResolver: mockResolverTwo(), - } - - testResolution(t, r, "Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", opts.DefaultDepthLimit, "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", nil) - testResolution(t, r, "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", opts.DefaultDepthLimit, "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", nil) - testResolution(t, r, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", opts.DefaultDepthLimit, "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", nil) - testResolution(t, r, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", 1, "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", ErrResolveRecursion) - testResolution(t, r, "/ipns/ipfs.io", opts.DefaultDepthLimit, "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", nil) - testResolution(t, r, "/ipns/ipfs.io", 1, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", ErrResolveRecursion) - testResolution(t, r, "/ipns/ipfs.io", 2, "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", ErrResolveRecursion) - testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", opts.DefaultDepthLimit, "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", nil) - 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, 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, 0) - p, err := path.ParsePath(unixfs.EmptyDirNode().Cid().String()) - if err != nil { - t.Fatal(err) - } - err = nsys.Publish(context.Background(), priv, p) - if err != nil { - 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(string(pid)) - 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/proquint.go b/namesys/proquint.go deleted file mode 100644 index 63cb62a0476..00000000000 --- a/namesys/proquint.go +++ /dev/null @@ -1,32 +0,0 @@ -package namesys - -import ( - "context" - "errors" - - proquint "github.com/bren2010/proquint" - path "github.com/ipfs/go-path" - opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" -) - -type ProquintResolver struct{} - -// Resolve implements Resolver. -func (r *ProquintResolver) Resolve(ctx context.Context, name string, options ...opts.ResolveOpt) (path.Path, error) { - return resolve(ctx, r, name, opts.ProcessOpts(options)) -} - -// resolveOnce implements resolver. Decodes the proquint string. -func (r *ProquintResolver) resolveOnceAsync(ctx context.Context, name string, options opts.ResolveOpts) <-chan onceResult { - out := make(chan onceResult, 1) - defer close(out) - - ok, err := proquint.IsProquint(name) - if err != nil || !ok { - out <- onceResult{err: errors.New("not a valid proquint string")} - return out - } - // Return a 0 TTL as caching this result is pointless. - out <- onceResult{value: path.FromString(string(proquint.Decode(name)))} - return out -} diff --git a/namesys/publisher.go b/namesys/publisher.go deleted file mode 100644 index f558eaf2885..00000000000 --- a/namesys/publisher.go +++ /dev/null @@ -1,309 +0,0 @@ -package namesys - -import ( - "context" - "strings" - "sync" - "time" - - 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-core/crypto" - peer "github.com/libp2p/go-libp2p-core/peer" - routing "github.com/libp2p/go-libp2p-core/routing" - base32 "github.com/whyrusleeping/base32" -) - -const ipnsPrefix = "/ipns/" - -const DefaultRecordEOL = 24 * time.Hour - -// IpnsPublisher is capable of publishing and resolving names to the IPFS -// routing system. -type IpnsPublisher struct { - routing routing.ValueStore - ds ds.Datastore - - // Used to ensure we assign IPNS records *sequential* sequence numbers. - mu sync.Mutex -} - -// NewIpnsPublisher constructs a publisher for the IPFS Routing name system. -func NewIpnsPublisher(route routing.ValueStore, ds ds.Datastore) *IpnsPublisher { - if ds == nil { - panic("nil datastore") - } - return &IpnsPublisher{routing: route, ds: ds} -} - -// Publish implements Publisher. Accepts a keypair and a value, -// and publishes it out to the routing system -func (p *IpnsPublisher) Publish(ctx context.Context, k ci.PrivKey, value path.Path) error { - log.Debugf("Publish %s", value) - return p.PublishWithEOL(ctx, k, value, time.Now().Add(DefaultRecordEOL)) -} - -func IpnsDsKey(id peer.ID) ds.Key { - return ds.NewKey("/ipns/" + base32.RawStdEncoding.EncodeToString([]byte(id))) -} - -// PublishedNames returns the latest IPNS records published by this node and -// their expiration times. -// -// This method will not search the routing system for records published by other -// nodes. -func (p *IpnsPublisher) ListPublished(ctx context.Context) (map[peer.ID]*pb.IpnsEntry, error) { - query, err := p.ds.Query(dsquery.Query{ - Prefix: ipnsPrefix, - }) - if err != nil { - return nil, err - } - defer query.Close() - - records := make(map[peer.ID]*pb.IpnsEntry) - for { - select { - case result, ok := <-query.Next(): - if !ok { - return records, nil - } - if result.Error != nil { - return nil, result.Error - } - e := new(pb.IpnsEntry) - if err := proto.Unmarshal(result.Value, e); err != nil { - // Might as well return what we can. - log.Error("found an invalid IPNS entry:", err) - continue - } - if !strings.HasPrefix(result.Key, ipnsPrefix) { - log.Errorf("datastore query for keys with prefix %s returned a key: %s", ipnsPrefix, result.Key) - continue - } - k := result.Key[len(ipnsPrefix):] - pid, err := base32.RawStdEncoding.DecodeString(k) - if err != nil { - log.Errorf("ipns ds key invalid: %s", result.Key) - continue - } - records[peer.ID(pid)] = e - case <-ctx.Done(): - return nil, ctx.Err() - } - } -} - -// GetPublished returns the record this node has published corresponding to the -// given peer ID. -// -// If `checkRouting` is true and we have no existing record, this method will -// check the routing system for any existing records. -func (p *IpnsPublisher) GetPublished(ctx context.Context, id peer.ID, checkRouting bool) (*pb.IpnsEntry, error) { - ctx, cancel := context.WithTimeout(ctx, time.Second*30) - defer cancel() - - value, err := p.ds.Get(IpnsDsKey(id)) - switch err { - case nil: - case ds.ErrNotFound: - if !checkRouting { - return nil, nil - } - ipnskey := ipns.RecordKey(id) - value, err = p.routing.GetValue(ctx, ipnskey) - if err != nil { - // Not found or other network issue. Can't really do - // anything about this case. - if err != routing.ErrNotFound { - log.Debugf("error when determining the last published IPNS record for %s: %s", id, err) - } - - return nil, nil - } - default: - return nil, err - } - e := new(pb.IpnsEntry) - if err := proto.Unmarshal(value, e); err != nil { - return nil, err - } - return e, nil -} - -func (p *IpnsPublisher) updateRecord(ctx context.Context, k ci.PrivKey, value path.Path, eol time.Time) (*pb.IpnsEntry, error) { - id, err := peer.IDFromPrivateKey(k) - if err != nil { - return nil, err - } - - p.mu.Lock() - defer p.mu.Unlock() - - // get previous records sequence number - rec, err := p.GetPublished(ctx, id, true) - if err != nil { - return nil, err - } - - seqno := rec.GetSequence() // returns 0 if rec is nil - if rec != nil && value != path.Path(rec.GetValue()) { - // Don't bother incrementing the sequence number unless the - // value changes. - seqno++ - } - - // Create record - entry, err := ipns.Create(k, []byte(value), seqno, eol) - if err != nil { - return nil, err - } - - // Set the TTL - // TODO: Make this less hacky. - ttl, ok := checkCtxTTL(ctx) - if ok { - entry.Ttl = proto.Uint64(uint64(ttl.Nanoseconds())) - } - - data, err := proto.Marshal(entry) - if err != nil { - return nil, err - } - - // Put the new record. - 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 -} - -// PublishWithEOL is a temporary stand in for the ipns records implementation -// see here for more details: https://github.com/ipfs/specs/tree/master/records -func (p *IpnsPublisher) PublishWithEOL(ctx context.Context, k ci.PrivKey, value path.Path, eol time.Time) error { - record, err := p.updateRecord(ctx, k, value, eol) - if err != nil { - return err - } - - return PutRecordToRouting(ctx, p.routing, k.GetPublic(), record) -} - -// setting the TTL on published records is an experimental feature. -// as such, i'm using the context to wire it through to avoid changing too -// much code along the way. -func checkCtxTTL(ctx context.Context) (time.Duration, bool) { - v := ctx.Value("ipns-publish-ttl") - if v == nil { - return 0, false - } - - d, ok := v.(time.Duration) - return d, ok -} - -func PutRecordToRouting(ctx context.Context, r routing.ValueStore, k ci.PubKey, entry *pb.IpnsEntry) error { - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - errs := make(chan error, 2) // At most two errors (IPNS, and public key) - - if err := ipns.EmbedPublicKey(k, entry); err != nil { - return err - } - - id, err := peer.IDFromPublicKey(k) - if err != nil { - return err - } - - go func() { - errs <- PublishEntry(ctx, r, ipns.RecordKey(id), entry) - }() - - // Publish the public key if a public key cannot be extracted from the ID - // TODO: once v0.4.16 is widespread enough, we can stop doing this - // and at that point we can even deprecate the /pk/ namespace in the dht - // - // NOTE: This check actually checks if the public key has been embedded - // in the IPNS entry. This check is sufficient because we embed the - // public key in the IPNS entry if it can't be extracted from the ID. - if entry.PubKey != nil { - go func() { - errs <- PublishPublicKey(ctx, r, PkKeyForID(id), k) - }() - - if err := waitOnErrChan(ctx, errs); err != nil { - return err - } - } - - return waitOnErrChan(ctx, errs) -} - -func waitOnErrChan(ctx context.Context, errs chan error) error { - select { - case err := <-errs: - return err - case <-ctx.Done(): - return ctx.Err() - } -} - -func PublishPublicKey(ctx context.Context, r routing.ValueStore, k string, pubk ci.PubKey) error { - log.Debugf("Storing pubkey at: %s", k) - pkbytes, err := pubk.Bytes() - if err != nil { - return err - } - - // Store associated public key - return r.PutValue(ctx, k, pkbytes) -} - -func PublishEntry(ctx context.Context, r routing.ValueStore, ipnskey string, rec *pb.IpnsEntry) error { - data, err := proto.Marshal(rec) - if err != nil { - return err - } - - log.Debugf("Storing ipns entry at: %s", ipnskey) - // Store ipns entry at "/ipns/"+h(pubkey) - return r.PutValue(ctx, ipnskey, data) -} - -// InitializeKeyspace sets the ipns record for the given key to -// point to an empty directory. -// TODO: this doesnt feel like it belongs here -func InitializeKeyspace(ctx context.Context, pub Publisher, pins pin.Pinner, key ci.PrivKey) error { - emptyDir := ft.EmptyDirNode() - - // pin recursively because this might already be pinned - // and doing a direct pin would throw an error in that case - err := pins.Pin(ctx, emptyDir, true) - if err != nil { - return err - } - - err = pins.Flush(ctx) - if err != nil { - return err - } - - return pub.Publish(ctx, key, path.FromCid(emptyDir.Cid())) -} - -// PkKeyForID returns the public key routing key for the given peer ID. -func PkKeyForID(id peer.ID) string { - return "/pk/" + string(id) -} diff --git a/namesys/publisher_test.go b/namesys/publisher_test.go deleted file mode 100644 index 62510338353..00000000000 --- a/namesys/publisher_test.go +++ /dev/null @@ -1,155 +0,0 @@ -package namesys - -import ( - "context" - "crypto/rand" - "github.com/ipfs/go-path" - "testing" - "time" - - ds "github.com/ipfs/go-datastore" - dssync "github.com/ipfs/go-datastore/sync" - 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-core/crypto" - peer "github.com/libp2p/go-libp2p-core/peer" - testutil "github.com/libp2p/go-libp2p-testing/net" - ma "github.com/multiformats/go-multiaddr" -) - -type identity struct { - testutil.PeerNetParams -} - -func (p *identity) ID() peer.ID { - return p.PeerNetParams.ID -} - -func (p *identity) Address() ma.Multiaddr { - return p.Addr -} - -func (p *identity) PrivateKey() ci.PrivKey { - return p.PrivKey -} - -func (p *identity) PublicKey() ci.PubKey { - return p.PubKey -} - -func testNamekeyPublisher(t *testing.T, keyType int, expectedErr error, expectedExistence bool) { - // Context - ctx := context.Background() - - // Private key - privKey, pubKey, err := ci.GenerateKeyPairWithReader(keyType, 2048, rand.Reader) - if err != nil { - t.Fatal(err) - } - - // ID - id, err := peer.IDFromPublicKey(pubKey) - if err != nil { - t.Fatal(err) - } - - // Value - value := []byte("ipfs/TESTING") - - // Seqnum - seqnum := uint64(0) - - // Eol - eol := time.Now().Add(24 * time.Hour) - - // Routing value store - p := testutil.PeerNetParams{ - ID: id, - PrivKey: privKey, - PubKey: pubKey, - Addr: testutil.ZeroLocalTCPAddress, - } - - dstore := dssync.MutexWrap(ds.NewMapDatastore()) - serv := mockrouting.NewServer() - r := serv.ClientWithDatastore(context.Background(), &identity{p}, dstore) - - entry, err := ipns.Create(privKey, value, seqnum, eol) - if err != nil { - t.Fatal(err) - } - - err = PutRecordToRouting(ctx, r, pubKey, entry) - if err != nil { - t.Fatal(err) - } - - // Check for namekey existence in value store - namekey := PkKeyForID(id) - _, err = r.GetValue(ctx, namekey) - if err != expectedErr { - t.Fatal(err) - } - - // Also check datastore for completeness - key := dshelp.NewKeyFromBinary([]byte(namekey)) - exists, err := dstore.Has(key) - if err != nil { - t.Fatal(err) - } - - if exists != expectedExistence { - t.Fatal("Unexpected key existence in datastore") - } -} - -func TestRSAPublisher(t *testing.T) { - testNamekeyPublisher(t, ci.RSA, nil, true) -} - -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 deleted file mode 100644 index 84dcc911cf4..00000000000 --- a/namesys/republisher/repub.go +++ /dev/null @@ -1,168 +0,0 @@ -package republisher - -import ( - "context" - "errors" - "time" - - keystore "github.com/ipfs/go-ipfs/keystore" - namesys "github.com/ipfs/go-ipfs/namesys" - path "github.com/ipfs/go-path" - - proto "github.com/gogo/protobuf/proto" - ds "github.com/ipfs/go-datastore" - ipns "github.com/ipfs/go-ipns" - pb "github.com/ipfs/go-ipns/pb" - logging "github.com/ipfs/go-log" - goprocess "github.com/jbenet/goprocess" - gpctx "github.com/jbenet/goprocess/context" - ic "github.com/libp2p/go-libp2p-core/crypto" - peer "github.com/libp2p/go-libp2p-core/peer" -) - -var errNoEntry = errors.New("no previous entry") - -var log = logging.Logger("ipns-repub") - -// DefaultRebroadcastInterval is the default interval at which we rebroadcast IPNS records -var DefaultRebroadcastInterval = time.Hour * 4 - -// InitialRebroadcastDelay is the delay before first broadcasting IPNS records on start -var InitialRebroadcastDelay = time.Minute * 1 - -// FailureRetryInterval is the interval at which we retry IPNS records broadcasts (when they fail) -var FailureRetryInterval = time.Minute * 5 - -// DefaultRecordLifetime is the default lifetime for IPNS records -const DefaultRecordLifetime = time.Hour * 24 - -type Republisher struct { - ns namesys.Publisher - ds ds.Datastore - self ic.PrivKey - ks keystore.Keystore - - Interval time.Duration - - // how long records that are republished should be valid for - RecordLifetime time.Duration -} - -// NewRepublisher creates a new Republisher -func NewRepublisher(ns namesys.Publisher, ds ds.Datastore, self ic.PrivKey, ks keystore.Keystore) *Republisher { - return &Republisher{ - ns: ns, - ds: ds, - self: self, - ks: ks, - Interval: DefaultRebroadcastInterval, - RecordLifetime: DefaultRecordLifetime, - } -} - -func (rp *Republisher) Run(proc goprocess.Process) { - timer := time.NewTimer(InitialRebroadcastDelay) - defer timer.Stop() - if rp.Interval < InitialRebroadcastDelay { - timer.Reset(rp.Interval) - } - - for { - select { - case <-timer.C: - timer.Reset(rp.Interval) - err := rp.republishEntries(proc) - if err != nil { - log.Info("republisher failed to republish: ", err) - if FailureRetryInterval < rp.Interval { - timer.Reset(FailureRetryInterval) - } - } - case <-proc.Closing(): - return - } - } -} - -func (rp *Republisher) republishEntries(p goprocess.Process) error { - ctx, cancel := context.WithCancel(gpctx.OnClosingContext(p)) - defer cancel() - - // TODO: Use rp.ipns.ListPublished(). We can't currently *do* that - // because: - // 1. There's no way to get keys from the keystore by ID. - // 2. We don't actually have access to the IPNS publisher. - err := rp.republishEntry(ctx, rp.self) - if err != nil { - return err - } - - if rp.ks != nil { - keyNames, err := rp.ks.List() - if err != nil { - return err - } - for _, name := range keyNames { - priv, err := rp.ks.Get(name) - if err != nil { - return err - } - err = rp.republishEntry(ctx, priv) - if err != nil { - return err - } - - } - } - - return nil -} - -func (rp *Republisher) republishEntry(ctx context.Context, priv ic.PrivKey) error { - id, err := peer.IDFromPrivateKey(priv) - if err != nil { - return err - } - - log.Debugf("republishing ipns entry for %s", id) - - // Look for it locally only - e, err := rp.getLastIPNSEntry(id) - if err != nil { - if err == errNoEntry { - return nil - } - return err - } - - p := path.Path(e.GetValue()) - prevEol, err := ipns.GetEOL(e) - if err != nil { - return err - } - - // update record with same sequence number - eol := time.Now().Add(rp.RecordLifetime) - if prevEol.After(eol) { - eol = prevEol - } - return rp.ns.PublishWithEOL(ctx, priv, p, eol) -} - -func (rp *Republisher) getLastIPNSEntry(id peer.ID) (*pb.IpnsEntry, error) { - // Look for it locally only - val, err := rp.ds.Get(namesys.IpnsDsKey(id)) - switch err { - case nil: - case ds.ErrNotFound: - return nil, errNoEntry - default: - return nil, err - } - - e := new(pb.IpnsEntry) - if err := proto.Unmarshal(val, e); err != nil { - return nil, err - } - return e, nil -} diff --git a/namesys/republisher/repub_test.go b/namesys/republisher/repub_test.go deleted file mode 100644 index c75d7faa9be..00000000000 --- a/namesys/republisher/repub_test.go +++ /dev/null @@ -1,245 +0,0 @@ -package republisher_test - -import ( - "context" - "errors" - "testing" - "time" - - "github.com/gogo/protobuf/proto" - - goprocess "github.com/jbenet/goprocess" - peer "github.com/libp2p/go-libp2p-core/peer" - mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" - - ds "github.com/ipfs/go-datastore" - "github.com/ipfs/go-ipns" - "github.com/ipfs/go-ipns/pb" - path "github.com/ipfs/go-path" - - "github.com/ipfs/go-ipfs/core" - "github.com/ipfs/go-ipfs/core/bootstrap" - mock "github.com/ipfs/go-ipfs/core/mock" - namesys "github.com/ipfs/go-ipfs/namesys" - . "github.com/ipfs/go-ipfs/namesys/republisher" -) - -func TestRepublish(t *testing.T) { - // set cache life to zero for testing low-period repubs - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - // create network - mn := mocknet.New(ctx) - - var nodes []*core.IpfsNode - for i := 0; i < 10; i++ { - nd, err := mock.MockPublicNode(ctx, mn) - if err != nil { - t.Fatal(err) - } - - nd.Namesys = namesys.NewNameSystem(nd.Routing, nd.Repo.Datastore(), 0) - - nodes = append(nodes, nd) - } - - if err := mn.LinkAll(); err != nil { - t.Fatal(err) - } - - bsinf := bootstrap.BootstrapConfigWithPeers( - []peer.AddrInfo{ - nodes[0].Peerstore.PeerInfo(nodes[0].Identity), - }, - ) - - for _, n := range nodes[1:] { - if err := n.Bootstrap(bsinf); err != nil { - t.Fatal(err) - } - } - - // have one node publish a record that is valid for 1 second - publisher := nodes[3] - p := path.FromString("/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn") // does not need to be valid - rp := namesys.NewIpnsPublisher(publisher.Routing, publisher.Repo.Datastore()) - name := "/ipns/" + publisher.Identity.Pretty() - - // Retry in case the record expires before we can fetch it. This can - // happen when running the test on a slow machine. - var expiration time.Time - timeout := time.Second - for { - expiration = time.Now().Add(time.Second) - err := rp.PublishWithEOL(ctx, publisher.PrivateKey, p, expiration) - if err != nil { - t.Fatal(err) - } - - err = verifyResolution(nodes, name, p) - if err == nil { - break - } - - if time.Now().After(expiration) { - timeout *= 2 - continue - } - t.Fatal(err) - } - - // Now wait a second, the records will be invalid and we should fail to resolve - time.Sleep(timeout) - if err := verifyResolutionFails(nodes, name); err != nil { - t.Fatal(err) - } - - // 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 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 - - proc := goprocess.Go(repub.Run) - defer proc.Close() - - // now wait a couple seconds for it to fire - time.Sleep(time.Second * 2) - - // we should be able to resolve them now - if err := verifyResolution(nodes, name, p); err != nil { - t.Fatal(err) - } -} - -func TestLongEOLRepublish(t *testing.T) { - // set cache life to zero for testing low-period repubs - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - // create network - mn := mocknet.New(ctx) - - var nodes []*core.IpfsNode - for i := 0; i < 10; i++ { - nd, err := mock.MockPublicNode(ctx, mn) - if err != nil { - t.Fatal(err) - } - - nd.Namesys = namesys.NewNameSystem(nd.Routing, nd.Repo.Datastore(), 0) - - nodes = append(nodes, nd) - } - - if err := mn.LinkAll(); err != nil { - t.Fatal(err) - } - - bsinf := bootstrap.BootstrapConfigWithPeers( - []peer.AddrInfo{ - nodes[0].Peerstore.PeerInfo(nodes[0].Identity), - }, - ) - - for _, n := range nodes[1:] { - if err := n.Bootstrap(bsinf); err != nil { - t.Fatal(err) - } - } - - // have one node publish a record that is valid for 1 second - publisher := nodes[3] - p := path.FromString("/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn") // does not need to be valid - rp := namesys.NewIpnsPublisher(publisher.Routing, publisher.Repo.Datastore()) - name := "/ipns/" + publisher.Identity.Pretty() - - expiration := time.Now().Add(time.Hour) - err := rp.PublishWithEOL(ctx, publisher.PrivateKey, p, expiration) - if err != nil { - t.Fatal(err) - } - - err = verifyResolution(nodes, name, p) - if err != nil { - t.Fatal(err) - } - - // 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 don't exist and make our own. - repub := NewRepublisher(rp, publisher.Repo.Datastore(), publisher.PrivateKey, publisher.Repo.Keystore()) - repub.Interval = time.Millisecond * 500 - repub.RecordLifetime = time.Second - - proc := goprocess.Go(repub.Run) - defer proc.Close() - - // now wait a couple seconds for it to fire a few times - time.Sleep(time.Second * 2) - - err = verifyResolution(nodes, name, p) - if err != nil { - t.Fatal(err) - } - - entry, err := getLastIPNSEntry(publisher.Repo.Datastore(), publisher.Identity) - if err != nil { - t.Fatal(err) - } - - finalEol, err := ipns.GetEOL(entry) - if err != nil { - t.Fatal(err) - } - - if !finalEol.Equal(expiration) { - t.Fatal("expiration time modified") - } -} - -func getLastIPNSEntry(dstore ds.Datastore, id peer.ID) (*ipns_pb.IpnsEntry, error) { - // Look for it locally only - val, err := dstore.Get(namesys.IpnsDsKey(id)) - if err != nil { - return nil, err - } - - e := new(ipns_pb.IpnsEntry) - if err := proto.Unmarshal(val, e); err != nil { - return nil, err - } - return e, nil -} - -func verifyResolution(nodes []*core.IpfsNode, key string, exp path.Path) error { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - for _, n := range nodes { - val, err := n.Namesys.Resolve(ctx, key) - if err != nil { - return err - } - - if val != exp { - return errors.New("resolved wrong record") - } - } - return nil -} - -func verifyResolutionFails(nodes []*core.IpfsNode, key string) error { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - for _, n := range nodes { - _, err := n.Namesys.Resolve(ctx, key) - if err == nil { - return errors.New("expected resolution to fail") - } - } - return nil -} diff --git a/namesys/resolve/resolve.go b/namesys/resolve/resolve.go deleted file mode 100644 index f838a6611f7..00000000000 --- a/namesys/resolve/resolve.go +++ /dev/null @@ -1,52 +0,0 @@ -package resolve - -import ( - "context" - "errors" - "fmt" - "strings" - - "github.com/ipfs/go-path" - - "github.com/ipfs/go-ipfs/namesys" -) - -// ErrNoNamesys is an explicit error for when an IPFS node doesn't -// (yet) have a name system -var ErrNoNamesys = errors.New( - "core/resolve: no Namesys on IpfsNode - can't resolve ipns entry") - -// ResolveIPNS resolves /ipns paths -func ResolveIPNS(ctx context.Context, nsys namesys.NameSystem, p path.Path) (path.Path, error) { - if strings.HasPrefix(p.String(), "/ipns/") { - // TODO(cryptix): we should be able to query the local cache for the path - if nsys == nil { - return "", ErrNoNamesys - } - - seg := p.Segments() - - if len(seg) < 2 || seg[1] == "" { // just "/" without further segments - err := fmt.Errorf("invalid path %q: ipns path missing IPNS ID", p) - return "", err - } - - extensions := seg[2:] - resolvable, err := path.FromSegments("/", seg[0], seg[1]) - if err != nil { - return "", err - } - - respath, err := nsys.Resolve(ctx, resolvable.String()) - if err != nil { - return "", err - } - - segments := append(respath.Segments(), extensions...) - p, err = path.FromSegments("/", segments...) - if err != nil { - return "", err - } - } - return p, nil -} diff --git a/namesys/resolve_test.go b/namesys/resolve_test.go deleted file mode 100644 index 4f92a2d0d0e..00000000000 --- a/namesys/resolve_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package namesys - -import ( - "context" - "errors" - "testing" - "time" - - ds "github.com/ipfs/go-datastore" - dssync "github.com/ipfs/go-datastore/sync" - mockrouting "github.com/ipfs/go-ipfs-routing/mock" - ipns "github.com/ipfs/go-ipns" - path "github.com/ipfs/go-path" - testutil "github.com/libp2p/go-libp2p-testing/net" - tnet "github.com/libp2p/go-libp2p-testing/net" -) - -func TestRoutingResolve(t *testing.T) { - dstore := dssync.MutexWrap(ds.NewMapDatastore()) - serv := mockrouting.NewServer() - id := testutil.RandIdentityOrFatal(t) - d := serv.ClientWithDatastore(context.Background(), id, dstore) - - resolver := NewIpnsResolver(d) - publisher := NewIpnsPublisher(d, dstore) - - identity := tnet.RandIdentityOrFatal(t) - - h := path.FromString("/ipfs/QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN") - err := publisher.Publish(context.Background(), identity.PrivateKey(), h) - if err != nil { - t.Fatal(err) - } - - res, err := resolver.Resolve(context.Background(), identity.ID().Pretty()) - if err != nil { - t.Fatal(err) - } - - if res != h { - t.Fatal("Got back incorrect value.") - } -} - -func TestPrexistingExpiredRecord(t *testing.T) { - dstore := dssync.MutexWrap(ds.NewMapDatastore()) - d := mockrouting.NewServer().ClientWithDatastore(context.Background(), testutil.RandIdentityOrFatal(t), dstore) - - resolver := NewIpnsResolver(d) - publisher := NewIpnsPublisher(d, dstore) - - 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(identity.PrivateKey(), []byte(h), 0, eol) - if err != nil { - t.Fatal(err) - } - 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(), identity.PrivateKey(), h) - if err != nil { - t.Fatal(err) - } - - err = verifyCanResolve(resolver, identity.ID().Pretty(), h) - if err != nil { - t.Fatal(err) - } -} - -func TestPrexistingRecord(t *testing.T) { - dstore := dssync.MutexWrap(ds.NewMapDatastore()) - d := mockrouting.NewServer().ClientWithDatastore(context.Background(), testutil.RandIdentityOrFatal(t), dstore) - - resolver := NewIpnsResolver(d) - publisher := NewIpnsPublisher(d, dstore) - - 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(identity.PrivateKey(), []byte(h), 0, eol) - if err != nil { - t.Fatal(err) - } - 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(), identity.PrivateKey(), h) - if err != nil { - t.Fatal(err) - } - - err = verifyCanResolve(resolver, identity.ID().Pretty(), h) - if err != nil { - t.Fatal(err) - } -} - -func verifyCanResolve(r Resolver, name string, exp path.Path) error { - res, err := r.Resolve(context.Background(), name) - if err != nil { - return err - } - - if res != exp { - return errors.New("got back wrong record") - } - - return nil -} diff --git a/namesys/routing.go b/namesys/routing.go deleted file mode 100644 index 8bdfe21e65b..00000000000 --- a/namesys/routing.go +++ /dev/null @@ -1,148 +0,0 @@ -package namesys - -import ( - "context" - "strings" - "time" - - proto "github.com/gogo/protobuf/proto" - cid "github.com/ipfs/go-cid" - ipns "github.com/ipfs/go-ipns" - pb "github.com/ipfs/go-ipns/pb" - 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" - mh "github.com/multiformats/go-multihash" -) - -var log = logging.Logger("namesys") - -// IpnsResolver implements NSResolver for the main IPFS SFS-like naming -type IpnsResolver struct { - routing routing.ValueStore -} - -// NewIpnsResolver constructs a name resolver using the IPFS Routing system -// to implement SFS-like naming on top. -func NewIpnsResolver(route routing.ValueStore) *IpnsResolver { - if route == nil { - panic("attempt to create resolver with nil routing system") - } - return &IpnsResolver{ - routing: route, - } -} - -// Resolve implements Resolver. -func (r *IpnsResolver) Resolve(ctx context.Context, name string, options ...opts.ResolveOpt) (path.Path, error) { - return resolve(ctx, r, name, opts.ProcessOpts(options)) -} - -// ResolveAsync implements Resolver. -func (r *IpnsResolver) ResolveAsync(ctx context.Context, name string, options ...opts.ResolveOpt) <-chan Result { - return resolveAsync(ctx, r, name, opts.ProcessOpts(options)) -} - -// resolveOnce implements resolver. Uses the IPFS routing system to -// resolve SFS-like names. -func (r *IpnsResolver) resolveOnceAsync(ctx context.Context, name string, options opts.ResolveOpts) <-chan onceResult { - out := make(chan onceResult, 1) - log.Debugf("RoutingResolver resolving %s", name) - cancel := func() {} - - if options.DhtTimeout != 0 { - // Resolution must complete within the timeout - ctx, cancel = context.WithTimeout(ctx, options.DhtTimeout) - } - - name = strings.TrimPrefix(name, "/ipns/") - - 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} - close(out) - cancel() - return out - } - - // Use the routing system to get the name. - // Note that the DHT will call the ipns validator when retrieving - // the value, which in turn verifies the ipns record signature - ipnsKey := ipns.RecordKey(pid) - - vals, err := r.routing.SearchValue(ctx, ipnsKey, dht.Quorum(int(options.DhtRecordCount))) - if err != nil { - log.Debugf("RoutingResolver: dht get for name %s failed: %s", name, err) - out <- onceResult{err: err} - close(out) - cancel() - return out - } - - go func() { - defer cancel() - defer close(out) - for { - select { - case val, ok := <-vals: - if !ok { - return - } - - entry := new(pb.IpnsEntry) - err = proto.Unmarshal(val, entry) - if err != nil { - log.Debugf("RoutingResolver: could not unmarshal value for name %s: %s", name, err) - emitOnceResult(ctx, out, onceResult{err: err}) - return - } - - var p path.Path - // check for old style record: - if valh, err := mh.Cast(entry.GetValue()); err == nil { - // Its an old style multihash record - log.Debugf("encountered CIDv0 ipns entry: %s", valh) - p = path.FromCid(cid.NewCidV0(valh)) - } else { - // Not a multihash, probably a new style record - p, err = path.ParsePath(string(entry.GetValue())) - if err != nil { - emitOnceResult(ctx, out, onceResult{err: err}) - return - } - } - - ttl := DefaultResolverCacheTTL - if entry.Ttl != nil { - ttl = time.Duration(*entry.Ttl) - } - switch eol, err := ipns.GetEOL(entry); err { - case ipns.ErrUnrecognizedValidity: - // No EOL. - case nil: - ttEol := time.Until(eol) - if ttEol < 0 { - // It *was* valid when we first resolved it. - ttl = 0 - } else if ttEol < ttl { - ttl = ttEol - } - default: - log.Errorf("encountered error when parsing EOL: %s", err) - emitOnceResult(ctx, out, onceResult{err: err}) - return - } - - emitOnceResult(ctx, out, onceResult{value: p, ttl: ttl}) - case <-ctx.Done(): - return - } - } - }() - - return out -} diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index 011c47a1d7c..56526e2e687 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -11,7 +11,7 @@ import ( "sync" filestore "github.com/ipfs/go-filestore" - keystore "github.com/ipfs/go-ipfs/keystore" + keystore "github.com/ipfs/go-ipfs-keystore" repo "github.com/ipfs/go-ipfs/repo" "github.com/ipfs/go-ipfs/repo/common" mfsr "github.com/ipfs/go-ipfs/repo/fsrepo/migrations" diff --git a/repo/mock.go b/repo/mock.go index f39fe6f1795..298a49a298d 100644 --- a/repo/mock.go +++ b/repo/mock.go @@ -4,7 +4,7 @@ import ( "errors" filestore "github.com/ipfs/go-filestore" - keystore "github.com/ipfs/go-ipfs/keystore" + keystore "github.com/ipfs/go-ipfs-keystore" config "github.com/ipfs/go-ipfs-config" ma "github.com/multiformats/go-multiaddr" diff --git a/repo/repo.go b/repo/repo.go index 5c2557c6a82..614bfa5beda 100644 --- a/repo/repo.go +++ b/repo/repo.go @@ -5,7 +5,7 @@ import ( "io" filestore "github.com/ipfs/go-filestore" - keystore "github.com/ipfs/go-ipfs/keystore" + keystore "github.com/ipfs/go-ipfs-keystore" ds "github.com/ipfs/go-datastore" config "github.com/ipfs/go-ipfs-config"